blob: 49deeee8bc58c9be545191b2a7c9180619a989dc [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.sling.scripting.jsp;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.apache.sling.api.SlingException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceMetadata;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.commons.classloader.ClassLoaderWriter;
import org.apache.sling.commons.compiler.JavaCompiler;
import org.apache.sling.scripting.jsp.jasper.IOProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The <code>SlingIOProvider</code>
*/
class SlingIOProvider implements IOProvider {
private static final String WEB_INF_TAGS = "/WEB-INF/tags";
/** default log */
private final Logger log = LoggerFactory.getLogger(SlingIOProvider.class);
private final ThreadLocal<ResourceResolver> requestResourceResolver;
private final ClassLoaderWriter classLoaderWriter;
private final JavaCompiler javaCompiler;
SlingIOProvider(final ClassLoaderWriter classLoaderWriter, final JavaCompiler compiler) {
this.requestResourceResolver = new ThreadLocal<ResourceResolver>();
this.classLoaderWriter = classLoaderWriter;
this.javaCompiler = compiler;
}
/**
* Set the thread context resource resolver.
*/
ResourceResolver setRequestResourceResolver(final ResourceResolver resolver) {
final ResourceResolver old = requestResourceResolver.get();
requestResourceResolver.set(resolver);
return old;
}
/**
* Reset the thread context resource resolver.
*/
void resetRequestResourceResolver(final ResourceResolver resolver) {
requestResourceResolver.set(resolver);
}
// ---------- IOProvider interface -----------------------------------------
/**
* Returns an InputStream for the file name which is looked up with the
* ResourceProvider and retrieved from the Resource if the StreamProvider
* interface is implemented.
*/
public InputStream getInputStream(final String path)
throws FileNotFoundException, IOException {
if ( path.startsWith(":") ) {
return this.classLoaderWriter.getInputStream(path.substring(1));
}
ResourceResolver resolver = requestResourceResolver.get();
if (resolver != null) {
try {
final Resource resource = resolver.getResource(cleanPath(path, true));
if (resource != null) {
final InputStream stream = resource.adaptTo(InputStream.class);
if (stream != null) {
return stream;
}
}
} catch (final SlingException se) {
throw (IOException) new IOException(
"Failed to get InputStream for " + path).initCause(se);
}
}
throw new FileNotFoundException("Cannot find " + path);
}
/**
* Returns the value of the last modified meta data field of the resource
* found at file name or zero if the meta data field is not set. If the
* resource does not exist or an error occurrs finding the resource, -1 is
* returned.
*/
public long lastModified(final String path) {
if ( path.startsWith(":") ) {
return this.classLoaderWriter.getLastModified(path.substring(1));
}
ResourceResolver resolver = requestResourceResolver.get();
if (resolver != null) {
try {
final Resource resource = resolver.getResource(cleanPath(path, true));
if (resource != null) {
ResourceMetadata meta = resource.getResourceMetadata();
long modTime = meta.getModificationTime();
return (modTime > 0) ? modTime : 0;
}
} catch (final SlingException se) {
log.error("Cannot get last modification time for " + path, se);
}
}
// fallback to "non-existant" in case of problems
return -1;
}
/**
* Removes the named item from the repository.
*/
public boolean delete(final String path) {
return this.classLoaderWriter.delete(path.substring(1));
}
/**
* Returns an output stream to write to the repository.
*/
public OutputStream getOutputStream(final String path) {
return this.classLoaderWriter.getOutputStream(path.substring(1));
}
/**
* Renames a node in the repository.
*/
public boolean rename(final String oldFileName, final String newFileName) {
return this.classLoaderWriter.rename(oldFileName.substring(1), newFileName.substring(1));
}
/**
* Creates a folder hierarchy in the repository.
*/
public boolean mkdirs(final String path) {
// we just do nothing
return true;
}
/**
* @see org.apache.sling.scripting.jsp.jasper.IOProvider#getClassLoader()
*/
public ClassLoader getClassLoader() {
return this.classLoaderWriter.getClassLoader();
}
// ---------- Helper Methods for JspServletContext -------------------------
URL getURL(final String path) throws MalformedURLException {
ResourceResolver resolver = requestResourceResolver.get();
if (resolver != null) {
try {
final Resource resource = resolver.getResource(cleanPath(path, true));
return (resource != null) ? resource.adaptTo(URL.class) : null;
} catch (final SlingException se) {
throw (MalformedURLException) new MalformedURLException(
"Cannot get URL for " + path).initCause(se);
}
}
return null;
}
Set<String> getResourcePaths(final String path) {
final Set<String> paths = new HashSet<String>();
ResourceResolver resolver = requestResourceResolver.get();
if (resolver != null) {
try {
final String cleanedPath = cleanPath(path, false);
final boolean startsWithWebInfTags = cleanedPath.startsWith(WEB_INF_TAGS);
Resource resource = resolver.getResource(startsWithWebInfTags ? cleanedPath.substring(WEB_INF_TAGS.length()) : cleanedPath);
if (resource != null) {
Iterator<Resource> entries = resolver.listChildren(resource);
while (entries.hasNext()) {
final String entryPath = entries.next().getPath();
if (startsWithWebInfTags) {
paths.add(WEB_INF_TAGS + entryPath);
} else {
paths.add(entryPath);
}
}
}
} catch (final SlingException se) {
log.warn("getResourcePaths: Cannot list children of " + path,
se);
}
}
return paths.isEmpty() ? null : paths;
}
// ---------- internal -----------------------------------------------------
private String cleanPath(String path, final boolean removeWebInfTags) {
// replace backslash by slash
path = path.replace('\\', '/');
// cut off trailing slash
while (path.endsWith("/")) {
path = path.substring(0, path.length() - 1);
}
if (removeWebInfTags && path.startsWith(WEB_INF_TAGS)) {
path = path.substring(WEB_INF_TAGS.length());
}
return path;
}
/**
* @see org.apache.sling.scripting.jsp.jasper.IOProvider#getJavaCompiler()
*/
public JavaCompiler getJavaCompiler() {
return this.javaCompiler;
}
/**
* @see org.apache.sling.scripting.jsp.jasper.IOProvider#getClassLoaderWriter()
*/
public ClassLoaderWriter getClassLoaderWriter() {
return this.classLoaderWriter;
}
}