init
This commit is contained in:
764
java/org/apache/jasper/JspCompilationContext.java
Normal file
764
java/org/apache/jasper/JspCompilationContext.java
Normal file
@@ -0,0 +1,764 @@
|
||||
/*
|
||||
* 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.jasper;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarEntry;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.jsp.tagext.TagInfo;
|
||||
|
||||
import org.apache.jasper.compiler.Compiler;
|
||||
import org.apache.jasper.compiler.JspRuntimeContext;
|
||||
import org.apache.jasper.compiler.JspUtil;
|
||||
import org.apache.jasper.compiler.Localizer;
|
||||
import org.apache.jasper.compiler.ServletWriter;
|
||||
import org.apache.jasper.servlet.JasperLoader;
|
||||
import org.apache.jasper.servlet.JspServletWrapper;
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.Jar;
|
||||
import org.apache.tomcat.util.descriptor.tld.TldResourcePath;
|
||||
|
||||
/**
|
||||
* A place holder for various things that are used through out the JSP
|
||||
* engine. This is a per-request/per-context data structure. Some of
|
||||
* the instance variables are set at different points.
|
||||
*
|
||||
* Most of the path-related stuff is here - mangling names, versions, dirs,
|
||||
* loading resources and dealing with uris.
|
||||
*
|
||||
* @author Anil K. Vijendran
|
||||
* @author Harish Prabandham
|
||||
* @author Pierre Delisle
|
||||
* @author Costin Manolache
|
||||
* @author Kin-man Chung
|
||||
*/
|
||||
public class JspCompilationContext {
|
||||
|
||||
private final Log log = LogFactory.getLog(JspCompilationContext.class); // must not be static
|
||||
|
||||
private String className;
|
||||
private final String jspUri;
|
||||
private String basePackageName;
|
||||
private String derivedPackageName;
|
||||
private String servletJavaFileName;
|
||||
private String javaPath;
|
||||
private String classFileName;
|
||||
private ServletWriter writer;
|
||||
private final Options options;
|
||||
private final JspServletWrapper jsw;
|
||||
private Compiler jspCompiler;
|
||||
private String classPath;
|
||||
|
||||
private final String baseURI;
|
||||
private String outputDir;
|
||||
private final ServletContext context;
|
||||
private ClassLoader loader;
|
||||
|
||||
private final JspRuntimeContext rctxt;
|
||||
|
||||
private volatile boolean removed = false;
|
||||
|
||||
// volatile so changes are visible when multiple threads request a JSP file
|
||||
// that has been modified
|
||||
private volatile URLClassLoader jspLoader;
|
||||
private URL baseUrl;
|
||||
private Class<?> servletClass;
|
||||
|
||||
private final boolean isTagFile;
|
||||
private boolean protoTypeMode;
|
||||
private TagInfo tagInfo;
|
||||
private Jar tagJar;
|
||||
|
||||
// jspURI _must_ be relative to the context
|
||||
public JspCompilationContext(String jspUri, Options options,
|
||||
ServletContext context, JspServletWrapper jsw,
|
||||
JspRuntimeContext rctxt) {
|
||||
this(jspUri, null, options, context, jsw, rctxt, null, false);
|
||||
}
|
||||
|
||||
public JspCompilationContext(String tagfile, TagInfo tagInfo,
|
||||
Options options, ServletContext context, JspServletWrapper jsw,
|
||||
JspRuntimeContext rctxt, Jar tagJar) {
|
||||
this(tagfile, tagInfo, options, context, jsw, rctxt, tagJar, true);
|
||||
}
|
||||
|
||||
private JspCompilationContext(String jspUri, TagInfo tagInfo,
|
||||
Options options, ServletContext context, JspServletWrapper jsw,
|
||||
JspRuntimeContext rctxt, Jar tagJar, boolean isTagFile) {
|
||||
|
||||
this.jspUri = canonicalURI(jspUri);
|
||||
this.options = options;
|
||||
this.jsw = jsw;
|
||||
this.context = context;
|
||||
|
||||
String baseURI = jspUri.substring(0, jspUri.lastIndexOf('/') + 1);
|
||||
// hack fix for resolveRelativeURI
|
||||
if (baseURI.isEmpty()) {
|
||||
baseURI = "/";
|
||||
} else if (baseURI.charAt(0) != '/') {
|
||||
// strip the base slash since it will be combined with the
|
||||
// uriBase to generate a file
|
||||
baseURI = "/" + baseURI;
|
||||
}
|
||||
if (baseURI.charAt(baseURI.length() - 1) != '/') {
|
||||
baseURI += '/';
|
||||
}
|
||||
this.baseURI = baseURI;
|
||||
|
||||
this.rctxt = rctxt;
|
||||
this.basePackageName = Constants.JSP_PACKAGE_NAME;
|
||||
|
||||
this.tagInfo = tagInfo;
|
||||
this.tagJar = tagJar;
|
||||
this.isTagFile = isTagFile;
|
||||
}
|
||||
|
||||
|
||||
/* ==================== Methods to override ==================== */
|
||||
|
||||
/** ---------- Class path and loader ---------- */
|
||||
|
||||
/**
|
||||
* @return the classpath that is passed off to the Java compiler.
|
||||
*/
|
||||
public String getClassPath() {
|
||||
if( classPath != null ) {
|
||||
return classPath;
|
||||
}
|
||||
return rctxt.getClassPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* The classpath that is passed off to the Java compiler.
|
||||
* @param classPath The class path to use
|
||||
*/
|
||||
public void setClassPath(String classPath) {
|
||||
this.classPath = classPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* What class loader to use for loading classes while compiling
|
||||
* this JSP?
|
||||
* @return the class loader used to load all compiled classes
|
||||
*/
|
||||
public ClassLoader getClassLoader() {
|
||||
if( loader != null ) {
|
||||
return loader;
|
||||
}
|
||||
return rctxt.getParentClassLoader();
|
||||
}
|
||||
|
||||
public void setClassLoader(ClassLoader loader) {
|
||||
this.loader = loader;
|
||||
}
|
||||
|
||||
public ClassLoader getJspLoader() {
|
||||
if( jspLoader == null ) {
|
||||
jspLoader = new JasperLoader
|
||||
(new URL[] {baseUrl},
|
||||
getClassLoader(),
|
||||
rctxt.getPermissionCollection());
|
||||
}
|
||||
return jspLoader;
|
||||
}
|
||||
|
||||
public void clearJspLoader() {
|
||||
jspLoader = null;
|
||||
}
|
||||
|
||||
|
||||
/** ---------- Input/Output ---------- */
|
||||
|
||||
/**
|
||||
* The output directory to generate code into. The output directory
|
||||
* is make up of the scratch directory, which is provide in Options,
|
||||
* plus the directory derived from the package name.
|
||||
* @return the output directory in which the generated sources are placed
|
||||
*/
|
||||
public String getOutputDir() {
|
||||
if (outputDir == null) {
|
||||
createOutputDir();
|
||||
}
|
||||
|
||||
return outputDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a "Compiler" object based on some init param data. This
|
||||
* is not done yet. Right now we're just hardcoding the actual
|
||||
* compilers that are created.
|
||||
* @return the Java compiler wrapper
|
||||
*/
|
||||
public Compiler createCompiler() {
|
||||
if (jspCompiler != null ) {
|
||||
return jspCompiler;
|
||||
}
|
||||
jspCompiler = null;
|
||||
if (options.getCompilerClassName() != null) {
|
||||
jspCompiler = createCompiler(options.getCompilerClassName());
|
||||
} else {
|
||||
if (options.getCompiler() == null) {
|
||||
jspCompiler = createCompiler("org.apache.jasper.compiler.JDTCompiler");
|
||||
if (jspCompiler == null) {
|
||||
jspCompiler = createCompiler("org.apache.jasper.compiler.AntCompiler");
|
||||
}
|
||||
} else {
|
||||
jspCompiler = createCompiler("org.apache.jasper.compiler.AntCompiler");
|
||||
if (jspCompiler == null) {
|
||||
jspCompiler = createCompiler("org.apache.jasper.compiler.JDTCompiler");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (jspCompiler == null) {
|
||||
throw new IllegalStateException(Localizer.getMessage("jsp.error.compiler.config",
|
||||
options.getCompilerClassName(), options.getCompiler()));
|
||||
}
|
||||
jspCompiler.init(this, jsw);
|
||||
return jspCompiler;
|
||||
}
|
||||
|
||||
protected Compiler createCompiler(String className) {
|
||||
Compiler compiler = null;
|
||||
try {
|
||||
compiler = (Compiler) Class.forName(className).getConstructor().newInstance();
|
||||
} catch (NoClassDefFoundError | ClassNotFoundException e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(Localizer.getMessage("jsp.error.compiler"), e);
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
log.warn(Localizer.getMessage("jsp.error.compiler"), e);
|
||||
}
|
||||
return compiler;
|
||||
}
|
||||
|
||||
public Compiler getCompiler() {
|
||||
return jspCompiler;
|
||||
}
|
||||
|
||||
/** ---------- Access resources in the webapp ---------- */
|
||||
|
||||
/**
|
||||
* Get the full value of a URI relative to this compilations context
|
||||
* uses current file as the base.
|
||||
* @param uri The relative URI
|
||||
* @return absolute URI
|
||||
*/
|
||||
public String resolveRelativeUri(String uri) {
|
||||
// sometimes we get uri's massaged from File(String), so check for
|
||||
// a root directory separator char
|
||||
if (uri.startsWith("/") || uri.startsWith(File.separator)) {
|
||||
return uri;
|
||||
} else {
|
||||
return baseURI + uri;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a resource as a stream, relative to the meanings of this
|
||||
* context's implementation.
|
||||
* @param res the resource to look for
|
||||
* @return a null if the resource cannot be found or represented
|
||||
* as an InputStream.
|
||||
*/
|
||||
public java.io.InputStream getResourceAsStream(String res) {
|
||||
return context.getResourceAsStream(canonicalURI(res));
|
||||
}
|
||||
|
||||
|
||||
public URL getResource(String res) throws MalformedURLException {
|
||||
return context.getResource(canonicalURI(res));
|
||||
}
|
||||
|
||||
|
||||
public Set<String> getResourcePaths(String path) {
|
||||
return context.getResourcePaths(canonicalURI(path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the actual path of a URI relative to the context of
|
||||
* the compilation.
|
||||
* @param path The webapp path
|
||||
* @return the corresponding path in the filesystem
|
||||
*/
|
||||
public String getRealPath(String path) {
|
||||
if (context != null) {
|
||||
return context.getRealPath(path);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the JAR file in which the tag file for which this
|
||||
* JspCompilationContext was created is packaged, or null if this
|
||||
* JspCompilationContext does not correspond to a tag file, or if the
|
||||
* corresponding tag file is not packaged in a JAR.
|
||||
* @return a JAR file
|
||||
*/
|
||||
public Jar getTagFileJar() {
|
||||
return this.tagJar;
|
||||
}
|
||||
|
||||
public void setTagFileJar(Jar tagJar) {
|
||||
this.tagJar = tagJar;
|
||||
}
|
||||
|
||||
/* ==================== Common implementation ==================== */
|
||||
|
||||
/**
|
||||
* Just the class name (does not include package name) of the
|
||||
* generated class.
|
||||
* @return the class name
|
||||
*/
|
||||
public String getServletClassName() {
|
||||
|
||||
if (className != null) {
|
||||
return className;
|
||||
}
|
||||
|
||||
if (isTagFile) {
|
||||
className = tagInfo.getTagClassName();
|
||||
int lastIndex = className.lastIndexOf('.');
|
||||
if (lastIndex != -1) {
|
||||
className = className.substring(lastIndex + 1);
|
||||
}
|
||||
} else {
|
||||
int iSep = jspUri.lastIndexOf('/') + 1;
|
||||
className = JspUtil.makeJavaIdentifier(jspUri.substring(iSep));
|
||||
}
|
||||
return className;
|
||||
}
|
||||
|
||||
public void setServletClassName(String className) {
|
||||
this.className = className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Path of the JSP URI. Note that this is not a file name. This is
|
||||
* the context rooted URI of the JSP file.
|
||||
* @return the path to the JSP
|
||||
*/
|
||||
public String getJspFile() {
|
||||
return jspUri;
|
||||
}
|
||||
|
||||
|
||||
public Long getLastModified(String resource) {
|
||||
return getLastModified(resource, tagJar);
|
||||
}
|
||||
|
||||
|
||||
public Long getLastModified(String resource, Jar tagJar) {
|
||||
long result = -1;
|
||||
URLConnection uc = null;
|
||||
try {
|
||||
if (tagJar != null) {
|
||||
if (resource.startsWith("/")) {
|
||||
resource = resource.substring(1);
|
||||
}
|
||||
result = tagJar.getLastModified(resource);
|
||||
} else {
|
||||
URL jspUrl = getResource(resource);
|
||||
if (jspUrl == null) {
|
||||
incrementRemoved();
|
||||
return Long.valueOf(result);
|
||||
}
|
||||
uc = jspUrl.openConnection();
|
||||
if (uc instanceof JarURLConnection) {
|
||||
JarEntry jarEntry = ((JarURLConnection) uc).getJarEntry();
|
||||
if (jarEntry != null) {
|
||||
result = jarEntry.getTime();
|
||||
} else {
|
||||
result = uc.getLastModified();
|
||||
}
|
||||
} else {
|
||||
result = uc.getLastModified();
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(Localizer.getMessage(
|
||||
"jsp.error.lastModified", getJspFile()), e);
|
||||
}
|
||||
result = -1;
|
||||
} finally {
|
||||
if (uc != null) {
|
||||
try {
|
||||
uc.getInputStream().close();
|
||||
} catch (IOException e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(Localizer.getMessage(
|
||||
"jsp.error.lastModified", getJspFile()), e);
|
||||
}
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Long.valueOf(result);
|
||||
}
|
||||
|
||||
public boolean isTagFile() {
|
||||
return isTagFile;
|
||||
}
|
||||
|
||||
public TagInfo getTagInfo() {
|
||||
return tagInfo;
|
||||
}
|
||||
|
||||
public void setTagInfo(TagInfo tagi) {
|
||||
tagInfo = tagi;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if we are compiling a tag file
|
||||
* in prototype mode.
|
||||
* ie we only generate codes with class for the tag handler with empty
|
||||
* method bodies.
|
||||
*/
|
||||
public boolean isPrototypeMode() {
|
||||
return protoTypeMode;
|
||||
}
|
||||
|
||||
public void setPrototypeMode(boolean pm) {
|
||||
protoTypeMode = pm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Package name for the generated class is make up of the base package
|
||||
* name, which is user settable, and the derived package name. The
|
||||
* derived package name directly mirrors the file hierarchy of the JSP page.
|
||||
* @return the package name
|
||||
*/
|
||||
public String getServletPackageName() {
|
||||
if (isTagFile()) {
|
||||
String className = tagInfo.getTagClassName();
|
||||
int lastIndex = className.lastIndexOf('.');
|
||||
String pkgName = "";
|
||||
if (lastIndex != -1) {
|
||||
pkgName = className.substring(0, lastIndex);
|
||||
}
|
||||
return pkgName;
|
||||
} else {
|
||||
String dPackageName = getDerivedPackageName();
|
||||
if (dPackageName.length() == 0) {
|
||||
return basePackageName;
|
||||
}
|
||||
return basePackageName + '.' + getDerivedPackageName();
|
||||
}
|
||||
}
|
||||
|
||||
protected String getDerivedPackageName() {
|
||||
if (derivedPackageName == null) {
|
||||
int iSep = jspUri.lastIndexOf('/');
|
||||
derivedPackageName = (iSep > 0) ?
|
||||
JspUtil.makeJavaPackage(jspUri.substring(1,iSep)) : "";
|
||||
}
|
||||
return derivedPackageName;
|
||||
}
|
||||
|
||||
/**
|
||||
* The package name into which the servlet class is generated.
|
||||
* @param servletPackageName The package name to use
|
||||
*/
|
||||
public void setServletPackageName(String servletPackageName) {
|
||||
this.basePackageName = servletPackageName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Full path name of the Java file into which the servlet is being
|
||||
* generated.
|
||||
*/
|
||||
public String getServletJavaFileName() {
|
||||
if (servletJavaFileName == null) {
|
||||
servletJavaFileName = getOutputDir() + getServletClassName() + ".java";
|
||||
}
|
||||
return servletJavaFileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the Options object for this context.
|
||||
*/
|
||||
public Options getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public ServletContext getServletContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public JspRuntimeContext getRuntimeContext() {
|
||||
return rctxt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the path of the Java file relative to the work directory.
|
||||
*/
|
||||
public String getJavaPath() {
|
||||
|
||||
if (javaPath != null) {
|
||||
return javaPath;
|
||||
}
|
||||
|
||||
if (isTagFile()) {
|
||||
String tagName = tagInfo.getTagClassName();
|
||||
javaPath = tagName.replace('.', '/') + ".java";
|
||||
} else {
|
||||
javaPath = getServletPackageName().replace('.', '/') + '/' +
|
||||
getServletClassName() + ".java";
|
||||
}
|
||||
return javaPath;
|
||||
}
|
||||
|
||||
public String getClassFileName() {
|
||||
if (classFileName == null) {
|
||||
classFileName = getOutputDir() + getServletClassName() + ".class";
|
||||
}
|
||||
return classFileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the writer that is used to write the generated Servlet source.
|
||||
*/
|
||||
public ServletWriter getWriter() {
|
||||
return writer;
|
||||
}
|
||||
|
||||
public void setWriter(ServletWriter writer) {
|
||||
this.writer = writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the 'location' of the TLD associated with the given taglib 'uri'.
|
||||
* @param uri The taglib URI
|
||||
* @return An array of two Strings: The first element denotes the real
|
||||
* path to the TLD. If the path to the TLD points to a jar file, then the
|
||||
* second element denotes the name of the TLD entry in the jar file.
|
||||
* Returns null if the given uri is not associated with any tag library
|
||||
* 'exposed' in the web application.
|
||||
*/
|
||||
public TldResourcePath getTldResourcePath(String uri) {
|
||||
return getOptions().getTldCache().getTldResourcePath(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if generated code is kept.
|
||||
*/
|
||||
public boolean keepGenerated() {
|
||||
return getOptions().getKeepGenerated();
|
||||
}
|
||||
|
||||
// ==================== Removal ====================
|
||||
|
||||
public void incrementRemoved() {
|
||||
if (removed == false && rctxt != null) {
|
||||
rctxt.removeWrapper(jspUri);
|
||||
}
|
||||
removed = true;
|
||||
}
|
||||
|
||||
public boolean isRemoved() {
|
||||
return removed;
|
||||
}
|
||||
|
||||
// ==================== Compile and reload ====================
|
||||
|
||||
public void compile() throws JasperException, FileNotFoundException {
|
||||
createCompiler();
|
||||
if (jspCompiler.isOutDated()) {
|
||||
if (isRemoved()) {
|
||||
throw new FileNotFoundException(jspUri);
|
||||
}
|
||||
try {
|
||||
jspCompiler.removeGeneratedFiles();
|
||||
jspLoader = null;
|
||||
jspCompiler.compile();
|
||||
jsw.setReload(true);
|
||||
jsw.setCompilationException(null);
|
||||
} catch (JasperException ex) {
|
||||
// Cache compilation exception
|
||||
jsw.setCompilationException(ex);
|
||||
if (options.getDevelopment() && options.getRecompileOnFail()) {
|
||||
// Force a recompilation attempt on next access
|
||||
jsw.setLastModificationTest(-1);
|
||||
}
|
||||
throw ex;
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
// Re-throw to let caller handle this - will result in a 404
|
||||
throw fnfe;
|
||||
} catch (Exception ex) {
|
||||
JasperException je = new JasperException(
|
||||
Localizer.getMessage("jsp.error.unable.compile"),
|
||||
ex);
|
||||
// Cache compilation exception
|
||||
jsw.setCompilationException(je);
|
||||
throw je;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== Manipulating the class ====================
|
||||
|
||||
public Class<?> load() throws JasperException {
|
||||
try {
|
||||
getJspLoader();
|
||||
|
||||
String name = getFQCN();
|
||||
servletClass = jspLoader.loadClass(name);
|
||||
} catch (ClassNotFoundException cex) {
|
||||
throw new JasperException(Localizer.getMessage("jsp.error.unable.load"),
|
||||
cex);
|
||||
} catch (Exception ex) {
|
||||
throw new JasperException(Localizer.getMessage("jsp.error.unable.compile"),
|
||||
ex);
|
||||
}
|
||||
removed = false;
|
||||
return servletClass;
|
||||
}
|
||||
|
||||
public String getFQCN() {
|
||||
String name;
|
||||
if (isTagFile()) {
|
||||
name = tagInfo.getTagClassName();
|
||||
} else {
|
||||
name = getServletPackageName() + "." + getServletClassName();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
// ==================== protected methods ====================
|
||||
|
||||
private static final Object outputDirLock = new Object();
|
||||
|
||||
public void checkOutputDir() {
|
||||
if (outputDir != null) {
|
||||
if (!(new File(outputDir)).exists()) {
|
||||
makeOutputDir();
|
||||
}
|
||||
} else {
|
||||
createOutputDir();
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean makeOutputDir() {
|
||||
synchronized(outputDirLock) {
|
||||
File outDirFile = new File(outputDir);
|
||||
return (outDirFile.mkdirs() || outDirFile.isDirectory());
|
||||
}
|
||||
}
|
||||
|
||||
protected void createOutputDir() {
|
||||
String path = null;
|
||||
if (isTagFile()) {
|
||||
String tagName = tagInfo.getTagClassName();
|
||||
path = tagName.replace('.', File.separatorChar);
|
||||
path = path.substring(0, path.lastIndexOf(File.separatorChar));
|
||||
} else {
|
||||
path = getServletPackageName().replace('.',File.separatorChar);
|
||||
}
|
||||
|
||||
// Append servlet or tag handler path to scratch dir
|
||||
try {
|
||||
File base = options.getScratchDir();
|
||||
baseUrl = base.toURI().toURL();
|
||||
outputDir = base.getAbsolutePath() + File.separator + path +
|
||||
File.separator;
|
||||
if (!makeOutputDir()) {
|
||||
throw new IllegalStateException(Localizer.getMessage("jsp.error.outputfolder"));
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
throw new IllegalStateException(Localizer.getMessage("jsp.error.outputfolder"), e);
|
||||
}
|
||||
}
|
||||
|
||||
protected static final boolean isPathSeparator(char c) {
|
||||
return (c == '/' || c == '\\');
|
||||
}
|
||||
|
||||
protected static final String canonicalURI(String s) {
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
StringBuilder result = new StringBuilder();
|
||||
final int len = s.length();
|
||||
int pos = 0;
|
||||
while (pos < len) {
|
||||
char c = s.charAt(pos);
|
||||
if ( isPathSeparator(c) ) {
|
||||
/*
|
||||
* multiple path separators.
|
||||
* 'foo///bar' -> 'foo/bar'
|
||||
*/
|
||||
while (pos+1 < len && isPathSeparator(s.charAt(pos+1))) {
|
||||
++pos;
|
||||
}
|
||||
|
||||
if (pos+1 < len && s.charAt(pos+1) == '.') {
|
||||
/*
|
||||
* a single dot at the end of the path - we are done.
|
||||
*/
|
||||
if (pos+2 >= len) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (s.charAt(pos+2)) {
|
||||
/*
|
||||
* self directory in path
|
||||
* foo/./bar -> foo/bar
|
||||
*/
|
||||
case '/':
|
||||
case '\\':
|
||||
pos += 2;
|
||||
continue;
|
||||
|
||||
/*
|
||||
* two dots in a path: go back one hierarchy.
|
||||
* foo/bar/../baz -> foo/baz
|
||||
*/
|
||||
case '.':
|
||||
// only if we have exactly _two_ dots.
|
||||
if (pos+3 < len && isPathSeparator(s.charAt(pos+3))) {
|
||||
pos += 3;
|
||||
int separatorPos = result.length()-1;
|
||||
while (separatorPos >= 0 &&
|
||||
! isPathSeparator(result
|
||||
.charAt(separatorPos))) {
|
||||
--separatorPos;
|
||||
}
|
||||
if (separatorPos >= 0) {
|
||||
result.setLength(separatorPos);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result.append(c);
|
||||
++pos;
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user