mirror of
https://github.com/apache/struts.git
synced 2026-08-07 15:46:57 +00:00
remove jasper source
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@819443 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -1,208 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
|
||||
/**
|
||||
* Some constants and other global data that are used by the compiler and the runtime.
|
||||
*
|
||||
* @author Anil K. Vijendran
|
||||
* @author Harish Prabandham
|
||||
* @author Shawn Bayern
|
||||
* @author Mark Roth
|
||||
*/
|
||||
public class Constants {
|
||||
|
||||
/**
|
||||
* The base class of the generated servlets.
|
||||
*/
|
||||
public static final String JSP_SERVLET_BASE =
|
||||
System.getProperty("org.apache.jasper.Constants.JSP_SERVLET_BASE", "org.apache.jasper.runtime.HttpJspBase");
|
||||
|
||||
/**
|
||||
* _jspService is the name of the method that is called by
|
||||
* HttpJspBase.service(). This is where most of the code generated
|
||||
* from JSPs go.
|
||||
*/
|
||||
public static final String SERVICE_METHOD_NAME =
|
||||
System.getProperty("org.apache.jasper.Constants.SERVICE_METHOD_NAME", "_jspService");
|
||||
|
||||
/**
|
||||
* Default servlet content type.
|
||||
*/
|
||||
public static final String SERVLET_CONTENT_TYPE = "text/html";
|
||||
|
||||
/**
|
||||
* These classes/packages are automatically imported by the
|
||||
* generated code.
|
||||
*/
|
||||
public static final String[] STANDARD_IMPORTS = {
|
||||
"javax.servlet.*",
|
||||
"javax.servlet.http.*",
|
||||
"javax.servlet.jsp.*"
|
||||
};
|
||||
|
||||
/**
|
||||
* ServletContext attribute for classpath. This is tomcat specific.
|
||||
* Other servlet engines may choose to support this attribute if they
|
||||
* want to have this JSP engine running on them.
|
||||
*/
|
||||
public static final String SERVLET_CLASSPATH =
|
||||
System.getProperty("org.apache.jasper.Constants.SERVLET_CLASSPATH", "org.apache.catalina.jsp_classpath");
|
||||
|
||||
/**
|
||||
* Request attribute for <code><jsp-file></code> element of a
|
||||
* servlet definition. If present on a request, this overrides the
|
||||
* value returned by <code>request.getServletPath()</code> to select
|
||||
* the JSP page to be executed.
|
||||
*/
|
||||
public static final String JSP_FILE =
|
||||
System.getProperty("org.apache.jasper.Constants.JSP_FILE", "org.apache.catalina.jsp_file");
|
||||
|
||||
|
||||
/**
|
||||
* Default size of the JSP buffer.
|
||||
*/
|
||||
public static final int DEFAULT_BUFFER_SIZE = 8 * 1024;
|
||||
|
||||
/**
|
||||
* Default size for the tag buffers.
|
||||
*/
|
||||
public static final int DEFAULT_TAG_BUFFER_SIZE = 512;
|
||||
|
||||
/**
|
||||
* Default tag handler pool size.
|
||||
*/
|
||||
public static final int MAX_POOL_SIZE = 5;
|
||||
|
||||
/**
|
||||
* The query parameter that causes the JSP engine to just
|
||||
* pregenerated the servlet but not invoke it.
|
||||
*/
|
||||
public static final String PRECOMPILE =
|
||||
System.getProperty("org.apache.jasper.Constants.PRECOMPILE", "jsp_precompile");
|
||||
|
||||
/**
|
||||
* The default package name for compiled jsp pages.
|
||||
*/
|
||||
public static final String JSP_PACKAGE_NAME =
|
||||
System.getProperty("org.apache.jasper.Constants.JSP_PACKAGE_NAME", "org.apache.jsp");
|
||||
|
||||
/**
|
||||
* The default package name for tag handlers generated from tag files
|
||||
*/
|
||||
public static final String TAG_FILE_PACKAGE_NAME =
|
||||
System.getProperty("org.apache.jasper.Constants.TAG_FILE_PACKAGE_NAME", "org.apache.jsp.tag");
|
||||
|
||||
/**
|
||||
* Servlet context and request attributes that the JSP engine
|
||||
* uses.
|
||||
*/
|
||||
public static final String INC_SERVLET_PATH = "javax.servlet.include.servlet_path";
|
||||
public static final String TMP_DIR = "javax.servlet.context.tempdir";
|
||||
|
||||
// Must be kept in sync with org/apache/catalina/Globals.java
|
||||
public static final String ALT_DD_ATTR =
|
||||
System.getProperty("org.apache.jasper.Constants.ALT_DD_ATTR", "org.apache.catalina.deploy.alt_dd");
|
||||
|
||||
/**
|
||||
* Public Id and the Resource path (of the cached copy)
|
||||
* of the DTDs for tag library descriptors.
|
||||
*/
|
||||
public static final String TAGLIB_DTD_PUBLIC_ID_11 =
|
||||
"-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN";
|
||||
public static final String TAGLIB_DTD_RESOURCE_PATH_11 =
|
||||
"/javax/servlet/jsp/resources/web-jsptaglibrary_1_1.dtd";
|
||||
public static final String TAGLIB_DTD_PUBLIC_ID_12 =
|
||||
"-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN";
|
||||
public static final String TAGLIB_DTD_RESOURCE_PATH_12 =
|
||||
"/javax/servlet/jsp/resources/web-jsptaglibrary_1_2.dtd";
|
||||
|
||||
/**
|
||||
* Public Id and the Resource path (of the cached copy)
|
||||
* of the DTDs for web application deployment descriptors
|
||||
*/
|
||||
public static final String WEBAPP_DTD_PUBLIC_ID_22 =
|
||||
"-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN";
|
||||
public static final String WEBAPP_DTD_RESOURCE_PATH_22 =
|
||||
"/javax/servlet/resources/web-app_2_2.dtd";
|
||||
public static final String WEBAPP_DTD_PUBLIC_ID_23 =
|
||||
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN";
|
||||
public static final String WEBAPP_DTD_RESOURCE_PATH_23 =
|
||||
"/javax/servlet/resources/web-app_2_3.dtd";
|
||||
|
||||
/**
|
||||
* List of the Public IDs that we cache, and their
|
||||
* associated location. This is used by
|
||||
* an EntityResolver to return the location of the
|
||||
* cached copy of a DTD.
|
||||
*/
|
||||
public static final String[] CACHED_DTD_PUBLIC_IDS = {
|
||||
TAGLIB_DTD_PUBLIC_ID_11,
|
||||
TAGLIB_DTD_PUBLIC_ID_12,
|
||||
WEBAPP_DTD_PUBLIC_ID_22,
|
||||
WEBAPP_DTD_PUBLIC_ID_23,
|
||||
};
|
||||
public static final String[] CACHED_DTD_RESOURCE_PATHS = {
|
||||
TAGLIB_DTD_RESOURCE_PATH_11,
|
||||
TAGLIB_DTD_RESOURCE_PATH_12,
|
||||
WEBAPP_DTD_RESOURCE_PATH_22,
|
||||
WEBAPP_DTD_RESOURCE_PATH_23,
|
||||
};
|
||||
|
||||
/**
|
||||
* Default URLs to download the pluging for Netscape and IE.
|
||||
*/
|
||||
public static final String NS_PLUGIN_URL =
|
||||
"http://java.sun.com/products/plugin/";
|
||||
|
||||
public static final String IE_PLUGIN_URL =
|
||||
"http://java.sun.com/products/plugin/1.2.2/jinstall-1_2_2-win.cab#Version=1,2,2,0";
|
||||
|
||||
/**
|
||||
* Prefix to use for generated temporary variable names
|
||||
*/
|
||||
public static final String TEMP_VARIABLE_NAME_PREFIX =
|
||||
System.getProperty("org.apache.jasper.Constants.TEMP_VARIABLE_NAME_PREFIX", "_jspx_temp");
|
||||
|
||||
/**
|
||||
* A replacement char for "\$".
|
||||
* XXX This is a hack to avoid changing EL interpreter to recognize "\$"
|
||||
* @deprecated
|
||||
*/
|
||||
public static final char ESC = '\u001b';
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public static final String ESCStr = "'\\u001b'";
|
||||
|
||||
/**
|
||||
* Has security been turned on?
|
||||
*/
|
||||
public static final boolean IS_SECURITY_ENABLED =
|
||||
(System.getSecurityManager() != null);
|
||||
|
||||
/**
|
||||
* The name of the path parameter used to pass the session identifier
|
||||
* back and forth with the client.
|
||||
*/
|
||||
public static final String SESSION_PARAMETER_NAME =
|
||||
System.getProperty("org.apache.catalina.SESSION_PARAMETER_NAME",
|
||||
"jsessionid");
|
||||
|
||||
}
|
||||
-673
@@ -1,673 +0,0 @@
|
||||
/*
|
||||
* 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.util.*;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.apache.jasper.compiler.TldLocationsCache;
|
||||
import org.apache.jasper.compiler.JspConfig;
|
||||
import org.apache.jasper.compiler.TagPluginManager;
|
||||
import org.apache.jasper.compiler.Localizer;
|
||||
import org.apache.jasper.xmlparser.ParserUtils;
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* A class to hold all init parameters specific to the JSP engine.
|
||||
*
|
||||
* @author Anil K. Vijendran
|
||||
* @author Hans Bergsten
|
||||
* @author Pierre Delisle
|
||||
*/
|
||||
public final class EmbeddedServletOptions implements Options {
|
||||
|
||||
// Logger
|
||||
private Log log = LogFactory.getLog(EmbeddedServletOptions.class);
|
||||
|
||||
private Properties settings = new Properties();
|
||||
|
||||
/**
|
||||
* Is Jasper being used in development mode?
|
||||
*/
|
||||
private boolean development = true;
|
||||
|
||||
/**
|
||||
* Should Ant fork its java compiles of JSP pages.
|
||||
*/
|
||||
public boolean fork = true;
|
||||
|
||||
/**
|
||||
* Do you want to keep the generated Java files around?
|
||||
*/
|
||||
private boolean keepGenerated = true;
|
||||
|
||||
/**
|
||||
* Should white spaces between directives or actions be trimmed?
|
||||
*/
|
||||
private boolean trimSpaces = false;
|
||||
|
||||
/**
|
||||
* Determines whether tag handler pooling is enabled.
|
||||
*/
|
||||
private boolean isPoolingEnabled = true;
|
||||
|
||||
/**
|
||||
* Do you want support for "mapped" files? This will generate
|
||||
* servlet that has a print statement per line of the JSP file.
|
||||
* This seems like a really nice feature to have for debugging.
|
||||
*/
|
||||
private boolean mappedFile = true;
|
||||
|
||||
/**
|
||||
* Do we want to include debugging information in the class file?
|
||||
*/
|
||||
private boolean classDebugInfo = true;
|
||||
|
||||
/**
|
||||
* Background compile thread check interval in seconds.
|
||||
*/
|
||||
private int checkInterval = 0;
|
||||
|
||||
/**
|
||||
* Is the generation of SMAP info for JSR45 debuggin suppressed?
|
||||
*/
|
||||
private boolean isSmapSuppressed = false;
|
||||
|
||||
/**
|
||||
* Should SMAP info for JSR45 debugging be dumped to a file?
|
||||
*/
|
||||
private boolean isSmapDumped = false;
|
||||
|
||||
/**
|
||||
* Are Text strings to be generated as char arrays?
|
||||
*/
|
||||
private boolean genStringAsCharArray = false;
|
||||
|
||||
private boolean errorOnUseBeanInvalidClassAttribute = true;
|
||||
|
||||
/**
|
||||
* I want to see my generated servlets. Which directory are they
|
||||
* in?
|
||||
*/
|
||||
private File scratchDir;
|
||||
|
||||
/**
|
||||
* Need to have this as is for versions 4 and 5 of IE. Can be set from
|
||||
* the initParams so if it changes in the future all that is needed is
|
||||
* to have a jsp initParam of type ieClassId="<value>"
|
||||
*/
|
||||
private String ieClassId = "clsid:8AD9C840-044E-11D1-B3E9-00805F499D93";
|
||||
|
||||
/**
|
||||
* What classpath should I use while compiling generated servlets?
|
||||
*/
|
||||
private String classpath = null;
|
||||
|
||||
/**
|
||||
* Compiler to use.
|
||||
*/
|
||||
private String compiler = null;
|
||||
|
||||
/**
|
||||
* Compiler target VM.
|
||||
*/
|
||||
private String compilerTargetVM = "1.5";
|
||||
|
||||
/**
|
||||
* The compiler source VM.
|
||||
*/
|
||||
private String compilerSourceVM = "1.5";
|
||||
|
||||
/**
|
||||
* The compiler class name.
|
||||
*/
|
||||
private String compilerClassName = null;
|
||||
|
||||
/**
|
||||
* Cache for the TLD locations
|
||||
*/
|
||||
private TldLocationsCache tldLocationsCache = null;
|
||||
|
||||
/**
|
||||
* Jsp config information
|
||||
*/
|
||||
private JspConfig jspConfig = null;
|
||||
|
||||
/**
|
||||
* TagPluginManager
|
||||
*/
|
||||
private TagPluginManager tagPluginManager = null;
|
||||
|
||||
/**
|
||||
* Java platform encoding to generate the JSP
|
||||
* page servlet.
|
||||
*/
|
||||
private String javaEncoding = "UTF8";
|
||||
|
||||
/**
|
||||
* Modification test interval.
|
||||
*/
|
||||
private int modificationTestInterval = 4;
|
||||
|
||||
/**
|
||||
* Is generation of X-Powered-By response header enabled/disabled?
|
||||
*/
|
||||
private boolean xpoweredBy;
|
||||
|
||||
/**
|
||||
* Should we include a source fragment in exception messages, which could be displayed
|
||||
* to the developer ?
|
||||
*/
|
||||
private boolean displaySourceFragment = true;
|
||||
|
||||
|
||||
public String getProperty(String name ) {
|
||||
return settings.getProperty( name );
|
||||
}
|
||||
|
||||
public void setProperty(String name, String value ) {
|
||||
if (name != null && value != null){
|
||||
settings.setProperty( name, value );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Are we keeping generated code around?
|
||||
*/
|
||||
public boolean getKeepGenerated() {
|
||||
return keepGenerated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should white spaces between directives or actions be trimmed?
|
||||
*/
|
||||
public boolean getTrimSpaces() {
|
||||
return trimSpaces;
|
||||
}
|
||||
|
||||
public boolean isPoolingEnabled() {
|
||||
return isPoolingEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Are we supporting HTML mapped servlets?
|
||||
*/
|
||||
public boolean getMappedFile() {
|
||||
return mappedFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should errors be sent to client or thrown into stderr?
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean getSendErrorToClient() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should class files be compiled with debug information?
|
||||
*/
|
||||
public boolean getClassDebugInfo() {
|
||||
return classDebugInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Background JSP compile thread check intervall
|
||||
*/
|
||||
public int getCheckInterval() {
|
||||
return checkInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modification test interval.
|
||||
*/
|
||||
public int getModificationTestInterval() {
|
||||
return modificationTestInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is Jasper being used in development mode?
|
||||
*/
|
||||
public boolean getDevelopment() {
|
||||
return development;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the generation of SMAP info for JSR45 debuggin suppressed?
|
||||
*/
|
||||
public boolean isSmapSuppressed() {
|
||||
return isSmapSuppressed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should SMAP info for JSR45 debugging be dumped to a file?
|
||||
*/
|
||||
public boolean isSmapDumped() {
|
||||
return isSmapDumped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Are Text strings to be generated as char arrays?
|
||||
*/
|
||||
public boolean genStringAsCharArray() {
|
||||
return this.genStringAsCharArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class ID for use in the plugin tag when the browser is IE.
|
||||
*/
|
||||
public String getIeClassId() {
|
||||
return ieClassId;
|
||||
}
|
||||
|
||||
/**
|
||||
* What is my scratch dir?
|
||||
*/
|
||||
public File getScratchDir() {
|
||||
return scratchDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* What classpath should I use while compiling the servlets
|
||||
* generated from JSP files?
|
||||
*/
|
||||
public String getClassPath() {
|
||||
return classpath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is generation of X-Powered-By response header enabled/disabled?
|
||||
*/
|
||||
public boolean isXpoweredBy() {
|
||||
return xpoweredBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiler to use.
|
||||
*/
|
||||
public String getCompiler() {
|
||||
return compiler;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Options#getCompilerTargetVM
|
||||
*/
|
||||
public String getCompilerTargetVM() {
|
||||
return compilerTargetVM;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Options#getCompilerSourceVM
|
||||
*/
|
||||
public String getCompilerSourceVM() {
|
||||
return compilerSourceVM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Java compiler class to use.
|
||||
*/
|
||||
public String getCompilerClassName() {
|
||||
return compilerClassName;
|
||||
}
|
||||
|
||||
public boolean getErrorOnUseBeanInvalidClassAttribute() {
|
||||
return errorOnUseBeanInvalidClassAttribute;
|
||||
}
|
||||
|
||||
public void setErrorOnUseBeanInvalidClassAttribute(boolean b) {
|
||||
errorOnUseBeanInvalidClassAttribute = b;
|
||||
}
|
||||
|
||||
public TldLocationsCache getTldLocationsCache() {
|
||||
return tldLocationsCache;
|
||||
}
|
||||
|
||||
public void setTldLocationsCache( TldLocationsCache tldC ) {
|
||||
tldLocationsCache = tldC;
|
||||
}
|
||||
|
||||
public String getJavaEncoding() {
|
||||
return javaEncoding;
|
||||
}
|
||||
|
||||
public boolean getFork() {
|
||||
return fork;
|
||||
}
|
||||
|
||||
public JspConfig getJspConfig() {
|
||||
return jspConfig;
|
||||
}
|
||||
|
||||
public TagPluginManager getTagPluginManager() {
|
||||
return tagPluginManager;
|
||||
}
|
||||
|
||||
public boolean isCaching() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Map getCache() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should we include a source fragment in exception messages, which could be displayed
|
||||
* to the developer ?
|
||||
*/
|
||||
public boolean getDisplaySourceFragment() {
|
||||
return displaySourceFragment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an EmbeddedServletOptions object using data available from
|
||||
* ServletConfig and ServletContext.
|
||||
*/
|
||||
public EmbeddedServletOptions(ServletConfig config,
|
||||
ServletContext context) {
|
||||
|
||||
// JVM version numbers
|
||||
try {
|
||||
if (Float.parseFloat(System.getProperty("java.specification.version")) > 1.4) {
|
||||
compilerSourceVM = compilerTargetVM = "1.5";
|
||||
} else {
|
||||
compilerSourceVM = compilerTargetVM = "1.4";
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
Enumeration enumeration=config.getInitParameterNames();
|
||||
while( enumeration.hasMoreElements() ) {
|
||||
String k=(String)enumeration.nextElement();
|
||||
String v=config.getInitParameter( k );
|
||||
setProperty( k, v);
|
||||
}
|
||||
|
||||
// quick hack
|
||||
String validating=config.getInitParameter( "validating");
|
||||
if( "false".equals( validating )) ParserUtils.validating=false;
|
||||
|
||||
String keepgen = config.getInitParameter("keepgenerated");
|
||||
if (keepgen != null) {
|
||||
if (keepgen.equalsIgnoreCase("true")) {
|
||||
this.keepGenerated = true;
|
||||
} else if (keepgen.equalsIgnoreCase("false")) {
|
||||
this.keepGenerated = false;
|
||||
} else {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage("jsp.warning.keepgen"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String trimsp = config.getInitParameter("trimSpaces");
|
||||
if (trimsp != null) {
|
||||
if (trimsp.equalsIgnoreCase("true")) {
|
||||
trimSpaces = true;
|
||||
} else if (trimsp.equalsIgnoreCase("false")) {
|
||||
trimSpaces = false;
|
||||
} else {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage("jsp.warning.trimspaces"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.isPoolingEnabled = true;
|
||||
String poolingEnabledParam
|
||||
= config.getInitParameter("enablePooling");
|
||||
if (poolingEnabledParam != null
|
||||
&& !poolingEnabledParam.equalsIgnoreCase("true")) {
|
||||
if (poolingEnabledParam.equalsIgnoreCase("false")) {
|
||||
this.isPoolingEnabled = false;
|
||||
} else {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage("jsp.warning.enablePooling"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String mapFile = config.getInitParameter("mappedfile");
|
||||
if (mapFile != null) {
|
||||
if (mapFile.equalsIgnoreCase("true")) {
|
||||
this.mappedFile = true;
|
||||
} else if (mapFile.equalsIgnoreCase("false")) {
|
||||
this.mappedFile = false;
|
||||
} else {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage("jsp.warning.mappedFile"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String debugInfo = config.getInitParameter("classdebuginfo");
|
||||
if (debugInfo != null) {
|
||||
if (debugInfo.equalsIgnoreCase("true")) {
|
||||
this.classDebugInfo = true;
|
||||
} else if (debugInfo.equalsIgnoreCase("false")) {
|
||||
this.classDebugInfo = false;
|
||||
} else {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage("jsp.warning.classDebugInfo"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String checkInterval = config.getInitParameter("checkInterval");
|
||||
if (checkInterval != null) {
|
||||
try {
|
||||
this.checkInterval = Integer.parseInt(checkInterval);
|
||||
} catch(NumberFormatException ex) {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage("jsp.warning.checkInterval"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String modificationTestInterval = config.getInitParameter("modificationTestInterval");
|
||||
if (modificationTestInterval != null) {
|
||||
try {
|
||||
this.modificationTestInterval = Integer.parseInt(modificationTestInterval);
|
||||
} catch(NumberFormatException ex) {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage("jsp.warning.modificationTestInterval"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String development = config.getInitParameter("development");
|
||||
if (development != null) {
|
||||
if (development.equalsIgnoreCase("true")) {
|
||||
this.development = true;
|
||||
} else if (development.equalsIgnoreCase("false")) {
|
||||
this.development = false;
|
||||
} else {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage("jsp.warning.development"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String suppressSmap = config.getInitParameter("suppressSmap");
|
||||
if (suppressSmap != null) {
|
||||
if (suppressSmap.equalsIgnoreCase("true")) {
|
||||
isSmapSuppressed = true;
|
||||
} else if (suppressSmap.equalsIgnoreCase("false")) {
|
||||
isSmapSuppressed = false;
|
||||
} else {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage("jsp.warning.suppressSmap"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String dumpSmap = config.getInitParameter("dumpSmap");
|
||||
if (dumpSmap != null) {
|
||||
if (dumpSmap.equalsIgnoreCase("true")) {
|
||||
isSmapDumped = true;
|
||||
} else if (dumpSmap.equalsIgnoreCase("false")) {
|
||||
isSmapDumped = false;
|
||||
} else {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage("jsp.warning.dumpSmap"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String genCharArray = config.getInitParameter("genStrAsCharArray");
|
||||
if (genCharArray != null) {
|
||||
if (genCharArray.equalsIgnoreCase("true")) {
|
||||
genStringAsCharArray = true;
|
||||
} else if (genCharArray.equalsIgnoreCase("false")) {
|
||||
genStringAsCharArray = false;
|
||||
} else {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage("jsp.warning.genchararray"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String errBeanClass =
|
||||
config.getInitParameter("errorOnUseBeanInvalidClassAttribute");
|
||||
if (errBeanClass != null) {
|
||||
if (errBeanClass.equalsIgnoreCase("true")) {
|
||||
errorOnUseBeanInvalidClassAttribute = true;
|
||||
} else if (errBeanClass.equalsIgnoreCase("false")) {
|
||||
errorOnUseBeanInvalidClassAttribute = false;
|
||||
} else {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage("jsp.warning.errBean"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String ieClassId = config.getInitParameter("ieClassId");
|
||||
if (ieClassId != null)
|
||||
this.ieClassId = ieClassId;
|
||||
|
||||
String classpath = config.getInitParameter("classpath");
|
||||
if (classpath != null)
|
||||
this.classpath = classpath;
|
||||
|
||||
/*
|
||||
* scratchdir
|
||||
*/
|
||||
String dir = config.getInitParameter("scratchdir");
|
||||
if (dir != null) {
|
||||
scratchDir = new File(dir);
|
||||
} else {
|
||||
// First try the Servlet 2.2 javax.servlet.context.tempdir property
|
||||
scratchDir = (File) context.getAttribute(Constants.TMP_DIR);
|
||||
if (scratchDir == null) {
|
||||
// Not running in a Servlet 2.2 container.
|
||||
// Try to get the JDK 1.2 java.io.tmpdir property
|
||||
dir = System.getProperty("java.io.tmpdir");
|
||||
if (dir != null)
|
||||
scratchDir = new File(dir);
|
||||
}
|
||||
}
|
||||
if (this.scratchDir == null) {
|
||||
log.fatal(Localizer.getMessage("jsp.error.no.scratch.dir"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(scratchDir.exists() && scratchDir.canRead() &&
|
||||
scratchDir.canWrite() && scratchDir.isDirectory()))
|
||||
log.fatal(Localizer.getMessage("jsp.error.bad.scratch.dir",
|
||||
scratchDir.getAbsolutePath()));
|
||||
|
||||
this.compiler = config.getInitParameter("compiler");
|
||||
|
||||
String compilerTargetVM = config.getInitParameter("compilerTargetVM");
|
||||
if(compilerTargetVM != null) {
|
||||
this.compilerTargetVM = compilerTargetVM;
|
||||
}
|
||||
|
||||
String compilerSourceVM = config.getInitParameter("compilerSourceVM");
|
||||
if(compilerSourceVM != null) {
|
||||
this.compilerSourceVM = compilerSourceVM;
|
||||
}
|
||||
|
||||
String javaEncoding = config.getInitParameter("javaEncoding");
|
||||
if (javaEncoding != null) {
|
||||
this.javaEncoding = javaEncoding;
|
||||
}
|
||||
|
||||
String compilerClassName = config.getInitParameter("compilerClassName");
|
||||
if (compilerClassName != null) {
|
||||
this.compilerClassName = compilerClassName;
|
||||
}
|
||||
|
||||
String fork = config.getInitParameter("fork");
|
||||
if (fork != null) {
|
||||
if (fork.equalsIgnoreCase("true")) {
|
||||
this.fork = true;
|
||||
} else if (fork.equalsIgnoreCase("false")) {
|
||||
this.fork = false;
|
||||
} else {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage("jsp.warning.fork"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String xpoweredBy = config.getInitParameter("xpoweredBy");
|
||||
if (xpoweredBy != null) {
|
||||
if (xpoweredBy.equalsIgnoreCase("true")) {
|
||||
this.xpoweredBy = true;
|
||||
} else if (xpoweredBy.equalsIgnoreCase("false")) {
|
||||
this.xpoweredBy = false;
|
||||
} else {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage("jsp.warning.xpoweredBy"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String displaySourceFragment = config.getInitParameter("displaySourceFragment");
|
||||
if (displaySourceFragment != null) {
|
||||
if (displaySourceFragment.equalsIgnoreCase("true")) {
|
||||
this.displaySourceFragment = true;
|
||||
} else if (displaySourceFragment.equalsIgnoreCase("false")) {
|
||||
this.displaySourceFragment = false;
|
||||
} else {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage("jsp.warning.displaySourceFragment"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Setup the global Tag Libraries location cache for this
|
||||
// web-application.
|
||||
tldLocationsCache = new TldLocationsCache(context);
|
||||
|
||||
// Setup the jsp config info for this web app.
|
||||
jspConfig = new JspConfig(context);
|
||||
|
||||
// Create a Tag plugin instance
|
||||
tagPluginManager = new TagPluginManager(context);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Base class for all exceptions generated by the JSP engine. Makes it
|
||||
* convienient to catch just this at the top-level.
|
||||
*
|
||||
* @author Anil K. Vijendran
|
||||
*/
|
||||
public class JasperException extends javax.servlet.ServletException {
|
||||
|
||||
public JasperException(String reason) {
|
||||
super(reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JasperException with the embedded exception and the reason for
|
||||
* throwing a JasperException
|
||||
*/
|
||||
public JasperException (String reason, Throwable exception) {
|
||||
super(reason, exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JasperException with the embedded exception
|
||||
*/
|
||||
public JasperException (Throwable exception) {
|
||||
super(exception);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
-738
@@ -1,738 +0,0 @@
|
||||
/*
|
||||
* 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.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
protected org.apache.juli.logging.Log log =
|
||||
org.apache.juli.logging.LogFactory.getLog(JspCompilationContext.class);
|
||||
|
||||
protected Map<String, URL> tagFileJarUrls;
|
||||
protected boolean isPackagedTagFile;
|
||||
|
||||
protected String className;
|
||||
protected String jspUri;
|
||||
protected boolean isErrPage;
|
||||
protected String basePackageName;
|
||||
protected String derivedPackageName;
|
||||
protected String servletJavaFileName;
|
||||
protected String javaPath;
|
||||
protected String classFileName;
|
||||
protected String contentType;
|
||||
protected ServletWriter writer;
|
||||
protected Options options;
|
||||
protected JspServletWrapper jsw;
|
||||
protected Compiler jspCompiler;
|
||||
protected String classPath;
|
||||
|
||||
protected String baseURI;
|
||||
protected String outputDir;
|
||||
protected ServletContext context;
|
||||
protected URLClassLoader loader;
|
||||
|
||||
protected JspRuntimeContext rctxt;
|
||||
|
||||
protected int removed = 0;
|
||||
|
||||
protected URLClassLoader jspLoader;
|
||||
protected URL baseUrl;
|
||||
protected Class servletClass;
|
||||
|
||||
protected boolean isTagFile;
|
||||
protected boolean protoTypeMode;
|
||||
protected TagInfo tagInfo;
|
||||
protected URL tagFileJarUrl;
|
||||
|
||||
// jspURI _must_ be relative to the context
|
||||
public JspCompilationContext(String jspUri,
|
||||
boolean isErrPage,
|
||||
Options options,
|
||||
ServletContext context,
|
||||
JspServletWrapper jsw,
|
||||
JspRuntimeContext rctxt) {
|
||||
|
||||
this.jspUri = canonicalURI(jspUri);
|
||||
this.isErrPage = isErrPage;
|
||||
this.options = options;
|
||||
this.jsw = jsw;
|
||||
this.context = context;
|
||||
|
||||
this.baseURI = jspUri.substring(0, jspUri.lastIndexOf('/') + 1);
|
||||
// hack fix for resolveRelativeURI
|
||||
if (baseURI == null) {
|
||||
baseURI = "/";
|
||||
} else if (baseURI.charAt(0) != '/') {
|
||||
// strip the basde slash since it will be combined with the
|
||||
// uriBase to generate a file
|
||||
baseURI = "/" + baseURI;
|
||||
}
|
||||
if (baseURI.charAt(baseURI.length() - 1) != '/') {
|
||||
baseURI += '/';
|
||||
}
|
||||
|
||||
this.rctxt = rctxt;
|
||||
this.tagFileJarUrls = new HashMap<String, URL>();
|
||||
this.basePackageName = Constants.JSP_PACKAGE_NAME;
|
||||
}
|
||||
|
||||
public JspCompilationContext(String tagfile,
|
||||
TagInfo tagInfo,
|
||||
Options options,
|
||||
ServletContext context,
|
||||
JspServletWrapper jsw,
|
||||
JspRuntimeContext rctxt,
|
||||
URL tagFileJarUrl) {
|
||||
this(tagfile, false, options, context, jsw, rctxt);
|
||||
this.isTagFile = true;
|
||||
this.tagInfo = tagInfo;
|
||||
this.tagFileJarUrl = tagFileJarUrl;
|
||||
if (tagFileJarUrl != null) {
|
||||
isPackagedTagFile = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== Methods to override ==================== */
|
||||
|
||||
/** ---------- Class path and loader ---------- */
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public void setClassPath(String classPath) {
|
||||
this.classPath = classPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* What class loader to use for loading classes while compiling
|
||||
* this JSP?
|
||||
*/
|
||||
public ClassLoader getClassLoader() {
|
||||
if( loader != null )
|
||||
return loader;
|
||||
return rctxt.getParentClassLoader();
|
||||
}
|
||||
|
||||
public void setClassLoader(URLClassLoader loader) {
|
||||
this.loader = loader;
|
||||
}
|
||||
|
||||
public ClassLoader getJspLoader() {
|
||||
if( jspLoader == null ) {
|
||||
jspLoader = new JasperLoader
|
||||
(new URL[] {baseUrl},
|
||||
getClassLoader(),
|
||||
rctxt.getPermissionCollection(),
|
||||
rctxt.getCodeSource());
|
||||
}
|
||||
return jspLoader;
|
||||
}
|
||||
|
||||
/** ---------- 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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
public Compiler createCompiler() throws JasperException {
|
||||
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"));
|
||||
}
|
||||
jspCompiler.init(this, jsw);
|
||||
return jspCompiler;
|
||||
}
|
||||
|
||||
protected Compiler createCompiler(String className) {
|
||||
Compiler compiler = null;
|
||||
try {
|
||||
compiler = (Compiler) Class.forName(className).newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
log.warn(Localizer.getMessage("jsp.error.compiler"), e);
|
||||
} catch (IllegalAccessException e) {
|
||||
log.warn(Localizer.getMessage("jsp.error.compiler"), e);
|
||||
} catch (NoClassDefFoundError e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(Localizer.getMessage("jsp.error.compiler"), e);
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(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.
|
||||
*/
|
||||
public String resolveRelativeUri(String uri) {
|
||||
// sometimes we get uri's massaged from File(String), so check for
|
||||
// a root directory deperator 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.
|
||||
* @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 {
|
||||
URL result = null;
|
||||
|
||||
if (res.startsWith("/META-INF/")) {
|
||||
// This is a tag file packaged in a jar that is being compiled
|
||||
URL jarUrl = tagFileJarUrls.get(res);
|
||||
if (jarUrl == null) {
|
||||
jarUrl = tagFileJarUrl;
|
||||
}
|
||||
if (jarUrl != null) {
|
||||
result = new URL(jarUrl.toExternalForm() + res.substring(1));
|
||||
}
|
||||
} else if (res.startsWith("jar:file:")) {
|
||||
// This is a tag file packaged in a jar that is being checked
|
||||
// for a dependency
|
||||
result = new URL(res);
|
||||
|
||||
} else {
|
||||
result = context.getResource(canonicalURI(res));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public Set getResourcePaths(String path) {
|
||||
return context.getResourcePaths(canonicalURI(path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the actual path of a URI relative to the context of
|
||||
* the compilation.
|
||||
*/
|
||||
public String getRealPath(String path) {
|
||||
if (context != null) {
|
||||
return context.getRealPath(path);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tag-file-name-to-JAR-file map of this compilation unit,
|
||||
* which maps tag file names to the JAR files in which the tag files are
|
||||
* packaged.
|
||||
*
|
||||
* The map is populated when parsing the tag-file elements of the TLDs
|
||||
* of any imported taglibs.
|
||||
*/
|
||||
public URL getTagFileJarUrl(String tagFile) {
|
||||
return this.tagFileJarUrls.get(tagFile);
|
||||
}
|
||||
|
||||
public void setTagFileJarUrl(String tagFile, URL tagFileURL) {
|
||||
this.tagFileJarUrls.put(tagFile, tagFileURL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public URL getTagFileJarUrl() {
|
||||
return this.tagFileJarUrl;
|
||||
}
|
||||
|
||||
/* ==================== Common implementation ==================== */
|
||||
|
||||
/**
|
||||
* Just the class name (does not include package name) of the
|
||||
* generated class.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
public String getJspFile() {
|
||||
return jspUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Are we processing something that has been declared as an
|
||||
* errorpage?
|
||||
*/
|
||||
public boolean isErrorPage() {
|
||||
return isErrPage;
|
||||
}
|
||||
|
||||
public void setErrorPage(boolean isErrPage) {
|
||||
this.isErrPage = isErrPage;
|
||||
}
|
||||
|
||||
public boolean isTagFile() {
|
||||
return isTagFile;
|
||||
}
|
||||
|
||||
public TagInfo getTagInfo() {
|
||||
return tagInfo;
|
||||
}
|
||||
|
||||
public void setTagInfo(TagInfo tagi) {
|
||||
tagInfo = tagi;
|
||||
}
|
||||
|
||||
/**
|
||||
* True 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 heirachy of the JSP page.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
public void setServletPackageName(String servletPackageName) {
|
||||
this.basePackageName = servletPackageName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get hold of the Options object for this context.
|
||||
*/
|
||||
public Options getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public ServletContext getServletContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public JspRuntimeContext getRuntimeContext() {
|
||||
return rctxt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the content type of this JSP.
|
||||
*
|
||||
* Content type includes content type and encoding.
|
||||
*/
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public void setContentType(String contentType) {
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Where is the servlet being generated?
|
||||
*/
|
||||
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'.
|
||||
*
|
||||
* @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 String[] getTldLocation(String uri) throws JasperException {
|
||||
String[] location =
|
||||
getOptions().getTldLocationsCache().getLocation(uri);
|
||||
return location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Are we keeping generated code around?
|
||||
*/
|
||||
public boolean keepGenerated() {
|
||||
return getOptions().getKeepGenerated();
|
||||
}
|
||||
|
||||
// ==================== Removal ====================
|
||||
|
||||
public void incrementRemoved() {
|
||||
if (removed == 0 && rctxt != null) {
|
||||
rctxt.removeWrapper(jspUri);
|
||||
}
|
||||
removed++;
|
||||
}
|
||||
|
||||
public boolean isRemoved() {
|
||||
if (removed > 1 ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ==================== Compile and reload ====================
|
||||
|
||||
public void compile() throws JasperException, FileNotFoundException {
|
||||
createCompiler();
|
||||
if (jspCompiler.isOutDated()) {
|
||||
try {
|
||||
jspCompiler.removeGeneratedFiles();
|
||||
jspLoader = null;
|
||||
jspCompiler.compile();
|
||||
jsw.setReload(true);
|
||||
jsw.setCompilationException(null);
|
||||
} catch (JasperException ex) {
|
||||
// Cache compilation exception
|
||||
jsw.setCompilationException(ex);
|
||||
throw ex;
|
||||
} 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, FileNotFoundException
|
||||
{
|
||||
try {
|
||||
getJspLoader();
|
||||
|
||||
String name;
|
||||
if (isTagFile()) {
|
||||
name = tagInfo.getTagClassName();
|
||||
} else {
|
||||
name = getServletPackageName() + "." + getServletClassName();
|
||||
}
|
||||
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 = 0;
|
||||
return servletClass;
|
||||
}
|
||||
|
||||
// ==================== protected methods ====================
|
||||
|
||||
static 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.exists() || outDirFile.mkdirs());
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
StringBuffer result = new StringBuffer();
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,202 +0,0 @@
|
||||
/*
|
||||
* 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.util.Map;
|
||||
|
||||
import org.apache.jasper.compiler.JspConfig;
|
||||
import org.apache.jasper.compiler.TagPluginManager;
|
||||
import org.apache.jasper.compiler.TldLocationsCache;
|
||||
|
||||
/**
|
||||
* A class to hold all init parameters specific to the JSP engine.
|
||||
*
|
||||
* @author Anil K. Vijendran
|
||||
* @author Hans Bergsten
|
||||
* @author Pierre Delisle
|
||||
*/
|
||||
public interface Options {
|
||||
|
||||
/**
|
||||
* Returns true if Jasper issues a compilation error instead of a runtime
|
||||
* Instantiation error if the class attribute specified in useBean action
|
||||
* is invalid.
|
||||
*/
|
||||
public boolean getErrorOnUseBeanInvalidClassAttribute();
|
||||
|
||||
/**
|
||||
* Are we keeping generated code around?
|
||||
*/
|
||||
public boolean getKeepGenerated();
|
||||
|
||||
/**
|
||||
* Returns true if tag handler pooling is enabled, false otherwise.
|
||||
*/
|
||||
public boolean isPoolingEnabled();
|
||||
|
||||
/**
|
||||
* Are we supporting HTML mapped servlets?
|
||||
*/
|
||||
public boolean getMappedFile();
|
||||
|
||||
/**
|
||||
* Should errors be sent to client or thrown into stderr?
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean getSendErrorToClient();
|
||||
|
||||
/**
|
||||
* Should we include debug information in compiled class?
|
||||
*/
|
||||
public boolean getClassDebugInfo();
|
||||
|
||||
/**
|
||||
* Background compile thread check interval in seconds
|
||||
*/
|
||||
public int getCheckInterval();
|
||||
|
||||
/**
|
||||
* Is Jasper being used in development mode?
|
||||
*/
|
||||
public boolean getDevelopment();
|
||||
|
||||
/**
|
||||
* Should we include a source fragment in exception messages, which could be displayed
|
||||
* to the developer ?
|
||||
*/
|
||||
public boolean getDisplaySourceFragment();
|
||||
|
||||
/**
|
||||
* Is the generation of SMAP info for JSR45 debugging suppressed?
|
||||
*/
|
||||
public boolean isSmapSuppressed();
|
||||
|
||||
/**
|
||||
* Indicates whether SMAP info for JSR45 debugging should be dumped to a
|
||||
* file.
|
||||
* Ignored is suppressSmap() is true
|
||||
*/
|
||||
public boolean isSmapDumped();
|
||||
|
||||
/**
|
||||
* Should white spaces between directives or actions be trimmed?
|
||||
*/
|
||||
public boolean getTrimSpaces();
|
||||
|
||||
/**
|
||||
* Class ID for use in the plugin tag when the browser is IE.
|
||||
*/
|
||||
public String getIeClassId();
|
||||
|
||||
/**
|
||||
* What is my scratch dir?
|
||||
*/
|
||||
public File getScratchDir();
|
||||
|
||||
/**
|
||||
* What classpath should I use while compiling the servlets
|
||||
* generated from JSP files?
|
||||
*/
|
||||
public String getClassPath();
|
||||
|
||||
/**
|
||||
* Compiler to use.
|
||||
*/
|
||||
public String getCompiler();
|
||||
|
||||
/**
|
||||
* The compiler target VM, e.g. 1.1, 1.2, 1.3, 1.4, or 1.5.
|
||||
*/
|
||||
public String getCompilerTargetVM();
|
||||
|
||||
/**
|
||||
* Compiler source VM, e.g. 1.3, 1.4, or 1.5.
|
||||
*/
|
||||
public String getCompilerSourceVM();
|
||||
|
||||
/**
|
||||
* Java compiler class to use.
|
||||
*/
|
||||
public String getCompilerClassName();
|
||||
|
||||
/**
|
||||
* The cache for the location of the TLD's
|
||||
* for the various tag libraries 'exposed'
|
||||
* by the web application.
|
||||
* A tag library is 'exposed' either explicitely in
|
||||
* web.xml or implicitely via the uri tag in the TLD
|
||||
* of a taglib deployed in a jar file (WEB-INF/lib).
|
||||
*
|
||||
* @return the instance of the TldLocationsCache
|
||||
* for the web-application.
|
||||
*/
|
||||
public TldLocationsCache getTldLocationsCache();
|
||||
|
||||
/**
|
||||
* Java platform encoding to generate the JSP
|
||||
* page servlet.
|
||||
*/
|
||||
public String getJavaEncoding();
|
||||
|
||||
/**
|
||||
* boolean flag to tell Ant whether to fork JSP page compilations.
|
||||
*/
|
||||
public boolean getFork();
|
||||
|
||||
/**
|
||||
* Obtain JSP configuration informantion specified in web.xml.
|
||||
*/
|
||||
public JspConfig getJspConfig();
|
||||
|
||||
/**
|
||||
* Is generation of X-Powered-By response header enabled/disabled?
|
||||
*/
|
||||
public boolean isXpoweredBy();
|
||||
|
||||
/**
|
||||
* Obtain a Tag Plugin Manager
|
||||
*/
|
||||
public TagPluginManager getTagPluginManager();
|
||||
|
||||
/**
|
||||
* Are Text strings to be generated as char arrays?
|
||||
*/
|
||||
public boolean genStringAsCharArray();
|
||||
|
||||
/**
|
||||
* Modification test interval.
|
||||
*/
|
||||
public int getModificationTestInterval();
|
||||
|
||||
/**
|
||||
* Is caching enabled (used for precompilation).
|
||||
*/
|
||||
public boolean isCaching();
|
||||
|
||||
/**
|
||||
* The web-application wide cache for the returned TreeNode
|
||||
* by parseXMLDocument in TagLibraryInfoImpl.parseTLD,
|
||||
* if isCaching returns true.
|
||||
*
|
||||
* @return the Map(String uri, TreeNode tld) instance.
|
||||
*/
|
||||
public Map getCache();
|
||||
|
||||
}
|
||||
-493
@@ -1,493 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.apache.jasper.JasperException;
|
||||
import org.apache.tools.ant.BuildException;
|
||||
import org.apache.tools.ant.DefaultLogger;
|
||||
import org.apache.tools.ant.Project;
|
||||
import org.apache.tools.ant.taskdefs.Javac;
|
||||
import org.apache.tools.ant.types.Path;
|
||||
import org.apache.tools.ant.types.PatternSet;
|
||||
|
||||
/**
|
||||
* Main JSP compiler class. This class uses Ant for compiling.
|
||||
*
|
||||
* @author Anil K. Vijendran
|
||||
* @author Mandar Raje
|
||||
* @author Pierre Delisle
|
||||
* @author Kin-man Chung
|
||||
* @author Remy Maucherat
|
||||
* @author Mark Roth
|
||||
*/
|
||||
public class AntCompiler extends Compiler {
|
||||
|
||||
protected static Object javacLock = new Object();
|
||||
|
||||
static {
|
||||
System.setErr(new SystemLogHandler(System.err));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- Instance Variables
|
||||
|
||||
protected Project project = null;
|
||||
protected JasperAntLogger logger;
|
||||
|
||||
// ------------------------------------------------------------ Constructor
|
||||
|
||||
// Lazy eval - if we don't need to compile we probably don't need the project
|
||||
protected Project getProject() {
|
||||
|
||||
if (project != null)
|
||||
return project;
|
||||
|
||||
// Initializing project
|
||||
project = new Project();
|
||||
logger = new JasperAntLogger();
|
||||
logger.setOutputPrintStream(System.out);
|
||||
logger.setErrorPrintStream(System.err);
|
||||
logger.setMessageOutputLevel(Project.MSG_INFO);
|
||||
project.addBuildListener( logger);
|
||||
if (System.getProperty("catalina.home") != null) {
|
||||
project.setBasedir( System.getProperty("catalina.home"));
|
||||
}
|
||||
|
||||
if( options.getCompiler() != null ) {
|
||||
if( log.isDebugEnabled() )
|
||||
log.debug("Compiler " + options.getCompiler() );
|
||||
project.setProperty("build.compiler", options.getCompiler() );
|
||||
}
|
||||
project.init();
|
||||
return project;
|
||||
}
|
||||
|
||||
public class JasperAntLogger extends DefaultLogger {
|
||||
|
||||
protected StringBuffer reportBuf = new StringBuffer();
|
||||
|
||||
protected void printMessage(final String message,
|
||||
final PrintStream stream,
|
||||
final int priority) {
|
||||
}
|
||||
|
||||
protected void log(String message) {
|
||||
reportBuf.append(message);
|
||||
reportBuf.append(System.getProperty("line.separator"));
|
||||
}
|
||||
|
||||
protected String getReport() {
|
||||
String report = reportBuf.toString();
|
||||
reportBuf.setLength(0);
|
||||
return report;
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------- Public Methods
|
||||
|
||||
|
||||
/**
|
||||
* Compile the servlet from .java file to .class file
|
||||
*/
|
||||
protected void generateClass(String[] smap)
|
||||
throws FileNotFoundException, JasperException, Exception {
|
||||
|
||||
long t1 = 0;
|
||||
if (log.isDebugEnabled()) {
|
||||
t1 = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
String javaEncoding = ctxt.getOptions().getJavaEncoding();
|
||||
String javaFileName = ctxt.getServletJavaFileName();
|
||||
String classpath = ctxt.getClassPath();
|
||||
|
||||
String sep = System.getProperty("path.separator");
|
||||
|
||||
StringBuffer errorReport = new StringBuffer();
|
||||
|
||||
StringBuffer info=new StringBuffer();
|
||||
info.append("Compile: javaFileName=" + javaFileName + "\n" );
|
||||
info.append(" classpath=" + classpath + "\n" );
|
||||
|
||||
// Start capturing the System.err output for this thread
|
||||
SystemLogHandler.setThread();
|
||||
|
||||
// Initializing javac task
|
||||
getProject();
|
||||
Javac javac = (Javac) project.createTask("javac");
|
||||
|
||||
// Initializing classpath
|
||||
Path path = new Path(project);
|
||||
path.setPath(System.getProperty("java.class.path"));
|
||||
info.append(" cp=" + System.getProperty("java.class.path") + "\n");
|
||||
StringTokenizer tokenizer = new StringTokenizer(classpath, sep);
|
||||
while (tokenizer.hasMoreElements()) {
|
||||
String pathElement = tokenizer.nextToken();
|
||||
File repository = new File(pathElement);
|
||||
path.setLocation(repository);
|
||||
info.append(" cp=" + repository + "\n");
|
||||
}
|
||||
|
||||
if( log.isDebugEnabled() )
|
||||
log.debug( "Using classpath: " + System.getProperty("java.class.path") + sep
|
||||
+ classpath);
|
||||
|
||||
// Initializing sourcepath
|
||||
Path srcPath = new Path(project);
|
||||
srcPath.setLocation(options.getScratchDir());
|
||||
|
||||
info.append(" work dir=" + options.getScratchDir() + "\n");
|
||||
|
||||
// Initialize and set java extensions
|
||||
String exts = System.getProperty("java.ext.dirs");
|
||||
if (exts != null) {
|
||||
Path extdirs = new Path(project);
|
||||
extdirs.setPath(exts);
|
||||
javac.setExtdirs(extdirs);
|
||||
info.append(" extension dir=" + exts + "\n");
|
||||
}
|
||||
|
||||
// Add endorsed directories if any are specified and we're forking
|
||||
// See Bugzilla 31257
|
||||
if(ctxt.getOptions().getFork()) {
|
||||
String endorsed = System.getProperty("java.endorsed.dirs");
|
||||
if(endorsed != null) {
|
||||
Javac.ImplementationSpecificArgument endorsedArg =
|
||||
javac.createCompilerArg();
|
||||
endorsedArg.setLine("-J-Djava.endorsed.dirs=" +
|
||||
quotePathList(endorsed));
|
||||
info.append(" endorsed dir=" + quotePathList(endorsed) +
|
||||
"\n");
|
||||
} else {
|
||||
info.append(" no endorsed dirs specified\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Configure the compiler object
|
||||
javac.setEncoding(javaEncoding);
|
||||
javac.setClasspath(path);
|
||||
javac.setDebug(ctxt.getOptions().getClassDebugInfo());
|
||||
javac.setSrcdir(srcPath);
|
||||
javac.setTempdir(options.getScratchDir());
|
||||
javac.setOptimize(! ctxt.getOptions().getClassDebugInfo() );
|
||||
javac.setFork(ctxt.getOptions().getFork());
|
||||
info.append(" srcDir=" + srcPath + "\n" );
|
||||
|
||||
// Set the Java compiler to use
|
||||
if (options.getCompiler() != null) {
|
||||
javac.setCompiler(options.getCompiler());
|
||||
info.append(" compiler=" + options.getCompiler() + "\n");
|
||||
}
|
||||
|
||||
if (options.getCompilerTargetVM() != null) {
|
||||
javac.setTarget(options.getCompilerTargetVM());
|
||||
info.append(" compilerTargetVM=" + options.getCompilerTargetVM() + "\n");
|
||||
}
|
||||
|
||||
if (options.getCompilerSourceVM() != null) {
|
||||
javac.setSource(options.getCompilerSourceVM());
|
||||
info.append(" compilerSourceVM=" + options.getCompilerSourceVM() + "\n");
|
||||
}
|
||||
|
||||
// Build includes path
|
||||
PatternSet.NameEntry includes = javac.createInclude();
|
||||
|
||||
includes.setName(ctxt.getJavaPath());
|
||||
info.append(" include="+ ctxt.getJavaPath() + "\n" );
|
||||
|
||||
BuildException be = null;
|
||||
|
||||
try {
|
||||
if (ctxt.getOptions().getFork()) {
|
||||
javac.execute();
|
||||
} else {
|
||||
synchronized(javacLock) {
|
||||
javac.execute();
|
||||
}
|
||||
}
|
||||
} catch (BuildException e) {
|
||||
be = e;
|
||||
log.error(Localizer.getMessage("jsp.error.javac"), e);
|
||||
log.error(Localizer.getMessage("jsp.error.javac.env") + info.toString());
|
||||
}
|
||||
|
||||
errorReport.append(logger.getReport());
|
||||
|
||||
// Stop capturing the System.err output for this thread
|
||||
String errorCapture = SystemLogHandler.unsetThread();
|
||||
if (errorCapture != null) {
|
||||
errorReport.append(System.getProperty("line.separator"));
|
||||
errorReport.append(errorCapture);
|
||||
}
|
||||
|
||||
if (!ctxt.keepGenerated()) {
|
||||
File javaFile = new File(javaFileName);
|
||||
javaFile.delete();
|
||||
}
|
||||
|
||||
if (be != null) {
|
||||
String errorReportString = errorReport.toString();
|
||||
log.error(Localizer.getMessage("jsp.error.compilation", javaFileName, errorReportString));
|
||||
JavacErrorDetail[] javacErrors = ErrorDispatcher.parseJavacErrors(
|
||||
errorReportString, javaFileName, pageNodes);
|
||||
if (javacErrors != null) {
|
||||
errDispatcher.javacError(javacErrors);
|
||||
} else {
|
||||
errDispatcher.javacError(errorReportString, be);
|
||||
}
|
||||
}
|
||||
|
||||
if( log.isDebugEnabled() ) {
|
||||
long t2 = System.currentTimeMillis();
|
||||
log.debug("Compiled " + ctxt.getServletJavaFileName() + " "
|
||||
+ (t2-t1) + "ms");
|
||||
}
|
||||
|
||||
logger = null;
|
||||
project = null;
|
||||
|
||||
if (ctxt.isPrototypeMode()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// JSR45 Support
|
||||
if (! options.isSmapSuppressed()) {
|
||||
SmapUtil.installSmap(smap);
|
||||
}
|
||||
}
|
||||
|
||||
private String quotePathList(String list) {
|
||||
StringBuffer result = new StringBuffer(list.length() + 10);
|
||||
StringTokenizer st = new StringTokenizer(list, File.pathSeparator);
|
||||
while (st.hasMoreTokens()) {
|
||||
String token = st.nextToken();
|
||||
if (token.indexOf(' ') == -1) {
|
||||
result.append(token);
|
||||
} else {
|
||||
result.append('\"');
|
||||
result.append(token);
|
||||
result.append('\"');
|
||||
}
|
||||
if (st.hasMoreTokens()) {
|
||||
result.append(File.pathSeparatorChar);
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
|
||||
protected static class SystemLogHandler extends PrintStream {
|
||||
|
||||
|
||||
// ----------------------------------------------------------- Constructors
|
||||
|
||||
|
||||
/**
|
||||
* Construct the handler to capture the output of the given steam.
|
||||
*/
|
||||
public SystemLogHandler(PrintStream wrapped) {
|
||||
super(wrapped);
|
||||
this.wrapped = wrapped;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------- Instance Variables
|
||||
|
||||
|
||||
/**
|
||||
* Wrapped PrintStream.
|
||||
*/
|
||||
protected PrintStream wrapped = null;
|
||||
|
||||
|
||||
/**
|
||||
* Thread <-> PrintStream associations.
|
||||
*/
|
||||
protected static ThreadLocal streams = new ThreadLocal();
|
||||
|
||||
|
||||
/**
|
||||
* Thread <-> ByteArrayOutputStream associations.
|
||||
*/
|
||||
protected static ThreadLocal data = new ThreadLocal();
|
||||
|
||||
|
||||
// --------------------------------------------------------- Public Methods
|
||||
|
||||
|
||||
public PrintStream getWrapped() {
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start capturing thread's output.
|
||||
*/
|
||||
public static void setThread() {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
data.set(baos);
|
||||
streams.set(new PrintStream(baos));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stop capturing thread's output and return captured data as a String.
|
||||
*/
|
||||
public static String unsetThread() {
|
||||
ByteArrayOutputStream baos =
|
||||
(ByteArrayOutputStream) data.get();
|
||||
if (baos == null) {
|
||||
return null;
|
||||
}
|
||||
streams.set(null);
|
||||
data.set(null);
|
||||
return baos.toString();
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------ Protected Methods
|
||||
|
||||
|
||||
/**
|
||||
* Find PrintStream to which the output must be written to.
|
||||
*/
|
||||
protected PrintStream findStream() {
|
||||
PrintStream ps = (PrintStream) streams.get();
|
||||
if (ps == null) {
|
||||
ps = wrapped;
|
||||
}
|
||||
return ps;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------- PrintStream Methods
|
||||
|
||||
|
||||
public void flush() {
|
||||
findStream().flush();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
findStream().close();
|
||||
}
|
||||
|
||||
public boolean checkError() {
|
||||
return findStream().checkError();
|
||||
}
|
||||
|
||||
protected void setError() {
|
||||
//findStream().setError();
|
||||
}
|
||||
|
||||
public void write(int b) {
|
||||
findStream().write(b);
|
||||
}
|
||||
|
||||
public void write(byte[] b)
|
||||
throws IOException {
|
||||
findStream().write(b);
|
||||
}
|
||||
|
||||
public void write(byte[] buf, int off, int len) {
|
||||
findStream().write(buf, off, len);
|
||||
}
|
||||
|
||||
public void print(boolean b) {
|
||||
findStream().print(b);
|
||||
}
|
||||
|
||||
public void print(char c) {
|
||||
findStream().print(c);
|
||||
}
|
||||
|
||||
public void print(int i) {
|
||||
findStream().print(i);
|
||||
}
|
||||
|
||||
public void print(long l) {
|
||||
findStream().print(l);
|
||||
}
|
||||
|
||||
public void print(float f) {
|
||||
findStream().print(f);
|
||||
}
|
||||
|
||||
public void print(double d) {
|
||||
findStream().print(d);
|
||||
}
|
||||
|
||||
public void print(char[] s) {
|
||||
findStream().print(s);
|
||||
}
|
||||
|
||||
public void print(String s) {
|
||||
findStream().print(s);
|
||||
}
|
||||
|
||||
public void print(Object obj) {
|
||||
findStream().print(obj);
|
||||
}
|
||||
|
||||
public void println() {
|
||||
findStream().println();
|
||||
}
|
||||
|
||||
public void println(boolean x) {
|
||||
findStream().println(x);
|
||||
}
|
||||
|
||||
public void println(char x) {
|
||||
findStream().println(x);
|
||||
}
|
||||
|
||||
public void println(int x) {
|
||||
findStream().println(x);
|
||||
}
|
||||
|
||||
public void println(long x) {
|
||||
findStream().println(x);
|
||||
}
|
||||
|
||||
public void println(float x) {
|
||||
findStream().println(x);
|
||||
}
|
||||
|
||||
public void println(double x) {
|
||||
findStream().println(x);
|
||||
}
|
||||
|
||||
public void println(char[] x) {
|
||||
findStream().println(x);
|
||||
}
|
||||
|
||||
public void println(String x) {
|
||||
findStream().println(x);
|
||||
}
|
||||
|
||||
public void println(Object x) {
|
||||
findStream().println(x);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-75
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.apache.jasper.JasperException;
|
||||
|
||||
/**
|
||||
* Repository of {page, request, session, application}-scoped beans
|
||||
*
|
||||
* @author Mandar Raje
|
||||
* @author Remy Maucherat
|
||||
*/
|
||||
public class BeanRepository {
|
||||
|
||||
protected HashMap<String, String> beanTypes;
|
||||
protected ClassLoader loader;
|
||||
protected ErrorDispatcher errDispatcher;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public BeanRepository(ClassLoader loader, ErrorDispatcher err) {
|
||||
this.loader = loader;
|
||||
this.errDispatcher = err;
|
||||
beanTypes = new HashMap<String, String>();
|
||||
}
|
||||
|
||||
public void addBean(Node.UseBean n, String s, String type, String scope)
|
||||
throws JasperException {
|
||||
|
||||
if (!(scope == null || scope.equals("page") || scope.equals("request")
|
||||
|| scope.equals("session") || scope.equals("application"))) {
|
||||
errDispatcher.jspError(n, "jsp.error.usebean.badScope");
|
||||
}
|
||||
|
||||
beanTypes.put(s, type);
|
||||
}
|
||||
|
||||
public Class getBeanType(String bean)
|
||||
throws JasperException {
|
||||
Class clazz = null;
|
||||
try {
|
||||
clazz = loader.loadClass(beanTypes.get(bean));
|
||||
} catch (ClassNotFoundException ex) {
|
||||
throw new JasperException (ex);
|
||||
}
|
||||
return clazz;
|
||||
}
|
||||
|
||||
public boolean checkVariable(String bean) {
|
||||
return beanTypes.containsKey(bean);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,204 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import org.apache.jasper.JasperException;
|
||||
|
||||
/**
|
||||
* Collect info about the page and nodes, and make them availabe through
|
||||
* the PageInfo object.
|
||||
*
|
||||
* @author Kin-man Chung
|
||||
* @author Mark Roth
|
||||
*/
|
||||
|
||||
class Collector {
|
||||
|
||||
/**
|
||||
* A visitor for collecting information on the page and the body of
|
||||
* the custom tags.
|
||||
*/
|
||||
static class CollectVisitor extends Node.Visitor {
|
||||
|
||||
private boolean scriptingElementSeen = false;
|
||||
private boolean usebeanSeen = false;
|
||||
private boolean includeActionSeen = false;
|
||||
private boolean paramActionSeen = false;
|
||||
private boolean setPropertySeen = false;
|
||||
private boolean hasScriptingVars = false;
|
||||
|
||||
public void visit(Node.ParamAction n) throws JasperException {
|
||||
if (n.getValue().isExpression()) {
|
||||
scriptingElementSeen = true;
|
||||
}
|
||||
paramActionSeen = true;
|
||||
}
|
||||
|
||||
public void visit(Node.IncludeAction n) throws JasperException {
|
||||
if (n.getPage().isExpression()) {
|
||||
scriptingElementSeen = true;
|
||||
}
|
||||
includeActionSeen = true;
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.ForwardAction n) throws JasperException {
|
||||
if (n.getPage().isExpression()) {
|
||||
scriptingElementSeen = true;
|
||||
}
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.SetProperty n) throws JasperException {
|
||||
if (n.getValue() != null && n.getValue().isExpression()) {
|
||||
scriptingElementSeen = true;
|
||||
}
|
||||
setPropertySeen = true;
|
||||
}
|
||||
|
||||
public void visit(Node.UseBean n) throws JasperException {
|
||||
if (n.getBeanName() != null && n.getBeanName().isExpression()) {
|
||||
scriptingElementSeen = true;
|
||||
}
|
||||
usebeanSeen = true;
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.PlugIn n) throws JasperException {
|
||||
if (n.getHeight() != null && n.getHeight().isExpression()) {
|
||||
scriptingElementSeen = true;
|
||||
}
|
||||
if (n.getWidth() != null && n.getWidth().isExpression()) {
|
||||
scriptingElementSeen = true;
|
||||
}
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.CustomTag n) throws JasperException {
|
||||
// Check to see what kinds of element we see as child elements
|
||||
checkSeen( n.getChildInfo(), n );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check all child nodes for various elements and update the given
|
||||
* ChildInfo object accordingly. Visits body in the process.
|
||||
*/
|
||||
private void checkSeen( Node.ChildInfo ci, Node n )
|
||||
throws JasperException
|
||||
{
|
||||
// save values collected so far
|
||||
boolean scriptingElementSeenSave = scriptingElementSeen;
|
||||
scriptingElementSeen = false;
|
||||
boolean usebeanSeenSave = usebeanSeen;
|
||||
usebeanSeen = false;
|
||||
boolean includeActionSeenSave = includeActionSeen;
|
||||
includeActionSeen = false;
|
||||
boolean paramActionSeenSave = paramActionSeen;
|
||||
paramActionSeen = false;
|
||||
boolean setPropertySeenSave = setPropertySeen;
|
||||
setPropertySeen = false;
|
||||
boolean hasScriptingVarsSave = hasScriptingVars;
|
||||
hasScriptingVars = false;
|
||||
|
||||
// Scan attribute list for expressions
|
||||
if( n instanceof Node.CustomTag ) {
|
||||
Node.CustomTag ct = (Node.CustomTag)n;
|
||||
Node.JspAttribute[] attrs = ct.getJspAttributes();
|
||||
for (int i = 0; attrs != null && i < attrs.length; i++) {
|
||||
if (attrs[i].isExpression()) {
|
||||
scriptingElementSeen = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
visitBody(n);
|
||||
|
||||
if( (n instanceof Node.CustomTag) && !hasScriptingVars) {
|
||||
Node.CustomTag ct = (Node.CustomTag)n;
|
||||
hasScriptingVars = ct.getVariableInfos().length > 0 ||
|
||||
ct.getTagVariableInfos().length > 0;
|
||||
}
|
||||
|
||||
// Record if the tag element and its body contains any scriptlet.
|
||||
ci.setScriptless(! scriptingElementSeen);
|
||||
ci.setHasUseBean(usebeanSeen);
|
||||
ci.setHasIncludeAction(includeActionSeen);
|
||||
ci.setHasParamAction(paramActionSeen);
|
||||
ci.setHasSetProperty(setPropertySeen);
|
||||
ci.setHasScriptingVars(hasScriptingVars);
|
||||
|
||||
// Propagate value of scriptingElementSeen up.
|
||||
scriptingElementSeen = scriptingElementSeen || scriptingElementSeenSave;
|
||||
usebeanSeen = usebeanSeen || usebeanSeenSave;
|
||||
setPropertySeen = setPropertySeen || setPropertySeenSave;
|
||||
includeActionSeen = includeActionSeen || includeActionSeenSave;
|
||||
paramActionSeen = paramActionSeen || paramActionSeenSave;
|
||||
hasScriptingVars = hasScriptingVars || hasScriptingVarsSave;
|
||||
}
|
||||
|
||||
public void visit(Node.JspElement n) throws JasperException {
|
||||
if (n.getNameAttribute().isExpression())
|
||||
scriptingElementSeen = true;
|
||||
|
||||
Node.JspAttribute[] attrs = n.getJspAttributes();
|
||||
for (int i = 0; i < attrs.length; i++) {
|
||||
if (attrs[i].isExpression()) {
|
||||
scriptingElementSeen = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.JspBody n) throws JasperException {
|
||||
checkSeen( n.getChildInfo(), n );
|
||||
}
|
||||
|
||||
public void visit(Node.NamedAttribute n) throws JasperException {
|
||||
checkSeen( n.getChildInfo(), n );
|
||||
}
|
||||
|
||||
public void visit(Node.Declaration n) throws JasperException {
|
||||
scriptingElementSeen = true;
|
||||
}
|
||||
|
||||
public void visit(Node.Expression n) throws JasperException {
|
||||
scriptingElementSeen = true;
|
||||
}
|
||||
|
||||
public void visit(Node.Scriptlet n) throws JasperException {
|
||||
scriptingElementSeen = true;
|
||||
}
|
||||
|
||||
public void updatePageInfo(PageInfo pageInfo) {
|
||||
pageInfo.setScriptless(! scriptingElementSeen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void collect(Compiler compiler, Node.Nodes page)
|
||||
throws JasperException {
|
||||
|
||||
CollectVisitor collectVisitor = new CollectVisitor();
|
||||
page.visit(collectVisitor);
|
||||
collectVisitor.updatePageInfo(compiler.getPageInfo());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,551 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.jasper.JasperException;
|
||||
import org.apache.jasper.JspCompilationContext;
|
||||
import org.apache.jasper.Options;
|
||||
import org.apache.jasper.servlet.JspServletWrapper;
|
||||
|
||||
/**
|
||||
* Main JSP compiler class. This class uses Ant for compiling.
|
||||
*
|
||||
* @author Anil K. Vijendran
|
||||
* @author Mandar Raje
|
||||
* @author Pierre Delisle
|
||||
* @author Kin-man Chung
|
||||
* @author Remy Maucherat
|
||||
* @author Mark Roth
|
||||
*/
|
||||
public abstract class Compiler {
|
||||
|
||||
protected org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory
|
||||
.getLog(Compiler.class);
|
||||
|
||||
// ----------------------------------------------------- Instance Variables
|
||||
|
||||
protected JspCompilationContext ctxt;
|
||||
|
||||
protected ErrorDispatcher errDispatcher;
|
||||
|
||||
protected PageInfo pageInfo;
|
||||
|
||||
protected JspServletWrapper jsw;
|
||||
|
||||
protected TagFileProcessor tfp;
|
||||
|
||||
protected Options options;
|
||||
|
||||
protected Node.Nodes pageNodes;
|
||||
|
||||
// ------------------------------------------------------------ Constructor
|
||||
|
||||
public void init(JspCompilationContext ctxt, JspServletWrapper jsw) {
|
||||
this.jsw = jsw;
|
||||
this.ctxt = ctxt;
|
||||
this.options = ctxt.getOptions();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------- Public Methods
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Retrieves the parsed nodes of the JSP page, if they are available. May
|
||||
* return null. Used in development mode for generating detailed error
|
||||
* messages. http://issues.apache.org/bugzilla/show_bug.cgi?id=37062.
|
||||
* </p>
|
||||
*/
|
||||
public Node.Nodes getPageNodes() {
|
||||
return this.pageNodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the jsp file into equivalent servlet in .java file
|
||||
*
|
||||
* @return a smap for the current JSP page, if one is generated, null
|
||||
* otherwise
|
||||
*/
|
||||
protected String[] generateJava() throws Exception {
|
||||
|
||||
String[] smapStr = null;
|
||||
|
||||
long t1, t2, t3, t4;
|
||||
|
||||
t1 = t2 = t3 = t4 = 0;
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
t1 = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
// Setup page info area
|
||||
pageInfo = new PageInfo(new BeanRepository(ctxt.getClassLoader(),
|
||||
errDispatcher), ctxt.getJspFile());
|
||||
|
||||
JspConfig jspConfig = options.getJspConfig();
|
||||
JspConfig.JspProperty jspProperty = jspConfig.findJspProperty(ctxt
|
||||
.getJspFile());
|
||||
|
||||
/*
|
||||
* If the current uri is matched by a pattern specified in a
|
||||
* jsp-property-group in web.xml, initialize pageInfo with those
|
||||
* properties.
|
||||
*/
|
||||
if (jspProperty.isELIgnored() != null) {
|
||||
pageInfo.setELIgnored(JspUtil.booleanValue(jspProperty
|
||||
.isELIgnored()));
|
||||
}
|
||||
if (jspProperty.isScriptingInvalid() != null) {
|
||||
pageInfo.setScriptingInvalid(JspUtil.booleanValue(jspProperty
|
||||
.isScriptingInvalid()));
|
||||
}
|
||||
if (jspProperty.getIncludePrelude() != null) {
|
||||
pageInfo.setIncludePrelude(jspProperty.getIncludePrelude());
|
||||
}
|
||||
if (jspProperty.getIncludeCoda() != null) {
|
||||
pageInfo.setIncludeCoda(jspProperty.getIncludeCoda());
|
||||
}
|
||||
if (jspProperty.isDeferedSyntaxAllowedAsLiteral() != null) {
|
||||
pageInfo.setDeferredSyntaxAllowedAsLiteral(JspUtil.booleanValue(jspProperty
|
||||
.isDeferedSyntaxAllowedAsLiteral()));
|
||||
}
|
||||
if (jspProperty.isTrimDirectiveWhitespaces() != null) {
|
||||
pageInfo.setTrimDirectiveWhitespaces(JspUtil.booleanValue(jspProperty
|
||||
.isTrimDirectiveWhitespaces()));
|
||||
}
|
||||
|
||||
ctxt.checkOutputDir();
|
||||
String javaFileName = ctxt.getServletJavaFileName();
|
||||
|
||||
ServletWriter writer = null;
|
||||
try {
|
||||
/*
|
||||
* The setting of isELIgnored changes the behaviour of the parser
|
||||
* in subtle ways. To add to the 'fun', isELIgnored can be set in
|
||||
* any file that forms part of the translation unit so setting it
|
||||
* in a file included towards the end of the translation unit can
|
||||
* change how the parser should have behaved when parsing content
|
||||
* up to the point where isELIgnored was set. Arghh!
|
||||
* Previous attempts to hack around this have only provided partial
|
||||
* solutions. We now use two passes to parse the translation unit.
|
||||
* The first just parses the directives and the second parses the
|
||||
* whole translation unit once we know how isELIgnored has been set.
|
||||
* TODO There are some possible optimisations of this process.
|
||||
*/
|
||||
// Parse the file
|
||||
ParserController parserCtl = new ParserController(ctxt, this);
|
||||
|
||||
// Pass 1 - the directives
|
||||
Node.Nodes directives =
|
||||
parserCtl.parseDirectives(ctxt.getJspFile());
|
||||
Validator.validateDirectives(this, directives);
|
||||
|
||||
// Pass 2 - the whole translation unit
|
||||
pageNodes = parserCtl.parse(ctxt.getJspFile());
|
||||
|
||||
if (ctxt.isPrototypeMode()) {
|
||||
// generate prototype .java file for the tag file
|
||||
writer = setupContextWriter(javaFileName);
|
||||
Generator.generate(writer, this, pageNodes);
|
||||
writer.close();
|
||||
writer = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
// Validate and process attributes - don't re-validate the
|
||||
// directives we validated in pass 1
|
||||
Validator.validateExDirectives(this, pageNodes);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
t2 = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
// Collect page info
|
||||
Collector.collect(this, pageNodes);
|
||||
|
||||
// Compile (if necessary) and load the tag files referenced in
|
||||
// this compilation unit.
|
||||
tfp = new TagFileProcessor();
|
||||
tfp.loadTagFiles(this, pageNodes);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
t3 = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
// Determine which custom tag needs to declare which scripting vars
|
||||
ScriptingVariabler.set(pageNodes, errDispatcher);
|
||||
|
||||
// Optimizations by Tag Plugins
|
||||
TagPluginManager tagPluginManager = options.getTagPluginManager();
|
||||
tagPluginManager.apply(pageNodes, errDispatcher, pageInfo);
|
||||
|
||||
// Optimization: concatenate contiguous template texts.
|
||||
TextOptimizer.concatenate(this, pageNodes);
|
||||
|
||||
// Generate static function mapper codes.
|
||||
ELFunctionMapper.map(this, pageNodes);
|
||||
|
||||
// generate servlet .java file
|
||||
writer = setupContextWriter(javaFileName);
|
||||
Generator.generate(writer, this, pageNodes);
|
||||
writer.close();
|
||||
writer = null;
|
||||
|
||||
// The writer is only used during the compile, dereference
|
||||
// it in the JspCompilationContext when done to allow it
|
||||
// to be GC'd and save memory.
|
||||
ctxt.setWriter(null);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
t4 = System.currentTimeMillis();
|
||||
log.debug("Generated " + javaFileName + " total=" + (t4 - t1)
|
||||
+ " generate=" + (t4 - t3) + " validate=" + (t2 - t1));
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
if (writer != null) {
|
||||
try {
|
||||
writer.close();
|
||||
writer = null;
|
||||
} catch (Exception e1) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
// Remove the generated .java file
|
||||
new File(javaFileName).delete();
|
||||
throw e;
|
||||
} finally {
|
||||
if (writer != null) {
|
||||
try {
|
||||
writer.close();
|
||||
} catch (Exception e2) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// JSR45 Support
|
||||
if (!options.isSmapSuppressed()) {
|
||||
smapStr = SmapUtil.generateSmap(ctxt, pageNodes);
|
||||
}
|
||||
|
||||
// If any proto type .java and .class files was generated,
|
||||
// the prototype .java may have been replaced by the current
|
||||
// compilation (if the tag file is self referencing), but the
|
||||
// .class file need to be removed, to make sure that javac would
|
||||
// generate .class again from the new .java file just generated.
|
||||
tfp.removeProtoTypeFiles(ctxt.getClassFileName());
|
||||
|
||||
return smapStr;
|
||||
}
|
||||
|
||||
private ServletWriter setupContextWriter(String javaFileName)
|
||||
throws FileNotFoundException, JasperException {
|
||||
ServletWriter writer;
|
||||
// Setup the ServletWriter
|
||||
String javaEncoding = ctxt.getOptions().getJavaEncoding();
|
||||
OutputStreamWriter osw = null;
|
||||
|
||||
try {
|
||||
osw = new OutputStreamWriter(
|
||||
new FileOutputStream(javaFileName), javaEncoding);
|
||||
} catch (UnsupportedEncodingException ex) {
|
||||
errDispatcher.jspError("jsp.error.needAlternateJavaEncoding",
|
||||
javaEncoding);
|
||||
}
|
||||
|
||||
writer = new ServletWriter(new PrintWriter(osw));
|
||||
ctxt.setWriter(writer);
|
||||
return writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the servlet from .java file to .class file
|
||||
*/
|
||||
protected abstract void generateClass(String[] smap)
|
||||
throws FileNotFoundException, JasperException, Exception;
|
||||
|
||||
/**
|
||||
* Compile the jsp file from the current engine context
|
||||
*/
|
||||
public void compile() throws FileNotFoundException, JasperException,
|
||||
Exception {
|
||||
compile(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the jsp file from the current engine context. As an side- effect,
|
||||
* tag files that are referenced by this page are also compiled.
|
||||
*
|
||||
* @param compileClass
|
||||
* If true, generate both .java and .class file If false,
|
||||
* generate only .java file
|
||||
*/
|
||||
public void compile(boolean compileClass) throws FileNotFoundException,
|
||||
JasperException, Exception {
|
||||
compile(compileClass, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the jsp file from the current engine context. As an side- effect,
|
||||
* tag files that are referenced by this page are also compiled.
|
||||
*
|
||||
* @param compileClass
|
||||
* If true, generate both .java and .class file If false,
|
||||
* generate only .java file
|
||||
* @param jspcMode
|
||||
* true if invoked from JspC, false otherwise
|
||||
*/
|
||||
public void compile(boolean compileClass, boolean jspcMode)
|
||||
throws FileNotFoundException, JasperException, Exception {
|
||||
if (errDispatcher == null) {
|
||||
this.errDispatcher = new ErrorDispatcher(jspcMode);
|
||||
}
|
||||
|
||||
try {
|
||||
String[] smap = generateJava();
|
||||
if (compileClass) {
|
||||
generateClass(smap);
|
||||
// Fix for bugzilla 41606
|
||||
// Set JspServletWrapper.servletClassLastModifiedTime after successful compile
|
||||
String targetFileName = ctxt.getClassFileName();
|
||||
if (targetFileName != null) {
|
||||
File targetFile = new File(targetFileName);
|
||||
if (targetFile.exists() && jsw != null) {
|
||||
jsw.setServletClassLastModifiedTime(targetFile.lastModified());
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (tfp != null && ctxt.isPrototypeMode()) {
|
||||
tfp.removeProtoTypeFiles(null);
|
||||
}
|
||||
// Make sure these object which are only used during the
|
||||
// generation and compilation of the JSP page get
|
||||
// dereferenced so that they can be GC'd and reduce the
|
||||
// memory footprint.
|
||||
tfp = null;
|
||||
errDispatcher = null;
|
||||
pageInfo = null;
|
||||
|
||||
// Only get rid of the pageNodes if in production.
|
||||
// In development mode, they are used for detailed
|
||||
// error messages.
|
||||
// http://issues.apache.org/bugzilla/show_bug.cgi?id=37062
|
||||
if (!this.options.getDevelopment()) {
|
||||
pageNodes = null;
|
||||
}
|
||||
|
||||
if (ctxt.getWriter() != null) {
|
||||
ctxt.getWriter().close();
|
||||
ctxt.setWriter(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a protected method intended to be overridden by subclasses of
|
||||
* Compiler. This is used by the compile method to do all the compilation.
|
||||
*/
|
||||
public boolean isOutDated() {
|
||||
return isOutDated(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a compilation is necessary by checking the time stamp of the
|
||||
* JSP page with that of the corresponding .class or .java file. If the page
|
||||
* has dependencies, the check is also extended to its dependeants, and so
|
||||
* on. This method can by overidden by a subclasses of Compiler.
|
||||
*
|
||||
* @param checkClass
|
||||
* If true, check against .class file, if false, check against
|
||||
* .java file.
|
||||
*/
|
||||
public boolean isOutDated(boolean checkClass) {
|
||||
|
||||
String jsp = ctxt.getJspFile();
|
||||
|
||||
if (jsw != null
|
||||
&& (ctxt.getOptions().getModificationTestInterval() > 0)) {
|
||||
|
||||
if (jsw.getLastModificationTest()
|
||||
+ (ctxt.getOptions().getModificationTestInterval() * 1000) > System
|
||||
.currentTimeMillis()) {
|
||||
return false;
|
||||
} else {
|
||||
jsw.setLastModificationTest(System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
|
||||
long jspRealLastModified = 0;
|
||||
try {
|
||||
URL jspUrl = ctxt.getResource(jsp);
|
||||
if (jspUrl == null) {
|
||||
ctxt.incrementRemoved();
|
||||
return false;
|
||||
}
|
||||
URLConnection uc = jspUrl.openConnection();
|
||||
if (uc instanceof JarURLConnection) {
|
||||
jspRealLastModified =
|
||||
((JarURLConnection) uc).getJarEntry().getTime();
|
||||
} else {
|
||||
jspRealLastModified = uc.getLastModified();
|
||||
}
|
||||
uc.getInputStream().close();
|
||||
} catch (Exception e) {
|
||||
return true;
|
||||
}
|
||||
|
||||
long targetLastModified = 0;
|
||||
File targetFile;
|
||||
|
||||
if (checkClass) {
|
||||
targetFile = new File(ctxt.getClassFileName());
|
||||
} else {
|
||||
targetFile = new File(ctxt.getServletJavaFileName());
|
||||
}
|
||||
|
||||
if (!targetFile.exists()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
targetLastModified = targetFile.lastModified();
|
||||
if (checkClass && jsw != null) {
|
||||
jsw.setServletClassLastModifiedTime(targetLastModified);
|
||||
}
|
||||
if (targetLastModified < jspRealLastModified) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Compiler: outdated: " + targetFile + " "
|
||||
+ targetLastModified);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// determine if source dependent files (e.g. includes using include
|
||||
// directives) have been changed.
|
||||
if (jsw == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List depends = jsw.getDependants();
|
||||
if (depends == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Iterator it = depends.iterator();
|
||||
while (it.hasNext()) {
|
||||
String include = (String) it.next();
|
||||
try {
|
||||
URL includeUrl = ctxt.getResource(include);
|
||||
if (includeUrl == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
URLConnection iuc = includeUrl.openConnection();
|
||||
long includeLastModified = 0;
|
||||
if (iuc instanceof JarURLConnection) {
|
||||
includeLastModified =
|
||||
((JarURLConnection) iuc).getJarEntry().getTime();
|
||||
} else {
|
||||
includeLastModified = iuc.getLastModified();
|
||||
}
|
||||
iuc.getInputStream().close();
|
||||
|
||||
if (includeLastModified > targetLastModified) {
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the error dispatcher.
|
||||
*/
|
||||
public ErrorDispatcher getErrorDispatcher() {
|
||||
return errDispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the info about the page under compilation
|
||||
*/
|
||||
public PageInfo getPageInfo() {
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
public JspCompilationContext getCompilationContext() {
|
||||
return ctxt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove generated files
|
||||
*/
|
||||
public void removeGeneratedFiles() {
|
||||
try {
|
||||
String classFileName = ctxt.getClassFileName();
|
||||
if (classFileName != null) {
|
||||
File classFile = new File(classFileName);
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("Deleting " + classFile);
|
||||
classFile.delete();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Remove as much as possible, ignore possible exceptions
|
||||
}
|
||||
try {
|
||||
String javaFileName = ctxt.getServletJavaFileName();
|
||||
if (javaFileName != null) {
|
||||
File javaFile = new File(javaFileName);
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("Deleting " + javaFile);
|
||||
javaFile.delete();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Remove as much as possible, ignore possible exceptions
|
||||
}
|
||||
}
|
||||
|
||||
public void removeGeneratedClassFiles() {
|
||||
try {
|
||||
String classFileName = ctxt.getClassFileName();
|
||||
if (classFileName != null) {
|
||||
File classFile = new File(classFileName);
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("Deleting " + classFile);
|
||||
classFile.delete();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Remove as much as possible, ignore possible exceptions
|
||||
}
|
||||
}
|
||||
}
|
||||
-109
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import org.apache.jasper.JasperException;
|
||||
|
||||
/**
|
||||
* Default implementation of ErrorHandler interface.
|
||||
*
|
||||
* @author Jan Luehe
|
||||
*/
|
||||
class DefaultErrorHandler implements ErrorHandler {
|
||||
|
||||
/*
|
||||
* Processes the given JSP parse error.
|
||||
*
|
||||
* @param fname Name of the JSP file in which the parse error occurred
|
||||
* @param line Parse error line number
|
||||
* @param column Parse error column number
|
||||
* @param errMsg Parse error message
|
||||
* @param exception Parse exception
|
||||
*/
|
||||
public void jspError(String fname, int line, int column, String errMsg,
|
||||
Exception ex) throws JasperException {
|
||||
throw new JasperException(fname + "(" + line + "," + column + ")"
|
||||
+ " " + errMsg, ex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Processes the given JSP parse error.
|
||||
*
|
||||
* @param errMsg Parse error message
|
||||
* @param exception Parse exception
|
||||
*/
|
||||
public void jspError(String errMsg, Exception ex) throws JasperException {
|
||||
throw new JasperException(errMsg, ex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Processes the given javac compilation errors.
|
||||
*
|
||||
* @param details Array of JavacErrorDetail instances corresponding to the
|
||||
* compilation errors
|
||||
*/
|
||||
public void javacError(JavacErrorDetail[] details) throws JasperException {
|
||||
|
||||
if (details == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object[] args = null;
|
||||
StringBuffer buf = new StringBuffer();
|
||||
|
||||
for (int i=0; i < details.length; i++) {
|
||||
if (details[i].getJspBeginLineNumber() >= 0) {
|
||||
args = new Object[] {
|
||||
new Integer(details[i].getJspBeginLineNumber()),
|
||||
details[i].getJspFileName() };
|
||||
buf.append("\n\n");
|
||||
buf.append(Localizer.getMessage("jsp.error.single.line.number",
|
||||
args));
|
||||
buf.append("\n");
|
||||
buf.append(details[i].getErrorMessage());
|
||||
buf.append("\n");
|
||||
buf.append(details[i].getJspExtract());
|
||||
} else {
|
||||
args = new Object[] {
|
||||
new Integer(details[i].getJavaLineNumber()) };
|
||||
buf.append("\n\n");
|
||||
buf.append(Localizer.getMessage("jsp.error.java.line.number",
|
||||
args));
|
||||
buf.append("\n");
|
||||
buf.append(details[i].getErrorMessage());
|
||||
}
|
||||
}
|
||||
buf.append("\n\nStacktrace:");
|
||||
throw new JasperException(
|
||||
Localizer.getMessage("jsp.error.unable.compile") + ": " + buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the given javac error report and exception.
|
||||
*
|
||||
* @param errorReport Compilation error report
|
||||
* @param exception Compilation exception
|
||||
*/
|
||||
public void javacError(String errorReport, Exception exception)
|
||||
throws JasperException {
|
||||
|
||||
throw new JasperException(
|
||||
Localizer.getMessage("jsp.error.unable.compile"), exception);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,207 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.apache.jasper.JasperException;
|
||||
|
||||
class Dumper {
|
||||
|
||||
static class DumpVisitor extends Node.Visitor {
|
||||
private int indent = 0;
|
||||
|
||||
private String getAttributes(Attributes attrs) {
|
||||
if (attrs == null)
|
||||
return "";
|
||||
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (int i=0; i < attrs.getLength(); i++) {
|
||||
buf.append(" " + attrs.getQName(i) + "=\""
|
||||
+ attrs.getValue(i) + "\"");
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private void printString(String str) {
|
||||
printIndent();
|
||||
System.out.print(str);
|
||||
}
|
||||
|
||||
private void printString(String prefix, char[] chars, String suffix) {
|
||||
String str = null;
|
||||
if (chars != null) {
|
||||
str = new String(chars);
|
||||
}
|
||||
printString(prefix, str, suffix);
|
||||
}
|
||||
|
||||
private void printString(String prefix, String str, String suffix) {
|
||||
printIndent();
|
||||
if (str != null) {
|
||||
System.out.print(prefix + str + suffix);
|
||||
} else {
|
||||
System.out.print(prefix + suffix);
|
||||
}
|
||||
}
|
||||
|
||||
private void printAttributes(String prefix, Attributes attrs,
|
||||
String suffix) {
|
||||
printString(prefix, getAttributes(attrs), suffix);
|
||||
}
|
||||
|
||||
private void dumpBody(Node n) throws JasperException {
|
||||
Node.Nodes page = n.getBody();
|
||||
if (page != null) {
|
||||
// indent++;
|
||||
page.visit(this);
|
||||
// indent--;
|
||||
}
|
||||
}
|
||||
|
||||
public void visit(Node.PageDirective n) throws JasperException {
|
||||
printAttributes("<%@ page", n.getAttributes(), "%>");
|
||||
}
|
||||
|
||||
public void visit(Node.TaglibDirective n) throws JasperException {
|
||||
printAttributes("<%@ taglib", n.getAttributes(), "%>");
|
||||
}
|
||||
|
||||
public void visit(Node.IncludeDirective n) throws JasperException {
|
||||
printAttributes("<%@ include", n.getAttributes(), "%>");
|
||||
dumpBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.Comment n) throws JasperException {
|
||||
printString("<%--", n.getText(), "--%>");
|
||||
}
|
||||
|
||||
public void visit(Node.Declaration n) throws JasperException {
|
||||
printString("<%!", n.getText(), "%>");
|
||||
}
|
||||
|
||||
public void visit(Node.Expression n) throws JasperException {
|
||||
printString("<%=", n.getText(), "%>");
|
||||
}
|
||||
|
||||
public void visit(Node.Scriptlet n) throws JasperException {
|
||||
printString("<%", n.getText(), "%>");
|
||||
}
|
||||
|
||||
public void visit(Node.IncludeAction n) throws JasperException {
|
||||
printAttributes("<jsp:include", n.getAttributes(), ">");
|
||||
dumpBody(n);
|
||||
printString("</jsp:include>");
|
||||
}
|
||||
|
||||
public void visit(Node.ForwardAction n) throws JasperException {
|
||||
printAttributes("<jsp:forward", n.getAttributes(), ">");
|
||||
dumpBody(n);
|
||||
printString("</jsp:forward>");
|
||||
}
|
||||
|
||||
public void visit(Node.GetProperty n) throws JasperException {
|
||||
printAttributes("<jsp:getProperty", n.getAttributes(), "/>");
|
||||
}
|
||||
|
||||
public void visit(Node.SetProperty n) throws JasperException {
|
||||
printAttributes("<jsp:setProperty", n.getAttributes(), ">");
|
||||
dumpBody(n);
|
||||
printString("</jsp:setProperty>");
|
||||
}
|
||||
|
||||
public void visit(Node.UseBean n) throws JasperException {
|
||||
printAttributes("<jsp:useBean", n.getAttributes(), ">");
|
||||
dumpBody(n);
|
||||
printString("</jsp:useBean>");
|
||||
}
|
||||
|
||||
public void visit(Node.PlugIn n) throws JasperException {
|
||||
printAttributes("<jsp:plugin", n.getAttributes(), ">");
|
||||
dumpBody(n);
|
||||
printString("</jsp:plugin>");
|
||||
}
|
||||
|
||||
public void visit(Node.ParamsAction n) throws JasperException {
|
||||
printAttributes("<jsp:params", n.getAttributes(), ">");
|
||||
dumpBody(n);
|
||||
printString("</jsp:params>");
|
||||
}
|
||||
|
||||
public void visit(Node.ParamAction n) throws JasperException {
|
||||
printAttributes("<jsp:param", n.getAttributes(), ">");
|
||||
dumpBody(n);
|
||||
printString("</jsp:param>");
|
||||
}
|
||||
|
||||
public void visit(Node.NamedAttribute n) throws JasperException {
|
||||
printAttributes("<jsp:attribute", n.getAttributes(), ">");
|
||||
dumpBody(n);
|
||||
printString("</jsp:attribute>");
|
||||
}
|
||||
|
||||
public void visit(Node.JspBody n) throws JasperException {
|
||||
printAttributes("<jsp:body", n.getAttributes(), ">");
|
||||
dumpBody(n);
|
||||
printString("</jsp:body>");
|
||||
}
|
||||
|
||||
public void visit(Node.ELExpression n) throws JasperException {
|
||||
printString( "${" + new String( n.getText() ) + "}" );
|
||||
}
|
||||
|
||||
public void visit(Node.CustomTag n) throws JasperException {
|
||||
printAttributes("<" + n.getQName(), n.getAttributes(), ">");
|
||||
dumpBody(n);
|
||||
printString("</" + n.getQName() + ">");
|
||||
}
|
||||
|
||||
public void visit(Node.UninterpretedTag n) throws JasperException {
|
||||
String tag = n.getQName();
|
||||
printAttributes("<"+tag, n.getAttributes(), ">");
|
||||
dumpBody(n);
|
||||
printString("</" + tag + ">");
|
||||
}
|
||||
|
||||
public void visit(Node.TemplateText n) throws JasperException {
|
||||
printString(new String(n.getText()));
|
||||
}
|
||||
|
||||
private void printIndent() {
|
||||
for (int i=0; i < indent; i++) {
|
||||
System.out.print(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void dump(Node n) {
|
||||
try {
|
||||
n.accept(new DumpVisitor());
|
||||
} catch (JasperException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void dump(Node.Nodes page) {
|
||||
try {
|
||||
page.visit(new DumpVisitor());
|
||||
} catch (JasperException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-281
@@ -1,281 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.util.*;
|
||||
import javax.servlet.jsp.tagext.FunctionInfo;
|
||||
import org.apache.jasper.JasperException;
|
||||
|
||||
/**
|
||||
* This class generates functions mappers for the EL expressions in the page.
|
||||
* Instead of a global mapper, a mapper is used for ecah call to EL
|
||||
* evaluator, thus avoiding the prefix overlapping and redefinition
|
||||
* issues.
|
||||
*
|
||||
* @author Kin-man Chung
|
||||
*/
|
||||
|
||||
public class ELFunctionMapper {
|
||||
private int currFunc = 0;
|
||||
StringBuffer ds; // Contains codes to initialize the functions mappers.
|
||||
StringBuffer ss; // Contains declarations of the functions mappers.
|
||||
|
||||
/**
|
||||
* Creates the functions mappers for all EL expressions in the JSP page.
|
||||
*
|
||||
* @param compiler Current compiler, mainly for accessing error dispatcher.
|
||||
* @param page The current compilation unit.
|
||||
*/
|
||||
public static void map(Compiler compiler, Node.Nodes page)
|
||||
throws JasperException {
|
||||
|
||||
ELFunctionMapper map = new ELFunctionMapper();
|
||||
map.ds = new StringBuffer();
|
||||
map.ss = new StringBuffer();
|
||||
|
||||
page.visit(map.new ELFunctionVisitor());
|
||||
|
||||
// Append the declarations to the root node
|
||||
String ds = map.ds.toString();
|
||||
if (ds.length() > 0) {
|
||||
Node root = page.getRoot();
|
||||
new Node.Declaration(map.ss.toString(), null, root);
|
||||
new Node.Declaration("static {\n" + ds + "}\n", null, root);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A visitor for the page. The places where EL is allowed are scanned
|
||||
* for functions, and if found functions mappers are created.
|
||||
*/
|
||||
class ELFunctionVisitor extends Node.Visitor {
|
||||
|
||||
/**
|
||||
* Use a global name map to facilitate reuse of function maps.
|
||||
* The key used is prefix:function:uri.
|
||||
*/
|
||||
private HashMap<String, String> gMap = new HashMap<String, String>();
|
||||
|
||||
public void visit(Node.ParamAction n) throws JasperException {
|
||||
doMap(n.getValue());
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.IncludeAction n) throws JasperException {
|
||||
doMap(n.getPage());
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.ForwardAction n) throws JasperException {
|
||||
doMap(n.getPage());
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.SetProperty n) throws JasperException {
|
||||
doMap(n.getValue());
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.UseBean n) throws JasperException {
|
||||
doMap(n.getBeanName());
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.PlugIn n) throws JasperException {
|
||||
doMap(n.getHeight());
|
||||
doMap(n.getWidth());
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.JspElement n) throws JasperException {
|
||||
|
||||
Node.JspAttribute[] attrs = n.getJspAttributes();
|
||||
for (int i = 0; attrs != null && i < attrs.length; i++) {
|
||||
doMap(attrs[i]);
|
||||
}
|
||||
doMap(n.getNameAttribute());
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.UninterpretedTag n) throws JasperException {
|
||||
|
||||
Node.JspAttribute[] attrs = n.getJspAttributes();
|
||||
for (int i = 0; attrs != null && i < attrs.length; i++) {
|
||||
doMap(attrs[i]);
|
||||
}
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.CustomTag n) throws JasperException {
|
||||
Node.JspAttribute[] attrs = n.getJspAttributes();
|
||||
for (int i = 0; attrs != null && i < attrs.length; i++) {
|
||||
doMap(attrs[i]);
|
||||
}
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.ELExpression n) throws JasperException {
|
||||
doMap(n.getEL());
|
||||
}
|
||||
|
||||
private void doMap(Node.JspAttribute attr)
|
||||
throws JasperException {
|
||||
if (attr != null) {
|
||||
doMap(attr.getEL());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates function mappers, if needed, from ELNodes
|
||||
*/
|
||||
private void doMap(ELNode.Nodes el)
|
||||
throws JasperException {
|
||||
|
||||
// Only care about functions in ELNode's
|
||||
class Fvisitor extends ELNode.Visitor {
|
||||
ArrayList<ELNode.Function> funcs =
|
||||
new ArrayList<ELNode.Function>();
|
||||
HashMap<String, String> keyMap = new HashMap<String, String>();
|
||||
public void visit(ELNode.Function n) throws JasperException {
|
||||
String key = n.getPrefix() + ":" + n.getName();
|
||||
if (! keyMap.containsKey(key)) {
|
||||
keyMap.put(key,"");
|
||||
funcs.add(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (el == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// First locate all unique functions in this EL
|
||||
Fvisitor fv = new Fvisitor();
|
||||
el.visit(fv);
|
||||
ArrayList functions = fv.funcs;
|
||||
|
||||
if (functions.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Reuse a previous map if possible
|
||||
String decName = matchMap(functions);
|
||||
if (decName != null) {
|
||||
el.setMapName(decName);
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate declaration for the map statically
|
||||
decName = getMapName();
|
||||
ss.append("static private org.apache.jasper.runtime.ProtectedFunctionMapper " + decName + ";\n");
|
||||
|
||||
ds.append(" " + decName + "= ");
|
||||
ds.append("org.apache.jasper.runtime.ProtectedFunctionMapper");
|
||||
|
||||
// Special case if there is only one function in the map
|
||||
String funcMethod = null;
|
||||
if (functions.size() == 1) {
|
||||
funcMethod = ".getMapForFunction";
|
||||
} else {
|
||||
ds.append(".getInstance();\n");
|
||||
funcMethod = " " + decName + ".mapFunction";
|
||||
}
|
||||
|
||||
// Setup arguments for either getMapForFunction or mapFunction
|
||||
for (int i = 0; i < functions.size(); i++) {
|
||||
ELNode.Function f = (ELNode.Function)functions.get(i);
|
||||
FunctionInfo funcInfo = f.getFunctionInfo();
|
||||
String key = f.getPrefix()+ ":" + f.getName();
|
||||
ds.append(funcMethod + "(\"" + key + "\", " +
|
||||
funcInfo.getFunctionClass() + ".class, " +
|
||||
'\"' + f.getMethodName() + "\", " +
|
||||
"new Class[] {");
|
||||
String params[] = f.getParameters();
|
||||
for (int k = 0; k < params.length; k++) {
|
||||
if (k != 0) {
|
||||
ds.append(", ");
|
||||
}
|
||||
int iArray = params[k].indexOf('[');
|
||||
if (iArray < 0) {
|
||||
ds.append(params[k] + ".class");
|
||||
}
|
||||
else {
|
||||
String baseType = params[k].substring(0, iArray);
|
||||
ds.append("java.lang.reflect.Array.newInstance(");
|
||||
ds.append(baseType);
|
||||
ds.append(".class,");
|
||||
|
||||
// Count the number of array dimension
|
||||
int aCount = 0;
|
||||
for (int jj = iArray; jj < params[k].length(); jj++ ) {
|
||||
if (params[k].charAt(jj) == '[') {
|
||||
aCount++;
|
||||
}
|
||||
}
|
||||
if (aCount == 1) {
|
||||
ds.append("0).getClass()");
|
||||
} else {
|
||||
ds.append("new int[" + aCount + "]).getClass()");
|
||||
}
|
||||
}
|
||||
}
|
||||
ds.append("});\n");
|
||||
// Put the current name in the global function map
|
||||
gMap.put(f.getPrefix() + ':' + f.getName() + ':' + f.getUri(),
|
||||
decName);
|
||||
}
|
||||
el.setMapName(decName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the name of the function mapper for an EL. Reuse a
|
||||
* previously generated one if possible.
|
||||
* @param functions An ArrayList of ELNode.Function instances that
|
||||
* represents the functions in an EL
|
||||
* @return A previous generated function mapper name that can be used
|
||||
* by this EL; null if none found.
|
||||
*/
|
||||
private String matchMap(ArrayList functions) {
|
||||
|
||||
String mapName = null;
|
||||
for (int i = 0; i < functions.size(); i++) {
|
||||
ELNode.Function f = (ELNode.Function)functions.get(i);
|
||||
String temName = (String) gMap.get(f.getPrefix() + ':' +
|
||||
f.getName() + ':' + f.getUri());
|
||||
if (temName == null) {
|
||||
return null;
|
||||
}
|
||||
if (mapName == null) {
|
||||
mapName = temName;
|
||||
} else if (!temName.equals(mapName)) {
|
||||
// If not all in the previous match, then no match.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return mapName;
|
||||
}
|
||||
|
||||
/*
|
||||
* @return An unique name for a function mapper.
|
||||
*/
|
||||
private String getMapName() {
|
||||
return "_jspx_fnmap_" + currFunc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,255 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.util.*;
|
||||
import javax.servlet.jsp.tagext.FunctionInfo;
|
||||
import org.apache.jasper.JasperException;
|
||||
|
||||
/**
|
||||
* This class defines internal representation for an EL Expression
|
||||
*
|
||||
* It currently only defines functions. It can be expanded to define
|
||||
* all the components of an EL expression, if need to.
|
||||
*
|
||||
* @author Kin-man Chung
|
||||
*/
|
||||
|
||||
abstract class ELNode {
|
||||
|
||||
abstract public void accept(Visitor v) throws JasperException;
|
||||
|
||||
/**
|
||||
* Child classes
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Represents an EL expression: anything in ${ and }.
|
||||
*/
|
||||
public static class Root extends ELNode {
|
||||
|
||||
private ELNode.Nodes expr;
|
||||
private char type;
|
||||
|
||||
Root(ELNode.Nodes expr, char type) {
|
||||
this.expr = expr;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void accept(Visitor v) throws JasperException {
|
||||
v.visit(this);
|
||||
}
|
||||
|
||||
public ELNode.Nodes getExpression() {
|
||||
return expr;
|
||||
}
|
||||
|
||||
public char getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents text outside of EL expression.
|
||||
*/
|
||||
public static class Text extends ELNode {
|
||||
|
||||
private String text;
|
||||
|
||||
Text(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public void accept(Visitor v) throws JasperException {
|
||||
v.visit(this);
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents anything in EL expression, other than functions, including
|
||||
* function arguments etc
|
||||
*/
|
||||
public static class ELText extends ELNode {
|
||||
|
||||
private String text;
|
||||
|
||||
ELText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public void accept(Visitor v) throws JasperException {
|
||||
v.visit(this);
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a function
|
||||
* Currently only include the prefix and function name, but not its
|
||||
* arguments.
|
||||
*/
|
||||
public static class Function extends ELNode {
|
||||
|
||||
private String prefix;
|
||||
private String name;
|
||||
private String uri;
|
||||
private FunctionInfo functionInfo;
|
||||
private String methodName;
|
||||
private String[] parameters;
|
||||
|
||||
Function(String prefix, String name) {
|
||||
this.prefix = prefix;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void accept(Visitor v) throws JasperException {
|
||||
v.visit(this);
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setUri(String uri) {
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public String getUri() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
public void setFunctionInfo(FunctionInfo f) {
|
||||
this.functionInfo = f;
|
||||
}
|
||||
|
||||
public FunctionInfo getFunctionInfo() {
|
||||
return functionInfo;
|
||||
}
|
||||
|
||||
public void setMethodName(String methodName) {
|
||||
this.methodName = methodName;
|
||||
}
|
||||
|
||||
public String getMethodName() {
|
||||
return methodName;
|
||||
}
|
||||
|
||||
public void setParameters(String[] parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public String[] getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An ordered list of ELNode.
|
||||
*/
|
||||
public static class Nodes {
|
||||
|
||||
/* Name used for creating a map for the functions in this
|
||||
EL expression, for communication to Generator.
|
||||
*/
|
||||
String mapName = null; // The function map associated this EL
|
||||
private List<ELNode> list;
|
||||
|
||||
public Nodes() {
|
||||
list = new ArrayList<ELNode>();
|
||||
}
|
||||
|
||||
public void add(ELNode en) {
|
||||
list.add(en);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit the nodes in the list with the supplied visitor
|
||||
* @param v The visitor used
|
||||
*/
|
||||
public void visit(Visitor v) throws JasperException {
|
||||
Iterator<ELNode> iter = list.iterator();
|
||||
while (iter.hasNext()) {
|
||||
ELNode n = iter.next();
|
||||
n.accept(v);
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<ELNode> iterator() {
|
||||
return list.iterator();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return list.size() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the expression contains a ${...}
|
||||
*/
|
||||
public boolean containsEL() {
|
||||
Iterator<ELNode> iter = list.iterator();
|
||||
while (iter.hasNext()) {
|
||||
ELNode n = iter.next();
|
||||
if (n instanceof Root) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setMapName(String name) {
|
||||
this.mapName = name;
|
||||
}
|
||||
|
||||
public String getMapName() {
|
||||
return mapName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* A visitor class for traversing ELNodes
|
||||
*/
|
||||
public static class Visitor {
|
||||
|
||||
public void visit(Root n) throws JasperException {
|
||||
n.getExpression().visit(this);
|
||||
}
|
||||
|
||||
public void visit(Function n) throws JasperException {
|
||||
}
|
||||
|
||||
public void visit(Text n) throws JasperException {
|
||||
}
|
||||
|
||||
public void visit(ELText n) throws JasperException {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,382 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
/**
|
||||
* This class implements a parser for EL expressions.
|
||||
*
|
||||
* It takes strings of the form xxx${..}yyy${..}zzz etc, and turn it into a
|
||||
* ELNode.Nodes.
|
||||
*
|
||||
* Currently, it only handles text outside ${..} and functions in ${ ..}.
|
||||
*
|
||||
* @author Kin-man Chung
|
||||
*/
|
||||
|
||||
public class ELParser {
|
||||
|
||||
private Token curToken; // current token
|
||||
|
||||
private ELNode.Nodes expr;
|
||||
|
||||
private ELNode.Nodes ELexpr;
|
||||
|
||||
private int index; // Current index of the expression
|
||||
|
||||
private String expression; // The EL expression
|
||||
|
||||
private char type;
|
||||
|
||||
private boolean escapeBS; // is '\' an escape char in text outside EL?
|
||||
|
||||
private static final String reservedWords[] = { "and", "div", "empty",
|
||||
"eq", "false", "ge", "gt", "instanceof", "le", "lt", "mod", "ne",
|
||||
"not", "null", "or", "true" };
|
||||
|
||||
public ELParser(String expression) {
|
||||
index = 0;
|
||||
this.expression = expression;
|
||||
expr = new ELNode.Nodes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an EL expression
|
||||
*
|
||||
* @param expression
|
||||
* The input expression string of the form Char* ('${' Char*
|
||||
* '}')* Char*
|
||||
* @return Parsed EL expression in ELNode.Nodes
|
||||
*/
|
||||
public static ELNode.Nodes parse(String expression) {
|
||||
ELParser parser = new ELParser(expression);
|
||||
while (parser.hasNextChar()) {
|
||||
String text = parser.skipUntilEL();
|
||||
if (text.length() > 0) {
|
||||
parser.expr.add(new ELNode.Text(text));
|
||||
}
|
||||
ELNode.Nodes elexpr = parser.parseEL();
|
||||
if (!elexpr.isEmpty()) {
|
||||
parser.expr.add(new ELNode.Root(elexpr, parser.type));
|
||||
}
|
||||
}
|
||||
return parser.expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an EL expression string '${...}'
|
||||
*
|
||||
* @return An ELNode.Nodes representing the EL expression TODO: Currently
|
||||
* only parsed into functions and text strings. This should be
|
||||
* rewritten for a full parser.
|
||||
*/
|
||||
private ELNode.Nodes parseEL() {
|
||||
|
||||
StringBuffer buf = new StringBuffer();
|
||||
ELexpr = new ELNode.Nodes();
|
||||
while (hasNext()) {
|
||||
curToken = nextToken();
|
||||
if (curToken instanceof Char) {
|
||||
if (curToken.toChar() == '}') {
|
||||
break;
|
||||
}
|
||||
buf.append(curToken.toChar());
|
||||
} else {
|
||||
// Output whatever is in buffer
|
||||
if (buf.length() > 0) {
|
||||
ELexpr.add(new ELNode.ELText(buf.toString()));
|
||||
}
|
||||
if (!parseFunction()) {
|
||||
ELexpr.add(new ELNode.ELText(curToken.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (buf.length() > 0) {
|
||||
ELexpr.add(new ELNode.ELText(buf.toString()));
|
||||
}
|
||||
|
||||
return ELexpr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse for a function FunctionInvokation ::= (identifier ':')? identifier
|
||||
* '(' (Expression (,Expression)*)? ')' Note: currently we don't parse
|
||||
* arguments
|
||||
*/
|
||||
private boolean parseFunction() {
|
||||
if (!(curToken instanceof Id) || isELReserved(curToken.toString())) {
|
||||
return false;
|
||||
}
|
||||
String s1 = null; // Function prefix
|
||||
String s2 = curToken.toString(); // Function name
|
||||
int mark = getIndex();
|
||||
if (hasNext()) {
|
||||
Token t = nextToken();
|
||||
if (t.toChar() == ':') {
|
||||
if (hasNext()) {
|
||||
Token t2 = nextToken();
|
||||
if (t2 instanceof Id) {
|
||||
s1 = s2;
|
||||
s2 = t2.toString();
|
||||
if (hasNext()) {
|
||||
t = nextToken();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (t.toChar() == '(') {
|
||||
ELexpr.add(new ELNode.Function(s1, s2));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
setIndex(mark);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if an id is a reserved word in EL
|
||||
*/
|
||||
private boolean isELReserved(String id) {
|
||||
int i = 0;
|
||||
int j = reservedWords.length;
|
||||
while (i < j) {
|
||||
int k = (i + j) / 2;
|
||||
int result = reservedWords[k].compareTo(id);
|
||||
if (result == 0) {
|
||||
return true;
|
||||
}
|
||||
if (result < 0) {
|
||||
i = k + 1;
|
||||
} else {
|
||||
j = k;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip until an EL expression ('${' || '#{') is reached, allowing escape
|
||||
* sequences '\\' and '\$' and '\#'.
|
||||
*
|
||||
* @return The text string up to the EL expression
|
||||
*/
|
||||
private String skipUntilEL() {
|
||||
char prev = 0;
|
||||
StringBuffer buf = new StringBuffer();
|
||||
while (hasNextChar()) {
|
||||
char ch = nextChar();
|
||||
if (prev == '\\') {
|
||||
prev = 0;
|
||||
if (ch == '\\') {
|
||||
buf.append('\\');
|
||||
if (!escapeBS)
|
||||
prev = '\\';
|
||||
} else if (ch == '$' || ch == '#') {
|
||||
buf.append(ch);
|
||||
}
|
||||
// else error!
|
||||
} else if (prev == '$' || prev == '#') {
|
||||
if (ch == '{') {
|
||||
this.type = prev;
|
||||
prev = 0;
|
||||
break;
|
||||
}
|
||||
buf.append(prev);
|
||||
prev = 0;
|
||||
}
|
||||
if (ch == '\\' || ch == '$' || ch == '#') {
|
||||
prev = ch;
|
||||
} else {
|
||||
buf.append(ch);
|
||||
}
|
||||
}
|
||||
if (prev != 0) {
|
||||
buf.append(prev);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* @return true if there is something left in EL expression buffer other
|
||||
* than white spaces.
|
||||
*/
|
||||
private boolean hasNext() {
|
||||
skipSpaces();
|
||||
return hasNextChar();
|
||||
}
|
||||
|
||||
/*
|
||||
* @return The next token in the EL expression buffer.
|
||||
*/
|
||||
private Token nextToken() {
|
||||
skipSpaces();
|
||||
if (hasNextChar()) {
|
||||
char ch = nextChar();
|
||||
if (Character.isJavaIdentifierStart(ch)) {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(ch);
|
||||
while ((ch = peekChar()) != -1
|
||||
&& Character.isJavaIdentifierPart(ch)) {
|
||||
buf.append(ch);
|
||||
nextChar();
|
||||
}
|
||||
return new Id(buf.toString());
|
||||
}
|
||||
|
||||
if (ch == '\'' || ch == '"') {
|
||||
return parseQuotedChars(ch);
|
||||
} else {
|
||||
// For now...
|
||||
return new Char(ch);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a string in single or double quotes, allowing for escape sequences
|
||||
* '\\', and ('\"', or "\'")
|
||||
*/
|
||||
private Token parseQuotedChars(char quote) {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(quote);
|
||||
while (hasNextChar()) {
|
||||
char ch = nextChar();
|
||||
if (ch == '\\') {
|
||||
ch = nextChar();
|
||||
if (ch == '\\' || ch == quote) {
|
||||
buf.append(ch);
|
||||
}
|
||||
// else error!
|
||||
} else if (ch == quote) {
|
||||
buf.append(ch);
|
||||
break;
|
||||
} else {
|
||||
buf.append(ch);
|
||||
}
|
||||
}
|
||||
return new QuotedString(buf.toString());
|
||||
}
|
||||
|
||||
/*
|
||||
* A collection of low level parse methods dealing with character in the EL
|
||||
* expression buffer.
|
||||
*/
|
||||
|
||||
private void skipSpaces() {
|
||||
while (hasNextChar()) {
|
||||
if (expression.charAt(index) > ' ')
|
||||
break;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasNextChar() {
|
||||
return index < expression.length();
|
||||
}
|
||||
|
||||
private char nextChar() {
|
||||
if (index >= expression.length()) {
|
||||
return (char) -1;
|
||||
}
|
||||
return expression.charAt(index++);
|
||||
}
|
||||
|
||||
private char peekChar() {
|
||||
if (index >= expression.length()) {
|
||||
return (char) -1;
|
||||
}
|
||||
return expression.charAt(index);
|
||||
}
|
||||
|
||||
private int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
private void setIndex(int i) {
|
||||
index = i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Represents a token in EL expression string
|
||||
*/
|
||||
private static class Token {
|
||||
|
||||
char toChar() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Represents an ID token in EL
|
||||
*/
|
||||
private static class Id extends Token {
|
||||
String id;
|
||||
|
||||
Id(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Represents a character token in EL
|
||||
*/
|
||||
private static class Char extends Token {
|
||||
|
||||
private char ch;
|
||||
|
||||
Char(char ch) {
|
||||
this.ch = ch;
|
||||
}
|
||||
|
||||
char toChar() {
|
||||
return ch;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return (new Character(ch)).toString();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Represents a quoted (single or double) string token in EL
|
||||
*/
|
||||
private static class QuotedString extends Token {
|
||||
|
||||
private String value;
|
||||
|
||||
QuotedString(String v) {
|
||||
this.value = v;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public char getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
-615
@@ -1,615 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.apache.jasper.JasperException;
|
||||
import org.apache.jasper.JspCompilationContext;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Class responsible for dispatching JSP parse and javac compilation errors
|
||||
* to the configured error handler.
|
||||
*
|
||||
* This class is also responsible for localizing any error codes before they
|
||||
* are passed on to the configured error handler.
|
||||
*
|
||||
* In the case of a Java compilation error, the compiler error message is
|
||||
* parsed into an array of JavacErrorDetail instances, which is passed on to
|
||||
* the configured error handler.
|
||||
*
|
||||
* @author Jan Luehe
|
||||
* @author Kin-man Chung
|
||||
*/
|
||||
public class ErrorDispatcher {
|
||||
|
||||
// Custom error handler
|
||||
private ErrorHandler errHandler;
|
||||
|
||||
// Indicates whether the compilation was initiated by JspServlet or JspC
|
||||
private boolean jspcMode = false;
|
||||
|
||||
|
||||
/*
|
||||
* Constructor.
|
||||
*
|
||||
* @param jspcMode true if compilation has been initiated by JspC, false
|
||||
* otherwise
|
||||
*/
|
||||
public ErrorDispatcher(boolean jspcMode) {
|
||||
// XXX check web.xml for custom error handler
|
||||
errHandler = new DefaultErrorHandler();
|
||||
this.jspcMode = jspcMode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispatches the given JSP parse error to the configured error handler.
|
||||
*
|
||||
* The given error code is localized. If it is not found in the
|
||||
* resource bundle for localized error messages, it is used as the error
|
||||
* message.
|
||||
*
|
||||
* @param errCode Error code
|
||||
*/
|
||||
public void jspError(String errCode) throws JasperException {
|
||||
dispatch(null, errCode, null, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispatches the given JSP parse error to the configured error handler.
|
||||
*
|
||||
* The given error code is localized. If it is not found in the
|
||||
* resource bundle for localized error messages, it is used as the error
|
||||
* message.
|
||||
*
|
||||
* @param where Error location
|
||||
* @param errCode Error code
|
||||
*/
|
||||
public void jspError(Mark where, String errCode) throws JasperException {
|
||||
dispatch(where, errCode, null, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispatches the given JSP parse error to the configured error handler.
|
||||
*
|
||||
* The given error code is localized. If it is not found in the
|
||||
* resource bundle for localized error messages, it is used as the error
|
||||
* message.
|
||||
*
|
||||
* @param n Node that caused the error
|
||||
* @param errCode Error code
|
||||
*/
|
||||
public void jspError(Node n, String errCode) throws JasperException {
|
||||
dispatch(n.getStart(), errCode, null, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispatches the given JSP parse error to the configured error handler.
|
||||
*
|
||||
* The given error code is localized. If it is not found in the
|
||||
* resource bundle for localized error messages, it is used as the error
|
||||
* message.
|
||||
*
|
||||
* @param errCode Error code
|
||||
* @param arg Argument for parametric replacement
|
||||
*/
|
||||
public void jspError(String errCode, String arg) throws JasperException {
|
||||
dispatch(null, errCode, new Object[] {arg}, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispatches the given JSP parse error to the configured error handler.
|
||||
*
|
||||
* The given error code is localized. If it is not found in the
|
||||
* resource bundle for localized error messages, it is used as the error
|
||||
* message.
|
||||
*
|
||||
* @param where Error location
|
||||
* @param errCode Error code
|
||||
* @param arg Argument for parametric replacement
|
||||
*/
|
||||
public void jspError(Mark where, String errCode, String arg)
|
||||
throws JasperException {
|
||||
dispatch(where, errCode, new Object[] {arg}, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispatches the given JSP parse error to the configured error handler.
|
||||
*
|
||||
* The given error code is localized. If it is not found in the
|
||||
* resource bundle for localized error messages, it is used as the error
|
||||
* message.
|
||||
*
|
||||
* @param n Node that caused the error
|
||||
* @param errCode Error code
|
||||
* @param arg Argument for parametric replacement
|
||||
*/
|
||||
public void jspError(Node n, String errCode, String arg)
|
||||
throws JasperException {
|
||||
dispatch(n.getStart(), errCode, new Object[] {arg}, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispatches the given JSP parse error to the configured error handler.
|
||||
*
|
||||
* The given error code is localized. If it is not found in the
|
||||
* resource bundle for localized error messages, it is used as the error
|
||||
* message.
|
||||
*
|
||||
* @param errCode Error code
|
||||
* @param arg1 First argument for parametric replacement
|
||||
* @param arg2 Second argument for parametric replacement
|
||||
*/
|
||||
public void jspError(String errCode, String arg1, String arg2)
|
||||
throws JasperException {
|
||||
dispatch(null, errCode, new Object[] {arg1, arg2}, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispatches the given JSP parse error to the configured error handler.
|
||||
*
|
||||
* The given error code is localized. If it is not found in the
|
||||
* resource bundle for localized error messages, it is used as the error
|
||||
* message.
|
||||
*
|
||||
* @param errCode Error code
|
||||
* @param arg1 First argument for parametric replacement
|
||||
* @param arg2 Second argument for parametric replacement
|
||||
* @param arg3 Third argument for parametric replacement
|
||||
*/
|
||||
public void jspError(String errCode, String arg1, String arg2, String arg3)
|
||||
throws JasperException {
|
||||
dispatch(null, errCode, new Object[] {arg1, arg2, arg3}, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispatches the given JSP parse error to the configured error handler.
|
||||
*
|
||||
* The given error code is localized. If it is not found in the
|
||||
* resource bundle for localized error messages, it is used as the error
|
||||
* message.
|
||||
*
|
||||
* @param where Error location
|
||||
* @param errCode Error code
|
||||
* @param arg1 First argument for parametric replacement
|
||||
* @param arg2 Second argument for parametric replacement
|
||||
*/
|
||||
public void jspError(Mark where, String errCode, String arg1, String arg2)
|
||||
throws JasperException {
|
||||
dispatch(where, errCode, new Object[] {arg1, arg2}, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispatches the given JSP parse error to the configured error handler.
|
||||
*
|
||||
* The given error code is localized. If it is not found in the
|
||||
* resource bundle for localized error messages, it is used as the error
|
||||
* message.
|
||||
*
|
||||
* @param where Error location
|
||||
* @param errCode Error code
|
||||
* @param arg1 First argument for parametric replacement
|
||||
* @param arg2 Second argument for parametric replacement
|
||||
* @param arg3 Third argument for parametric replacement
|
||||
*/
|
||||
|
||||
public void jspError(Mark where, String errCode, String arg1, String arg2,
|
||||
String arg3)
|
||||
throws JasperException {
|
||||
dispatch(where, errCode, new Object[] {arg1, arg2, arg3}, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispatches the given JSP parse error to the configured error handler.
|
||||
*
|
||||
* The given error code is localized. If it is not found in the
|
||||
* resource bundle for localized error messages, it is used as the error
|
||||
* message.
|
||||
*
|
||||
* @param n Node that caused the error
|
||||
* @param errCode Error code
|
||||
* @param arg1 First argument for parametric replacement
|
||||
* @param arg2 Second argument for parametric replacement
|
||||
*/
|
||||
|
||||
public void jspError(Node n, String errCode, String arg1, String arg2)
|
||||
throws JasperException {
|
||||
dispatch(n.getStart(), errCode, new Object[] {arg1, arg2}, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispatches the given JSP parse error to the configured error handler.
|
||||
*
|
||||
* The given error code is localized. If it is not found in the
|
||||
* resource bundle for localized error messages, it is used as the error
|
||||
* message.
|
||||
*
|
||||
* @param n Node that caused the error
|
||||
* @param errCode Error code
|
||||
* @param arg1 First argument for parametric replacement
|
||||
* @param arg2 Second argument for parametric replacement
|
||||
* @param arg3 Third argument for parametric replacement
|
||||
*/
|
||||
|
||||
public void jspError(Node n, String errCode, String arg1, String arg2,
|
||||
String arg3)
|
||||
throws JasperException {
|
||||
dispatch(n.getStart(), errCode, new Object[] {arg1, arg2, arg3}, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispatches the given parsing exception to the configured error handler.
|
||||
*
|
||||
* @param e Parsing exception
|
||||
*/
|
||||
public void jspError(Exception e) throws JasperException {
|
||||
dispatch(null, null, null, e);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispatches the given JSP parse error to the configured error handler.
|
||||
*
|
||||
* The given error code is localized. If it is not found in the
|
||||
* resource bundle for localized error messages, it is used as the error
|
||||
* message.
|
||||
*
|
||||
* @param errCode Error code
|
||||
* @param arg Argument for parametric replacement
|
||||
* @param e Parsing exception
|
||||
*/
|
||||
public void jspError(String errCode, String arg, Exception e)
|
||||
throws JasperException {
|
||||
dispatch(null, errCode, new Object[] {arg}, e);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispatches the given JSP parse error to the configured error handler.
|
||||
*
|
||||
* The given error code is localized. If it is not found in the
|
||||
* resource bundle for localized error messages, it is used as the error
|
||||
* message.
|
||||
*
|
||||
* @param n Node that caused the error
|
||||
* @param errCode Error code
|
||||
* @param arg Argument for parametric replacement
|
||||
* @param e Parsing exception
|
||||
*/
|
||||
public void jspError(Node n, String errCode, String arg, Exception e)
|
||||
throws JasperException {
|
||||
dispatch(n.getStart(), errCode, new Object[] {arg}, e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the given error message into an array of javac compilation error
|
||||
* messages (one per javac compilation error line number).
|
||||
*
|
||||
* @param errMsg Error message
|
||||
* @param fname Name of Java source file whose compilation failed
|
||||
* @param page Node representation of JSP page from which the Java source
|
||||
* file was generated
|
||||
*
|
||||
* @return Array of javac compilation errors, or null if the given error
|
||||
* message does not contain any compilation error line numbers
|
||||
*/
|
||||
public static JavacErrorDetail[] parseJavacErrors(String errMsg,
|
||||
String fname,
|
||||
Node.Nodes page)
|
||||
throws JasperException, IOException {
|
||||
|
||||
return parseJavacMessage(errMsg, fname, page);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispatches the given javac compilation errors to the configured error
|
||||
* handler.
|
||||
*
|
||||
* @param javacErrors Array of javac compilation errors
|
||||
*/
|
||||
public void javacError(JavacErrorDetail[] javacErrors)
|
||||
throws JasperException {
|
||||
|
||||
errHandler.javacError(javacErrors);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Dispatches the given compilation error report and exception to the
|
||||
* configured error handler.
|
||||
*
|
||||
* @param errorReport Compilation error report
|
||||
* @param e Compilation exception
|
||||
*/
|
||||
public void javacError(String errorReport, Exception e)
|
||||
throws JasperException {
|
||||
|
||||
errHandler.javacError(errorReport, e);
|
||||
}
|
||||
|
||||
|
||||
//*********************************************************************
|
||||
// Private utility methods
|
||||
|
||||
/*
|
||||
* Dispatches the given JSP parse error to the configured error handler.
|
||||
*
|
||||
* The given error code is localized. If it is not found in the
|
||||
* resource bundle for localized error messages, it is used as the error
|
||||
* message.
|
||||
*
|
||||
* @param where Error location
|
||||
* @param errCode Error code
|
||||
* @param args Arguments for parametric replacement
|
||||
* @param e Parsing exception
|
||||
*/
|
||||
private void dispatch(Mark where, String errCode, Object[] args,
|
||||
Exception e) throws JasperException {
|
||||
String file = null;
|
||||
String errMsg = null;
|
||||
int line = -1;
|
||||
int column = -1;
|
||||
boolean hasLocation = false;
|
||||
|
||||
// Localize
|
||||
if (errCode != null) {
|
||||
errMsg = Localizer.getMessage(errCode, args);
|
||||
} else if (e != null) {
|
||||
// give a hint about what's wrong
|
||||
errMsg = e.getMessage();
|
||||
}
|
||||
|
||||
// Get error location
|
||||
if (where != null) {
|
||||
if (jspcMode) {
|
||||
// Get the full URL of the resource that caused the error
|
||||
try {
|
||||
file = where.getURL().toString();
|
||||
} catch (MalformedURLException me) {
|
||||
// Fallback to using context-relative path
|
||||
file = where.getFile();
|
||||
}
|
||||
} else {
|
||||
// Get the context-relative resource path, so as to not
|
||||
// disclose any local filesystem details
|
||||
file = where.getFile();
|
||||
}
|
||||
line = where.getLineNumber();
|
||||
column = where.getColumnNumber();
|
||||
hasLocation = true;
|
||||
}
|
||||
|
||||
// Get nested exception
|
||||
Exception nestedEx = e;
|
||||
if ((e instanceof SAXException)
|
||||
&& (((SAXException) e).getException() != null)) {
|
||||
nestedEx = ((SAXException) e).getException();
|
||||
}
|
||||
|
||||
if (hasLocation) {
|
||||
errHandler.jspError(file, line, column, errMsg, nestedEx);
|
||||
} else {
|
||||
errHandler.jspError(errMsg, nestedEx);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Parses the given Java compilation error message, which may contain one
|
||||
* or more compilation errors, into an array of JavacErrorDetail instances.
|
||||
*
|
||||
* Each JavacErrorDetail instance contains the information about a single
|
||||
* compilation error.
|
||||
*
|
||||
* @param errMsg Compilation error message that was generated by the
|
||||
* javac compiler
|
||||
* @param fname Name of Java source file whose compilation failed
|
||||
* @param page Node representation of JSP page from which the Java source
|
||||
* file was generated
|
||||
*
|
||||
* @return Array of JavacErrorDetail instances corresponding to the
|
||||
* compilation errors
|
||||
*/
|
||||
private static JavacErrorDetail[] parseJavacMessage(
|
||||
String errMsg, String fname, Node.Nodes page)
|
||||
throws IOException, JasperException {
|
||||
|
||||
ArrayList<JavacErrorDetail> errors = new ArrayList<JavacErrorDetail>();
|
||||
StringBuffer errMsgBuf = null;
|
||||
int lineNum = -1;
|
||||
JavacErrorDetail javacError = null;
|
||||
|
||||
BufferedReader reader = new BufferedReader(new StringReader(errMsg));
|
||||
|
||||
/*
|
||||
* Parse compilation errors. Each compilation error consists of a file
|
||||
* path and error line number, followed by a number of lines describing
|
||||
* the error.
|
||||
*/
|
||||
String line = null;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
|
||||
/*
|
||||
* Error line number is delimited by set of colons.
|
||||
* Ignore colon following drive letter on Windows (fromIndex = 2).
|
||||
* XXX Handle deprecation warnings that don't have line info
|
||||
*/
|
||||
int beginColon = line.indexOf(':', 2);
|
||||
int endColon = line.indexOf(':', beginColon + 1);
|
||||
if ((beginColon >= 0) && (endColon >= 0)) {
|
||||
if (javacError != null) {
|
||||
// add previous error to error vector
|
||||
errors.add(javacError);
|
||||
}
|
||||
|
||||
String lineNumStr = line.substring(beginColon + 1, endColon);
|
||||
try {
|
||||
lineNum = Integer.parseInt(lineNumStr);
|
||||
} catch (NumberFormatException e) {
|
||||
lineNum = -1;
|
||||
}
|
||||
|
||||
errMsgBuf = new StringBuffer();
|
||||
|
||||
javacError = createJavacError(fname, page, errMsgBuf, lineNum);
|
||||
}
|
||||
|
||||
// Ignore messages preceding first error
|
||||
if (errMsgBuf != null) {
|
||||
errMsgBuf.append(line);
|
||||
errMsgBuf.append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Add last error to error vector
|
||||
if (javacError != null) {
|
||||
errors.add(javacError);
|
||||
}
|
||||
|
||||
reader.close();
|
||||
|
||||
JavacErrorDetail[] errDetails = null;
|
||||
if (errors.size() > 0) {
|
||||
errDetails = new JavacErrorDetail[errors.size()];
|
||||
errors.toArray(errDetails);
|
||||
}
|
||||
|
||||
return errDetails;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param fname
|
||||
* @param page
|
||||
* @param errMsgBuf
|
||||
* @param lineNum
|
||||
* @return JavacErrorDetail The error details
|
||||
* @throws JasperException
|
||||
*/
|
||||
public static JavacErrorDetail createJavacError(String fname,
|
||||
Node.Nodes page, StringBuffer errMsgBuf, int lineNum)
|
||||
throws JasperException {
|
||||
return createJavacError(fname, page, errMsgBuf, lineNum, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param fname
|
||||
* @param page
|
||||
* @param errMsgBuf
|
||||
* @param lineNum
|
||||
* @param ctxt
|
||||
* @return JavacErrorDetail The error details
|
||||
* @throws JasperException
|
||||
*/
|
||||
public static JavacErrorDetail createJavacError(String fname,
|
||||
Node.Nodes page, StringBuffer errMsgBuf, int lineNum,
|
||||
JspCompilationContext ctxt) throws JasperException {
|
||||
JavacErrorDetail javacError;
|
||||
// Attempt to map javac error line number to line in JSP page
|
||||
ErrorVisitor errVisitor = new ErrorVisitor(lineNum);
|
||||
page.visit(errVisitor);
|
||||
Node errNode = errVisitor.getJspSourceNode();
|
||||
if ((errNode != null) && (errNode.getStart() != null)) {
|
||||
// If this is a scriplet node then there is a one to one mapping
|
||||
// between JSP lines and Java lines
|
||||
if (errVisitor.getJspSourceNode() instanceof Node.Scriptlet) {
|
||||
javacError = new JavacErrorDetail(
|
||||
fname,
|
||||
lineNum,
|
||||
errNode.getStart().getFile(),
|
||||
errNode.getStart().getLineNumber() + lineNum -
|
||||
errVisitor.getJspSourceNode().getBeginJavaLine(),
|
||||
errMsgBuf,
|
||||
ctxt);
|
||||
} else {
|
||||
javacError = new JavacErrorDetail(
|
||||
fname,
|
||||
lineNum,
|
||||
errNode.getStart().getFile(),
|
||||
errNode.getStart().getLineNumber(),
|
||||
errMsgBuf,
|
||||
ctxt);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* javac error line number cannot be mapped to JSP page
|
||||
* line number. For example, this is the case if a
|
||||
* scriptlet is missing a closing brace, which causes
|
||||
* havoc with the try-catch-finally block that the code
|
||||
* generator places around all generated code: As a result
|
||||
* of this, the javac error line numbers will be outside
|
||||
* the range of begin and end java line numbers that were
|
||||
* generated for the scriptlet, and therefore cannot be
|
||||
* mapped to the start line number of the scriptlet in the
|
||||
* JSP page.
|
||||
* Include just the javac error info in the error detail.
|
||||
*/
|
||||
javacError = new JavacErrorDetail(
|
||||
fname,
|
||||
lineNum,
|
||||
errMsgBuf);
|
||||
}
|
||||
return javacError;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Visitor responsible for mapping a line number in the generated servlet
|
||||
* source code to the corresponding JSP node.
|
||||
*/
|
||||
static class ErrorVisitor extends Node.Visitor {
|
||||
|
||||
// Java source line number to be mapped
|
||||
private int lineNum;
|
||||
|
||||
/*
|
||||
* JSP node whose Java source code range in the generated servlet
|
||||
* contains the Java source line number to be mapped
|
||||
*/
|
||||
Node found;
|
||||
|
||||
/*
|
||||
* Constructor.
|
||||
*
|
||||
* @param lineNum Source line number in the generated servlet code
|
||||
*/
|
||||
public ErrorVisitor(int lineNum) {
|
||||
this.lineNum = lineNum;
|
||||
}
|
||||
|
||||
public void doVisit(Node n) throws JasperException {
|
||||
if ((lineNum >= n.getBeginJavaLine())
|
||||
&& (lineNum < n.getEndJavaLine())) {
|
||||
found = n;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the JSP node to which the source line number in the generated
|
||||
* servlet code was mapped.
|
||||
*
|
||||
* @return JSP node to which the source line number in the generated
|
||||
* servlet code was mapped
|
||||
*/
|
||||
public Node getJspSourceNode() {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
}
|
||||
-73
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import org.apache.jasper.JasperException;
|
||||
|
||||
/**
|
||||
* Interface for handling JSP parse and javac compilation errors.
|
||||
*
|
||||
* An implementation of this interface may be registered with the
|
||||
* ErrorDispatcher by setting the XXX initialization parameter in the JSP
|
||||
* page compiler and execution servlet in Catalina's web.xml file to the
|
||||
* implementation's fully qualified class name.
|
||||
*
|
||||
* @author Jan Luehe
|
||||
* @author Kin-man Chung
|
||||
*/
|
||||
public interface ErrorHandler {
|
||||
|
||||
/**
|
||||
* Processes the given JSP parse error.
|
||||
*
|
||||
* @param fname Name of the JSP file in which the parse error occurred
|
||||
* @param line Parse error line number
|
||||
* @param column Parse error column number
|
||||
* @param msg Parse error message
|
||||
* @param exception Parse exception
|
||||
*/
|
||||
public void jspError(String fname, int line, int column, String msg,
|
||||
Exception exception) throws JasperException;
|
||||
|
||||
/**
|
||||
* Processes the given JSP parse error.
|
||||
*
|
||||
* @param msg Parse error message
|
||||
* @param exception Parse exception
|
||||
*/
|
||||
public void jspError(String msg, Exception exception)
|
||||
throws JasperException;
|
||||
|
||||
/**
|
||||
* Processes the given javac compilation errors.
|
||||
*
|
||||
* @param details Array of JavacErrorDetail instances corresponding to the
|
||||
* compilation errors
|
||||
*/
|
||||
public void javacError(JavacErrorDetail[] details)
|
||||
throws JasperException;
|
||||
|
||||
/**
|
||||
* Processes the given javac error report and exception.
|
||||
*
|
||||
* @param errorReport Compilation error report
|
||||
* @param exception Compilation exception
|
||||
*/
|
||||
public void javacError(String errorReport, Exception exception)
|
||||
throws JasperException;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
-218
@@ -1,218 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.servlet.jsp.tagext.FunctionInfo;
|
||||
import javax.servlet.jsp.tagext.TagFileInfo;
|
||||
import javax.servlet.jsp.tagext.TagInfo;
|
||||
import javax.servlet.jsp.tagext.TagLibraryInfo;
|
||||
|
||||
import org.apache.jasper.JasperException;
|
||||
import org.apache.jasper.JspCompilationContext;
|
||||
import org.apache.jasper.xmlparser.ParserUtils;
|
||||
import org.apache.jasper.xmlparser.TreeNode;
|
||||
|
||||
/**
|
||||
* Class responsible for generating an implicit tag library containing tag
|
||||
* handlers corresponding to the tag files in "/WEB-INF/tags/" or a
|
||||
* subdirectory of it.
|
||||
*
|
||||
* @author Jan Luehe
|
||||
*/
|
||||
class ImplicitTagLibraryInfo extends TagLibraryInfo {
|
||||
|
||||
private static final String WEB_INF_TAGS = "/WEB-INF/tags";
|
||||
private static final String TAG_FILE_SUFFIX = ".tag";
|
||||
private static final String TAGX_FILE_SUFFIX = ".tagx";
|
||||
private static final String TAGS_SHORTNAME = "tags";
|
||||
private static final String TLIB_VERSION = "1.0";
|
||||
private static final String JSP_VERSION = "2.0";
|
||||
private static final String IMPLICIT_TLD = "implicit.tld";
|
||||
|
||||
// Maps tag names to tag file paths
|
||||
private Hashtable tagFileMap;
|
||||
|
||||
private ParserController pc;
|
||||
private PageInfo pi;
|
||||
private Vector vec;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public ImplicitTagLibraryInfo(JspCompilationContext ctxt,
|
||||
ParserController pc,
|
||||
PageInfo pi,
|
||||
String prefix,
|
||||
String tagdir,
|
||||
ErrorDispatcher err) throws JasperException {
|
||||
super(prefix, null);
|
||||
this.pc = pc;
|
||||
this.pi = pi;
|
||||
this.tagFileMap = new Hashtable();
|
||||
this.vec = new Vector();
|
||||
|
||||
// Implicit tag libraries have no functions:
|
||||
this.functions = new FunctionInfo[0];
|
||||
|
||||
tlibversion = TLIB_VERSION;
|
||||
jspversion = JSP_VERSION;
|
||||
|
||||
if (!tagdir.startsWith(WEB_INF_TAGS)) {
|
||||
err.jspError("jsp.error.invalid.tagdir", tagdir);
|
||||
}
|
||||
|
||||
// Determine the value of the <short-name> subelement of the
|
||||
// "imaginary" <taglib> element
|
||||
if (tagdir.equals(WEB_INF_TAGS)
|
||||
|| tagdir.equals( WEB_INF_TAGS + "/")) {
|
||||
shortname = TAGS_SHORTNAME;
|
||||
} else {
|
||||
shortname = tagdir.substring(WEB_INF_TAGS.length());
|
||||
shortname = shortname.replace('/', '-');
|
||||
}
|
||||
|
||||
// Populate mapping of tag names to tag file paths
|
||||
Set dirList = ctxt.getResourcePaths(tagdir);
|
||||
if (dirList != null) {
|
||||
Iterator it = dirList.iterator();
|
||||
while (it.hasNext()) {
|
||||
String path = (String) it.next();
|
||||
if (path.endsWith(TAG_FILE_SUFFIX)
|
||||
|| path.endsWith(TAGX_FILE_SUFFIX)) {
|
||||
/*
|
||||
* Use the filename of the tag file, without the .tag or
|
||||
* .tagx extension, respectively, as the <name> subelement
|
||||
* of the "imaginary" <tag-file> element
|
||||
*/
|
||||
String suffix = path.endsWith(TAG_FILE_SUFFIX) ?
|
||||
TAG_FILE_SUFFIX : TAGX_FILE_SUFFIX;
|
||||
String tagName = path.substring(path.lastIndexOf("/") + 1);
|
||||
tagName = tagName.substring(0,
|
||||
tagName.lastIndexOf(suffix));
|
||||
tagFileMap.put(tagName, path);
|
||||
} else if (path.endsWith(IMPLICIT_TLD)) {
|
||||
InputStream in = null;
|
||||
try {
|
||||
in = ctxt.getResourceAsStream(path);
|
||||
if (in != null) {
|
||||
|
||||
// Add implicit TLD to dependency list
|
||||
if (pi != null) {
|
||||
pi.addDependant(path);
|
||||
}
|
||||
|
||||
ParserUtils pu = new ParserUtils();
|
||||
TreeNode tld = pu.parseXMLDocument(uri, in);
|
||||
|
||||
if (tld.findAttribute("version") != null) {
|
||||
this.jspversion = tld.findAttribute("version");
|
||||
}
|
||||
|
||||
// Process each child element of our <taglib> element
|
||||
Iterator list = tld.findChildren();
|
||||
|
||||
while (list.hasNext()) {
|
||||
TreeNode element = (TreeNode) list.next();
|
||||
String tname = element.getName();
|
||||
|
||||
if ("tlibversion".equals(tname) // JSP 1.1
|
||||
|| "tlib-version".equals(tname)) { // JSP 1.2
|
||||
this.tlibversion = element.getBody();
|
||||
} else if ("jspversion".equals(tname)
|
||||
|| "jsp-version".equals(tname)) {
|
||||
this.jspversion = element.getBody();
|
||||
} else if ("shortname".equals(tname) || "short-name".equals(tname)) {
|
||||
// Ignore
|
||||
} else {
|
||||
// All other elements are invalid
|
||||
err.jspError("jsp.error.invalid.implicit", path);
|
||||
}
|
||||
}
|
||||
try {
|
||||
double version = Double.parseDouble(this.jspversion);
|
||||
if (version < 2.0) {
|
||||
err.jspError("jsp.error.invalid.implicit.version", path);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
err.jspError("jsp.error.invalid.implicit.version", path);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (in != null) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (Throwable t) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the given tag name maps to a tag file path,
|
||||
* and if so, parses the corresponding tag file.
|
||||
*
|
||||
* @return The TagFileInfo corresponding to the given tag name, or null if
|
||||
* the given tag name is not implemented as a tag file
|
||||
*/
|
||||
public TagFileInfo getTagFile(String shortName) {
|
||||
|
||||
TagFileInfo tagFile = super.getTagFile(shortName);
|
||||
if (tagFile == null) {
|
||||
String path = (String) tagFileMap.get(shortName);
|
||||
if (path == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
TagInfo tagInfo = null;
|
||||
try {
|
||||
tagInfo = TagFileProcessor.parseTagFileDirectives(pc,
|
||||
shortName,
|
||||
path,
|
||||
pc.getJspCompilationContext().getTagFileJarUrl(path),
|
||||
this);
|
||||
} catch (JasperException je) {
|
||||
throw new RuntimeException(je.toString(), je);
|
||||
}
|
||||
|
||||
tagFile = new TagFileInfo(shortName, path, tagInfo);
|
||||
vec.addElement(tagFile);
|
||||
|
||||
this.tagFiles = new TagFileInfo[vec.size()];
|
||||
vec.copyInto(this.tagFiles);
|
||||
}
|
||||
|
||||
return tagFile;
|
||||
}
|
||||
|
||||
public TagLibraryInfo[] getTagLibraryInfos() {
|
||||
Collection coll = pi.getTaglibs();
|
||||
return (TagLibraryInfo[]) coll.toArray(new TagLibraryInfo[0]);
|
||||
}
|
||||
|
||||
}
|
||||
-460
@@ -1,460 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.apache.jasper.JasperException;
|
||||
import org.eclipse.jdt.core.compiler.IProblem;
|
||||
import org.eclipse.jdt.internal.compiler.ClassFile;
|
||||
import org.eclipse.jdt.internal.compiler.CompilationResult;
|
||||
import org.eclipse.jdt.internal.compiler.Compiler;
|
||||
import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
|
||||
import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
|
||||
import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
|
||||
import org.eclipse.jdt.internal.compiler.IProblemFactory;
|
||||
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
|
||||
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
|
||||
import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
|
||||
import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
|
||||
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
|
||||
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
|
||||
|
||||
/**
|
||||
* JDT class compiler. This compiler will load source dependencies from the
|
||||
* context classloader, reducing dramatically disk access during
|
||||
* the compilation process.
|
||||
*
|
||||
* @author Cocoon2
|
||||
* @author Remy Maucherat
|
||||
*/
|
||||
public class JDTCompiler extends org.apache.jasper.compiler.Compiler {
|
||||
|
||||
|
||||
/**
|
||||
* Compile the servlet from .java file to .class file
|
||||
*/
|
||||
protected void generateClass(String[] smap)
|
||||
throws FileNotFoundException, JasperException, Exception {
|
||||
|
||||
long t1 = 0;
|
||||
if (log.isDebugEnabled()) {
|
||||
t1 = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
final String sourceFile = ctxt.getServletJavaFileName();
|
||||
final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();
|
||||
String packageName = ctxt.getServletPackageName();
|
||||
final String targetClassName =
|
||||
((packageName.length() != 0) ? (packageName + ".") : "")
|
||||
+ ctxt.getServletClassName();
|
||||
final ClassLoader classLoader = ctxt.getJspLoader();
|
||||
String[] fileNames = new String[] {sourceFile};
|
||||
String[] classNames = new String[] {targetClassName};
|
||||
final ArrayList problemList = new ArrayList();
|
||||
|
||||
class CompilationUnit implements ICompilationUnit {
|
||||
|
||||
String className;
|
||||
String sourceFile;
|
||||
|
||||
CompilationUnit(String sourceFile, String className) {
|
||||
this.className = className;
|
||||
this.sourceFile = sourceFile;
|
||||
}
|
||||
|
||||
public char[] getFileName() {
|
||||
return sourceFile.toCharArray();
|
||||
}
|
||||
|
||||
public char[] getContents() {
|
||||
char[] result = null;
|
||||
FileInputStream is = null;
|
||||
try {
|
||||
is = new FileInputStream(sourceFile);
|
||||
Reader reader =
|
||||
new BufferedReader(new InputStreamReader(is, ctxt.getOptions().getJavaEncoding()));
|
||||
if (reader != null) {
|
||||
char[] chars = new char[8192];
|
||||
StringBuffer buf = new StringBuffer();
|
||||
int count;
|
||||
while ((count = reader.read(chars, 0,
|
||||
chars.length)) > 0) {
|
||||
buf.append(chars, 0, count);
|
||||
}
|
||||
result = new char[buf.length()];
|
||||
buf.getChars(0, result.length, result, 0);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("Compilation error", e);
|
||||
} finally {
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException exc) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public char[] getMainTypeName() {
|
||||
int dot = className.lastIndexOf('.');
|
||||
if (dot > 0) {
|
||||
return className.substring(dot + 1).toCharArray();
|
||||
}
|
||||
return className.toCharArray();
|
||||
}
|
||||
|
||||
public char[][] getPackageName() {
|
||||
StringTokenizer izer =
|
||||
new StringTokenizer(className, ".");
|
||||
char[][] result = new char[izer.countTokens()-1][];
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
String tok = izer.nextToken();
|
||||
result[i] = tok.toCharArray();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
final INameEnvironment env = new INameEnvironment() {
|
||||
|
||||
public NameEnvironmentAnswer
|
||||
findType(char[][] compoundTypeName) {
|
||||
String result = "";
|
||||
String sep = "";
|
||||
for (int i = 0; i < compoundTypeName.length; i++) {
|
||||
result += sep;
|
||||
result += new String(compoundTypeName[i]);
|
||||
sep = ".";
|
||||
}
|
||||
return findType(result);
|
||||
}
|
||||
|
||||
public NameEnvironmentAnswer
|
||||
findType(char[] typeName,
|
||||
char[][] packageName) {
|
||||
String result = "";
|
||||
String sep = "";
|
||||
for (int i = 0; i < packageName.length; i++) {
|
||||
result += sep;
|
||||
result += new String(packageName[i]);
|
||||
sep = ".";
|
||||
}
|
||||
result += sep;
|
||||
result += new String(typeName);
|
||||
return findType(result);
|
||||
}
|
||||
|
||||
private NameEnvironmentAnswer findType(String className) {
|
||||
|
||||
InputStream is = null;
|
||||
try {
|
||||
if (className.equals(targetClassName)) {
|
||||
ICompilationUnit compilationUnit =
|
||||
new CompilationUnit(sourceFile, className);
|
||||
return
|
||||
new NameEnvironmentAnswer(compilationUnit, null);
|
||||
}
|
||||
String resourceName =
|
||||
className.replace('.', '/') + ".class";
|
||||
is = classLoader.getResourceAsStream(resourceName);
|
||||
if (is != null) {
|
||||
byte[] classBytes;
|
||||
byte[] buf = new byte[8192];
|
||||
ByteArrayOutputStream baos =
|
||||
new ByteArrayOutputStream(buf.length);
|
||||
int count;
|
||||
while ((count = is.read(buf, 0, buf.length)) > 0) {
|
||||
baos.write(buf, 0, count);
|
||||
}
|
||||
baos.flush();
|
||||
classBytes = baos.toByteArray();
|
||||
char[] fileName = className.toCharArray();
|
||||
ClassFileReader classFileReader =
|
||||
new ClassFileReader(classBytes, fileName,
|
||||
true);
|
||||
return
|
||||
new NameEnvironmentAnswer(classFileReader, null);
|
||||
}
|
||||
} catch (IOException exc) {
|
||||
log.error("Compilation error", exc);
|
||||
} catch (org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException exc) {
|
||||
log.error("Compilation error", exc);
|
||||
} finally {
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException exc) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isPackage(String result) {
|
||||
if (result.equals(targetClassName)) {
|
||||
return false;
|
||||
}
|
||||
String resourceName = result.replace('.', '/') + ".class";
|
||||
InputStream is =
|
||||
classLoader.getResourceAsStream(resourceName);
|
||||
return is == null;
|
||||
}
|
||||
|
||||
public boolean isPackage(char[][] parentPackageName,
|
||||
char[] packageName) {
|
||||
String result = "";
|
||||
String sep = "";
|
||||
if (parentPackageName != null) {
|
||||
for (int i = 0; i < parentPackageName.length; i++) {
|
||||
result += sep;
|
||||
String str = new String(parentPackageName[i]);
|
||||
result += str;
|
||||
sep = ".";
|
||||
}
|
||||
}
|
||||
String str = new String(packageName);
|
||||
if (Character.isUpperCase(str.charAt(0))) {
|
||||
if (!isPackage(result)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
result += sep;
|
||||
result += str;
|
||||
return isPackage(result);
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
final IErrorHandlingPolicy policy =
|
||||
DefaultErrorHandlingPolicies.proceedWithAllProblems();
|
||||
|
||||
final Map settings = new HashMap();
|
||||
settings.put(CompilerOptions.OPTION_LineNumberAttribute,
|
||||
CompilerOptions.GENERATE);
|
||||
settings.put(CompilerOptions.OPTION_SourceFileAttribute,
|
||||
CompilerOptions.GENERATE);
|
||||
settings.put(CompilerOptions.OPTION_ReportDeprecation,
|
||||
CompilerOptions.IGNORE);
|
||||
if (ctxt.getOptions().getJavaEncoding() != null) {
|
||||
settings.put(CompilerOptions.OPTION_Encoding,
|
||||
ctxt.getOptions().getJavaEncoding());
|
||||
}
|
||||
if (ctxt.getOptions().getClassDebugInfo()) {
|
||||
settings.put(CompilerOptions.OPTION_LocalVariableAttribute,
|
||||
CompilerOptions.GENERATE);
|
||||
}
|
||||
|
||||
// Source JVM
|
||||
if(ctxt.getOptions().getCompilerSourceVM() != null) {
|
||||
String opt = ctxt.getOptions().getCompilerSourceVM();
|
||||
if(opt.equals("1.1")) {
|
||||
settings.put(CompilerOptions.OPTION_Source,
|
||||
CompilerOptions.VERSION_1_1);
|
||||
} else if(opt.equals("1.2")) {
|
||||
settings.put(CompilerOptions.OPTION_Source,
|
||||
CompilerOptions.VERSION_1_2);
|
||||
} else if(opt.equals("1.3")) {
|
||||
settings.put(CompilerOptions.OPTION_Source,
|
||||
CompilerOptions.VERSION_1_3);
|
||||
} else if(opt.equals("1.4")) {
|
||||
settings.put(CompilerOptions.OPTION_Source,
|
||||
CompilerOptions.VERSION_1_4);
|
||||
} else if(opt.equals("1.5")) {
|
||||
settings.put(CompilerOptions.OPTION_Source,
|
||||
CompilerOptions.VERSION_1_5);
|
||||
} else if(opt.equals("1.6")) {
|
||||
settings.put(CompilerOptions.OPTION_Source,
|
||||
CompilerOptions.VERSION_1_6);
|
||||
} else if(opt.equals("1.7")) {
|
||||
settings.put(CompilerOptions.OPTION_Source,
|
||||
CompilerOptions.VERSION_1_7);
|
||||
} else {
|
||||
log.warn("Unknown source VM " + opt + " ignored.");
|
||||
settings.put(CompilerOptions.OPTION_Source,
|
||||
CompilerOptions.VERSION_1_5);
|
||||
}
|
||||
} else {
|
||||
// Default to 1.5
|
||||
settings.put(CompilerOptions.OPTION_Source,
|
||||
CompilerOptions.VERSION_1_5);
|
||||
}
|
||||
|
||||
// Target JVM
|
||||
if(ctxt.getOptions().getCompilerTargetVM() != null) {
|
||||
String opt = ctxt.getOptions().getCompilerTargetVM();
|
||||
if(opt.equals("1.1")) {
|
||||
settings.put(CompilerOptions.OPTION_TargetPlatform,
|
||||
CompilerOptions.VERSION_1_1);
|
||||
} else if(opt.equals("1.2")) {
|
||||
settings.put(CompilerOptions.OPTION_TargetPlatform,
|
||||
CompilerOptions.VERSION_1_2);
|
||||
} else if(opt.equals("1.3")) {
|
||||
settings.put(CompilerOptions.OPTION_TargetPlatform,
|
||||
CompilerOptions.VERSION_1_3);
|
||||
} else if(opt.equals("1.4")) {
|
||||
settings.put(CompilerOptions.OPTION_TargetPlatform,
|
||||
CompilerOptions.VERSION_1_4);
|
||||
} else if(opt.equals("1.5")) {
|
||||
settings.put(CompilerOptions.OPTION_TargetPlatform,
|
||||
CompilerOptions.VERSION_1_5);
|
||||
settings.put(CompilerOptions.OPTION_Compliance,
|
||||
CompilerOptions.VERSION_1_5);
|
||||
} else if(opt.equals("1.6")) {
|
||||
settings.put(CompilerOptions.OPTION_TargetPlatform,
|
||||
CompilerOptions.VERSION_1_6);
|
||||
settings.put(CompilerOptions.OPTION_Compliance,
|
||||
CompilerOptions.VERSION_1_6);
|
||||
} else if(opt.equals("1.7")) {
|
||||
settings.put(CompilerOptions.OPTION_TargetPlatform,
|
||||
CompilerOptions.VERSION_1_7);
|
||||
settings.put(CompilerOptions.OPTION_Compliance,
|
||||
CompilerOptions.VERSION_1_7);
|
||||
} else {
|
||||
log.warn("Unknown target VM " + opt + " ignored.");
|
||||
settings.put(CompilerOptions.OPTION_TargetPlatform,
|
||||
CompilerOptions.VERSION_1_5);
|
||||
}
|
||||
} else {
|
||||
// Default to 1.5
|
||||
settings.put(CompilerOptions.OPTION_TargetPlatform,
|
||||
CompilerOptions.VERSION_1_5);
|
||||
settings.put(CompilerOptions.OPTION_Compliance,
|
||||
CompilerOptions.VERSION_1_5);
|
||||
}
|
||||
|
||||
final IProblemFactory problemFactory =
|
||||
new DefaultProblemFactory(Locale.getDefault());
|
||||
|
||||
final ICompilerRequestor requestor = new ICompilerRequestor() {
|
||||
public void acceptResult(CompilationResult result) {
|
||||
try {
|
||||
if (result.hasProblems()) {
|
||||
IProblem[] problems = result.getProblems();
|
||||
for (int i = 0; i < problems.length; i++) {
|
||||
IProblem problem = problems[i];
|
||||
if (problem.isError()) {
|
||||
String name =
|
||||
new String(problems[i].getOriginatingFileName());
|
||||
try {
|
||||
problemList.add(ErrorDispatcher.createJavacError
|
||||
(name, pageNodes, new StringBuffer(problem.getMessage()),
|
||||
problem.getSourceLineNumber(), ctxt));
|
||||
} catch (JasperException e) {
|
||||
log.error("Error visiting node", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (problemList.isEmpty()) {
|
||||
ClassFile[] classFiles = result.getClassFiles();
|
||||
for (int i = 0; i < classFiles.length; i++) {
|
||||
ClassFile classFile = classFiles[i];
|
||||
char[][] compoundName =
|
||||
classFile.getCompoundName();
|
||||
String className = "";
|
||||
String sep = "";
|
||||
for (int j = 0;
|
||||
j < compoundName.length; j++) {
|
||||
className += sep;
|
||||
className += new String(compoundName[j]);
|
||||
sep = ".";
|
||||
}
|
||||
byte[] bytes = classFile.getBytes();
|
||||
String outFile = outputDir + "/" +
|
||||
className.replace('.', '/') + ".class";
|
||||
FileOutputStream fout =
|
||||
new FileOutputStream(outFile);
|
||||
BufferedOutputStream bos =
|
||||
new BufferedOutputStream(fout);
|
||||
bos.write(bytes);
|
||||
bos.close();
|
||||
}
|
||||
}
|
||||
} catch (IOException exc) {
|
||||
log.error("Compilation error", exc);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ICompilationUnit[] compilationUnits =
|
||||
new ICompilationUnit[classNames.length];
|
||||
for (int i = 0; i < compilationUnits.length; i++) {
|
||||
String className = classNames[i];
|
||||
compilationUnits[i] = new CompilationUnit(fileNames[i], className);
|
||||
}
|
||||
Compiler compiler = new Compiler(env,
|
||||
policy,
|
||||
settings,
|
||||
requestor,
|
||||
problemFactory,
|
||||
true);
|
||||
compiler.compile(compilationUnits);
|
||||
|
||||
if (!ctxt.keepGenerated()) {
|
||||
File javaFile = new File(ctxt.getServletJavaFileName());
|
||||
javaFile.delete();
|
||||
}
|
||||
|
||||
if (!problemList.isEmpty()) {
|
||||
JavacErrorDetail[] jeds =
|
||||
(JavacErrorDetail[]) problemList.toArray(new JavacErrorDetail[0]);
|
||||
errDispatcher.javacError(jeds);
|
||||
}
|
||||
|
||||
if( log.isDebugEnabled() ) {
|
||||
long t2=System.currentTimeMillis();
|
||||
log.debug("Compiled " + ctxt.getServletJavaFileName() + " "
|
||||
+ (t2-t1) + "ms");
|
||||
}
|
||||
|
||||
if (ctxt.isPrototypeMode()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// JSR45 Support
|
||||
if (! options.isSmapSuppressed()) {
|
||||
SmapUtil.installSmap(smap);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
-58
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import javax.servlet.jsp.tagext.*;
|
||||
|
||||
/**
|
||||
* TagInfo extension used by tag handlers that are implemented via tag files.
|
||||
* This class provides access to the name of the Map used to store the
|
||||
* dynamic attribute names and values passed to the custom action invocation.
|
||||
* This information is used by the code generator.
|
||||
*/
|
||||
class JasperTagInfo extends TagInfo {
|
||||
|
||||
private String dynamicAttrsMapName;
|
||||
|
||||
public JasperTagInfo(String tagName,
|
||||
String tagClassName,
|
||||
String bodyContent,
|
||||
String infoString,
|
||||
TagLibraryInfo taglib,
|
||||
TagExtraInfo tagExtraInfo,
|
||||
TagAttributeInfo[] attributeInfo,
|
||||
String displayName,
|
||||
String smallIcon,
|
||||
String largeIcon,
|
||||
TagVariableInfo[] tvi,
|
||||
String mapName) {
|
||||
|
||||
super(tagName, tagClassName, bodyContent, infoString, taglib,
|
||||
tagExtraInfo, attributeInfo, displayName, smallIcon, largeIcon,
|
||||
tvi);
|
||||
this.dynamicAttrsMapName = mapName;
|
||||
}
|
||||
|
||||
public String getDynamicAttributesMapName() {
|
||||
return dynamicAttrsMapName;
|
||||
}
|
||||
|
||||
public boolean hasDynamicAttributes() {
|
||||
return dynamicAttrsMapName != null;
|
||||
}
|
||||
}
|
||||
-232
@@ -1,232 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.jasper.JspCompilationContext;
|
||||
|
||||
/**
|
||||
* Class providing details about a javac compilation error.
|
||||
*
|
||||
* @author Jan Luehe
|
||||
* @author Kin-man Chung
|
||||
*/
|
||||
public class JavacErrorDetail {
|
||||
|
||||
private String javaFileName;
|
||||
private int javaLineNum;
|
||||
private String jspFileName;
|
||||
private int jspBeginLineNum;
|
||||
private StringBuffer errMsg;
|
||||
private String jspExtract = null;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param javaFileName The name of the Java file in which the
|
||||
* compilation error occurred
|
||||
* @param javaLineNum The compilation error line number
|
||||
* @param errMsg The compilation error message
|
||||
*/
|
||||
public JavacErrorDetail(String javaFileName,
|
||||
int javaLineNum,
|
||||
StringBuffer errMsg) {
|
||||
|
||||
this.javaFileName = javaFileName;
|
||||
this.javaLineNum = javaLineNum;
|
||||
this.errMsg = errMsg;
|
||||
this.jspBeginLineNum = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param javaFileName The name of the Java file in which the
|
||||
* compilation error occurred
|
||||
* @param javaLineNum The compilation error line number
|
||||
* @param jspFileName The name of the JSP file from which the Java source
|
||||
* file was generated
|
||||
* @param jspBeginLineNum The start line number of the JSP element
|
||||
* responsible for the compilation error
|
||||
* @param errMsg The compilation error message
|
||||
*/
|
||||
public JavacErrorDetail(String javaFileName,
|
||||
int javaLineNum,
|
||||
String jspFileName,
|
||||
int jspBeginLineNum,
|
||||
StringBuffer errMsg) {
|
||||
|
||||
this(javaFileName, javaLineNum, jspFileName, jspBeginLineNum, errMsg,
|
||||
null);
|
||||
}
|
||||
|
||||
public JavacErrorDetail(String javaFileName,
|
||||
int javaLineNum,
|
||||
String jspFileName,
|
||||
int jspBeginLineNum,
|
||||
StringBuffer errMsg,
|
||||
JspCompilationContext ctxt) {
|
||||
|
||||
this(javaFileName, javaLineNum, errMsg);
|
||||
this.jspFileName = jspFileName;
|
||||
this.jspBeginLineNum = jspBeginLineNum;
|
||||
|
||||
if (jspBeginLineNum > 0 && ctxt != null) {
|
||||
InputStream is = null;
|
||||
FileInputStream fis = null;
|
||||
|
||||
try {
|
||||
// Read both files in, so we can inspect them
|
||||
is = ctxt.getResourceAsStream(jspFileName);
|
||||
String[] jspLines = readFile(is);
|
||||
|
||||
fis = new FileInputStream(ctxt.getServletJavaFileName());
|
||||
String[] javaLines = readFile(fis);
|
||||
|
||||
// If the line contains the opening of a multi-line scriptlet
|
||||
// block, then the JSP line number we got back is probably
|
||||
// faulty. Scan forward to match the java line...
|
||||
if (jspLines[jspBeginLineNum-1].lastIndexOf("<%") >
|
||||
jspLines[jspBeginLineNum-1].lastIndexOf("%>")) {
|
||||
String javaLine = javaLines[javaLineNum-1].trim();
|
||||
|
||||
for (int i=jspBeginLineNum-1; i<jspLines.length; i++) {
|
||||
if (jspLines[i].indexOf(javaLine) != -1) {
|
||||
// Update jsp line number
|
||||
this.jspBeginLineNum = i+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// copy out a fragment of JSP to display to the user
|
||||
StringBuffer fragment = new StringBuffer(1024);
|
||||
int startIndex = Math.max(0, this.jspBeginLineNum-1-3);
|
||||
int endIndex = Math.min(
|
||||
jspLines.length-1, this.jspBeginLineNum-1+3);
|
||||
|
||||
for (int i=startIndex;i<=endIndex; ++i) {
|
||||
fragment.append(i+1);
|
||||
fragment.append(": ");
|
||||
fragment.append(jspLines[i]);
|
||||
fragment.append("\n");
|
||||
}
|
||||
jspExtract = fragment.toString();
|
||||
|
||||
} catch (IOException ioe) {
|
||||
// Can't read files - ignore
|
||||
} finally {
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException ioe) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
if (fis != null) {
|
||||
try {
|
||||
fis.close();
|
||||
} catch (IOException ioe) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the Java source file in which the compilation error
|
||||
* occurred.
|
||||
*
|
||||
* @return Java source file name
|
||||
*/
|
||||
public String getJavaFileName() {
|
||||
return this.javaFileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the compilation error line number.
|
||||
*
|
||||
* @return Compilation error line number
|
||||
*/
|
||||
public int getJavaLineNumber() {
|
||||
return this.javaLineNum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the JSP file from which the Java source file was
|
||||
* generated.
|
||||
*
|
||||
* @return JSP file from which the Java source file was generated.
|
||||
*/
|
||||
public String getJspFileName() {
|
||||
return this.jspFileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the start line number (in the JSP file) of the JSP element
|
||||
* responsible for the compilation error.
|
||||
*
|
||||
* @return Start line number of the JSP element responsible for the
|
||||
* compilation error
|
||||
*/
|
||||
public int getJspBeginLineNumber() {
|
||||
return this.jspBeginLineNum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the compilation error message.
|
||||
*
|
||||
* @return Compilation error message
|
||||
*/
|
||||
public String getErrorMessage() {
|
||||
return this.errMsg.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the extract of the JSP that corresponds to this message.
|
||||
*
|
||||
* @return Extract of JSP where error occurred
|
||||
*/
|
||||
public String getJspExtract() {
|
||||
return this.jspExtract;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a text file from an input stream into a String[]. Used to read in
|
||||
* the JSP and generated Java file when generating error messages.
|
||||
*/
|
||||
private String[] readFile(InputStream s) throws IOException {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(s));
|
||||
List lines = new ArrayList();
|
||||
String line;
|
||||
|
||||
while ( (line = reader.readLine()) != null ) {
|
||||
lines.add(line);
|
||||
}
|
||||
|
||||
return (String[]) lines.toArray( new String[lines.size()] );
|
||||
}
|
||||
}
|
||||
@@ -1,531 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Iterator;
|
||||
import java.util.Vector;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.apache.jasper.JasperException;
|
||||
import org.apache.jasper.xmlparser.ParserUtils;
|
||||
import org.apache.jasper.xmlparser.TreeNode;
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
/**
|
||||
* Handles the jsp-config element in WEB_INF/web.xml. This is used
|
||||
* for specifying the JSP configuration information on a JSP page
|
||||
*
|
||||
* @author Kin-man Chung
|
||||
* @author Remy Maucherat
|
||||
*/
|
||||
|
||||
public class JspConfig {
|
||||
|
||||
private static final String WEB_XML = "/WEB-INF/web.xml";
|
||||
|
||||
// Logger
|
||||
private Log log = LogFactory.getLog(JspConfig.class);
|
||||
|
||||
private Vector jspProperties = null;
|
||||
private ServletContext ctxt;
|
||||
private boolean initialized = false;
|
||||
|
||||
private String defaultIsXml = null; // unspecified
|
||||
private String defaultIsELIgnored = null; // unspecified
|
||||
private String defaultIsScriptingInvalid = null;
|
||||
private String defaultDeferedSyntaxAllowedAsLiteral = null;
|
||||
private String defaultTrimDirectiveWhitespaces = null;
|
||||
private JspProperty defaultJspProperty;
|
||||
|
||||
public JspConfig(ServletContext ctxt) {
|
||||
this.ctxt = ctxt;
|
||||
}
|
||||
|
||||
private double getVersion(TreeNode webApp) {
|
||||
String v = webApp.findAttribute("version");
|
||||
if (v != null) {
|
||||
try {
|
||||
return Double.parseDouble(v);
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
}
|
||||
return 2.3;
|
||||
}
|
||||
|
||||
private void processWebDotXml(ServletContext ctxt) throws JasperException {
|
||||
|
||||
InputStream is = null;
|
||||
|
||||
try {
|
||||
URL uri = ctxt.getResource(WEB_XML);
|
||||
if (uri == null) {
|
||||
// no web.xml
|
||||
return;
|
||||
}
|
||||
|
||||
is = uri.openStream();
|
||||
InputSource ip = new InputSource(is);
|
||||
ip.setSystemId(uri.toExternalForm());
|
||||
|
||||
ParserUtils pu = new ParserUtils();
|
||||
TreeNode webApp = pu.parseXMLDocument(WEB_XML, ip);
|
||||
|
||||
if (webApp == null
|
||||
|| getVersion(webApp) < 2.4) {
|
||||
defaultIsELIgnored = "true";
|
||||
return;
|
||||
}
|
||||
TreeNode jspConfig = webApp.findChild("jsp-config");
|
||||
if (jspConfig == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
jspProperties = new Vector();
|
||||
Iterator jspPropertyList = jspConfig.findChildren("jsp-property-group");
|
||||
while (jspPropertyList.hasNext()) {
|
||||
|
||||
TreeNode element = (TreeNode) jspPropertyList.next();
|
||||
Iterator list = element.findChildren();
|
||||
|
||||
Vector urlPatterns = new Vector();
|
||||
String pageEncoding = null;
|
||||
String scriptingInvalid = null;
|
||||
String elIgnored = null;
|
||||
String isXml = null;
|
||||
Vector includePrelude = new Vector();
|
||||
Vector includeCoda = new Vector();
|
||||
String deferredSyntaxAllowedAsLiteral = null;
|
||||
String trimDirectiveWhitespaces = null;
|
||||
|
||||
while (list.hasNext()) {
|
||||
|
||||
element = (TreeNode) list.next();
|
||||
String tname = element.getName();
|
||||
|
||||
if ("url-pattern".equals(tname))
|
||||
urlPatterns.addElement( element.getBody() );
|
||||
else if ("page-encoding".equals(tname))
|
||||
pageEncoding = element.getBody();
|
||||
else if ("is-xml".equals(tname))
|
||||
isXml = element.getBody();
|
||||
else if ("el-ignored".equals(tname))
|
||||
elIgnored = element.getBody();
|
||||
else if ("scripting-invalid".equals(tname))
|
||||
scriptingInvalid = element.getBody();
|
||||
else if ("include-prelude".equals(tname))
|
||||
includePrelude.addElement(element.getBody());
|
||||
else if ("include-coda".equals(tname))
|
||||
includeCoda.addElement(element.getBody());
|
||||
else if ("deferred-syntax-allowed-as-literal".equals(tname))
|
||||
deferredSyntaxAllowedAsLiteral = element.getBody();
|
||||
else if ("trim-directive-whitespaces".equals(tname))
|
||||
trimDirectiveWhitespaces = element.getBody();
|
||||
}
|
||||
|
||||
if (urlPatterns.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add one JspPropertyGroup for each URL Pattern. This makes
|
||||
// the matching logic easier.
|
||||
for( int p = 0; p < urlPatterns.size(); p++ ) {
|
||||
String urlPattern = (String)urlPatterns.elementAt( p );
|
||||
String path = null;
|
||||
String extension = null;
|
||||
|
||||
if (urlPattern.indexOf('*') < 0) {
|
||||
// Exact match
|
||||
path = urlPattern;
|
||||
} else {
|
||||
int i = urlPattern.lastIndexOf('/');
|
||||
String file;
|
||||
if (i >= 0) {
|
||||
path = urlPattern.substring(0,i+1);
|
||||
file = urlPattern.substring(i+1);
|
||||
} else {
|
||||
file = urlPattern;
|
||||
}
|
||||
|
||||
// pattern must be "*", or of the form "*.jsp"
|
||||
if (file.equals("*")) {
|
||||
extension = "*";
|
||||
} else if (file.startsWith("*.")) {
|
||||
extension = file.substring(file.indexOf('.')+1);
|
||||
}
|
||||
|
||||
// The url patterns are reconstructed as the follwoing:
|
||||
// path != null, extension == null: / or /foo/bar.ext
|
||||
// path == null, extension != null: *.ext
|
||||
// path != null, extension == "*": /foo/*
|
||||
boolean isStar = "*".equals(extension);
|
||||
if ((path == null && (extension == null || isStar))
|
||||
|| (path != null && !isStar)) {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage(
|
||||
"jsp.warning.bad.urlpattern.propertygroup",
|
||||
urlPattern));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
JspProperty property = new JspProperty(isXml,
|
||||
elIgnored,
|
||||
scriptingInvalid,
|
||||
pageEncoding,
|
||||
includePrelude,
|
||||
includeCoda,
|
||||
deferredSyntaxAllowedAsLiteral,
|
||||
trimDirectiveWhitespaces);
|
||||
JspPropertyGroup propertyGroup =
|
||||
new JspPropertyGroup(path, extension, property);
|
||||
|
||||
jspProperties.addElement(propertyGroup);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new JasperException(ex);
|
||||
} finally {
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch (Throwable t) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void init() throws JasperException {
|
||||
|
||||
if (!initialized) {
|
||||
processWebDotXml(ctxt);
|
||||
defaultJspProperty = new JspProperty(defaultIsXml,
|
||||
defaultIsELIgnored,
|
||||
defaultIsScriptingInvalid,
|
||||
null, null, null, defaultDeferedSyntaxAllowedAsLiteral,
|
||||
defaultTrimDirectiveWhitespaces);
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the property group that has more restrictive url-pattern.
|
||||
* In case of tie, select the first.
|
||||
*/
|
||||
private JspPropertyGroup selectProperty(JspPropertyGroup prev,
|
||||
JspPropertyGroup curr) {
|
||||
if (prev == null) {
|
||||
return curr;
|
||||
}
|
||||
if (prev.getExtension() == null) {
|
||||
// exact match
|
||||
return prev;
|
||||
}
|
||||
if (curr.getExtension() == null) {
|
||||
// exact match
|
||||
return curr;
|
||||
}
|
||||
String prevPath = prev.getPath();
|
||||
String currPath = curr.getPath();
|
||||
if (prevPath == null && currPath == null) {
|
||||
// Both specifies a *.ext, keep the first one
|
||||
return prev;
|
||||
}
|
||||
if (prevPath == null && currPath != null) {
|
||||
return curr;
|
||||
}
|
||||
if (prevPath != null && currPath == null) {
|
||||
return prev;
|
||||
}
|
||||
if (prevPath.length() >= currPath.length()) {
|
||||
return prev;
|
||||
}
|
||||
return curr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find a property that best matches the supplied resource.
|
||||
* @param uri the resource supplied.
|
||||
* @return a JspProperty indicating the best match, or some default.
|
||||
*/
|
||||
public JspProperty findJspProperty(String uri) throws JasperException {
|
||||
|
||||
init();
|
||||
|
||||
// JSP Configuration settings do not apply to tag files
|
||||
if (jspProperties == null || uri.endsWith(".tag")
|
||||
|| uri.endsWith(".tagx")) {
|
||||
return defaultJspProperty;
|
||||
}
|
||||
|
||||
String uriPath = null;
|
||||
int index = uri.lastIndexOf('/');
|
||||
if (index >=0 ) {
|
||||
uriPath = uri.substring(0, index+1);
|
||||
}
|
||||
String uriExtension = null;
|
||||
index = uri.lastIndexOf('.');
|
||||
if (index >=0) {
|
||||
uriExtension = uri.substring(index+1);
|
||||
}
|
||||
|
||||
Vector includePreludes = new Vector();
|
||||
Vector includeCodas = new Vector();
|
||||
|
||||
JspPropertyGroup isXmlMatch = null;
|
||||
JspPropertyGroup elIgnoredMatch = null;
|
||||
JspPropertyGroup scriptingInvalidMatch = null;
|
||||
JspPropertyGroup pageEncodingMatch = null;
|
||||
JspPropertyGroup deferedSyntaxAllowedAsLiteralMatch = null;
|
||||
JspPropertyGroup trimDirectiveWhitespacesMatch = null;
|
||||
|
||||
Iterator iter = jspProperties.iterator();
|
||||
while (iter.hasNext()) {
|
||||
|
||||
JspPropertyGroup jpg = (JspPropertyGroup) iter.next();
|
||||
JspProperty jp = jpg.getJspProperty();
|
||||
|
||||
// (arrays will be the same length)
|
||||
String extension = jpg.getExtension();
|
||||
String path = jpg.getPath();
|
||||
|
||||
if (extension == null) {
|
||||
// exact match pattern: /a/foo.jsp
|
||||
if (!uri.equals(path)) {
|
||||
// not matched;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// Matching patterns *.ext or /p/*
|
||||
if (path != null && uriPath != null &&
|
||||
! uriPath.startsWith(path)) {
|
||||
// not matched
|
||||
continue;
|
||||
}
|
||||
if (!extension.equals("*") &&
|
||||
!extension.equals(uriExtension)) {
|
||||
// not matched
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// We have a match
|
||||
// Add include-preludes and include-codas
|
||||
if (jp.getIncludePrelude() != null) {
|
||||
includePreludes.addAll(jp.getIncludePrelude());
|
||||
}
|
||||
if (jp.getIncludeCoda() != null) {
|
||||
includeCodas.addAll(jp.getIncludeCoda());
|
||||
}
|
||||
|
||||
// If there is a previous match for the same property, remember
|
||||
// the one that is more restrictive.
|
||||
if (jp.isXml() != null) {
|
||||
isXmlMatch = selectProperty(isXmlMatch, jpg);
|
||||
}
|
||||
if (jp.isELIgnored() != null) {
|
||||
elIgnoredMatch = selectProperty(elIgnoredMatch, jpg);
|
||||
}
|
||||
if (jp.isScriptingInvalid() != null) {
|
||||
scriptingInvalidMatch =
|
||||
selectProperty(scriptingInvalidMatch, jpg);
|
||||
}
|
||||
if (jp.getPageEncoding() != null) {
|
||||
pageEncodingMatch = selectProperty(pageEncodingMatch, jpg);
|
||||
}
|
||||
if (jp.isDeferedSyntaxAllowedAsLiteral() != null) {
|
||||
deferedSyntaxAllowedAsLiteralMatch =
|
||||
selectProperty(deferedSyntaxAllowedAsLiteralMatch, jpg);
|
||||
}
|
||||
if (jp.isTrimDirectiveWhitespaces() != null) {
|
||||
trimDirectiveWhitespacesMatch =
|
||||
selectProperty(trimDirectiveWhitespacesMatch, jpg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String isXml = defaultIsXml;
|
||||
String isELIgnored = defaultIsELIgnored;
|
||||
String isScriptingInvalid = defaultIsScriptingInvalid;
|
||||
String pageEncoding = null;
|
||||
String isDeferedSyntaxAllowedAsLiteral = defaultDeferedSyntaxAllowedAsLiteral;
|
||||
String isTrimDirectiveWhitespaces = defaultTrimDirectiveWhitespaces;
|
||||
|
||||
if (isXmlMatch != null) {
|
||||
isXml = isXmlMatch.getJspProperty().isXml();
|
||||
}
|
||||
if (elIgnoredMatch != null) {
|
||||
isELIgnored = elIgnoredMatch.getJspProperty().isELIgnored();
|
||||
}
|
||||
if (scriptingInvalidMatch != null) {
|
||||
isScriptingInvalid =
|
||||
scriptingInvalidMatch.getJspProperty().isScriptingInvalid();
|
||||
}
|
||||
if (pageEncodingMatch != null) {
|
||||
pageEncoding = pageEncodingMatch.getJspProperty().getPageEncoding();
|
||||
}
|
||||
if (deferedSyntaxAllowedAsLiteralMatch != null) {
|
||||
isDeferedSyntaxAllowedAsLiteral =
|
||||
deferedSyntaxAllowedAsLiteralMatch.getJspProperty().isDeferedSyntaxAllowedAsLiteral();
|
||||
}
|
||||
if (trimDirectiveWhitespacesMatch != null) {
|
||||
isTrimDirectiveWhitespaces =
|
||||
trimDirectiveWhitespacesMatch.getJspProperty().isTrimDirectiveWhitespaces();
|
||||
}
|
||||
|
||||
return new JspProperty(isXml, isELIgnored, isScriptingInvalid,
|
||||
pageEncoding, includePreludes, includeCodas,
|
||||
isDeferedSyntaxAllowedAsLiteral, isTrimDirectiveWhitespaces);
|
||||
}
|
||||
|
||||
/**
|
||||
* To find out if an uri matches an url pattern in jsp config. If so,
|
||||
* then the uri is a JSP page. This is used primarily for jspc.
|
||||
*/
|
||||
public boolean isJspPage(String uri) throws JasperException {
|
||||
|
||||
init();
|
||||
if (jspProperties == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String uriPath = null;
|
||||
int index = uri.lastIndexOf('/');
|
||||
if (index >=0 ) {
|
||||
uriPath = uri.substring(0, index+1);
|
||||
}
|
||||
String uriExtension = null;
|
||||
index = uri.lastIndexOf('.');
|
||||
if (index >=0) {
|
||||
uriExtension = uri.substring(index+1);
|
||||
}
|
||||
|
||||
Iterator iter = jspProperties.iterator();
|
||||
while (iter.hasNext()) {
|
||||
|
||||
JspPropertyGroup jpg = (JspPropertyGroup) iter.next();
|
||||
JspProperty jp = jpg.getJspProperty();
|
||||
|
||||
String extension = jpg.getExtension();
|
||||
String path = jpg.getPath();
|
||||
|
||||
if (extension == null) {
|
||||
if (uri.equals(path)) {
|
||||
// There is an exact match
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if ((path == null || path.equals(uriPath)) &&
|
||||
(extension.equals("*") || extension.equals(uriExtension))) {
|
||||
// Matches *, *.ext, /p/*, or /p/*.ext
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static class JspPropertyGroup {
|
||||
private String path;
|
||||
private String extension;
|
||||
private JspProperty jspProperty;
|
||||
|
||||
JspPropertyGroup(String path, String extension,
|
||||
JspProperty jspProperty) {
|
||||
this.path = path;
|
||||
this.extension = extension;
|
||||
this.jspProperty = jspProperty;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public String getExtension() {
|
||||
return extension;
|
||||
}
|
||||
|
||||
public JspProperty getJspProperty() {
|
||||
return jspProperty;
|
||||
}
|
||||
}
|
||||
|
||||
static public class JspProperty {
|
||||
|
||||
private String isXml;
|
||||
private String elIgnored;
|
||||
private String scriptingInvalid;
|
||||
private String pageEncoding;
|
||||
private Vector includePrelude;
|
||||
private Vector includeCoda;
|
||||
private String deferedSyntaxAllowedAsLiteral;
|
||||
private String trimDirectiveWhitespaces;
|
||||
|
||||
public JspProperty(String isXml, String elIgnored,
|
||||
String scriptingInvalid, String pageEncoding,
|
||||
Vector includePrelude, Vector includeCoda,
|
||||
String deferedSyntaxAllowedAsLiteral,
|
||||
String trimDirectiveWhitespaces) {
|
||||
|
||||
this.isXml = isXml;
|
||||
this.elIgnored = elIgnored;
|
||||
this.scriptingInvalid = scriptingInvalid;
|
||||
this.pageEncoding = pageEncoding;
|
||||
this.includePrelude = includePrelude;
|
||||
this.includeCoda = includeCoda;
|
||||
this.deferedSyntaxAllowedAsLiteral = deferedSyntaxAllowedAsLiteral;
|
||||
this.trimDirectiveWhitespaces = trimDirectiveWhitespaces;
|
||||
}
|
||||
|
||||
public String isXml() {
|
||||
return isXml;
|
||||
}
|
||||
|
||||
public String isELIgnored() {
|
||||
return elIgnored;
|
||||
}
|
||||
|
||||
public String isScriptingInvalid() {
|
||||
return scriptingInvalid;
|
||||
}
|
||||
|
||||
public String getPageEncoding() {
|
||||
return pageEncoding;
|
||||
}
|
||||
|
||||
public Vector getIncludePrelude() {
|
||||
return includePrelude;
|
||||
}
|
||||
|
||||
public Vector getIncludeCoda() {
|
||||
return includeCoda;
|
||||
}
|
||||
|
||||
public String isDeferedSyntaxAllowedAsLiteral() {
|
||||
return deferedSyntaxAllowedAsLiteral;
|
||||
}
|
||||
|
||||
public String isTrimDirectiveWhitespaces() {
|
||||
return trimDirectiveWhitespaces;
|
||||
}
|
||||
}
|
||||
}
|
||||
-1453
File diff suppressed because it is too large
Load Diff
@@ -1,657 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.io.CharArrayWriter;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
import java.util.jar.JarFile;
|
||||
import java.net.URL;
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
import org.apache.jasper.JasperException;
|
||||
import org.apache.jasper.JspCompilationContext;
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* JspReader is an input buffer for the JSP parser. It should allow
|
||||
* unlimited lookahead and pushback. It also has a bunch of parsing
|
||||
* utility methods for understanding htmlesque thingies.
|
||||
*
|
||||
* @author Anil K. Vijendran
|
||||
* @author Anselm Baird-Smith
|
||||
* @author Harish Prabandham
|
||||
* @author Rajiv Mordani
|
||||
* @author Mandar Raje
|
||||
* @author Danno Ferrin
|
||||
* @author Kin-man Chung
|
||||
* @author Shawn Bayern
|
||||
* @author Mark Roth
|
||||
*/
|
||||
|
||||
class JspReader {
|
||||
|
||||
/**
|
||||
* Logger.
|
||||
*/
|
||||
private Log log = LogFactory.getLog(JspReader.class);
|
||||
|
||||
/**
|
||||
* The current spot in the file.
|
||||
*/
|
||||
private Mark current;
|
||||
|
||||
/**
|
||||
* What is this?
|
||||
*/
|
||||
private String master;
|
||||
|
||||
/**
|
||||
* The list of source files.
|
||||
*/
|
||||
private List sourceFiles;
|
||||
|
||||
/**
|
||||
* The current file ID (-1 indicates an error or no file).
|
||||
*/
|
||||
private int currFileId;
|
||||
|
||||
/**
|
||||
* Seems redundant.
|
||||
*/
|
||||
private int size;
|
||||
|
||||
/**
|
||||
* The compilation context.
|
||||
*/
|
||||
private JspCompilationContext context;
|
||||
|
||||
/**
|
||||
* The Jasper error dispatcher.
|
||||
*/
|
||||
private ErrorDispatcher err;
|
||||
|
||||
/**
|
||||
* Set to true when using the JspReader on a single file where we read up
|
||||
* to the end and reset to the beginning many times.
|
||||
* (as in ParserController.figureOutJspDocument()).
|
||||
*/
|
||||
private boolean singleFile;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ctxt The compilation context
|
||||
* @param fname The file name
|
||||
* @param encoding The file encoding
|
||||
* @param jarFile ?
|
||||
* @param err The error dispatcher
|
||||
* @throws JasperException If a Jasper-internal error occurs
|
||||
* @throws FileNotFoundException If the JSP file is not found (or is unreadable)
|
||||
* @throws IOException If an IO-level error occurs, e.g. reading the file
|
||||
*/
|
||||
public JspReader(JspCompilationContext ctxt,
|
||||
String fname,
|
||||
String encoding,
|
||||
JarFile jarFile,
|
||||
ErrorDispatcher err)
|
||||
throws JasperException, FileNotFoundException, IOException {
|
||||
|
||||
this(ctxt, fname, encoding,
|
||||
JspUtil.getReader(fname, encoding, jarFile, ctxt, err),
|
||||
err);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor: same as above constructor but with initialized reader
|
||||
* to the file given.
|
||||
*/
|
||||
public JspReader(JspCompilationContext ctxt,
|
||||
String fname,
|
||||
String encoding,
|
||||
InputStreamReader reader,
|
||||
ErrorDispatcher err)
|
||||
throws JasperException, FileNotFoundException {
|
||||
|
||||
this.context = ctxt;
|
||||
this.err = err;
|
||||
sourceFiles = new Vector();
|
||||
currFileId = 0;
|
||||
size = 0;
|
||||
singleFile = false;
|
||||
pushFile(fname, encoding, reader);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return JSP compilation context with which this JspReader is
|
||||
* associated
|
||||
*/
|
||||
JspCompilationContext getJspCompilationContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the file at the given position in the list.
|
||||
*
|
||||
* @param fileid The file position in the list
|
||||
* @return The file at that position, if found, null otherwise
|
||||
*/
|
||||
String getFile(final int fileid) {
|
||||
return (String) sourceFiles.get(fileid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current file has more input.
|
||||
*
|
||||
* @return True if more reading is possible
|
||||
* @throws JasperException if an error occurs
|
||||
*/
|
||||
boolean hasMoreInput() throws JasperException {
|
||||
if (current.cursor >= current.stream.length) {
|
||||
if (singleFile) return false;
|
||||
while (popFile()) {
|
||||
if (current.cursor < current.stream.length) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int nextChar() throws JasperException {
|
||||
if (!hasMoreInput())
|
||||
return -1;
|
||||
|
||||
int ch = current.stream[current.cursor];
|
||||
|
||||
current.cursor++;
|
||||
|
||||
if (ch == '\n') {
|
||||
current.line++;
|
||||
current.col = 0;
|
||||
} else {
|
||||
current.col++;
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Back up the current cursor by one char, assumes current.cursor > 0,
|
||||
* and that the char to be pushed back is not '\n'.
|
||||
*/
|
||||
void pushChar() {
|
||||
current.cursor--;
|
||||
current.col--;
|
||||
}
|
||||
|
||||
String getText(Mark start, Mark stop) throws JasperException {
|
||||
Mark oldstart = mark();
|
||||
reset(start);
|
||||
CharArrayWriter caw = new CharArrayWriter();
|
||||
while (!stop.equals(mark()))
|
||||
caw.write(nextChar());
|
||||
caw.close();
|
||||
reset(oldstart);
|
||||
return caw.toString();
|
||||
}
|
||||
|
||||
int peekChar() throws JasperException {
|
||||
if (!hasMoreInput())
|
||||
return -1;
|
||||
return current.stream[current.cursor];
|
||||
}
|
||||
|
||||
Mark mark() {
|
||||
return new Mark(current);
|
||||
}
|
||||
|
||||
void reset(Mark mark) {
|
||||
current = new Mark(mark);
|
||||
}
|
||||
|
||||
boolean matchesIgnoreCase(String string) throws JasperException {
|
||||
Mark mark = mark();
|
||||
int ch = 0;
|
||||
int i = 0;
|
||||
do {
|
||||
ch = nextChar();
|
||||
if (Character.toLowerCase((char) ch) != string.charAt(i++)) {
|
||||
reset(mark);
|
||||
return false;
|
||||
}
|
||||
} while (i < string.length());
|
||||
reset(mark);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* search the stream for a match to a string
|
||||
* @param string The string to match
|
||||
* @return <strong>true</strong> is one is found, the current position
|
||||
* in stream is positioned after the search string, <strong>
|
||||
* false</strong> otherwise, position in stream unchanged.
|
||||
*/
|
||||
boolean matches(String string) throws JasperException {
|
||||
Mark mark = mark();
|
||||
int ch = 0;
|
||||
int i = 0;
|
||||
do {
|
||||
ch = nextChar();
|
||||
if (((char) ch) != string.charAt(i++)) {
|
||||
reset(mark);
|
||||
return false;
|
||||
}
|
||||
} while (i < string.length());
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean matchesETag(String tagName) throws JasperException {
|
||||
Mark mark = mark();
|
||||
|
||||
if (!matches("</" + tagName))
|
||||
return false;
|
||||
skipSpaces();
|
||||
if (nextChar() == '>')
|
||||
return true;
|
||||
|
||||
reset(mark);
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean matchesETagWithoutLessThan(String tagName)
|
||||
throws JasperException
|
||||
{
|
||||
Mark mark = mark();
|
||||
|
||||
if (!matches("/" + tagName))
|
||||
return false;
|
||||
skipSpaces();
|
||||
if (nextChar() == '>')
|
||||
return true;
|
||||
|
||||
reset(mark);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Looks ahead to see if there are optional spaces followed by
|
||||
* the given String. If so, true is returned and those spaces and
|
||||
* characters are skipped. If not, false is returned and the
|
||||
* position is restored to where we were before.
|
||||
*/
|
||||
boolean matchesOptionalSpacesFollowedBy( String s )
|
||||
throws JasperException
|
||||
{
|
||||
Mark mark = mark();
|
||||
|
||||
skipSpaces();
|
||||
boolean result = matches( s );
|
||||
if( !result ) {
|
||||
reset( mark );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int skipSpaces() throws JasperException {
|
||||
int i = 0;
|
||||
while (hasMoreInput() && isSpace()) {
|
||||
i++;
|
||||
nextChar();
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip until the given string is matched in the stream.
|
||||
* When returned, the context is positioned past the end of the match.
|
||||
*
|
||||
* @param s The String to match.
|
||||
* @return A non-null <code>Mark</code> instance (positioned immediately
|
||||
* before the search string) if found, <strong>null</strong>
|
||||
* otherwise.
|
||||
*/
|
||||
Mark skipUntil(String limit) throws JasperException {
|
||||
Mark ret = null;
|
||||
int limlen = limit.length();
|
||||
int ch;
|
||||
|
||||
skip:
|
||||
for (ret = mark(), ch = nextChar() ; ch != -1 ;
|
||||
ret = mark(), ch = nextChar()) {
|
||||
if (ch == limit.charAt(0)) {
|
||||
Mark restart = mark();
|
||||
for (int i = 1 ; i < limlen ; i++) {
|
||||
if (peekChar() == limit.charAt(i))
|
||||
nextChar();
|
||||
else {
|
||||
reset(restart);
|
||||
continue skip;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip until the given string is matched in the stream, but ignoring
|
||||
* chars initially escaped by a '\'.
|
||||
* When returned, the context is positioned past the end of the match.
|
||||
*
|
||||
* @param s The String to match.
|
||||
* @return A non-null <code>Mark</code> instance (positioned immediately
|
||||
* before the search string) if found, <strong>null</strong>
|
||||
* otherwise.
|
||||
*/
|
||||
Mark skipUntilIgnoreEsc(String limit) throws JasperException {
|
||||
Mark ret = null;
|
||||
int limlen = limit.length();
|
||||
int ch;
|
||||
int prev = 'x'; // Doesn't matter
|
||||
|
||||
skip:
|
||||
for (ret = mark(), ch = nextChar() ; ch != -1 ;
|
||||
ret = mark(), prev = ch, ch = nextChar()) {
|
||||
if (ch == '\\' && prev == '\\') {
|
||||
ch = 0; // Double \ is not an escape char anymore
|
||||
}
|
||||
else if (ch == limit.charAt(0) && prev != '\\') {
|
||||
for (int i = 1 ; i < limlen ; i++) {
|
||||
if (peekChar() == limit.charAt(i))
|
||||
nextChar();
|
||||
else
|
||||
continue skip;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip until the given end tag is matched in the stream.
|
||||
* When returned, the context is positioned past the end of the tag.
|
||||
*
|
||||
* @param tag The name of the tag whose ETag (</tag>) to match.
|
||||
* @return A non-null <code>Mark</code> instance (positioned immediately
|
||||
* before the ETag) if found, <strong>null</strong> otherwise.
|
||||
*/
|
||||
Mark skipUntilETag(String tag) throws JasperException {
|
||||
Mark ret = skipUntil("</" + tag);
|
||||
if (ret != null) {
|
||||
skipSpaces();
|
||||
if (nextChar() != '>')
|
||||
ret = null;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
final boolean isSpace() throws JasperException {
|
||||
// Note: If this logic changes, also update Node.TemplateText.rtrim()
|
||||
return peekChar() <= ' ';
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a space delimited token.
|
||||
* If quoted the token will consume all characters up to a matching quote,
|
||||
* otherwise, it consumes up to the first delimiter character.
|
||||
*
|
||||
* @param quoted If <strong>true</strong> accept quoted strings.
|
||||
*/
|
||||
String parseToken(boolean quoted) throws JasperException {
|
||||
StringBuffer stringBuffer = new StringBuffer();
|
||||
skipSpaces();
|
||||
stringBuffer.setLength(0);
|
||||
|
||||
if (!hasMoreInput()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
int ch = peekChar();
|
||||
|
||||
if (quoted) {
|
||||
if (ch == '"' || ch == '\'') {
|
||||
|
||||
char endQuote = ch == '"' ? '"' : '\'';
|
||||
// Consume the open quote:
|
||||
ch = nextChar();
|
||||
for (ch = nextChar(); ch != -1 && ch != endQuote;
|
||||
ch = nextChar()) {
|
||||
if (ch == '\\')
|
||||
ch = nextChar();
|
||||
stringBuffer.append((char) ch);
|
||||
}
|
||||
// Check end of quote, skip closing quote:
|
||||
if (ch == -1) {
|
||||
err.jspError(mark(), "jsp.error.quotes.unterminated");
|
||||
}
|
||||
} else {
|
||||
err.jspError(mark(), "jsp.error.attr.quoted");
|
||||
}
|
||||
} else {
|
||||
if (!isDelimiter()) {
|
||||
// Read value until delimiter is found:
|
||||
do {
|
||||
ch = nextChar();
|
||||
// Take care of the quoting here.
|
||||
if (ch == '\\') {
|
||||
if (peekChar() == '"' || peekChar() == '\'' ||
|
||||
peekChar() == '>' || peekChar() == '%')
|
||||
ch = nextChar();
|
||||
}
|
||||
stringBuffer.append((char) ch);
|
||||
} while (!isDelimiter());
|
||||
}
|
||||
}
|
||||
|
||||
return stringBuffer.toString();
|
||||
}
|
||||
|
||||
void setSingleFile(boolean val) {
|
||||
singleFile = val;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the URL for the given path name.
|
||||
*
|
||||
* @param path Path name
|
||||
*
|
||||
* @return URL for the given path name.
|
||||
*
|
||||
* @exception MalformedURLException if the path name is not given in
|
||||
* the correct form
|
||||
*/
|
||||
URL getResource(String path) throws MalformedURLException {
|
||||
return context.getResource(path);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse utils - Is current character a token delimiter ?
|
||||
* Delimiters are currently defined to be =, >, <, ", and ' or any
|
||||
* any space character as defined by <code>isSpace</code>.
|
||||
*
|
||||
* @return A boolean.
|
||||
*/
|
||||
private boolean isDelimiter() throws JasperException {
|
||||
if (! isSpace()) {
|
||||
int ch = peekChar();
|
||||
// Look for a single-char work delimiter:
|
||||
if (ch == '=' || ch == '>' || ch == '"' || ch == '\''
|
||||
|| ch == '/') {
|
||||
return true;
|
||||
}
|
||||
// Look for an end-of-comment or end-of-tag:
|
||||
if (ch == '-') {
|
||||
Mark mark = mark();
|
||||
if (((ch = nextChar()) == '>')
|
||||
|| ((ch == '-') && (nextChar() == '>'))) {
|
||||
reset(mark);
|
||||
return true;
|
||||
} else {
|
||||
reset(mark);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new source file.
|
||||
* This method is used to implement file inclusion. Each included file
|
||||
* gets a unique identifier (which is the index in the array of source
|
||||
* files).
|
||||
*
|
||||
* @return The index of the now registered file.
|
||||
*/
|
||||
private int registerSourceFile(final String file) {
|
||||
if (sourceFiles.contains(file)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
sourceFiles.add(file);
|
||||
this.size++;
|
||||
|
||||
return sourceFiles.size() - 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unregister the source file.
|
||||
* This method is used to implement file inclusion. Each included file
|
||||
* gets a uniq identifier (which is the index in the array of source
|
||||
* files).
|
||||
*
|
||||
* @return The index of the now registered file.
|
||||
*/
|
||||
private int unregisterSourceFile(final String file) {
|
||||
if (!sourceFiles.contains(file)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
sourceFiles.remove(file);
|
||||
this.size--;
|
||||
return sourceFiles.size() - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Push a file (and its associated Stream) on the file stack. THe
|
||||
* current position in the current file is remembered.
|
||||
*/
|
||||
private void pushFile(String file, String encoding,
|
||||
InputStreamReader reader)
|
||||
throws JasperException, FileNotFoundException {
|
||||
|
||||
// Register the file
|
||||
String longName = file;
|
||||
|
||||
int fileid = registerSourceFile(longName);
|
||||
|
||||
if (fileid == -1) {
|
||||
// Bugzilla 37407: http://issues.apache.org/bugzilla/show_bug.cgi?id=37407
|
||||
if(reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (Exception any) {
|
||||
if(log.isDebugEnabled()) {
|
||||
log.debug("Exception closing reader: ", any);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err.jspError("jsp.error.file.already.registered", file);
|
||||
}
|
||||
|
||||
currFileId = fileid;
|
||||
|
||||
try {
|
||||
CharArrayWriter caw = new CharArrayWriter();
|
||||
char buf[] = new char[1024];
|
||||
for (int i = 0 ; (i = reader.read(buf)) != -1 ;)
|
||||
caw.write(buf, 0, i);
|
||||
caw.close();
|
||||
if (current == null) {
|
||||
current = new Mark(this, caw.toCharArray(), fileid,
|
||||
getFile(fileid), master, encoding);
|
||||
} else {
|
||||
current.pushStream(caw.toCharArray(), fileid, getFile(fileid),
|
||||
longName, encoding);
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
log.error("Exception parsing file ", ex);
|
||||
// Pop state being constructed:
|
||||
popFile();
|
||||
err.jspError("jsp.error.file.cannot.read", file);
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (Exception any) {
|
||||
if(log.isDebugEnabled()) {
|
||||
log.debug("Exception closing reader: ", any);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop a file from the file stack. The field "current" is retored
|
||||
* to the value to point to the previous files, if any, and is set
|
||||
* to null otherwise.
|
||||
* @return true is there is a previous file on the stack.
|
||||
* false otherwise.
|
||||
*/
|
||||
private boolean popFile() throws JasperException {
|
||||
|
||||
// Is stack created ? (will happen if the Jsp file we're looking at is
|
||||
// missing.
|
||||
if (current == null || currFileId < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Restore parser state:
|
||||
String fName = getFile(currFileId);
|
||||
currFileId = unregisterSourceFile(fName);
|
||||
if (currFileId < -1) {
|
||||
err.jspError("jsp.error.file.not.registered", fName);
|
||||
}
|
||||
|
||||
Mark previous = current.popStream();
|
||||
if (previous != null) {
|
||||
master = current.baseDir;
|
||||
current = previous;
|
||||
return true;
|
||||
}
|
||||
// Note that although the current file is undefined here, "current"
|
||||
// is not set to null just for convience, for it maybe used to
|
||||
// set the current (undefined) position.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
-446
@@ -1,446 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FilePermission;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.security.CodeSource;
|
||||
import java.security.PermissionCollection;
|
||||
import java.security.Policy;
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.jsp.JspFactory;
|
||||
|
||||
import org.apache.jasper.Constants;
|
||||
import org.apache.jasper.JspCompilationContext;
|
||||
import org.apache.jasper.Options;
|
||||
import org.apache.jasper.runtime.JspFactoryImpl;
|
||||
import org.apache.jasper.security.SecurityClassLoad;
|
||||
import org.apache.jasper.servlet.JspServletWrapper;
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Class for tracking JSP compile time file dependencies when the
|
||||
* &060;%@include file="..."%&062; directive is used.
|
||||
*
|
||||
* A background thread periodically checks the files a JSP page
|
||||
* is dependent upon. If a dpendent file changes the JSP page
|
||||
* which included it is recompiled.
|
||||
*
|
||||
* Only used if a web application context is a directory.
|
||||
*
|
||||
* @author Glenn L. Nielsen
|
||||
* @version $Revision: 505593 $
|
||||
*/
|
||||
public final class JspRuntimeContext {
|
||||
|
||||
// Logger
|
||||
private Log log = LogFactory.getLog(JspRuntimeContext.class);
|
||||
|
||||
/*
|
||||
* Counts how many times the webapp's JSPs have been reloaded.
|
||||
*/
|
||||
private int jspReloadCount;
|
||||
|
||||
/**
|
||||
* Preload classes required at runtime by a JSP servlet so that
|
||||
* we don't get a defineClassInPackage security exception.
|
||||
*/
|
||||
static {
|
||||
JspFactoryImpl factory = new JspFactoryImpl();
|
||||
SecurityClassLoad.securityClassLoad(factory.getClass().getClassLoader());
|
||||
if( System.getSecurityManager() != null ) {
|
||||
String basePackage = "org.apache.jasper.";
|
||||
try {
|
||||
factory.getClass().getClassLoader().loadClass( basePackage +
|
||||
"runtime.JspFactoryImpl$PrivilegedGetPageContext");
|
||||
factory.getClass().getClassLoader().loadClass( basePackage +
|
||||
"runtime.JspFactoryImpl$PrivilegedReleasePageContext");
|
||||
factory.getClass().getClassLoader().loadClass( basePackage +
|
||||
"runtime.JspRuntimeLibrary");
|
||||
factory.getClass().getClassLoader().loadClass( basePackage +
|
||||
"runtime.JspRuntimeLibrary$PrivilegedIntrospectHelper");
|
||||
factory.getClass().getClassLoader().loadClass( basePackage +
|
||||
"runtime.ServletResponseWrapperInclude");
|
||||
factory.getClass().getClassLoader().loadClass( basePackage +
|
||||
"servlet.JspServletWrapper");
|
||||
} catch (ClassNotFoundException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
JspFactory.setDefaultFactory(factory);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------- Constructors
|
||||
|
||||
/**
|
||||
* Create a JspRuntimeContext for a web application context.
|
||||
*
|
||||
* Loads in any previously generated dependencies from file.
|
||||
*
|
||||
* @param context ServletContext for web application
|
||||
*/
|
||||
public JspRuntimeContext(ServletContext context, Options options) {
|
||||
|
||||
this.context = context;
|
||||
this.options = options;
|
||||
|
||||
// Get the parent class loader
|
||||
parentClassLoader =
|
||||
(URLClassLoader) Thread.currentThread().getContextClassLoader();
|
||||
if (parentClassLoader == null) {
|
||||
parentClassLoader =
|
||||
(URLClassLoader)this.getClass().getClassLoader();
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
if (parentClassLoader != null) {
|
||||
log.debug(Localizer.getMessage("jsp.message.parent_class_loader_is",
|
||||
parentClassLoader.toString()));
|
||||
} else {
|
||||
log.debug(Localizer.getMessage("jsp.message.parent_class_loader_is",
|
||||
"<none>"));
|
||||
}
|
||||
}
|
||||
|
||||
initClassPath();
|
||||
|
||||
if (context instanceof org.apache.jasper.servlet.JspCServletContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Constants.IS_SECURITY_ENABLED) {
|
||||
initSecurity();
|
||||
}
|
||||
|
||||
// If this web application context is running from a
|
||||
// directory, start the background compilation thread
|
||||
String appBase = context.getRealPath("/");
|
||||
if (!options.getDevelopment()
|
||||
&& appBase != null
|
||||
&& options.getCheckInterval() > 0) {
|
||||
lastCheck = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- Instance Variables
|
||||
|
||||
/**
|
||||
* This web applications ServletContext
|
||||
*/
|
||||
private ServletContext context;
|
||||
private Options options;
|
||||
private URLClassLoader parentClassLoader;
|
||||
private PermissionCollection permissionCollection;
|
||||
private CodeSource codeSource;
|
||||
private String classpath;
|
||||
private long lastCheck = -1L;
|
||||
|
||||
/**
|
||||
* Maps JSP pages to their JspServletWrapper's
|
||||
*/
|
||||
private Map<String, JspServletWrapper> jsps = new ConcurrentHashMap<String, JspServletWrapper>();
|
||||
|
||||
|
||||
// ------------------------------------------------------ Public Methods
|
||||
|
||||
/**
|
||||
* Add a new JspServletWrapper.
|
||||
*
|
||||
* @param jspUri JSP URI
|
||||
* @param jsw Servlet wrapper for JSP
|
||||
*/
|
||||
public void addWrapper(String jspUri, JspServletWrapper jsw) {
|
||||
jsps.put(jspUri, jsw);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an already existing JspServletWrapper.
|
||||
*
|
||||
* @param jspUri JSP URI
|
||||
* @return JspServletWrapper for JSP
|
||||
*/
|
||||
public JspServletWrapper getWrapper(String jspUri) {
|
||||
return jsps.get(jspUri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a JspServletWrapper.
|
||||
*
|
||||
* @param jspUri JSP URI of JspServletWrapper to remove
|
||||
*/
|
||||
public void removeWrapper(String jspUri) {
|
||||
jsps.remove(jspUri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of JSPs for which JspServletWrappers exist, i.e.,
|
||||
* the number of JSPs that have been loaded into the webapp.
|
||||
*
|
||||
* @return The number of JSPs that have been loaded into the webapp
|
||||
*/
|
||||
public int getJspCount() {
|
||||
return jsps.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SecurityManager Policy CodeSource for this web
|
||||
* applicaiton context.
|
||||
*
|
||||
* @return CodeSource for JSP
|
||||
*/
|
||||
public CodeSource getCodeSource() {
|
||||
return codeSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parent URLClassLoader.
|
||||
*
|
||||
* @return URLClassLoader parent
|
||||
*/
|
||||
public URLClassLoader getParentClassLoader() {
|
||||
return parentClassLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SecurityManager PermissionCollection for this
|
||||
* web application context.
|
||||
*
|
||||
* @return PermissionCollection permissions
|
||||
*/
|
||||
public PermissionCollection getPermissionCollection() {
|
||||
return permissionCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a "destory" event for this web application context.
|
||||
*/
|
||||
public void destroy() {
|
||||
Iterator servlets = jsps.values().iterator();
|
||||
while (servlets.hasNext()) {
|
||||
((JspServletWrapper) servlets.next()).destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the JSP reload counter.
|
||||
*/
|
||||
public synchronized void incrementJspReloadCount() {
|
||||
jspReloadCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the JSP reload counter.
|
||||
*
|
||||
* @param count Value to which to reset the JSP reload counter
|
||||
*/
|
||||
public synchronized void setJspReloadCount(int count) {
|
||||
this.jspReloadCount = count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current value of the JSP reload counter.
|
||||
*
|
||||
* @return The current value of the JSP reload counter
|
||||
*/
|
||||
public int getJspReloadCount() {
|
||||
return jspReloadCount;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method used by background thread to check the JSP dependencies
|
||||
* registered with this class for JSP's.
|
||||
*/
|
||||
public void checkCompile() {
|
||||
|
||||
if (lastCheck < 0) {
|
||||
// Checking was disabled
|
||||
return;
|
||||
}
|
||||
long now = System.currentTimeMillis();
|
||||
if (now > (lastCheck + (options.getCheckInterval() * 1000L))) {
|
||||
lastCheck = now;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
Object [] wrappers = jsps.values().toArray();
|
||||
for (int i = 0; i < wrappers.length; i++ ) {
|
||||
JspServletWrapper jsw = (JspServletWrapper)wrappers[i];
|
||||
JspCompilationContext ctxt = jsw.getJspEngineContext();
|
||||
// JspServletWrapper also synchronizes on this when
|
||||
// it detects it has to do a reload
|
||||
synchronized(jsw) {
|
||||
try {
|
||||
ctxt.compile();
|
||||
} catch (FileNotFoundException ex) {
|
||||
ctxt.incrementRemoved();
|
||||
} catch (Throwable t) {
|
||||
jsw.getServletContext().log("Background compile failed",
|
||||
t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The classpath that is passed off to the Java compiler.
|
||||
*/
|
||||
public String getClassPath() {
|
||||
return classpath;
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------- Private Methods
|
||||
|
||||
|
||||
/**
|
||||
* Method used to initialize classpath for compiles.
|
||||
*/
|
||||
private void initClassPath() {
|
||||
|
||||
URL [] urls = parentClassLoader.getURLs();
|
||||
StringBuffer cpath = new StringBuffer();
|
||||
String sep = System.getProperty("path.separator");
|
||||
|
||||
for(int i = 0; i < urls.length; i++) {
|
||||
// Tomcat 4 can use URL's other than file URL's,
|
||||
// a protocol other than file: will generate a
|
||||
// bad file system path, so only add file:
|
||||
// protocol URL's to the classpath.
|
||||
|
||||
if( urls[i].getProtocol().equals("file") ) {
|
||||
cpath.append((String)urls[i].getFile()+sep);
|
||||
}
|
||||
}
|
||||
|
||||
cpath.append(options.getScratchDir() + sep);
|
||||
|
||||
String cp = (String) context.getAttribute(Constants.SERVLET_CLASSPATH);
|
||||
if (cp == null || cp.equals("")) {
|
||||
cp = options.getClassPath();
|
||||
}
|
||||
|
||||
classpath = cpath.toString() + cp;
|
||||
|
||||
if(log.isDebugEnabled()) {
|
||||
log.debug("Compilation classpath initialized: " + getClassPath());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to initialize SecurityManager data.
|
||||
*/
|
||||
private void initSecurity() {
|
||||
|
||||
// Setup the PermissionCollection for this web app context
|
||||
// based on the permissions configured for the root of the
|
||||
// web app context directory, then add a file read permission
|
||||
// for that directory.
|
||||
Policy policy = Policy.getPolicy();
|
||||
if( policy != null ) {
|
||||
try {
|
||||
// Get the permissions for the web app context
|
||||
String docBase = context.getRealPath("/");
|
||||
if( docBase == null ) {
|
||||
docBase = options.getScratchDir().toString();
|
||||
}
|
||||
String codeBase = docBase;
|
||||
if (!codeBase.endsWith(File.separator)){
|
||||
codeBase = codeBase + File.separator;
|
||||
}
|
||||
File contextDir = new File(codeBase);
|
||||
URL url = contextDir.getCanonicalFile().toURL();
|
||||
codeSource = new CodeSource(url,(Certificate[])null);
|
||||
permissionCollection = policy.getPermissions(codeSource);
|
||||
|
||||
// Create a file read permission for web app context directory
|
||||
if (!docBase.endsWith(File.separator)){
|
||||
permissionCollection.add
|
||||
(new FilePermission(docBase,"read"));
|
||||
docBase = docBase + File.separator;
|
||||
} else {
|
||||
permissionCollection.add
|
||||
(new FilePermission
|
||||
(docBase.substring(0,docBase.length() - 1),"read"));
|
||||
}
|
||||
docBase = docBase + "-";
|
||||
permissionCollection.add(new FilePermission(docBase,"read"));
|
||||
|
||||
// Create a file read permission for web app tempdir (work)
|
||||
// directory
|
||||
String workDir = options.getScratchDir().toString();
|
||||
if (!workDir.endsWith(File.separator)){
|
||||
permissionCollection.add
|
||||
(new FilePermission(workDir,"read"));
|
||||
workDir = workDir + File.separator;
|
||||
}
|
||||
workDir = workDir + "-";
|
||||
permissionCollection.add(new FilePermission(workDir,"read"));
|
||||
|
||||
// Allow the JSP to access org.apache.jasper.runtime.HttpJspBase
|
||||
permissionCollection.add( new RuntimePermission(
|
||||
"accessClassInPackage.org.apache.jasper.runtime") );
|
||||
|
||||
if (parentClassLoader instanceof URLClassLoader) {
|
||||
URL [] urls = parentClassLoader.getURLs();
|
||||
String jarUrl = null;
|
||||
String jndiUrl = null;
|
||||
for (int i=0; i<urls.length; i++) {
|
||||
if (jndiUrl == null
|
||||
&& urls[i].toString().startsWith("jndi:") ) {
|
||||
jndiUrl = urls[i].toString() + "-";
|
||||
}
|
||||
if (jarUrl == null
|
||||
&& urls[i].toString().startsWith("jar:jndi:")
|
||||
) {
|
||||
jarUrl = urls[i].toString();
|
||||
jarUrl = jarUrl.substring(0,jarUrl.length() - 2);
|
||||
jarUrl = jarUrl.substring(0,
|
||||
jarUrl.lastIndexOf('/')) + "/-";
|
||||
}
|
||||
}
|
||||
if (jarUrl != null) {
|
||||
permissionCollection.add(
|
||||
new FilePermission(jarUrl,"read"));
|
||||
permissionCollection.add(
|
||||
new FilePermission(jarUrl.substring(4),"read"));
|
||||
}
|
||||
if (jndiUrl != null)
|
||||
permissionCollection.add(
|
||||
new FilePermission(jndiUrl,"read") );
|
||||
}
|
||||
} catch(Exception e) {
|
||||
context.log("Security Init for context failed",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,160 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* Class responsible for converting error codes to corresponding localized
|
||||
* error messages.
|
||||
*
|
||||
* @author Jan Luehe
|
||||
*/
|
||||
public class Localizer {
|
||||
|
||||
private static ResourceBundle bundle = null;
|
||||
|
||||
static {
|
||||
try {
|
||||
bundle = ResourceBundle.getBundle(
|
||||
"org.apache.jasper.resources.LocalStrings");
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the localized error message corresponding to the given error
|
||||
* code.
|
||||
*
|
||||
* If the given error code is not defined in the resource bundle for
|
||||
* localized error messages, it is used as the error message.
|
||||
*
|
||||
* @param errCode Error code to localize
|
||||
*
|
||||
* @return Localized error message
|
||||
*/
|
||||
public static String getMessage(String errCode) {
|
||||
String errMsg = errCode;
|
||||
try {
|
||||
errMsg = bundle.getString(errCode);
|
||||
} catch (MissingResourceException e) {
|
||||
}
|
||||
return errMsg;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the localized error message corresponding to the given error
|
||||
* code.
|
||||
*
|
||||
* If the given error code is not defined in the resource bundle for
|
||||
* localized error messages, it is used as the error message.
|
||||
*
|
||||
* @param errCode Error code to localize
|
||||
* @param arg Argument for parametric replacement
|
||||
*
|
||||
* @return Localized error message
|
||||
*/
|
||||
public static String getMessage(String errCode, String arg) {
|
||||
return getMessage(errCode, new Object[] {arg});
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the localized error message corresponding to the given error
|
||||
* code.
|
||||
*
|
||||
* If the given error code is not defined in the resource bundle for
|
||||
* localized error messages, it is used as the error message.
|
||||
*
|
||||
* @param errCode Error code to localize
|
||||
* @param arg1 First argument for parametric replacement
|
||||
* @param arg2 Second argument for parametric replacement
|
||||
*
|
||||
* @return Localized error message
|
||||
*/
|
||||
public static String getMessage(String errCode, String arg1, String arg2) {
|
||||
return getMessage(errCode, new Object[] {arg1, arg2});
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the localized error message corresponding to the given error
|
||||
* code.
|
||||
*
|
||||
* If the given error code is not defined in the resource bundle for
|
||||
* localized error messages, it is used as the error message.
|
||||
*
|
||||
* @param errCode Error code to localize
|
||||
* @param arg1 First argument for parametric replacement
|
||||
* @param arg2 Second argument for parametric replacement
|
||||
* @param arg3 Third argument for parametric replacement
|
||||
*
|
||||
* @return Localized error message
|
||||
*/
|
||||
public static String getMessage(String errCode, String arg1, String arg2,
|
||||
String arg3) {
|
||||
return getMessage(errCode, new Object[] {arg1, arg2, arg3});
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the localized error message corresponding to the given error
|
||||
* code.
|
||||
*
|
||||
* If the given error code is not defined in the resource bundle for
|
||||
* localized error messages, it is used as the error message.
|
||||
*
|
||||
* @param errCode Error code to localize
|
||||
* @param arg1 First argument for parametric replacement
|
||||
* @param arg2 Second argument for parametric replacement
|
||||
* @param arg3 Third argument for parametric replacement
|
||||
* @param arg4 Fourth argument for parametric replacement
|
||||
*
|
||||
* @return Localized error message
|
||||
*/
|
||||
public static String getMessage(String errCode, String arg1, String arg2,
|
||||
String arg3, String arg4) {
|
||||
return getMessage(errCode, new Object[] {arg1, arg2, arg3, arg4});
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the localized error message corresponding to the given error
|
||||
* code.
|
||||
*
|
||||
* If the given error code is not defined in the resource bundle for
|
||||
* localized error messages, it is used as the error message.
|
||||
*
|
||||
* @param errCode Error code to localize
|
||||
* @param args Arguments for parametric replacement
|
||||
*
|
||||
* @return Localized error message
|
||||
*/
|
||||
public static String getMessage(String errCode, Object[] args) {
|
||||
String errMsg = errCode;
|
||||
try {
|
||||
errMsg = bundle.getString(errCode);
|
||||
if (args != null) {
|
||||
MessageFormat formatter = new MessageFormat(errMsg);
|
||||
errMsg = formatter.format(args);
|
||||
}
|
||||
} catch (MissingResourceException e) {
|
||||
}
|
||||
|
||||
return errMsg;
|
||||
}
|
||||
}
|
||||
@@ -1,282 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.util.Stack;
|
||||
import java.net.URL;
|
||||
import java.net.MalformedURLException;
|
||||
import org.apache.jasper.JspCompilationContext;
|
||||
|
||||
/**
|
||||
* Mark represents a point in the JSP input.
|
||||
*
|
||||
* @author Anil K. Vijendran
|
||||
*/
|
||||
final class Mark {
|
||||
|
||||
// position within current stream
|
||||
int cursor, line, col;
|
||||
|
||||
// directory of file for current stream
|
||||
String baseDir;
|
||||
|
||||
// current stream
|
||||
char[] stream = null;
|
||||
|
||||
// fileid of current stream
|
||||
private int fileId;
|
||||
|
||||
// name of the current file
|
||||
private String fileName;
|
||||
|
||||
/*
|
||||
* stack of stream and stream state of streams that have included
|
||||
* current stream
|
||||
*/
|
||||
private Stack includeStack = null;
|
||||
|
||||
// encoding of current file
|
||||
private String encoding = null;
|
||||
|
||||
// reader that owns this mark (so we can look up fileid's)
|
||||
private JspReader reader;
|
||||
|
||||
private JspCompilationContext ctxt;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param reader JspReader this mark belongs to
|
||||
* @param inStream current stream for this mark
|
||||
* @param fileId id of requested jsp file
|
||||
* @param name JSP file name
|
||||
* @param inBaseDir base directory of requested jsp file
|
||||
* @param inEncoding encoding of current file
|
||||
*/
|
||||
Mark(JspReader reader, char[] inStream, int fileId, String name,
|
||||
String inBaseDir, String inEncoding) {
|
||||
|
||||
this.reader = reader;
|
||||
this.ctxt = reader.getJspCompilationContext();
|
||||
this.stream = inStream;
|
||||
this.cursor = 0;
|
||||
this.line = 1;
|
||||
this.col = 1;
|
||||
this.fileId = fileId;
|
||||
this.fileName = name;
|
||||
this.baseDir = inBaseDir;
|
||||
this.encoding = inEncoding;
|
||||
this.includeStack = new Stack();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Mark(Mark other) {
|
||||
|
||||
this.reader = other.reader;
|
||||
this.ctxt = other.reader.getJspCompilationContext();
|
||||
this.stream = other.stream;
|
||||
this.fileId = other.fileId;
|
||||
this.fileName = other.fileName;
|
||||
this.cursor = other.cursor;
|
||||
this.line = other.line;
|
||||
this.col = other.col;
|
||||
this.baseDir = other.baseDir;
|
||||
this.encoding = other.encoding;
|
||||
|
||||
// clone includeStack without cloning contents
|
||||
includeStack = new Stack();
|
||||
for ( int i=0; i < other.includeStack.size(); i++ ) {
|
||||
includeStack.addElement( other.includeStack.elementAt(i) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Mark(JspCompilationContext ctxt, String filename, int line, int col) {
|
||||
|
||||
this.reader = null;
|
||||
this.ctxt = ctxt;
|
||||
this.stream = null;
|
||||
this.cursor = 0;
|
||||
this.line = line;
|
||||
this.col = col;
|
||||
this.fileId = -1;
|
||||
this.fileName = filename;
|
||||
this.baseDir = "le-basedir";
|
||||
this.encoding = "le-endocing";
|
||||
this.includeStack = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets this mark's state to a new stream.
|
||||
* It will store the current stream in it's includeStack.
|
||||
*
|
||||
* @param inStream new stream for mark
|
||||
* @param inFileId id of new file from which stream comes from
|
||||
* @param inBaseDir directory of file
|
||||
* @param inEncoding encoding of new file
|
||||
*/
|
||||
public void pushStream(char[] inStream, int inFileId, String name,
|
||||
String inBaseDir, String inEncoding)
|
||||
{
|
||||
// store current state in stack
|
||||
includeStack.push(new IncludeState(cursor, line, col, fileId,
|
||||
fileName, baseDir,
|
||||
encoding, stream) );
|
||||
|
||||
// set new variables
|
||||
cursor = 0;
|
||||
line = 1;
|
||||
col = 1;
|
||||
fileId = inFileId;
|
||||
fileName = name;
|
||||
baseDir = inBaseDir;
|
||||
encoding = inEncoding;
|
||||
stream = inStream;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Restores this mark's state to a previously stored stream.
|
||||
* @return The previous Mark instance when the stream was pushed, or null
|
||||
* if there is no previous stream
|
||||
*/
|
||||
public Mark popStream() {
|
||||
// make sure we have something to pop
|
||||
if ( includeStack.size() <= 0 ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// get previous state in stack
|
||||
IncludeState state = (IncludeState) includeStack.pop( );
|
||||
|
||||
// set new variables
|
||||
cursor = state.cursor;
|
||||
line = state.line;
|
||||
col = state.col;
|
||||
fileId = state.fileId;
|
||||
fileName = state.fileName;
|
||||
baseDir = state.baseDir;
|
||||
stream = state.stream;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
// -------------------- Locator interface --------------------
|
||||
|
||||
public int getLineNumber() {
|
||||
return line;
|
||||
}
|
||||
|
||||
public int getColumnNumber() {
|
||||
return col;
|
||||
}
|
||||
|
||||
public String getSystemId() {
|
||||
return getFile();
|
||||
}
|
||||
|
||||
public String getPublicId() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getFile()+"("+line+","+col+")";
|
||||
}
|
||||
|
||||
public String getFile() {
|
||||
return this.fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the URL of the resource with which this Mark is associated
|
||||
*
|
||||
* @return URL of the resource with which this Mark is associated
|
||||
*
|
||||
* @exception MalformedURLException if the resource pathname is incorrect
|
||||
*/
|
||||
public URL getURL() throws MalformedURLException {
|
||||
return ctxt.getResource(getFile());
|
||||
}
|
||||
|
||||
public String toShortString() {
|
||||
return "("+line+","+col+")";
|
||||
}
|
||||
|
||||
public boolean equals(Object other) {
|
||||
if (other instanceof Mark) {
|
||||
Mark m = (Mark) other;
|
||||
return this.reader == m.reader && this.fileId == m.fileId
|
||||
&& this.cursor == m.cursor && this.line == m.line
|
||||
&& this.col == m.col;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this Mark is greather than the <code>other</code>
|
||||
* Mark, false otherwise.
|
||||
*/
|
||||
public boolean isGreater(Mark other) {
|
||||
|
||||
boolean greater = false;
|
||||
|
||||
if (this.line > other.line) {
|
||||
greater = true;
|
||||
} else if (this.line == other.line && this.col > other.col) {
|
||||
greater = true;
|
||||
}
|
||||
|
||||
return greater;
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep track of parser before parsing an included file.
|
||||
* This class keeps track of the parser before we switch to parsing an
|
||||
* included file. In other words, it's the parser's continuation to be
|
||||
* reinstalled after the included file parsing is done.
|
||||
*/
|
||||
class IncludeState {
|
||||
int cursor, line, col;
|
||||
int fileId;
|
||||
String fileName;
|
||||
String baseDir;
|
||||
String encoding;
|
||||
char[] stream = null;
|
||||
|
||||
IncludeState(int inCursor, int inLine, int inCol, int inFileId,
|
||||
String name, String inBaseDir, String inEncoding,
|
||||
char[] inStream) {
|
||||
cursor = inCursor;
|
||||
line = inLine;
|
||||
col = inCol;
|
||||
fileId = inFileId;
|
||||
fileName = name;
|
||||
baseDir = inBaseDir;
|
||||
encoding = inEncoding;
|
||||
stream = inStream;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
-711
@@ -1,711 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.CharArrayWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ListIterator;
|
||||
import javax.servlet.jsp.tagext.PageData;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.helpers.AttributesImpl;
|
||||
import org.apache.jasper.JasperException;
|
||||
|
||||
/**
|
||||
* An implementation of <tt>javax.servlet.jsp.tagext.PageData</tt> which
|
||||
* builds the XML view of a given page.
|
||||
*
|
||||
* The XML view is built in two passes:
|
||||
*
|
||||
* During the first pass, the FirstPassVisitor collects the attributes of the
|
||||
* top-level jsp:root and those of the jsp:root elements of any included
|
||||
* pages, and adds them to the jsp:root element of the XML view.
|
||||
* In addition, any taglib directives are converted into xmlns: attributes and
|
||||
* added to the jsp:root element of the XML view.
|
||||
* This pass ignores any nodes other than JspRoot and TaglibDirective.
|
||||
*
|
||||
* During the second pass, the SecondPassVisitor produces the XML view, using
|
||||
* the combined jsp:root attributes determined in the first pass and any
|
||||
* remaining pages nodes (this pass ignores any JspRoot and TaglibDirective
|
||||
* nodes).
|
||||
*
|
||||
* @author Jan Luehe
|
||||
*/
|
||||
class PageDataImpl extends PageData implements TagConstants {
|
||||
|
||||
private static final String JSP_VERSION = "2.0";
|
||||
private static final String CDATA_START_SECTION = "<![CDATA[\n";
|
||||
private static final String CDATA_END_SECTION = "]]>\n";
|
||||
|
||||
// string buffer used to build XML view
|
||||
private StringBuffer buf;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param page the page nodes from which to generate the XML view
|
||||
*/
|
||||
public PageDataImpl(Node.Nodes page, Compiler compiler)
|
||||
throws JasperException {
|
||||
|
||||
// First pass
|
||||
FirstPassVisitor firstPass = new FirstPassVisitor(page.getRoot(),
|
||||
compiler.getPageInfo());
|
||||
page.visit(firstPass);
|
||||
|
||||
// Second pass
|
||||
buf = new StringBuffer();
|
||||
SecondPassVisitor secondPass
|
||||
= new SecondPassVisitor(page.getRoot(), buf, compiler,
|
||||
firstPass.getJspIdPrefix());
|
||||
page.visit(secondPass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the input stream of the XML view.
|
||||
*
|
||||
* @return the input stream of the XML view
|
||||
*/
|
||||
public InputStream getInputStream() {
|
||||
// Turn StringBuffer into InputStream
|
||||
try {
|
||||
return new ByteArrayInputStream(buf.toString().getBytes("UTF-8"));
|
||||
} catch (UnsupportedEncodingException uee) {
|
||||
// should never happen
|
||||
throw new RuntimeException(uee.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* First-pass Visitor for JspRoot nodes (representing jsp:root elements)
|
||||
* and TablibDirective nodes, ignoring any other nodes.
|
||||
*
|
||||
* The purpose of this Visitor is to collect the attributes of the
|
||||
* top-level jsp:root and those of the jsp:root elements of any included
|
||||
* pages, and add them to the jsp:root element of the XML view.
|
||||
* In addition, this Visitor converts any taglib directives into xmlns:
|
||||
* attributes and adds them to the jsp:root element of the XML view.
|
||||
*/
|
||||
static class FirstPassVisitor
|
||||
extends Node.Visitor implements TagConstants {
|
||||
|
||||
private Node.Root root;
|
||||
private AttributesImpl rootAttrs;
|
||||
private PageInfo pageInfo;
|
||||
|
||||
// Prefix for the 'id' attribute
|
||||
private String jspIdPrefix;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public FirstPassVisitor(Node.Root root, PageInfo pageInfo) {
|
||||
this.root = root;
|
||||
this.pageInfo = pageInfo;
|
||||
this.rootAttrs = new AttributesImpl();
|
||||
this.rootAttrs.addAttribute("", "", "version", "CDATA",
|
||||
JSP_VERSION);
|
||||
this.jspIdPrefix = "jsp";
|
||||
}
|
||||
|
||||
public void visit(Node.Root n) throws JasperException {
|
||||
visitBody(n);
|
||||
if (n == root) {
|
||||
/*
|
||||
* Top-level page.
|
||||
*
|
||||
* Add
|
||||
* xmlns:jsp="http://java.sun.com/JSP/Page"
|
||||
* attribute only if not already present.
|
||||
*/
|
||||
if (!JSP_URI.equals(rootAttrs.getValue("xmlns:jsp"))) {
|
||||
rootAttrs.addAttribute("", "", "xmlns:jsp", "CDATA",
|
||||
JSP_URI);
|
||||
}
|
||||
|
||||
if (pageInfo.isJspPrefixHijacked()) {
|
||||
/*
|
||||
* 'jsp' prefix has been hijacked, that is, bound to a
|
||||
* namespace other than the JSP namespace. This means that
|
||||
* when adding an 'id' attribute to each element, we can't
|
||||
* use the 'jsp' prefix. Therefore, create a new prefix
|
||||
* (one that is unique across the translation unit) for use
|
||||
* by the 'id' attribute, and bind it to the JSP namespace
|
||||
*/
|
||||
jspIdPrefix += "jsp";
|
||||
while (pageInfo.containsPrefix(jspIdPrefix)) {
|
||||
jspIdPrefix += "jsp";
|
||||
}
|
||||
rootAttrs.addAttribute("", "", "xmlns:" + jspIdPrefix,
|
||||
"CDATA", JSP_URI);
|
||||
}
|
||||
|
||||
root.setAttributes(rootAttrs);
|
||||
}
|
||||
}
|
||||
|
||||
public void visit(Node.JspRoot n) throws JasperException {
|
||||
addAttributes(n.getTaglibAttributes());
|
||||
addAttributes(n.getNonTaglibXmlnsAttributes());
|
||||
addAttributes(n.getAttributes());
|
||||
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts taglib directive into "xmlns:..." attribute of jsp:root
|
||||
* element.
|
||||
*/
|
||||
public void visit(Node.TaglibDirective n) throws JasperException {
|
||||
Attributes attrs = n.getAttributes();
|
||||
if (attrs != null) {
|
||||
String qName = "xmlns:" + attrs.getValue("prefix");
|
||||
/*
|
||||
* According to javadocs of org.xml.sax.helpers.AttributesImpl,
|
||||
* the addAttribute method does not check to see if the
|
||||
* specified attribute is already contained in the list: This
|
||||
* is the application's responsibility!
|
||||
*/
|
||||
if (rootAttrs.getIndex(qName) == -1) {
|
||||
String location = attrs.getValue("uri");
|
||||
if (location != null) {
|
||||
if (location.startsWith("/")) {
|
||||
location = URN_JSPTLD + location;
|
||||
}
|
||||
rootAttrs.addAttribute("", "", qName, "CDATA",
|
||||
location);
|
||||
} else {
|
||||
location = attrs.getValue("tagdir");
|
||||
rootAttrs.addAttribute("", "", qName, "CDATA",
|
||||
URN_JSPTAGDIR + location);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getJspIdPrefix() {
|
||||
return jspIdPrefix;
|
||||
}
|
||||
|
||||
private void addAttributes(Attributes attrs) {
|
||||
if (attrs != null) {
|
||||
int len = attrs.getLength();
|
||||
|
||||
for (int i=0; i<len; i++) {
|
||||
String qName = attrs.getQName(i);
|
||||
if ("version".equals(qName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Bugzilla 35252: http://issues.apache.org/bugzilla/show_bug.cgi?id=35252
|
||||
if(rootAttrs.getIndex(qName) == -1) {
|
||||
rootAttrs.addAttribute(attrs.getURI(i),
|
||||
attrs.getLocalName(i),
|
||||
qName,
|
||||
attrs.getType(i),
|
||||
attrs.getValue(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Second-pass Visitor responsible for producing XML view and assigning
|
||||
* each element a unique jsp:id attribute.
|
||||
*/
|
||||
static class SecondPassVisitor extends Node.Visitor
|
||||
implements TagConstants {
|
||||
|
||||
private Node.Root root;
|
||||
private StringBuffer buf;
|
||||
private Compiler compiler;
|
||||
private String jspIdPrefix;
|
||||
private boolean resetDefaultNS = false;
|
||||
|
||||
// Current value of jsp:id attribute
|
||||
private int jspId;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public SecondPassVisitor(Node.Root root, StringBuffer buf,
|
||||
Compiler compiler, String jspIdPrefix) {
|
||||
this.root = root;
|
||||
this.buf = buf;
|
||||
this.compiler = compiler;
|
||||
this.jspIdPrefix = jspIdPrefix;
|
||||
}
|
||||
|
||||
/*
|
||||
* Visits root node.
|
||||
*/
|
||||
public void visit(Node.Root n) throws JasperException {
|
||||
if (n == this.root) {
|
||||
// top-level page
|
||||
appendXmlProlog();
|
||||
appendTag(n);
|
||||
} else {
|
||||
boolean resetDefaultNSSave = resetDefaultNS;
|
||||
if (n.isXmlSyntax()) {
|
||||
resetDefaultNS = true;
|
||||
}
|
||||
visitBody(n);
|
||||
resetDefaultNS = resetDefaultNSSave;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Visits jsp:root element of JSP page in XML syntax.
|
||||
*
|
||||
* Any nested jsp:root elements (from pages included via an
|
||||
* include directive) are ignored.
|
||||
*/
|
||||
public void visit(Node.JspRoot n) throws JasperException {
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.PageDirective n) throws JasperException {
|
||||
appendPageDirective(n);
|
||||
}
|
||||
|
||||
public void visit(Node.IncludeDirective n) throws JasperException {
|
||||
// expand in place
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.Comment n) throws JasperException {
|
||||
// Comments are ignored in XML view
|
||||
}
|
||||
|
||||
public void visit(Node.Declaration n) throws JasperException {
|
||||
appendTag(n);
|
||||
}
|
||||
|
||||
public void visit(Node.Expression n) throws JasperException {
|
||||
appendTag(n);
|
||||
}
|
||||
|
||||
public void visit(Node.Scriptlet n) throws JasperException {
|
||||
appendTag(n);
|
||||
}
|
||||
|
||||
public void visit(Node.JspElement n) throws JasperException {
|
||||
appendTag(n);
|
||||
}
|
||||
|
||||
public void visit(Node.ELExpression n) throws JasperException {
|
||||
if (!n.getRoot().isXmlSyntax()) {
|
||||
buf.append("<").append(JSP_TEXT_ACTION);
|
||||
buf.append(" ");
|
||||
buf.append(jspIdPrefix);
|
||||
buf.append(":id=\"");
|
||||
buf.append(jspId++).append("\">");
|
||||
}
|
||||
buf.append("${");
|
||||
buf.append(JspUtil.escapeXml(n.getText()));
|
||||
buf.append("}");
|
||||
if (!n.getRoot().isXmlSyntax()) {
|
||||
buf.append(JSP_TEXT_ACTION_END);
|
||||
}
|
||||
buf.append("\n");
|
||||
}
|
||||
|
||||
public void visit(Node.IncludeAction n) throws JasperException {
|
||||
appendTag(n);
|
||||
}
|
||||
|
||||
public void visit(Node.ForwardAction n) throws JasperException {
|
||||
appendTag(n);
|
||||
}
|
||||
|
||||
public void visit(Node.GetProperty n) throws JasperException {
|
||||
appendTag(n);
|
||||
}
|
||||
|
||||
public void visit(Node.SetProperty n) throws JasperException {
|
||||
appendTag(n);
|
||||
}
|
||||
|
||||
public void visit(Node.ParamAction n) throws JasperException {
|
||||
appendTag(n);
|
||||
}
|
||||
|
||||
public void visit(Node.ParamsAction n) throws JasperException {
|
||||
appendTag(n);
|
||||
}
|
||||
|
||||
public void visit(Node.FallBackAction n) throws JasperException {
|
||||
appendTag(n);
|
||||
}
|
||||
|
||||
public void visit(Node.UseBean n) throws JasperException {
|
||||
appendTag(n);
|
||||
}
|
||||
|
||||
public void visit(Node.PlugIn n) throws JasperException {
|
||||
appendTag(n);
|
||||
}
|
||||
|
||||
public void visit(Node.NamedAttribute n) throws JasperException {
|
||||
appendTag(n);
|
||||
}
|
||||
|
||||
public void visit(Node.JspBody n) throws JasperException {
|
||||
appendTag(n);
|
||||
}
|
||||
|
||||
public void visit(Node.CustomTag n) throws JasperException {
|
||||
boolean resetDefaultNSSave = resetDefaultNS;
|
||||
appendTag(n, resetDefaultNS);
|
||||
resetDefaultNS = resetDefaultNSSave;
|
||||
}
|
||||
|
||||
public void visit(Node.UninterpretedTag n) throws JasperException {
|
||||
boolean resetDefaultNSSave = resetDefaultNS;
|
||||
appendTag(n, resetDefaultNS);
|
||||
resetDefaultNS = resetDefaultNSSave;
|
||||
}
|
||||
|
||||
public void visit(Node.JspText n) throws JasperException {
|
||||
appendTag(n);
|
||||
}
|
||||
|
||||
public void visit(Node.DoBodyAction n) throws JasperException {
|
||||
appendTag(n);
|
||||
}
|
||||
|
||||
public void visit(Node.InvokeAction n) throws JasperException {
|
||||
appendTag(n);
|
||||
}
|
||||
|
||||
public void visit(Node.TagDirective n) throws JasperException {
|
||||
appendTagDirective(n);
|
||||
}
|
||||
|
||||
public void visit(Node.AttributeDirective n) throws JasperException {
|
||||
appendTag(n);
|
||||
}
|
||||
|
||||
public void visit(Node.VariableDirective n) throws JasperException {
|
||||
appendTag(n);
|
||||
}
|
||||
|
||||
public void visit(Node.TemplateText n) throws JasperException {
|
||||
/*
|
||||
* If the template text came from a JSP page written in JSP syntax,
|
||||
* create a jsp:text element for it (JSP 5.3.2).
|
||||
*/
|
||||
appendText(n.getText(), !n.getRoot().isXmlSyntax());
|
||||
}
|
||||
|
||||
/*
|
||||
* Appends the given tag, including its body, to the XML view.
|
||||
*/
|
||||
private void appendTag(Node n) throws JasperException {
|
||||
appendTag(n, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Appends the given tag, including its body, to the XML view,
|
||||
* and optionally reset default namespace to "", if none specified.
|
||||
*/
|
||||
private void appendTag(Node n, boolean addDefaultNS)
|
||||
throws JasperException {
|
||||
|
||||
Node.Nodes body = n.getBody();
|
||||
String text = n.getText();
|
||||
|
||||
buf.append("<").append(n.getQName());
|
||||
buf.append("\n");
|
||||
|
||||
printAttributes(n, addDefaultNS);
|
||||
buf.append(" ").append(jspIdPrefix).append(":id").append("=\"");
|
||||
buf.append(jspId++).append("\"\n");
|
||||
|
||||
if (ROOT_ACTION.equals(n.getLocalName()) || body != null
|
||||
|| text != null) {
|
||||
buf.append(">\n");
|
||||
if (ROOT_ACTION.equals(n.getLocalName())) {
|
||||
if (compiler.getCompilationContext().isTagFile()) {
|
||||
appendTagDirective();
|
||||
} else {
|
||||
appendPageDirective();
|
||||
}
|
||||
}
|
||||
if (body != null) {
|
||||
body.visit(this);
|
||||
} else {
|
||||
appendText(text, false);
|
||||
}
|
||||
buf.append("</" + n.getQName() + ">\n");
|
||||
} else {
|
||||
buf.append("/>\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Appends the page directive with the given attributes to the XML
|
||||
* view.
|
||||
*
|
||||
* Since the import attribute of the page directive is the only page
|
||||
* attribute that is allowed to appear multiple times within the same
|
||||
* document, and since XML allows only single-value attributes,
|
||||
* the values of multiple import attributes must be combined into one,
|
||||
* separated by comma.
|
||||
*
|
||||
* If the given page directive contains just 'contentType' and/or
|
||||
* 'pageEncoding' attributes, we ignore it, as we've already appended
|
||||
* a page directive containing just these two attributes.
|
||||
*/
|
||||
private void appendPageDirective(Node.PageDirective n) {
|
||||
boolean append = false;
|
||||
Attributes attrs = n.getAttributes();
|
||||
int len = (attrs == null) ? 0 : attrs.getLength();
|
||||
for (int i=0; i<len; i++) {
|
||||
String attrName = attrs.getQName(i);
|
||||
if (!"pageEncoding".equals(attrName)
|
||||
&& !"contentType".equals(attrName)) {
|
||||
append = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!append) {
|
||||
return;
|
||||
}
|
||||
|
||||
buf.append("<").append(n.getQName());
|
||||
buf.append("\n");
|
||||
|
||||
// append jsp:id
|
||||
buf.append(" ").append(jspIdPrefix).append(":id").append("=\"");
|
||||
buf.append(jspId++).append("\"\n");
|
||||
|
||||
// append remaining attributes
|
||||
for (int i=0; i<len; i++) {
|
||||
String attrName = attrs.getQName(i);
|
||||
if ("import".equals(attrName) || "contentType".equals(attrName)
|
||||
|| "pageEncoding".equals(attrName)) {
|
||||
/*
|
||||
* Page directive's 'import' attribute is considered
|
||||
* further down, and its 'pageEncoding' and 'contentType'
|
||||
* attributes are ignored, since we've already appended
|
||||
* a new page directive containing just these two
|
||||
* attributes
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
String value = attrs.getValue(i);
|
||||
buf.append(" ").append(attrName).append("=\"");
|
||||
buf.append(JspUtil.getExprInXml(value)).append("\"\n");
|
||||
}
|
||||
if (n.getImports().size() > 0) {
|
||||
// Concatenate names of imported classes/packages
|
||||
boolean first = true;
|
||||
ListIterator iter = n.getImports().listIterator();
|
||||
while (iter.hasNext()) {
|
||||
if (first) {
|
||||
first = false;
|
||||
buf.append(" import=\"");
|
||||
} else {
|
||||
buf.append(",");
|
||||
}
|
||||
buf.append(JspUtil.getExprInXml((String) iter.next()));
|
||||
}
|
||||
buf.append("\"\n");
|
||||
}
|
||||
buf.append("/>\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Appends a page directive with 'pageEncoding' and 'contentType'
|
||||
* attributes.
|
||||
*
|
||||
* The value of the 'pageEncoding' attribute is hard-coded
|
||||
* to UTF-8, whereas the value of the 'contentType' attribute, which
|
||||
* is identical to what the container will pass to
|
||||
* ServletResponse.setContentType(), is derived from the pageInfo.
|
||||
*/
|
||||
private void appendPageDirective() {
|
||||
buf.append("<").append(JSP_PAGE_DIRECTIVE_ACTION);
|
||||
buf.append("\n");
|
||||
|
||||
// append jsp:id
|
||||
buf.append(" ").append(jspIdPrefix).append(":id").append("=\"");
|
||||
buf.append(jspId++).append("\"\n");
|
||||
buf.append(" ").append("pageEncoding").append("=\"UTF-8\"\n");
|
||||
buf.append(" ").append("contentType").append("=\"");
|
||||
buf.append(compiler.getPageInfo().getContentType()).append("\"\n");
|
||||
buf.append("/>\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Appends the tag directive with the given attributes to the XML
|
||||
* view.
|
||||
*
|
||||
* If the given tag directive contains just a 'pageEncoding'
|
||||
* attributes, we ignore it, as we've already appended
|
||||
* a tag directive containing just this attributes.
|
||||
*/
|
||||
private void appendTagDirective(Node.TagDirective n)
|
||||
throws JasperException {
|
||||
|
||||
boolean append = false;
|
||||
Attributes attrs = n.getAttributes();
|
||||
int len = (attrs == null) ? 0 : attrs.getLength();
|
||||
for (int i=0; i<len; i++) {
|
||||
String attrName = attrs.getQName(i);
|
||||
if (!"pageEncoding".equals(attrName)) {
|
||||
append = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!append) {
|
||||
return;
|
||||
}
|
||||
|
||||
appendTag(n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Appends a tag directive containing a single 'pageEncoding'
|
||||
* attribute whose value is hard-coded to UTF-8.
|
||||
*/
|
||||
private void appendTagDirective() {
|
||||
buf.append("<").append(JSP_TAG_DIRECTIVE_ACTION);
|
||||
buf.append("\n");
|
||||
|
||||
// append jsp:id
|
||||
buf.append(" ").append(jspIdPrefix).append(":id").append("=\"");
|
||||
buf.append(jspId++).append("\"\n");
|
||||
buf.append(" ").append("pageEncoding").append("=\"UTF-8\"\n");
|
||||
buf.append("/>\n");
|
||||
}
|
||||
|
||||
private void appendText(String text, boolean createJspTextElement) {
|
||||
if (createJspTextElement) {
|
||||
buf.append("<").append(JSP_TEXT_ACTION);
|
||||
buf.append("\n");
|
||||
|
||||
// append jsp:id
|
||||
buf.append(" ").append(jspIdPrefix).append(":id").append("=\"");
|
||||
buf.append(jspId++).append("\"\n");
|
||||
buf.append(">\n");
|
||||
|
||||
appendCDATA(text);
|
||||
buf.append(JSP_TEXT_ACTION_END);
|
||||
buf.append("\n");
|
||||
} else {
|
||||
appendCDATA(text);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Appends the given text as a CDATA section to the XML view, unless
|
||||
* the text has already been marked as CDATA.
|
||||
*/
|
||||
private void appendCDATA(String text) {
|
||||
buf.append(CDATA_START_SECTION);
|
||||
buf.append(escapeCDATA(text));
|
||||
buf.append(CDATA_END_SECTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Escapes any occurrences of "]]>" (by replacing them with "]]>")
|
||||
* within the given text, so it can be included in a CDATA section.
|
||||
*/
|
||||
private String escapeCDATA(String text) {
|
||||
if( text==null ) return "";
|
||||
int len = text.length();
|
||||
CharArrayWriter result = new CharArrayWriter(len);
|
||||
for (int i=0; i<len; i++) {
|
||||
if (((i+2) < len)
|
||||
&& (text.charAt(i) == ']')
|
||||
&& (text.charAt(i+1) == ']')
|
||||
&& (text.charAt(i+2) == '>')) {
|
||||
// match found
|
||||
result.write(']');
|
||||
result.write(']');
|
||||
result.write('&');
|
||||
result.write('g');
|
||||
result.write('t');
|
||||
result.write(';');
|
||||
i += 2;
|
||||
} else {
|
||||
result.write(text.charAt(i));
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Appends the attributes of the given Node to the XML view.
|
||||
*/
|
||||
private void printAttributes(Node n, boolean addDefaultNS) {
|
||||
|
||||
/*
|
||||
* Append "xmlns" attributes that represent tag libraries
|
||||
*/
|
||||
Attributes attrs = n.getTaglibAttributes();
|
||||
int len = (attrs == null) ? 0 : attrs.getLength();
|
||||
for (int i=0; i<len; i++) {
|
||||
String name = attrs.getQName(i);
|
||||
String value = attrs.getValue(i);
|
||||
buf.append(" ").append(name).append("=\"").append(value).append("\"\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Append "xmlns" attributes that do not represent tag libraries
|
||||
*/
|
||||
attrs = n.getNonTaglibXmlnsAttributes();
|
||||
len = (attrs == null) ? 0 : attrs.getLength();
|
||||
boolean defaultNSSeen = false;
|
||||
for (int i=0; i<len; i++) {
|
||||
String name = attrs.getQName(i);
|
||||
String value = attrs.getValue(i);
|
||||
buf.append(" ").append(name).append("=\"").append(value).append("\"\n");
|
||||
defaultNSSeen |= "xmlns".equals(name);
|
||||
}
|
||||
if (addDefaultNS && !defaultNSSeen) {
|
||||
buf.append(" xmlns=\"\"\n");
|
||||
}
|
||||
resetDefaultNS = false;
|
||||
|
||||
/*
|
||||
* Append all other attributes
|
||||
*/
|
||||
attrs = n.getAttributes();
|
||||
len = (attrs == null) ? 0 : attrs.getLength();
|
||||
for (int i=0; i<len; i++) {
|
||||
String name = attrs.getQName(i);
|
||||
String value = attrs.getValue(i);
|
||||
buf.append(" ").append(name).append("=\"");
|
||||
buf.append(JspUtil.getExprInXml(value)).append("\"\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Appends XML prolog with encoding declaration.
|
||||
*/
|
||||
private void appendXmlProlog() {
|
||||
buf.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,711 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.apache.el.ExpressionFactoryImpl;
|
||||
import org.apache.jasper.Constants;
|
||||
import org.apache.jasper.JasperException;
|
||||
|
||||
import javax.el.ExpressionFactory;
|
||||
import javax.servlet.jsp.tagext.TagLibraryInfo;
|
||||
|
||||
/**
|
||||
* A repository for various info about the translation unit under compilation.
|
||||
*
|
||||
* @author Kin-man Chung
|
||||
*/
|
||||
|
||||
class PageInfo {
|
||||
|
||||
private Vector imports;
|
||||
private Vector dependants;
|
||||
|
||||
private BeanRepository beanRepository;
|
||||
private HashMap taglibsMap;
|
||||
private HashMap jspPrefixMapper;
|
||||
private HashMap xmlPrefixMapper;
|
||||
private HashMap nonCustomTagPrefixMap;
|
||||
private String jspFile;
|
||||
private String defaultLanguage = "java";
|
||||
private String language;
|
||||
private String defaultExtends = Constants.JSP_SERVLET_BASE;
|
||||
private String xtends;
|
||||
private String contentType = null;
|
||||
private String session;
|
||||
private boolean isSession = true;
|
||||
private String bufferValue;
|
||||
private int buffer = 8*1024; // XXX confirm
|
||||
private String autoFlush;
|
||||
private boolean isAutoFlush = true;
|
||||
private String isThreadSafeValue;
|
||||
private boolean isThreadSafe = true;
|
||||
private String isErrorPageValue;
|
||||
private boolean isErrorPage = false;
|
||||
private String errorPage = null;
|
||||
private String info;
|
||||
|
||||
private boolean scriptless = false;
|
||||
private boolean scriptingInvalid = false;
|
||||
|
||||
private String isELIgnoredValue;
|
||||
private boolean isELIgnored = false;
|
||||
|
||||
// JSP 2.1
|
||||
private String deferredSyntaxAllowedAsLiteralValue;
|
||||
private boolean deferredSyntaxAllowedAsLiteral = false;
|
||||
private ExpressionFactory expressionFactory = new ExpressionFactoryImpl();
|
||||
private String trimDirectiveWhitespacesValue;
|
||||
private boolean trimDirectiveWhitespaces = false;
|
||||
|
||||
private String omitXmlDecl = null;
|
||||
private String doctypeName = null;
|
||||
private String doctypePublic = null;
|
||||
private String doctypeSystem = null;
|
||||
|
||||
private boolean isJspPrefixHijacked;
|
||||
|
||||
// Set of all element and attribute prefixes used in this translation unit
|
||||
private HashSet prefixes;
|
||||
|
||||
private boolean hasJspRoot = false;
|
||||
private Vector includePrelude;
|
||||
private Vector includeCoda;
|
||||
private Vector pluginDcls; // Id's for tagplugin declarations
|
||||
|
||||
|
||||
PageInfo(BeanRepository beanRepository, String jspFile) {
|
||||
|
||||
this.jspFile = jspFile;
|
||||
this.beanRepository = beanRepository;
|
||||
this.taglibsMap = new HashMap();
|
||||
this.jspPrefixMapper = new HashMap();
|
||||
this.xmlPrefixMapper = new HashMap();
|
||||
this.nonCustomTagPrefixMap = new HashMap();
|
||||
this.imports = new Vector();
|
||||
this.dependants = new Vector();
|
||||
this.includePrelude = new Vector();
|
||||
this.includeCoda = new Vector();
|
||||
this.pluginDcls = new Vector();
|
||||
this.prefixes = new HashSet();
|
||||
|
||||
// Enter standard imports
|
||||
for(int i = 0; i < Constants.STANDARD_IMPORTS.length; i++)
|
||||
imports.add(Constants.STANDARD_IMPORTS[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the plugin ID has been previously declared. Make a not
|
||||
* that this Id is now declared.
|
||||
* @return true if Id has been declared.
|
||||
*/
|
||||
public boolean isPluginDeclared(String id) {
|
||||
if (pluginDcls.contains(id))
|
||||
return true;
|
||||
pluginDcls.add(id);
|
||||
return false;
|
||||
}
|
||||
|
||||
public void addImports(List imports) {
|
||||
this.imports.addAll(imports);
|
||||
}
|
||||
|
||||
public void addImport(String imp) {
|
||||
this.imports.add(imp);
|
||||
}
|
||||
|
||||
public List getImports() {
|
||||
return imports;
|
||||
}
|
||||
|
||||
public String getJspFile() {
|
||||
return jspFile;
|
||||
}
|
||||
|
||||
public void addDependant(String d) {
|
||||
if (!dependants.contains(d) && !jspFile.equals(d))
|
||||
dependants.add(d);
|
||||
}
|
||||
|
||||
public List getDependants() {
|
||||
return dependants;
|
||||
}
|
||||
|
||||
public BeanRepository getBeanRepository() {
|
||||
return beanRepository;
|
||||
}
|
||||
|
||||
public void setScriptless(boolean s) {
|
||||
scriptless = s;
|
||||
}
|
||||
|
||||
public boolean isScriptless() {
|
||||
return scriptless;
|
||||
}
|
||||
|
||||
public void setScriptingInvalid(boolean s) {
|
||||
scriptingInvalid = s;
|
||||
}
|
||||
|
||||
public boolean isScriptingInvalid() {
|
||||
return scriptingInvalid;
|
||||
}
|
||||
|
||||
public List getIncludePrelude() {
|
||||
return includePrelude;
|
||||
}
|
||||
|
||||
public void setIncludePrelude(Vector prelude) {
|
||||
includePrelude = prelude;
|
||||
}
|
||||
|
||||
public List getIncludeCoda() {
|
||||
return includeCoda;
|
||||
}
|
||||
|
||||
public void setIncludeCoda(Vector coda) {
|
||||
includeCoda = coda;
|
||||
}
|
||||
|
||||
public void setHasJspRoot(boolean s) {
|
||||
hasJspRoot = s;
|
||||
}
|
||||
|
||||
public boolean hasJspRoot() {
|
||||
return hasJspRoot;
|
||||
}
|
||||
|
||||
public String getOmitXmlDecl() {
|
||||
return omitXmlDecl;
|
||||
}
|
||||
|
||||
public void setOmitXmlDecl(String omit) {
|
||||
omitXmlDecl = omit;
|
||||
}
|
||||
|
||||
public String getDoctypeName() {
|
||||
return doctypeName;
|
||||
}
|
||||
|
||||
public void setDoctypeName(String doctypeName) {
|
||||
this.doctypeName = doctypeName;
|
||||
}
|
||||
|
||||
public String getDoctypeSystem() {
|
||||
return doctypeSystem;
|
||||
}
|
||||
|
||||
public void setDoctypeSystem(String doctypeSystem) {
|
||||
this.doctypeSystem = doctypeSystem;
|
||||
}
|
||||
|
||||
public String getDoctypePublic() {
|
||||
return doctypePublic;
|
||||
}
|
||||
|
||||
public void setDoctypePublic(String doctypePublic) {
|
||||
this.doctypePublic = doctypePublic;
|
||||
}
|
||||
|
||||
/* Tag library and XML namespace management methods */
|
||||
|
||||
public void setIsJspPrefixHijacked(boolean isHijacked) {
|
||||
isJspPrefixHijacked = isHijacked;
|
||||
}
|
||||
|
||||
public boolean isJspPrefixHijacked() {
|
||||
return isJspPrefixHijacked;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds the given prefix to the set of prefixes of this translation unit.
|
||||
*
|
||||
* @param prefix The prefix to add
|
||||
*/
|
||||
public void addPrefix(String prefix) {
|
||||
prefixes.add(prefix);
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks to see if this translation unit contains the given prefix.
|
||||
*
|
||||
* @param prefix The prefix to check
|
||||
*
|
||||
* @return true if this translation unit contains the given prefix, false
|
||||
* otherwise
|
||||
*/
|
||||
public boolean containsPrefix(String prefix) {
|
||||
return prefixes.contains(prefix);
|
||||
}
|
||||
|
||||
/*
|
||||
* Maps the given URI to the given tag library.
|
||||
*
|
||||
* @param uri The URI to map
|
||||
* @param info The tag library to be associated with the given URI
|
||||
*/
|
||||
public void addTaglib(String uri, TagLibraryInfo info) {
|
||||
taglibsMap.put(uri, info);
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the tag library corresponding to the given URI.
|
||||
*
|
||||
* @return Tag library corresponding to the given URI
|
||||
*/
|
||||
public TagLibraryInfo getTaglib(String uri) {
|
||||
return (TagLibraryInfo) taglibsMap.get(uri);
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the collection of tag libraries that are associated with a URI
|
||||
*
|
||||
* @return Collection of tag libraries that are associated with a URI
|
||||
*/
|
||||
public Collection getTaglibs() {
|
||||
return taglibsMap.values();
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks to see if the given URI is mapped to a tag library.
|
||||
*
|
||||
* @param uri The URI to map
|
||||
*
|
||||
* @return true if the given URI is mapped to a tag library, false
|
||||
* otherwise
|
||||
*/
|
||||
public boolean hasTaglib(String uri) {
|
||||
return taglibsMap.containsKey(uri);
|
||||
}
|
||||
|
||||
/*
|
||||
* Maps the given prefix to the given URI.
|
||||
*
|
||||
* @param prefix The prefix to map
|
||||
* @param uri The URI to be associated with the given prefix
|
||||
*/
|
||||
public void addPrefixMapping(String prefix, String uri) {
|
||||
jspPrefixMapper.put(prefix, uri);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pushes the given URI onto the stack of URIs to which the given prefix
|
||||
* is mapped.
|
||||
*
|
||||
* @param prefix The prefix whose stack of URIs is to be pushed
|
||||
* @param uri The URI to be pushed onto the stack
|
||||
*/
|
||||
public void pushPrefixMapping(String prefix, String uri) {
|
||||
LinkedList stack = (LinkedList) xmlPrefixMapper.get(prefix);
|
||||
if (stack == null) {
|
||||
stack = new LinkedList();
|
||||
xmlPrefixMapper.put(prefix, stack);
|
||||
}
|
||||
stack.addFirst(uri);
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes the URI at the top of the stack of URIs to which the given
|
||||
* prefix is mapped.
|
||||
*
|
||||
* @param prefix The prefix whose stack of URIs is to be popped
|
||||
*/
|
||||
public void popPrefixMapping(String prefix) {
|
||||
LinkedList stack = (LinkedList) xmlPrefixMapper.get(prefix);
|
||||
if (stack == null || stack.size() == 0) {
|
||||
// XXX throw new Exception("XXX");
|
||||
}
|
||||
stack.removeFirst();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the URI to which the given prefix maps.
|
||||
*
|
||||
* @param prefix The prefix whose URI is sought
|
||||
*
|
||||
* @return The URI to which the given prefix maps
|
||||
*/
|
||||
public String getURI(String prefix) {
|
||||
|
||||
String uri = null;
|
||||
|
||||
LinkedList stack = (LinkedList) xmlPrefixMapper.get(prefix);
|
||||
if (stack == null || stack.size() == 0) {
|
||||
uri = (String) jspPrefixMapper.get(prefix);
|
||||
} else {
|
||||
uri = (String) stack.getFirst();
|
||||
}
|
||||
|
||||
return uri;
|
||||
}
|
||||
|
||||
|
||||
/* Page/Tag directive attributes */
|
||||
|
||||
/*
|
||||
* language
|
||||
*/
|
||||
public void setLanguage(String value, Node n, ErrorDispatcher err,
|
||||
boolean pagedir)
|
||||
throws JasperException {
|
||||
|
||||
if (!"java".equalsIgnoreCase(value)) {
|
||||
if (pagedir)
|
||||
err.jspError(n, "jsp.error.page.language.nonjava");
|
||||
else
|
||||
err.jspError(n, "jsp.error.tag.language.nonjava");
|
||||
}
|
||||
|
||||
language = value;
|
||||
}
|
||||
|
||||
public String getLanguage(boolean useDefault) {
|
||||
return (language == null && useDefault ? defaultLanguage : language);
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return getLanguage(true);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* extends
|
||||
*/
|
||||
public void setExtends(String value, Node.PageDirective n) {
|
||||
|
||||
xtends = value;
|
||||
|
||||
/*
|
||||
* If page superclass is top level class (i.e. not in a package)
|
||||
* explicitly import it. If this is not done, the compiler will assume
|
||||
* the extended class is in the same pkg as the generated servlet.
|
||||
*/
|
||||
if (value.indexOf('.') < 0)
|
||||
n.addImport(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the 'extends' page directive attribute.
|
||||
*
|
||||
* @param useDefault TRUE if the default
|
||||
* (org.apache.jasper.runtime.HttpJspBase) should be returned if this
|
||||
* attribute has not been set, FALSE otherwise
|
||||
*
|
||||
* @return The value of the 'extends' page directive attribute, or the
|
||||
* default (org.apache.jasper.runtime.HttpJspBase) if this attribute has
|
||||
* not been set and useDefault is TRUE
|
||||
*/
|
||||
public String getExtends(boolean useDefault) {
|
||||
return (xtends == null && useDefault ? defaultExtends : xtends);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the 'extends' page directive attribute.
|
||||
*
|
||||
* @return The value of the 'extends' page directive attribute, or the
|
||||
* default (org.apache.jasper.runtime.HttpJspBase) if this attribute has
|
||||
* not been set
|
||||
*/
|
||||
public String getExtends() {
|
||||
return getExtends(true);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* contentType
|
||||
*/
|
||||
public void setContentType(String value) {
|
||||
contentType = value;
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* buffer
|
||||
*/
|
||||
public void setBufferValue(String value, Node n, ErrorDispatcher err)
|
||||
throws JasperException {
|
||||
|
||||
if ("none".equalsIgnoreCase(value))
|
||||
buffer = 0;
|
||||
else {
|
||||
if (value == null || !value.endsWith("kb"))
|
||||
err.jspError(n, "jsp.error.page.invalid.buffer");
|
||||
try {
|
||||
Integer k = new Integer(value.substring(0, value.length()-2));
|
||||
buffer = k.intValue() * 1024;
|
||||
} catch (NumberFormatException e) {
|
||||
err.jspError(n, "jsp.error.page.invalid.buffer");
|
||||
}
|
||||
}
|
||||
|
||||
bufferValue = value;
|
||||
}
|
||||
|
||||
public String getBufferValue() {
|
||||
return bufferValue;
|
||||
}
|
||||
|
||||
public int getBuffer() {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* session
|
||||
*/
|
||||
public void setSession(String value, Node n, ErrorDispatcher err)
|
||||
throws JasperException {
|
||||
|
||||
if ("true".equalsIgnoreCase(value))
|
||||
isSession = true;
|
||||
else if ("false".equalsIgnoreCase(value))
|
||||
isSession = false;
|
||||
else
|
||||
err.jspError(n, "jsp.error.page.invalid.session");
|
||||
|
||||
session = value;
|
||||
}
|
||||
|
||||
public String getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
public boolean isSession() {
|
||||
return isSession;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* autoFlush
|
||||
*/
|
||||
public void setAutoFlush(String value, Node n, ErrorDispatcher err)
|
||||
throws JasperException {
|
||||
|
||||
if ("true".equalsIgnoreCase(value))
|
||||
isAutoFlush = true;
|
||||
else if ("false".equalsIgnoreCase(value))
|
||||
isAutoFlush = false;
|
||||
else
|
||||
err.jspError(n, "jsp.error.autoFlush.invalid");
|
||||
|
||||
autoFlush = value;
|
||||
}
|
||||
|
||||
public String getAutoFlush() {
|
||||
return autoFlush;
|
||||
}
|
||||
|
||||
public boolean isAutoFlush() {
|
||||
return isAutoFlush;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* isThreadSafe
|
||||
*/
|
||||
public void setIsThreadSafe(String value, Node n, ErrorDispatcher err)
|
||||
throws JasperException {
|
||||
|
||||
if ("true".equalsIgnoreCase(value))
|
||||
isThreadSafe = true;
|
||||
else if ("false".equalsIgnoreCase(value))
|
||||
isThreadSafe = false;
|
||||
else
|
||||
err.jspError(n, "jsp.error.page.invalid.isthreadsafe");
|
||||
|
||||
isThreadSafeValue = value;
|
||||
}
|
||||
|
||||
public String getIsThreadSafe() {
|
||||
return isThreadSafeValue;
|
||||
}
|
||||
|
||||
public boolean isThreadSafe() {
|
||||
return isThreadSafe;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* info
|
||||
*/
|
||||
public void setInfo(String value) {
|
||||
info = value;
|
||||
}
|
||||
|
||||
public String getInfo() {
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* errorPage
|
||||
*/
|
||||
public void setErrorPage(String value) {
|
||||
errorPage = value;
|
||||
}
|
||||
|
||||
public String getErrorPage() {
|
||||
return errorPage;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* isErrorPage
|
||||
*/
|
||||
public void setIsErrorPage(String value, Node n, ErrorDispatcher err)
|
||||
throws JasperException {
|
||||
|
||||
if ("true".equalsIgnoreCase(value))
|
||||
isErrorPage = true;
|
||||
else if ("false".equalsIgnoreCase(value))
|
||||
isErrorPage = false;
|
||||
else
|
||||
err.jspError(n, "jsp.error.page.invalid.iserrorpage");
|
||||
|
||||
isErrorPageValue = value;
|
||||
}
|
||||
|
||||
public String getIsErrorPage() {
|
||||
return isErrorPageValue;
|
||||
}
|
||||
|
||||
public boolean isErrorPage() {
|
||||
return isErrorPage;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* isELIgnored
|
||||
*/
|
||||
public void setIsELIgnored(String value, Node n, ErrorDispatcher err,
|
||||
boolean pagedir)
|
||||
throws JasperException {
|
||||
|
||||
if ("true".equalsIgnoreCase(value))
|
||||
isELIgnored = true;
|
||||
else if ("false".equalsIgnoreCase(value))
|
||||
isELIgnored = false;
|
||||
else {
|
||||
if (pagedir)
|
||||
err.jspError(n, "jsp.error.page.invalid.iselignored");
|
||||
else
|
||||
err.jspError(n, "jsp.error.tag.invalid.iselignored");
|
||||
}
|
||||
|
||||
isELIgnoredValue = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* deferredSyntaxAllowedAsLiteral
|
||||
*/
|
||||
public void setDeferredSyntaxAllowedAsLiteral(String value, Node n, ErrorDispatcher err,
|
||||
boolean pagedir)
|
||||
throws JasperException {
|
||||
|
||||
if ("true".equalsIgnoreCase(value))
|
||||
deferredSyntaxAllowedAsLiteral = true;
|
||||
else if ("false".equalsIgnoreCase(value))
|
||||
deferredSyntaxAllowedAsLiteral = false;
|
||||
else {
|
||||
if (pagedir)
|
||||
err.jspError(n, "jsp.error.page.invalid.deferredsyntaxallowedasliteral");
|
||||
else
|
||||
err.jspError(n, "jsp.error.tag.invalid.deferredsyntaxallowedasliteral");
|
||||
}
|
||||
|
||||
deferredSyntaxAllowedAsLiteralValue = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* trimDirectiveWhitespaces
|
||||
*/
|
||||
public void setTrimDirectiveWhitespaces(String value, Node n, ErrorDispatcher err,
|
||||
boolean pagedir)
|
||||
throws JasperException {
|
||||
|
||||
if ("true".equalsIgnoreCase(value))
|
||||
trimDirectiveWhitespaces = true;
|
||||
else if ("false".equalsIgnoreCase(value))
|
||||
trimDirectiveWhitespaces = false;
|
||||
else {
|
||||
if (pagedir)
|
||||
err.jspError(n, "jsp.error.page.invalid.trimdirectivewhitespaces");
|
||||
else
|
||||
err.jspError(n, "jsp.error.tag.invalid.trimdirectivewhitespaces");
|
||||
}
|
||||
|
||||
trimDirectiveWhitespacesValue = value;
|
||||
}
|
||||
|
||||
public void setELIgnored(boolean s) {
|
||||
isELIgnored = s;
|
||||
}
|
||||
|
||||
public String getIsELIgnored() {
|
||||
return isELIgnoredValue;
|
||||
}
|
||||
|
||||
public boolean isELIgnored() {
|
||||
return isELIgnored;
|
||||
}
|
||||
|
||||
public void putNonCustomTagPrefix(String prefix, Mark where) {
|
||||
nonCustomTagPrefixMap.put(prefix, where);
|
||||
}
|
||||
|
||||
public Mark getNonCustomTagPrefix(String prefix) {
|
||||
return (Mark) nonCustomTagPrefixMap.get(prefix);
|
||||
}
|
||||
|
||||
public String getDeferredSyntaxAllowedAsLiteral() {
|
||||
return deferredSyntaxAllowedAsLiteralValue;
|
||||
}
|
||||
|
||||
public boolean isDeferredSyntaxAllowedAsLiteral() {
|
||||
return deferredSyntaxAllowedAsLiteral;
|
||||
}
|
||||
|
||||
public void setDeferredSyntaxAllowedAsLiteral(boolean isELDeferred) {
|
||||
this.deferredSyntaxAllowedAsLiteral = isELDeferred;
|
||||
}
|
||||
|
||||
public ExpressionFactory getExpressionFactory() {
|
||||
return expressionFactory;
|
||||
}
|
||||
|
||||
public String getTrimDirectiveWhitespaces() {
|
||||
return trimDirectiveWhitespacesValue;
|
||||
}
|
||||
|
||||
public boolean isTrimDirectiveWhitespaces() {
|
||||
return trimDirectiveWhitespaces;
|
||||
}
|
||||
|
||||
public void setTrimDirectiveWhitespaces(boolean trimDirectiveWhitespaces) {
|
||||
this.trimDirectiveWhitespaces = trimDirectiveWhitespaces;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
-638
@@ -1,638 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Stack;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import org.apache.jasper.JasperException;
|
||||
import org.apache.jasper.JspCompilationContext;
|
||||
import org.apache.jasper.xmlparser.XMLEncodingDetector;
|
||||
import org.xml.sax.Attributes;
|
||||
|
||||
/**
|
||||
* Controller for the parsing of a JSP page.
|
||||
* <p>
|
||||
* The same ParserController instance is used for a JSP page and any JSP
|
||||
* segments included by it (via an include directive), where each segment may
|
||||
* be provided in standard or XML syntax. This class selects and invokes the
|
||||
* appropriate parser for the JSP page and its included segments.
|
||||
*
|
||||
* @author Pierre Delisle
|
||||
* @author Jan Luehe
|
||||
*/
|
||||
class ParserController implements TagConstants {
|
||||
|
||||
private static final String CHARSET = "charset=";
|
||||
|
||||
private JspCompilationContext ctxt;
|
||||
private Compiler compiler;
|
||||
private ErrorDispatcher err;
|
||||
|
||||
/*
|
||||
* Indicates the syntax (XML or standard) of the file being processed
|
||||
*/
|
||||
private boolean isXml;
|
||||
|
||||
/*
|
||||
* A stack to keep track of the 'current base directory'
|
||||
* for include directives that refer to relative paths.
|
||||
*/
|
||||
private Stack baseDirStack = new Stack();
|
||||
|
||||
private boolean isEncodingSpecifiedInProlog;
|
||||
private boolean isBomPresent;
|
||||
private int skip;
|
||||
|
||||
private String sourceEnc;
|
||||
|
||||
private boolean isDefaultPageEncoding;
|
||||
private boolean isTagFile;
|
||||
private boolean directiveOnly;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public ParserController(JspCompilationContext ctxt, Compiler compiler) {
|
||||
this.ctxt = ctxt;
|
||||
this.compiler = compiler;
|
||||
this.err = compiler.getErrorDispatcher();
|
||||
}
|
||||
|
||||
public JspCompilationContext getJspCompilationContext () {
|
||||
return ctxt;
|
||||
}
|
||||
|
||||
public Compiler getCompiler () {
|
||||
return compiler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a JSP page or tag file. This is invoked by the compiler.
|
||||
*
|
||||
* @param inFileName The path to the JSP page or tag file to be parsed.
|
||||
*/
|
||||
public Node.Nodes parse(String inFileName)
|
||||
throws FileNotFoundException, JasperException, IOException {
|
||||
// If we're parsing a packaged tag file or a resource included by it
|
||||
// (using an include directive), ctxt.getTagFileJar() returns the
|
||||
// JAR file from which to read the tag file or included resource,
|
||||
// respectively.
|
||||
isTagFile = ctxt.isTagFile();
|
||||
directiveOnly = false;
|
||||
return doParse(inFileName, null, ctxt.getTagFileJarUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the directives of a JSP page or tag file. This is invoked by the
|
||||
* compiler.
|
||||
*
|
||||
* @param inFileName The path to the JSP page or tag file to be parsed.
|
||||
*/
|
||||
public Node.Nodes parseDirectives(String inFileName)
|
||||
throws FileNotFoundException, JasperException, IOException {
|
||||
// If we're parsing a packaged tag file or a resource included by it
|
||||
// (using an include directive), ctxt.getTagFileJar() returns the
|
||||
// JAR file from which to read the tag file or included resource,
|
||||
// respectively.
|
||||
isTagFile = ctxt.isTagFile();
|
||||
directiveOnly = true;
|
||||
return doParse(inFileName, null, ctxt.getTagFileJarUrl());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Processes an include directive with the given path.
|
||||
*
|
||||
* @param inFileName The path to the resource to be included.
|
||||
* @param parent The parent node of the include directive.
|
||||
* @param jarFile The JAR file from which to read the included resource,
|
||||
* or null of the included resource is to be read from the filesystem
|
||||
*/
|
||||
public Node.Nodes parse(String inFileName, Node parent,
|
||||
URL jarFileUrl)
|
||||
throws FileNotFoundException, JasperException, IOException {
|
||||
// For files that are statically included, isTagfile and directiveOnly
|
||||
// remain unchanged.
|
||||
return doParse(inFileName, parent, jarFileUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts tag file directive information from the tag file with the
|
||||
* given name.
|
||||
*
|
||||
* This is invoked by the compiler
|
||||
*
|
||||
* @param inFileName The name of the tag file to be parsed.
|
||||
* @deprecated Use {@link #parseTagFileDirectives(String, URL)}
|
||||
* See https://issues.apache.org/bugzilla/show_bug.cgi?id=46471
|
||||
*/
|
||||
public Node.Nodes parseTagFileDirectives(String inFileName)
|
||||
throws FileNotFoundException, JasperException, IOException {
|
||||
return parseTagFileDirectives(
|
||||
inFileName, ctxt.getTagFileJarUrl(inFileName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts tag file directive information from the given tag file.
|
||||
*
|
||||
* This is invoked by the compiler
|
||||
*
|
||||
* @param inFileName The name of the tag file to be parsed.
|
||||
* @param tagFileJarUrl The location of the tag file.
|
||||
*/
|
||||
public Node.Nodes parseTagFileDirectives(String inFileName,
|
||||
URL tagFileJarUrl)
|
||||
throws FileNotFoundException, JasperException, IOException {
|
||||
boolean isTagFileSave = isTagFile;
|
||||
boolean directiveOnlySave = directiveOnly;
|
||||
isTagFile = true;
|
||||
directiveOnly = true;
|
||||
Node.Nodes page = doParse(inFileName, null, tagFileJarUrl);
|
||||
directiveOnly = directiveOnlySave;
|
||||
isTagFile = isTagFileSave;
|
||||
return page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the JSP page or tag file with the given path name.
|
||||
*
|
||||
* @param inFileName The name of the JSP page or tag file to be parsed.
|
||||
* @param parent The parent node (non-null when processing an include
|
||||
* directive)
|
||||
* @param isTagFile true if file to be parsed is tag file, and false if it
|
||||
* is a regular JSP page
|
||||
* @param directivesOnly true if the file to be parsed is a tag file and
|
||||
* we are only interested in the directives needed for constructing a
|
||||
* TagFileInfo.
|
||||
* @param jarFile The JAR file from which to read the JSP page or tag file,
|
||||
* or null if the JSP page or tag file is to be read from the filesystem
|
||||
*/
|
||||
private Node.Nodes doParse(String inFileName,
|
||||
Node parent,
|
||||
URL jarFileUrl)
|
||||
throws FileNotFoundException, JasperException, IOException {
|
||||
|
||||
Node.Nodes parsedPage = null;
|
||||
isEncodingSpecifiedInProlog = false;
|
||||
isBomPresent = false;
|
||||
isDefaultPageEncoding = false;
|
||||
|
||||
JarFile jarFile = getJarFile(jarFileUrl);
|
||||
String absFileName = resolveFileName(inFileName);
|
||||
String jspConfigPageEnc = getJspConfigPageEncoding(absFileName);
|
||||
|
||||
// Figure out what type of JSP document and encoding type we are
|
||||
// dealing with
|
||||
determineSyntaxAndEncoding(absFileName, jarFile, jspConfigPageEnc);
|
||||
|
||||
if (parent != null) {
|
||||
// Included resource, add to dependent list
|
||||
if (jarFile == null) {
|
||||
compiler.getPageInfo().addDependant(absFileName);
|
||||
} else {
|
||||
compiler.getPageInfo().addDependant(
|
||||
jarFileUrl.toExternalForm() + absFileName.substring(1));
|
||||
}
|
||||
}
|
||||
|
||||
if ((isXml && isEncodingSpecifiedInProlog) || isBomPresent) {
|
||||
/*
|
||||
* Make sure the encoding explicitly specified in the XML
|
||||
* prolog (if any) matches that in the JSP config element
|
||||
* (if any), treating "UTF-16", "UTF-16BE", and "UTF-16LE" as
|
||||
* identical.
|
||||
*/
|
||||
if (jspConfigPageEnc != null && !jspConfigPageEnc.equals(sourceEnc)
|
||||
&& (!jspConfigPageEnc.startsWith("UTF-16")
|
||||
|| !sourceEnc.startsWith("UTF-16"))) {
|
||||
err.jspError("jsp.error.prolog_config_encoding_mismatch",
|
||||
sourceEnc, jspConfigPageEnc);
|
||||
}
|
||||
}
|
||||
|
||||
// Dispatch to the appropriate parser
|
||||
if (isXml) {
|
||||
// JSP document (XML syntax)
|
||||
// InputStream for jspx page is created and properly closed in
|
||||
// JspDocumentParser.
|
||||
parsedPage = JspDocumentParser.parse(this, absFileName,
|
||||
jarFile, parent,
|
||||
isTagFile, directiveOnly,
|
||||
sourceEnc,
|
||||
jspConfigPageEnc,
|
||||
isEncodingSpecifiedInProlog,
|
||||
isBomPresent);
|
||||
} else {
|
||||
// Standard syntax
|
||||
InputStreamReader inStreamReader = null;
|
||||
try {
|
||||
inStreamReader = JspUtil.getReader(absFileName, sourceEnc,
|
||||
jarFile, ctxt, err, skip);
|
||||
JspReader jspReader = new JspReader(ctxt, absFileName,
|
||||
sourceEnc, inStreamReader,
|
||||
err);
|
||||
parsedPage = Parser.parse(this, jspReader, parent, isTagFile,
|
||||
directiveOnly, jarFileUrl,
|
||||
sourceEnc, jspConfigPageEnc,
|
||||
isDefaultPageEncoding, isBomPresent);
|
||||
} finally {
|
||||
if (inStreamReader != null) {
|
||||
try {
|
||||
inStreamReader.close();
|
||||
} catch (Exception any) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (jarFile != null) {
|
||||
try {
|
||||
jarFile.close();
|
||||
} catch (Throwable t) {}
|
||||
}
|
||||
|
||||
baseDirStack.pop();
|
||||
|
||||
return parsedPage;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks to see if the given URI is matched by a URL pattern specified in
|
||||
* a jsp-property-group in web.xml, and if so, returns the value of the
|
||||
* <page-encoding> element.
|
||||
*
|
||||
* @param absFileName The URI to match
|
||||
*
|
||||
* @return The value of the <page-encoding> attribute of the
|
||||
* jsp-property-group with matching URL pattern
|
||||
*/
|
||||
private String getJspConfigPageEncoding(String absFileName)
|
||||
throws JasperException {
|
||||
|
||||
JspConfig jspConfig = ctxt.getOptions().getJspConfig();
|
||||
JspConfig.JspProperty jspProperty
|
||||
= jspConfig.findJspProperty(absFileName);
|
||||
return jspProperty.getPageEncoding();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the syntax (standard or XML) and page encoding properties
|
||||
* for the given file, and stores them in the 'isXml' and 'sourceEnc'
|
||||
* instance variables, respectively.
|
||||
*/
|
||||
private void determineSyntaxAndEncoding(String absFileName,
|
||||
JarFile jarFile,
|
||||
String jspConfigPageEnc)
|
||||
throws JasperException, IOException {
|
||||
|
||||
isXml = false;
|
||||
|
||||
/*
|
||||
* 'true' if the syntax (XML or standard) of the file is given
|
||||
* from external information: either via a JSP configuration element,
|
||||
* the ".jspx" suffix, or the enclosing file (for included resources)
|
||||
*/
|
||||
boolean isExternal = false;
|
||||
|
||||
/*
|
||||
* Indicates whether we need to revert from temporary usage of
|
||||
* "ISO-8859-1" back to "UTF-8"
|
||||
*/
|
||||
boolean revert = false;
|
||||
|
||||
JspConfig jspConfig = ctxt.getOptions().getJspConfig();
|
||||
JspConfig.JspProperty jspProperty = jspConfig.findJspProperty(
|
||||
absFileName);
|
||||
if (jspProperty.isXml() != null) {
|
||||
// If <is-xml> is specified in a <jsp-property-group>, it is used.
|
||||
isXml = JspUtil.booleanValue(jspProperty.isXml());
|
||||
isExternal = true;
|
||||
} else if (absFileName.endsWith(".jspx")
|
||||
|| absFileName.endsWith(".tagx")) {
|
||||
isXml = true;
|
||||
isExternal = true;
|
||||
}
|
||||
|
||||
if (isExternal && !isXml) {
|
||||
// JSP (standard) syntax. Use encoding specified in jsp-config
|
||||
// if provided.
|
||||
sourceEnc = jspConfigPageEnc;
|
||||
if (sourceEnc != null) {
|
||||
return;
|
||||
}
|
||||
// We don't know the encoding, so use BOM to determine it
|
||||
sourceEnc = "ISO-8859-1";
|
||||
} else {
|
||||
// XML syntax or unknown, (auto)detect encoding ...
|
||||
Object[] ret = XMLEncodingDetector.getEncoding(absFileName,
|
||||
jarFile, ctxt, err);
|
||||
sourceEnc = (String) ret[0];
|
||||
if (((Boolean) ret[1]).booleanValue()) {
|
||||
isEncodingSpecifiedInProlog = true;
|
||||
}
|
||||
if (((Boolean) ret[2]).booleanValue()) {
|
||||
isBomPresent = true;
|
||||
}
|
||||
skip = ((Integer) ret[3]).intValue();
|
||||
|
||||
if (!isXml && sourceEnc.equals("UTF-8")) {
|
||||
/*
|
||||
* We don't know if we're dealing with XML or standard syntax.
|
||||
* Therefore, we need to check to see if the page contains
|
||||
* a <jsp:root> element.
|
||||
*
|
||||
* We need to be careful, because the page may be encoded in
|
||||
* ISO-8859-1 (or something entirely different), and may
|
||||
* contain byte sequences that will cause a UTF-8 converter to
|
||||
* throw exceptions.
|
||||
*
|
||||
* It is safe to use a source encoding of ISO-8859-1 in this
|
||||
* case, as there are no invalid byte sequences in ISO-8859-1,
|
||||
* and the byte/character sequences we're looking for (i.e.,
|
||||
* <jsp:root>) are identical in either encoding (both UTF-8
|
||||
* and ISO-8859-1 are extensions of ASCII).
|
||||
*/
|
||||
sourceEnc = "ISO-8859-1";
|
||||
revert = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isXml) {
|
||||
// (This implies 'isExternal' is TRUE.)
|
||||
// We know we're dealing with a JSP document (via JSP config or
|
||||
// ".jspx" suffix), so we're done.
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point, 'isExternal' or 'isXml' is FALSE.
|
||||
* Search for jsp:root action, in order to determine if we're dealing
|
||||
* with XML or standard syntax (unless we already know what we're
|
||||
* dealing with, i.e., when 'isExternal' is TRUE and 'isXml' is FALSE).
|
||||
* No check for XML prolog, since nothing prevents a page from
|
||||
* outputting XML and still using JSP syntax (in this case, the
|
||||
* XML prolog is treated as template text).
|
||||
*/
|
||||
JspReader jspReader = null;
|
||||
try {
|
||||
jspReader = new JspReader(ctxt, absFileName, sourceEnc, jarFile,
|
||||
err);
|
||||
} catch (FileNotFoundException ex) {
|
||||
throw new JasperException(ex);
|
||||
}
|
||||
jspReader.setSingleFile(true);
|
||||
Mark startMark = jspReader.mark();
|
||||
if (!isExternal) {
|
||||
jspReader.reset(startMark);
|
||||
if (hasJspRoot(jspReader)) {
|
||||
if (revert) {
|
||||
sourceEnc = "UTF-8";
|
||||
}
|
||||
isXml = true;
|
||||
return;
|
||||
} else {
|
||||
if (revert && isBomPresent) {
|
||||
sourceEnc = "UTF-8";
|
||||
}
|
||||
isXml = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point, we know we're dealing with JSP syntax.
|
||||
* If an XML prolog is provided, it's treated as template text.
|
||||
* Determine the page encoding from the page directive, unless it's
|
||||
* specified via JSP config.
|
||||
*/
|
||||
if (!isBomPresent) {
|
||||
sourceEnc = jspConfigPageEnc;
|
||||
if (sourceEnc == null) {
|
||||
sourceEnc = getPageEncodingForJspSyntax(jspReader, startMark);
|
||||
if (sourceEnc == null) {
|
||||
// Default to "ISO-8859-1" per JSP spec
|
||||
sourceEnc = "ISO-8859-1";
|
||||
isDefaultPageEncoding = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Determines page source encoding for page or tag file in JSP syntax,
|
||||
* by reading (in this order) the value of the 'pageEncoding' page
|
||||
* directive attribute, or the charset value of the 'contentType' page
|
||||
* directive attribute.
|
||||
*
|
||||
* @return The page encoding, or null if not found
|
||||
*/
|
||||
private String getPageEncodingForJspSyntax(JspReader jspReader,
|
||||
Mark startMark)
|
||||
throws JasperException {
|
||||
|
||||
String encoding = null;
|
||||
String saveEncoding = null;
|
||||
|
||||
jspReader.reset(startMark);
|
||||
|
||||
/*
|
||||
* Determine page encoding from directive of the form <%@ page %>,
|
||||
* <%@ tag %>, <jsp:directive.page > or <jsp:directive.tag >.
|
||||
*/
|
||||
while (true) {
|
||||
if (jspReader.skipUntil("<") == null) {
|
||||
break;
|
||||
}
|
||||
// If this is a comment, skip until its end
|
||||
if (jspReader.matches("%--")) {
|
||||
if (jspReader.skipUntil("--%>") == null) {
|
||||
// error will be caught in Parser
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
boolean isDirective = jspReader.matches("%@");
|
||||
if (isDirective) {
|
||||
jspReader.skipSpaces();
|
||||
}
|
||||
else {
|
||||
isDirective = jspReader.matches("jsp:directive.");
|
||||
}
|
||||
if (!isDirective) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// compare for "tag ", so we don't match "taglib"
|
||||
if (jspReader.matches("tag ") || jspReader.matches("page")) {
|
||||
|
||||
jspReader.skipSpaces();
|
||||
Attributes attrs = Parser.parseAttributes(this, jspReader);
|
||||
encoding = getPageEncodingFromDirective(attrs, "pageEncoding");
|
||||
if (encoding != null) {
|
||||
break;
|
||||
}
|
||||
encoding = getPageEncodingFromDirective(attrs, "contentType");
|
||||
if (encoding != null) {
|
||||
saveEncoding = encoding;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (encoding == null) {
|
||||
encoding = saveEncoding;
|
||||
}
|
||||
|
||||
return encoding;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scans the given attributes for the attribute with the given name,
|
||||
* which is either 'pageEncoding' or 'contentType', and returns the
|
||||
* specified page encoding.
|
||||
*
|
||||
* In the case of 'contentType', the page encoding is taken from the
|
||||
* content type's 'charset' component.
|
||||
*
|
||||
* @param attrs The page directive attributes
|
||||
* @param attrName The name of the attribute to search for (either
|
||||
* 'pageEncoding' or 'contentType')
|
||||
*
|
||||
* @return The page encoding, or null
|
||||
*/
|
||||
private String getPageEncodingFromDirective(Attributes attrs,
|
||||
String attrName) {
|
||||
String value = attrs.getValue(attrName);
|
||||
if (attrName.equals("pageEncoding")) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// attrName = contentType
|
||||
String contentType = value;
|
||||
String encoding = null;
|
||||
if (contentType != null) {
|
||||
int loc = contentType.indexOf(CHARSET);
|
||||
if (loc != -1) {
|
||||
encoding = contentType.substring(loc + CHARSET.length());
|
||||
}
|
||||
}
|
||||
|
||||
return encoding;
|
||||
}
|
||||
|
||||
/*
|
||||
* Resolve the name of the file and update baseDirStack() to keep track of
|
||||
* the current base directory for each included file.
|
||||
* The 'root' file is always an 'absolute' path, so no need to put an
|
||||
* initial value in the baseDirStack.
|
||||
*/
|
||||
private String resolveFileName(String inFileName) {
|
||||
String fileName = inFileName.replace('\\', '/');
|
||||
boolean isAbsolute = fileName.startsWith("/");
|
||||
fileName = isAbsolute ? fileName
|
||||
: (String) baseDirStack.peek() + fileName;
|
||||
String baseDir =
|
||||
fileName.substring(0, fileName.lastIndexOf("/") + 1);
|
||||
baseDirStack.push(baseDir);
|
||||
return fileName;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks to see if the given page contains, as its first element, a <root>
|
||||
* element whose prefix is bound to the JSP namespace, as in:
|
||||
*
|
||||
* <wombat:root xmlns:wombat="http://java.sun.com/JSP/Page" version="1.2">
|
||||
* ...
|
||||
* </wombat:root>
|
||||
*
|
||||
* @param reader The reader for this page
|
||||
*
|
||||
* @return true if this page contains a root element whose prefix is bound
|
||||
* to the JSP namespace, and false otherwise
|
||||
*/
|
||||
private boolean hasJspRoot(JspReader reader) throws JasperException {
|
||||
|
||||
// <prefix>:root must be the first element
|
||||
Mark start = null;
|
||||
while ((start = reader.skipUntil("<")) != null) {
|
||||
int c = reader.nextChar();
|
||||
if (c != '!' && c != '?') break;
|
||||
}
|
||||
if (start == null) {
|
||||
return false;
|
||||
}
|
||||
Mark stop = reader.skipUntil(":root");
|
||||
if (stop == null) {
|
||||
return false;
|
||||
}
|
||||
// call substring to get rid of leading '<'
|
||||
String prefix = reader.getText(start, stop).substring(1);
|
||||
|
||||
start = stop;
|
||||
stop = reader.skipUntil(">");
|
||||
if (stop == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Determine namespace associated with <root> element's prefix
|
||||
String root = reader.getText(start, stop);
|
||||
String xmlnsDecl = "xmlns:" + prefix;
|
||||
int index = root.indexOf(xmlnsDecl);
|
||||
if (index == -1) {
|
||||
return false;
|
||||
}
|
||||
index += xmlnsDecl.length();
|
||||
while (index < root.length()
|
||||
&& Character.isWhitespace(root.charAt(index))) {
|
||||
index++;
|
||||
}
|
||||
if (index < root.length() && root.charAt(index) == '=') {
|
||||
index++;
|
||||
while (index < root.length()
|
||||
&& Character.isWhitespace(root.charAt(index))) {
|
||||
index++;
|
||||
}
|
||||
if (index < root.length() && root.charAt(index++) == '"'
|
||||
&& root.regionMatches(index, JSP_URI, 0,
|
||||
JSP_URI.length())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private JarFile getJarFile(URL jarFileUrl) throws IOException {
|
||||
JarFile jarFile = null;
|
||||
|
||||
if (jarFileUrl != null) {
|
||||
JarURLConnection conn = (JarURLConnection) jarFileUrl.openConnection();
|
||||
conn.setUseCaches(false);
|
||||
conn.connect();
|
||||
jarFile = conn.getJarFile();
|
||||
}
|
||||
|
||||
return jarFile;
|
||||
}
|
||||
|
||||
}
|
||||
-148
@@ -1,148 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.util.*;
|
||||
import javax.servlet.jsp.tagext.*;
|
||||
import org.apache.jasper.JasperException;
|
||||
|
||||
/**
|
||||
* Class responsible for determining the scripting variables that every
|
||||
* custom action needs to declare.
|
||||
*
|
||||
* @author Jan Luehe
|
||||
*/
|
||||
class ScriptingVariabler {
|
||||
|
||||
private static final Integer MAX_SCOPE = new Integer(Integer.MAX_VALUE);
|
||||
|
||||
/*
|
||||
* Assigns an identifier (of type integer) to every custom tag, in order
|
||||
* to help identify, for every custom tag, the scripting variables that it
|
||||
* needs to declare.
|
||||
*/
|
||||
static class CustomTagCounter extends Node.Visitor {
|
||||
|
||||
private int count;
|
||||
private Node.CustomTag parent;
|
||||
|
||||
public void visit(Node.CustomTag n) throws JasperException {
|
||||
n.setCustomTagParent(parent);
|
||||
Node.CustomTag tmpParent = parent;
|
||||
parent = n;
|
||||
visitBody(n);
|
||||
parent = tmpParent;
|
||||
n.setNumCount(new Integer(count++));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* For every custom tag, determines the scripting variables it needs to
|
||||
* declare.
|
||||
*/
|
||||
static class ScriptingVariableVisitor extends Node.Visitor {
|
||||
|
||||
private ErrorDispatcher err;
|
||||
private Hashtable scriptVars;
|
||||
|
||||
public ScriptingVariableVisitor(ErrorDispatcher err) {
|
||||
this.err = err;
|
||||
scriptVars = new Hashtable();
|
||||
}
|
||||
|
||||
public void visit(Node.CustomTag n) throws JasperException {
|
||||
setScriptingVars(n, VariableInfo.AT_BEGIN);
|
||||
setScriptingVars(n, VariableInfo.NESTED);
|
||||
visitBody(n);
|
||||
setScriptingVars(n, VariableInfo.AT_END);
|
||||
}
|
||||
|
||||
private void setScriptingVars(Node.CustomTag n, int scope)
|
||||
throws JasperException {
|
||||
|
||||
TagVariableInfo[] tagVarInfos = n.getTagVariableInfos();
|
||||
VariableInfo[] varInfos = n.getVariableInfos();
|
||||
if (tagVarInfos.length == 0 && varInfos.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Vector vec = new Vector();
|
||||
|
||||
Integer ownRange = null;
|
||||
if (scope == VariableInfo.AT_BEGIN
|
||||
|| scope == VariableInfo.AT_END) {
|
||||
Node.CustomTag parent = n.getCustomTagParent();
|
||||
if (parent == null)
|
||||
ownRange = MAX_SCOPE;
|
||||
else
|
||||
ownRange = parent.getNumCount();
|
||||
} else {
|
||||
// NESTED
|
||||
ownRange = n.getNumCount();
|
||||
}
|
||||
|
||||
if (varInfos.length > 0) {
|
||||
for (int i=0; i<varInfos.length; i++) {
|
||||
if (varInfos[i].getScope() != scope
|
||||
|| !varInfos[i].getDeclare()) {
|
||||
continue;
|
||||
}
|
||||
String varName = varInfos[i].getVarName();
|
||||
|
||||
Integer currentRange = (Integer) scriptVars.get(varName);
|
||||
if (currentRange == null
|
||||
|| ownRange.compareTo(currentRange) > 0) {
|
||||
scriptVars.put(varName, ownRange);
|
||||
vec.add(varInfos[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i=0; i<tagVarInfos.length; i++) {
|
||||
if (tagVarInfos[i].getScope() != scope
|
||||
|| !tagVarInfos[i].getDeclare()) {
|
||||
continue;
|
||||
}
|
||||
String varName = tagVarInfos[i].getNameGiven();
|
||||
if (varName == null) {
|
||||
varName = n.getTagData().getAttributeString(
|
||||
tagVarInfos[i].getNameFromAttribute());
|
||||
if (varName == null) {
|
||||
err.jspError(n, "jsp.error.scripting.variable.missing_name",
|
||||
tagVarInfos[i].getNameFromAttribute());
|
||||
}
|
||||
}
|
||||
|
||||
Integer currentRange = (Integer) scriptVars.get(varName);
|
||||
if (currentRange == null
|
||||
|| ownRange.compareTo(currentRange) > 0) {
|
||||
scriptVars.put(varName, ownRange);
|
||||
vec.add(tagVarInfos[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
n.setScriptingVars(vec, scope);
|
||||
}
|
||||
}
|
||||
|
||||
public static void set(Node.Nodes page, ErrorDispatcher err)
|
||||
throws JasperException {
|
||||
page.visit(new CustomTagCounter());
|
||||
page.visit(new ScriptingVariableVisitor(err));
|
||||
}
|
||||
}
|
||||
-176
@@ -1,176 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* This is what is used to generate servlets.
|
||||
*
|
||||
* @author Anil K. Vijendran
|
||||
* @author Kin-man Chung
|
||||
*/
|
||||
public class ServletWriter {
|
||||
public static int TAB_WIDTH = 2;
|
||||
public static String SPACES = " ";
|
||||
|
||||
// Current indent level:
|
||||
private int indent = 0;
|
||||
private int virtual_indent = 0;
|
||||
|
||||
// The sink writer:
|
||||
PrintWriter writer;
|
||||
|
||||
// servlet line numbers start from 1
|
||||
private int javaLine = 1;
|
||||
|
||||
|
||||
public ServletWriter(PrintWriter writer) {
|
||||
this.writer = writer;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
writer.close();
|
||||
}
|
||||
|
||||
|
||||
// -------------------- Access informations --------------------
|
||||
|
||||
public int getJavaLine() {
|
||||
return javaLine;
|
||||
}
|
||||
|
||||
|
||||
// -------------------- Formatting --------------------
|
||||
|
||||
public void pushIndent() {
|
||||
virtual_indent += TAB_WIDTH;
|
||||
if (virtual_indent >= 0 && virtual_indent <= SPACES.length())
|
||||
indent = virtual_indent;
|
||||
}
|
||||
|
||||
public void popIndent() {
|
||||
virtual_indent -= TAB_WIDTH;
|
||||
if (virtual_indent >= 0 && virtual_indent <= SPACES.length())
|
||||
indent = virtual_indent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a standard comment for echo outputed chunk.
|
||||
* @param start The starting position of the JSP chunk being processed.
|
||||
* @param stop The ending position of the JSP chunk being processed.
|
||||
*/
|
||||
public void printComment(Mark start, Mark stop, char[] chars) {
|
||||
if (start != null && stop != null) {
|
||||
println("// from="+start);
|
||||
println("// to="+stop);
|
||||
}
|
||||
|
||||
if (chars != null)
|
||||
for(int i = 0; i < chars.length;) {
|
||||
printin();
|
||||
print("// ");
|
||||
while (chars[i] != '\n' && i < chars.length)
|
||||
writer.print(chars[i++]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the given string followed by '\n'
|
||||
*/
|
||||
public void println(String s) {
|
||||
javaLine++;
|
||||
writer.println(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a '\n'
|
||||
*/
|
||||
public void println() {
|
||||
javaLine++;
|
||||
writer.println("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the current indention
|
||||
*/
|
||||
public void printin() {
|
||||
writer.print(SPACES.substring(0, indent));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the current indention, followed by the given string
|
||||
*/
|
||||
public void printin(String s) {
|
||||
writer.print(SPACES.substring(0, indent));
|
||||
writer.print(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the current indention, and then the string, and a '\n'.
|
||||
*/
|
||||
public void printil(String s) {
|
||||
javaLine++;
|
||||
writer.print(SPACES.substring(0, indent));
|
||||
writer.println(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the given char.
|
||||
*
|
||||
* Use println() to print a '\n'.
|
||||
*/
|
||||
public void print(char c) {
|
||||
writer.print(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the given int.
|
||||
*/
|
||||
public void print(int i) {
|
||||
writer.print(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the given string.
|
||||
*
|
||||
* The string must not contain any '\n', otherwise the line count will be
|
||||
* off.
|
||||
*/
|
||||
public void print(String s) {
|
||||
writer.print(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the given string.
|
||||
*
|
||||
* If the string spans multiple lines, the line count will be adjusted
|
||||
* accordingly.
|
||||
*/
|
||||
public void printMultiLn(String s) {
|
||||
int index = 0;
|
||||
|
||||
// look for hidden newlines inside strings
|
||||
while ((index=s.indexOf('\n',index)) > -1 ) {
|
||||
javaLine++;
|
||||
index++;
|
||||
}
|
||||
|
||||
writer.print(s);
|
||||
}
|
||||
}
|
||||
-171
@@ -1,171 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Represents a source map (SMAP), which serves to associate lines
|
||||
* of the input JSP file(s) to lines in the generated servlet in the
|
||||
* final .class file, according to the JSR-045 spec.
|
||||
*
|
||||
* @author Shawn Bayern
|
||||
*/
|
||||
public class SmapGenerator {
|
||||
|
||||
//*********************************************************************
|
||||
// Overview
|
||||
|
||||
/*
|
||||
* The SMAP syntax is reasonably straightforward. The purpose of this
|
||||
* class is currently twofold:
|
||||
* - to provide a simple but low-level Java interface to build
|
||||
* a logical SMAP
|
||||
* - to serialize this logical SMAP for eventual inclusion directly
|
||||
* into a .class file.
|
||||
*/
|
||||
|
||||
|
||||
//*********************************************************************
|
||||
// Private state
|
||||
|
||||
private String outputFileName;
|
||||
private String defaultStratum = "Java";
|
||||
private List strata = new ArrayList();
|
||||
private List embedded = new ArrayList();
|
||||
private boolean doEmbedded = true;
|
||||
|
||||
//*********************************************************************
|
||||
// Methods for adding mapping data
|
||||
|
||||
/**
|
||||
* Sets the filename (without path information) for the generated
|
||||
* source file. E.g., "foo$jsp.java".
|
||||
*/
|
||||
public synchronized void setOutputFileName(String x) {
|
||||
outputFileName = x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given SmapStratum object, representing a Stratum with
|
||||
* logically associated FileSection and LineSection blocks, to
|
||||
* the current SmapGenerator. If <tt>default</tt> is true, this
|
||||
* stratum is made the default stratum, overriding any previously
|
||||
* set default.
|
||||
*
|
||||
* @param stratum the SmapStratum object to add
|
||||
* @param defaultStratum if <tt>true</tt>, this SmapStratum is considered
|
||||
* to represent the default SMAP stratum unless
|
||||
* overwritten
|
||||
*/
|
||||
public synchronized void addStratum(SmapStratum stratum,
|
||||
boolean defaultStratum) {
|
||||
strata.add(stratum);
|
||||
if (defaultStratum)
|
||||
this.defaultStratum = stratum.getStratumName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given string as an embedded SMAP with the given stratum name.
|
||||
*
|
||||
* @param smap the SMAP to embed
|
||||
* @param stratumName the name of the stratum output by the compilation
|
||||
* that produced the <tt>smap</tt> to be embedded
|
||||
*/
|
||||
public synchronized void addSmap(String smap, String stratumName) {
|
||||
embedded.add("*O " + stratumName + "\n"
|
||||
+ smap
|
||||
+ "*C " + stratumName + "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs the SmapGenerator whether to actually print any embedded
|
||||
* SMAPs or not. Intended for situations without an SMAP resolver.
|
||||
*
|
||||
* @param status If <tt>false</tt>, ignore any embedded SMAPs.
|
||||
*/
|
||||
public void setDoEmbedded(boolean status) {
|
||||
doEmbedded = status;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
// Methods for serializing the logical SMAP
|
||||
|
||||
public synchronized String getString() {
|
||||
// check state and initialize buffer
|
||||
if (outputFileName == null)
|
||||
throw new IllegalStateException();
|
||||
StringBuffer out = new StringBuffer();
|
||||
|
||||
// start the SMAP
|
||||
out.append("SMAP\n");
|
||||
out.append(outputFileName + '\n');
|
||||
out.append(defaultStratum + '\n');
|
||||
|
||||
// include embedded SMAPs
|
||||
if (doEmbedded) {
|
||||
int nEmbedded = embedded.size();
|
||||
for (int i = 0; i < nEmbedded; i++) {
|
||||
out.append(embedded.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
// print our StratumSections, FileSections, and LineSections
|
||||
int nStrata = strata.size();
|
||||
for (int i = 0; i < nStrata; i++) {
|
||||
SmapStratum s = (SmapStratum) strata.get(i);
|
||||
out.append(s.getString());
|
||||
}
|
||||
|
||||
// end the SMAP
|
||||
out.append("*E\n");
|
||||
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
public String toString() { return getString(); }
|
||||
|
||||
//*********************************************************************
|
||||
// For testing (and as an example of use)...
|
||||
|
||||
public static void main(String args[]) {
|
||||
SmapGenerator g = new SmapGenerator();
|
||||
g.setOutputFileName("foo.java");
|
||||
SmapStratum s = new SmapStratum("JSP");
|
||||
s.addFile("foo.jsp");
|
||||
s.addFile("bar.jsp", "/foo/foo/bar.jsp");
|
||||
s.addLineData(1, "foo.jsp", 1, 1, 1);
|
||||
s.addLineData(2, "foo.jsp", 1, 6, 1);
|
||||
s.addLineData(3, "foo.jsp", 2, 10, 5);
|
||||
s.addLineData(20, "bar.jsp", 1, 30, 1);
|
||||
g.addStratum(s, true);
|
||||
System.out.print(g);
|
||||
|
||||
System.out.println("---");
|
||||
|
||||
SmapGenerator embedded = new SmapGenerator();
|
||||
embedded.setOutputFileName("blargh.tier2");
|
||||
s = new SmapStratum("Tier2");
|
||||
s.addFile("1.tier2");
|
||||
s.addLineData(1, "1.tier2", 1, 1, 1);
|
||||
embedded.addStratum(s, true);
|
||||
g.addSmap(embedded.toString(), "JSP");
|
||||
System.out.println(g);
|
||||
}
|
||||
}
|
||||
-336
@@ -1,336 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Represents the line and file mappings associated with a JSR-045
|
||||
* "stratum".
|
||||
*
|
||||
* @author Jayson Falkner
|
||||
* @author Shawn Bayern
|
||||
*/
|
||||
public class SmapStratum {
|
||||
|
||||
//*********************************************************************
|
||||
// Class for storing LineInfo data
|
||||
|
||||
/**
|
||||
* Represents a single LineSection in an SMAP, associated with
|
||||
* a particular stratum.
|
||||
*/
|
||||
public static class LineInfo {
|
||||
private int inputStartLine = -1;
|
||||
private int outputStartLine = -1;
|
||||
private int lineFileID = 0;
|
||||
private int inputLineCount = 1;
|
||||
private int outputLineIncrement = 1;
|
||||
private boolean lineFileIDSet = false;
|
||||
|
||||
/** Sets InputStartLine. */
|
||||
public void setInputStartLine(int inputStartLine) {
|
||||
if (inputStartLine < 0)
|
||||
throw new IllegalArgumentException("" + inputStartLine);
|
||||
this.inputStartLine = inputStartLine;
|
||||
}
|
||||
|
||||
/** Sets OutputStartLine. */
|
||||
public void setOutputStartLine(int outputStartLine) {
|
||||
if (outputStartLine < 0)
|
||||
throw new IllegalArgumentException("" + outputStartLine);
|
||||
this.outputStartLine = outputStartLine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets lineFileID. Should be called only when different from
|
||||
* that of prior LineInfo object (in any given context) or 0
|
||||
* if the current LineInfo has no (logical) predecessor.
|
||||
* <tt>LineInfo</tt> will print this file number no matter what.
|
||||
*/
|
||||
public void setLineFileID(int lineFileID) {
|
||||
if (lineFileID < 0)
|
||||
throw new IllegalArgumentException("" + lineFileID);
|
||||
this.lineFileID = lineFileID;
|
||||
this.lineFileIDSet = true;
|
||||
}
|
||||
|
||||
/** Sets InputLineCount. */
|
||||
public void setInputLineCount(int inputLineCount) {
|
||||
if (inputLineCount < 0)
|
||||
throw new IllegalArgumentException("" + inputLineCount);
|
||||
this.inputLineCount = inputLineCount;
|
||||
}
|
||||
|
||||
/** Sets OutputLineIncrement. */
|
||||
public void setOutputLineIncrement(int outputLineIncrement) {
|
||||
if (outputLineIncrement < 0)
|
||||
throw new IllegalArgumentException("" + outputLineIncrement);
|
||||
this.outputLineIncrement = outputLineIncrement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current LineInfo as a String, print all values
|
||||
* only when appropriate (but LineInfoID if and only if it's been
|
||||
* specified, as its necessity is sensitive to context).
|
||||
*/
|
||||
public String getString() {
|
||||
if (inputStartLine == -1 || outputStartLine == -1)
|
||||
throw new IllegalStateException();
|
||||
StringBuffer out = new StringBuffer();
|
||||
out.append(inputStartLine);
|
||||
if (lineFileIDSet)
|
||||
out.append("#" + lineFileID);
|
||||
if (inputLineCount != 1)
|
||||
out.append("," + inputLineCount);
|
||||
out.append(":" + outputStartLine);
|
||||
if (outputLineIncrement != 1)
|
||||
out.append("," + outputLineIncrement);
|
||||
out.append('\n');
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getString();
|
||||
}
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
// Private state
|
||||
|
||||
private String stratumName;
|
||||
private List fileNameList;
|
||||
private List filePathList;
|
||||
private List lineData;
|
||||
private int lastFileID;
|
||||
|
||||
//*********************************************************************
|
||||
// Constructor
|
||||
|
||||
/**
|
||||
* Constructs a new SmapStratum object for the given stratum name
|
||||
* (e.g., JSP).
|
||||
*
|
||||
* @param stratumName the name of the stratum (e.g., JSP)
|
||||
*/
|
||||
public SmapStratum(String stratumName) {
|
||||
this.stratumName = stratumName;
|
||||
fileNameList = new ArrayList();
|
||||
filePathList = new ArrayList();
|
||||
lineData = new ArrayList();
|
||||
lastFileID = 0;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
// Methods to add mapping information
|
||||
|
||||
/**
|
||||
* Adds record of a new file, by filename.
|
||||
*
|
||||
* @param filename the filename to add, unqualified by path.
|
||||
*/
|
||||
public void addFile(String filename) {
|
||||
addFile(filename, filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds record of a new file, by filename and path. The path
|
||||
* may be relative to a source compilation path.
|
||||
*
|
||||
* @param filename the filename to add, unqualified by path
|
||||
* @param filePath the path for the filename, potentially relative
|
||||
* to a source compilation path
|
||||
*/
|
||||
public void addFile(String filename, String filePath) {
|
||||
int pathIndex = filePathList.indexOf(filePath);
|
||||
if (pathIndex == -1) {
|
||||
fileNameList.add(filename);
|
||||
filePathList.add(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines consecutive LineInfos wherever possible
|
||||
*/
|
||||
public void optimizeLineSection() {
|
||||
|
||||
/* Some debugging code
|
||||
for (int i = 0; i < lineData.size(); i++) {
|
||||
LineInfo li = (LineInfo)lineData.get(i);
|
||||
System.out.print(li.toString());
|
||||
}
|
||||
*/
|
||||
//Incorporate each LineInfo into the previous LineInfo's
|
||||
//outputLineIncrement, if possible
|
||||
int i = 0;
|
||||
while (i < lineData.size() - 1) {
|
||||
LineInfo li = (LineInfo)lineData.get(i);
|
||||
LineInfo liNext = (LineInfo)lineData.get(i + 1);
|
||||
if (!liNext.lineFileIDSet
|
||||
&& liNext.inputStartLine == li.inputStartLine
|
||||
&& liNext.inputLineCount == 1
|
||||
&& li.inputLineCount == 1
|
||||
&& liNext.outputStartLine
|
||||
== li.outputStartLine
|
||||
+ li.inputLineCount * li.outputLineIncrement) {
|
||||
li.setOutputLineIncrement(
|
||||
liNext.outputStartLine
|
||||
- li.outputStartLine
|
||||
+ liNext.outputLineIncrement);
|
||||
lineData.remove(i + 1);
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
//Incorporate each LineInfo into the previous LineInfo's
|
||||
//inputLineCount, if possible
|
||||
i = 0;
|
||||
while (i < lineData.size() - 1) {
|
||||
LineInfo li = (LineInfo)lineData.get(i);
|
||||
LineInfo liNext = (LineInfo)lineData.get(i + 1);
|
||||
if (!liNext.lineFileIDSet
|
||||
&& liNext.inputStartLine == li.inputStartLine + li.inputLineCount
|
||||
&& liNext.outputLineIncrement == li.outputLineIncrement
|
||||
&& liNext.outputStartLine
|
||||
== li.outputStartLine
|
||||
+ li.inputLineCount * li.outputLineIncrement) {
|
||||
li.setInputLineCount(li.inputLineCount + liNext.inputLineCount);
|
||||
lineData.remove(i + 1);
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds complete information about a simple line mapping. Specify
|
||||
* all the fields in this method; the back-end machinery takes care
|
||||
* of printing only those that are necessary in the final SMAP.
|
||||
* (My view is that fields are optional primarily for spatial efficiency,
|
||||
* not for programmer convenience. Could always add utility methods
|
||||
* later.)
|
||||
*
|
||||
* @param inputStartLine starting line in the source file
|
||||
* (SMAP <tt>InputStartLine</tt>)
|
||||
* @param inputFileName the filepath (or name) from which the input comes
|
||||
* (yields SMAP <tt>LineFileID</tt>) Use unqualified names
|
||||
* carefully, and only when they uniquely identify a file.
|
||||
* @param inputLineCount the number of lines in the input to map
|
||||
* (SMAP <tt>LineFileCount</tt>)
|
||||
* @param outputStartLine starting line in the output file
|
||||
* (SMAP <tt>OutputStartLine</tt>)
|
||||
* @param outputLineIncrement number of output lines to map to each
|
||||
* input line (SMAP <tt>OutputLineIncrement</tt>). <i>Given the
|
||||
* fact that the name starts with "output", I continuously have
|
||||
* the subconscious urge to call this field
|
||||
* <tt>OutputLineExcrement</tt>.</i>
|
||||
*/
|
||||
public void addLineData(
|
||||
int inputStartLine,
|
||||
String inputFileName,
|
||||
int inputLineCount,
|
||||
int outputStartLine,
|
||||
int outputLineIncrement) {
|
||||
// check the input - what are you doing here??
|
||||
int fileIndex = filePathList.indexOf(inputFileName);
|
||||
if (fileIndex == -1) // still
|
||||
throw new IllegalArgumentException(
|
||||
"inputFileName: " + inputFileName);
|
||||
|
||||
//Jasper incorrectly SMAPs certain Nodes, giving them an
|
||||
//outputStartLine of 0. This can cause a fatal error in
|
||||
//optimizeLineSection, making it impossible for Jasper to
|
||||
//compile the JSP. Until we can fix the underlying
|
||||
//SMAPping problem, we simply ignore the flawed SMAP entries.
|
||||
if (outputStartLine == 0)
|
||||
return;
|
||||
|
||||
// build the LineInfo
|
||||
LineInfo li = new LineInfo();
|
||||
li.setInputStartLine(inputStartLine);
|
||||
li.setInputLineCount(inputLineCount);
|
||||
li.setOutputStartLine(outputStartLine);
|
||||
li.setOutputLineIncrement(outputLineIncrement);
|
||||
if (fileIndex != lastFileID)
|
||||
li.setLineFileID(fileIndex);
|
||||
lastFileID = fileIndex;
|
||||
|
||||
// save it
|
||||
lineData.add(li);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
// Methods to retrieve information
|
||||
|
||||
/**
|
||||
* Returns the name of the stratum.
|
||||
*/
|
||||
public String getStratumName() {
|
||||
return stratumName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the given stratum as a String: a StratumSection,
|
||||
* followed by at least one FileSection and at least one LineSection.
|
||||
*/
|
||||
public String getString() {
|
||||
// check state and initialize buffer
|
||||
if (fileNameList.size() == 0 || lineData.size() == 0)
|
||||
return null;
|
||||
|
||||
StringBuffer out = new StringBuffer();
|
||||
|
||||
// print StratumSection
|
||||
out.append("*S " + stratumName + "\n");
|
||||
|
||||
// print FileSection
|
||||
out.append("*F\n");
|
||||
int bound = fileNameList.size();
|
||||
for (int i = 0; i < bound; i++) {
|
||||
if (filePathList.get(i) != null) {
|
||||
out.append("+ " + i + " " + fileNameList.get(i) + "\n");
|
||||
// Source paths must be relative, not absolute, so we
|
||||
// remove the leading "/", if one exists.
|
||||
String filePath = (String)filePathList.get(i);
|
||||
if (filePath.startsWith("/")) {
|
||||
filePath = filePath.substring(1);
|
||||
}
|
||||
out.append(filePath + "\n");
|
||||
} else {
|
||||
out.append(i + " " + fileNameList.get(i) + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
// print LineSection
|
||||
out.append("*L\n");
|
||||
bound = lineData.size();
|
||||
for (int i = 0; i < bound; i++) {
|
||||
LineInfo li = (LineInfo)lineData.get(i);
|
||||
out.append(li.getString());
|
||||
}
|
||||
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,729 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.jasper.JasperException;
|
||||
import org.apache.jasper.JspCompilationContext;
|
||||
|
||||
/**
|
||||
* Contains static utilities for generating SMAP data based on the
|
||||
* current version of Jasper.
|
||||
*
|
||||
* @author Jayson Falkner
|
||||
* @author Shawn Bayern
|
||||
* @author Robert Field (inner SDEInstaller class)
|
||||
* @author Mark Roth
|
||||
* @author Kin-man Chung
|
||||
*/
|
||||
public class SmapUtil {
|
||||
|
||||
private org.apache.juli.logging.Log log=
|
||||
org.apache.juli.logging.LogFactory.getLog( SmapUtil.class );
|
||||
|
||||
//*********************************************************************
|
||||
// Constants
|
||||
|
||||
public static final String SMAP_ENCODING = "UTF-8";
|
||||
|
||||
//*********************************************************************
|
||||
// Public entry points
|
||||
|
||||
/**
|
||||
* Generates an appropriate SMAP representing the current compilation
|
||||
* context. (JSR-045.)
|
||||
*
|
||||
* @param ctxt Current compilation context
|
||||
* @param pageNodes The current JSP page
|
||||
* @return a SMAP for the page
|
||||
*/
|
||||
public static String[] generateSmap(
|
||||
JspCompilationContext ctxt,
|
||||
Node.Nodes pageNodes)
|
||||
throws IOException {
|
||||
|
||||
// Scan the nodes for presence of Jasper generated inner classes
|
||||
PreScanVisitor psVisitor = new PreScanVisitor();
|
||||
try {
|
||||
pageNodes.visit(psVisitor);
|
||||
} catch (JasperException ex) {
|
||||
}
|
||||
HashMap map = psVisitor.getMap();
|
||||
|
||||
// set up our SMAP generator
|
||||
SmapGenerator g = new SmapGenerator();
|
||||
|
||||
/** Disable reading of input SMAP because:
|
||||
1. There is a bug here: getRealPath() is null if .jsp is in a jar
|
||||
Bugzilla 14660.
|
||||
2. Mappings from other sources into .jsp files are not supported.
|
||||
TODO: fix 1. if 2. is not true.
|
||||
// determine if we have an input SMAP
|
||||
String smapPath = inputSmapPath(ctxt.getRealPath(ctxt.getJspFile()));
|
||||
File inputSmap = new File(smapPath);
|
||||
if (inputSmap.exists()) {
|
||||
byte[] embeddedSmap = null;
|
||||
byte[] subSmap = SDEInstaller.readWhole(inputSmap);
|
||||
String subSmapString = new String(subSmap, SMAP_ENCODING);
|
||||
g.addSmap(subSmapString, "JSP");
|
||||
}
|
||||
**/
|
||||
|
||||
// now, assemble info about our own stratum (JSP) using JspLineMap
|
||||
SmapStratum s = new SmapStratum("JSP");
|
||||
|
||||
g.setOutputFileName(unqualify(ctxt.getServletJavaFileName()));
|
||||
|
||||
// Map out Node.Nodes
|
||||
evaluateNodes(pageNodes, s, map, ctxt.getOptions().getMappedFile());
|
||||
s.optimizeLineSection();
|
||||
g.addStratum(s, true);
|
||||
|
||||
if (ctxt.getOptions().isSmapDumped()) {
|
||||
File outSmap = new File(ctxt.getClassFileName() + ".smap");
|
||||
PrintWriter so =
|
||||
new PrintWriter(
|
||||
new OutputStreamWriter(
|
||||
new FileOutputStream(outSmap),
|
||||
SMAP_ENCODING));
|
||||
so.print(g.getString());
|
||||
so.close();
|
||||
}
|
||||
|
||||
String classFileName = ctxt.getClassFileName();
|
||||
int innerClassCount = map.size();
|
||||
String [] smapInfo = new String[2 + innerClassCount*2];
|
||||
smapInfo[0] = classFileName;
|
||||
smapInfo[1] = g.getString();
|
||||
|
||||
int count = 2;
|
||||
Iterator iter = map.entrySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
Map.Entry entry = (Map.Entry) iter.next();
|
||||
String innerClass = (String) entry.getKey();
|
||||
s = (SmapStratum) entry.getValue();
|
||||
s.optimizeLineSection();
|
||||
g = new SmapGenerator();
|
||||
g.setOutputFileName(unqualify(ctxt.getServletJavaFileName()));
|
||||
g.addStratum(s, true);
|
||||
|
||||
String innerClassFileName =
|
||||
classFileName.substring(0, classFileName.indexOf(".class")) +
|
||||
'$' + innerClass + ".class";
|
||||
if (ctxt.getOptions().isSmapDumped()) {
|
||||
File outSmap = new File(innerClassFileName + ".smap");
|
||||
PrintWriter so =
|
||||
new PrintWriter(
|
||||
new OutputStreamWriter(
|
||||
new FileOutputStream(outSmap),
|
||||
SMAP_ENCODING));
|
||||
so.print(g.getString());
|
||||
so.close();
|
||||
}
|
||||
smapInfo[count] = innerClassFileName;
|
||||
smapInfo[count+1] = g.getString();
|
||||
count += 2;
|
||||
}
|
||||
|
||||
return smapInfo;
|
||||
}
|
||||
|
||||
public static void installSmap(String[] smap)
|
||||
throws IOException {
|
||||
if (smap == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < smap.length; i += 2) {
|
||||
File outServlet = new File(smap[i]);
|
||||
SDEInstaller.install(outServlet, smap[i+1].getBytes());
|
||||
}
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
// Private utilities
|
||||
|
||||
/**
|
||||
* Returns an unqualified version of the given file path.
|
||||
*/
|
||||
private static String unqualify(String path) {
|
||||
path = path.replace('\\', '/');
|
||||
return path.substring(path.lastIndexOf('/') + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a file path corresponding to a potential SMAP input
|
||||
* for the given compilation input (JSP file).
|
||||
*/
|
||||
private static String inputSmapPath(String path) {
|
||||
return path.substring(0, path.lastIndexOf('.') + 1) + "smap";
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
// Installation logic (from Robert Field, JSR-045 spec lead)
|
||||
private static class SDEInstaller {
|
||||
|
||||
private org.apache.juli.logging.Log log=
|
||||
org.apache.juli.logging.LogFactory.getLog( SDEInstaller.class );
|
||||
|
||||
static final String nameSDE = "SourceDebugExtension";
|
||||
|
||||
byte[] orig;
|
||||
byte[] sdeAttr;
|
||||
byte[] gen;
|
||||
|
||||
int origPos = 0;
|
||||
int genPos = 0;
|
||||
|
||||
int sdeIndex;
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
if (args.length == 2) {
|
||||
install(new File(args[0]), new File(args[1]));
|
||||
} else if (args.length == 3) {
|
||||
install(
|
||||
new File(args[0]),
|
||||
new File(args[1]),
|
||||
new File(args[2]));
|
||||
} else {
|
||||
System.err.println(
|
||||
"Usage: <command> <input class file> "
|
||||
+ "<attribute file> <output class file name>\n"
|
||||
+ "<command> <input/output class file> <attribute file>");
|
||||
}
|
||||
}
|
||||
|
||||
static void install(File inClassFile, File attrFile, File outClassFile)
|
||||
throws IOException {
|
||||
new SDEInstaller(inClassFile, attrFile, outClassFile);
|
||||
}
|
||||
|
||||
static void install(File inOutClassFile, File attrFile)
|
||||
throws IOException {
|
||||
File tmpFile = new File(inOutClassFile.getPath() + "tmp");
|
||||
new SDEInstaller(inOutClassFile, attrFile, tmpFile);
|
||||
if (!inOutClassFile.delete()) {
|
||||
throw new IOException("inOutClassFile.delete() failed");
|
||||
}
|
||||
if (!tmpFile.renameTo(inOutClassFile)) {
|
||||
throw new IOException("tmpFile.renameTo(inOutClassFile) failed");
|
||||
}
|
||||
}
|
||||
|
||||
static void install(File classFile, byte[] smap) throws IOException {
|
||||
File tmpFile = new File(classFile.getPath() + "tmp");
|
||||
new SDEInstaller(classFile, smap, tmpFile);
|
||||
if (!classFile.delete()) {
|
||||
throw new IOException("classFile.delete() failed");
|
||||
}
|
||||
if (!tmpFile.renameTo(classFile)) {
|
||||
throw new IOException("tmpFile.renameTo(classFile) failed");
|
||||
}
|
||||
}
|
||||
|
||||
SDEInstaller(File inClassFile, byte[] sdeAttr, File outClassFile)
|
||||
throws IOException {
|
||||
if (!inClassFile.exists()) {
|
||||
throw new FileNotFoundException("no such file: " + inClassFile);
|
||||
}
|
||||
|
||||
this.sdeAttr = sdeAttr;
|
||||
// get the bytes
|
||||
orig = readWhole(inClassFile);
|
||||
gen = new byte[orig.length + sdeAttr.length + 100];
|
||||
|
||||
// do it
|
||||
addSDE();
|
||||
|
||||
// write result
|
||||
FileOutputStream outStream = new FileOutputStream(outClassFile);
|
||||
outStream.write(gen, 0, genPos);
|
||||
outStream.close();
|
||||
}
|
||||
|
||||
SDEInstaller(File inClassFile, File attrFile, File outClassFile)
|
||||
throws IOException {
|
||||
this(inClassFile, readWhole(attrFile), outClassFile);
|
||||
}
|
||||
|
||||
static byte[] readWhole(File input) throws IOException {
|
||||
FileInputStream inStream = new FileInputStream(input);
|
||||
int len = (int)input.length();
|
||||
byte[] bytes = new byte[len];
|
||||
if (inStream.read(bytes, 0, len) != len) {
|
||||
throw new IOException("expected size: " + len);
|
||||
}
|
||||
inStream.close();
|
||||
return bytes;
|
||||
}
|
||||
|
||||
void addSDE() throws UnsupportedEncodingException, IOException {
|
||||
int i;
|
||||
copy(4 + 2 + 2); // magic min/maj version
|
||||
int constantPoolCountPos = genPos;
|
||||
int constantPoolCount = readU2();
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("constant pool count: " + constantPoolCount);
|
||||
writeU2(constantPoolCount);
|
||||
|
||||
// copy old constant pool return index of SDE symbol, if found
|
||||
sdeIndex = copyConstantPool(constantPoolCount);
|
||||
if (sdeIndex < 0) {
|
||||
// if "SourceDebugExtension" symbol not there add it
|
||||
writeUtf8ForSDE();
|
||||
|
||||
// increment the countantPoolCount
|
||||
sdeIndex = constantPoolCount;
|
||||
++constantPoolCount;
|
||||
randomAccessWriteU2(constantPoolCountPos, constantPoolCount);
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("SourceDebugExtension not found, installed at: " + sdeIndex);
|
||||
} else {
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("SourceDebugExtension found at: " + sdeIndex);
|
||||
}
|
||||
copy(2 + 2 + 2); // access, this, super
|
||||
int interfaceCount = readU2();
|
||||
writeU2(interfaceCount);
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("interfaceCount: " + interfaceCount);
|
||||
copy(interfaceCount * 2);
|
||||
copyMembers(); // fields
|
||||
copyMembers(); // methods
|
||||
int attrCountPos = genPos;
|
||||
int attrCount = readU2();
|
||||
writeU2(attrCount);
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("class attrCount: " + attrCount);
|
||||
// copy the class attributes, return true if SDE attr found (not copied)
|
||||
if (!copyAttrs(attrCount)) {
|
||||
// we will be adding SDE and it isn't already counted
|
||||
++attrCount;
|
||||
randomAccessWriteU2(attrCountPos, attrCount);
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("class attrCount incremented");
|
||||
}
|
||||
writeAttrForSDE(sdeIndex);
|
||||
}
|
||||
|
||||
void copyMembers() {
|
||||
int count = readU2();
|
||||
writeU2(count);
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("members count: " + count);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
copy(6); // access, name, descriptor
|
||||
int attrCount = readU2();
|
||||
writeU2(attrCount);
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("member attr count: " + attrCount);
|
||||
copyAttrs(attrCount);
|
||||
}
|
||||
}
|
||||
|
||||
boolean copyAttrs(int attrCount) {
|
||||
boolean sdeFound = false;
|
||||
for (int i = 0; i < attrCount; ++i) {
|
||||
int nameIndex = readU2();
|
||||
// don't write old SDE
|
||||
if (nameIndex == sdeIndex) {
|
||||
sdeFound = true;
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("SDE attr found");
|
||||
} else {
|
||||
writeU2(nameIndex); // name
|
||||
int len = readU4();
|
||||
writeU4(len);
|
||||
copy(len);
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("attr len: " + len);
|
||||
}
|
||||
}
|
||||
return sdeFound;
|
||||
}
|
||||
|
||||
void writeAttrForSDE(int index) {
|
||||
writeU2(index);
|
||||
writeU4(sdeAttr.length);
|
||||
for (int i = 0; i < sdeAttr.length; ++i) {
|
||||
writeU1(sdeAttr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void randomAccessWriteU2(int pos, int val) {
|
||||
int savePos = genPos;
|
||||
genPos = pos;
|
||||
writeU2(val);
|
||||
genPos = savePos;
|
||||
}
|
||||
|
||||
int readU1() {
|
||||
return ((int)orig[origPos++]) & 0xFF;
|
||||
}
|
||||
|
||||
int readU2() {
|
||||
int res = readU1();
|
||||
return (res << 8) + readU1();
|
||||
}
|
||||
|
||||
int readU4() {
|
||||
int res = readU2();
|
||||
return (res << 16) + readU2();
|
||||
}
|
||||
|
||||
void writeU1(int val) {
|
||||
gen[genPos++] = (byte)val;
|
||||
}
|
||||
|
||||
void writeU2(int val) {
|
||||
writeU1(val >> 8);
|
||||
writeU1(val & 0xFF);
|
||||
}
|
||||
|
||||
void writeU4(int val) {
|
||||
writeU2(val >> 16);
|
||||
writeU2(val & 0xFFFF);
|
||||
}
|
||||
|
||||
void copy(int count) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
gen[genPos++] = orig[origPos++];
|
||||
}
|
||||
}
|
||||
|
||||
byte[] readBytes(int count) {
|
||||
byte[] bytes = new byte[count];
|
||||
for (int i = 0; i < count; ++i) {
|
||||
bytes[i] = orig[origPos++];
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
void writeBytes(byte[] bytes) {
|
||||
for (int i = 0; i < bytes.length; ++i) {
|
||||
gen[genPos++] = bytes[i];
|
||||
}
|
||||
}
|
||||
|
||||
int copyConstantPool(int constantPoolCount)
|
||||
throws UnsupportedEncodingException, IOException {
|
||||
int sdeIndex = -1;
|
||||
// copy const pool index zero not in class file
|
||||
for (int i = 1; i < constantPoolCount; ++i) {
|
||||
int tag = readU1();
|
||||
writeU1(tag);
|
||||
switch (tag) {
|
||||
case 7 : // Class
|
||||
case 8 : // String
|
||||
if (log.isDebugEnabled())
|
||||
log.debug(i + " copying 2 bytes");
|
||||
copy(2);
|
||||
break;
|
||||
case 9 : // Field
|
||||
case 10 : // Method
|
||||
case 11 : // InterfaceMethod
|
||||
case 3 : // Integer
|
||||
case 4 : // Float
|
||||
case 12 : // NameAndType
|
||||
if (log.isDebugEnabled())
|
||||
log.debug(i + " copying 4 bytes");
|
||||
copy(4);
|
||||
break;
|
||||
case 5 : // Long
|
||||
case 6 : // Double
|
||||
if (log.isDebugEnabled())
|
||||
log.debug(i + " copying 8 bytes");
|
||||
copy(8);
|
||||
i++;
|
||||
break;
|
||||
case 1 : // Utf8
|
||||
int len = readU2();
|
||||
writeU2(len);
|
||||
byte[] utf8 = readBytes(len);
|
||||
String str = new String(utf8, "UTF-8");
|
||||
if (log.isDebugEnabled())
|
||||
log.debug(i + " read class attr -- '" + str + "'");
|
||||
if (str.equals(nameSDE)) {
|
||||
sdeIndex = i;
|
||||
}
|
||||
writeBytes(utf8);
|
||||
break;
|
||||
default :
|
||||
throw new IOException("unexpected tag: " + tag);
|
||||
}
|
||||
}
|
||||
return sdeIndex;
|
||||
}
|
||||
|
||||
void writeUtf8ForSDE() {
|
||||
int len = nameSDE.length();
|
||||
writeU1(1); // Utf8 tag
|
||||
writeU2(len);
|
||||
for (int i = 0; i < len; ++i) {
|
||||
writeU1(nameSDE.charAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void evaluateNodes(
|
||||
Node.Nodes nodes,
|
||||
SmapStratum s,
|
||||
HashMap innerClassMap,
|
||||
boolean breakAtLF) {
|
||||
try {
|
||||
nodes.visit(new SmapGenVisitor(s, breakAtLF, innerClassMap));
|
||||
} catch (JasperException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
static class SmapGenVisitor extends Node.Visitor {
|
||||
|
||||
private SmapStratum smap;
|
||||
private boolean breakAtLF;
|
||||
private HashMap innerClassMap;
|
||||
|
||||
SmapGenVisitor(SmapStratum s, boolean breakAtLF, HashMap map) {
|
||||
this.smap = s;
|
||||
this.breakAtLF = breakAtLF;
|
||||
this.innerClassMap = map;
|
||||
}
|
||||
|
||||
public void visitBody(Node n) throws JasperException {
|
||||
SmapStratum smapSave = smap;
|
||||
String innerClass = n.getInnerClassName();
|
||||
if (innerClass != null) {
|
||||
this.smap = (SmapStratum) innerClassMap.get(innerClass);
|
||||
}
|
||||
super.visitBody(n);
|
||||
smap = smapSave;
|
||||
}
|
||||
|
||||
public void visit(Node.Declaration n) throws JasperException {
|
||||
doSmapText(n);
|
||||
}
|
||||
|
||||
public void visit(Node.Expression n) throws JasperException {
|
||||
doSmapText(n);
|
||||
}
|
||||
|
||||
public void visit(Node.Scriptlet n) throws JasperException {
|
||||
doSmapText(n);
|
||||
}
|
||||
|
||||
public void visit(Node.IncludeAction n) throws JasperException {
|
||||
doSmap(n);
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.ForwardAction n) throws JasperException {
|
||||
doSmap(n);
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.GetProperty n) throws JasperException {
|
||||
doSmap(n);
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.SetProperty n) throws JasperException {
|
||||
doSmap(n);
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.UseBean n) throws JasperException {
|
||||
doSmap(n);
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.PlugIn n) throws JasperException {
|
||||
doSmap(n);
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.CustomTag n) throws JasperException {
|
||||
doSmap(n);
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.UninterpretedTag n) throws JasperException {
|
||||
doSmap(n);
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.JspElement n) throws JasperException {
|
||||
doSmap(n);
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.JspText n) throws JasperException {
|
||||
doSmap(n);
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.NamedAttribute n) throws JasperException {
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.JspBody n) throws JasperException {
|
||||
doSmap(n);
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.InvokeAction n) throws JasperException {
|
||||
doSmap(n);
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.DoBodyAction n) throws JasperException {
|
||||
doSmap(n);
|
||||
visitBody(n);
|
||||
}
|
||||
|
||||
public void visit(Node.ELExpression n) throws JasperException {
|
||||
doSmap(n);
|
||||
}
|
||||
|
||||
public void visit(Node.TemplateText n) throws JasperException {
|
||||
Mark mark = n.getStart();
|
||||
if (mark == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Add the file information
|
||||
String fileName = mark.getFile();
|
||||
smap.addFile(unqualify(fileName), fileName);
|
||||
|
||||
//Add a LineInfo that corresponds to the beginning of this node
|
||||
int iInputStartLine = mark.getLineNumber();
|
||||
int iOutputStartLine = n.getBeginJavaLine();
|
||||
int iOutputLineIncrement = breakAtLF? 1: 0;
|
||||
smap.addLineData(iInputStartLine, fileName, 1, iOutputStartLine,
|
||||
iOutputLineIncrement);
|
||||
|
||||
// Output additional mappings in the text
|
||||
java.util.ArrayList extraSmap = n.getExtraSmap();
|
||||
|
||||
if (extraSmap != null) {
|
||||
for (int i = 0; i < extraSmap.size(); i++) {
|
||||
iOutputStartLine += iOutputLineIncrement;
|
||||
smap.addLineData(
|
||||
iInputStartLine+((Integer)extraSmap.get(i)).intValue(),
|
||||
fileName,
|
||||
1,
|
||||
iOutputStartLine,
|
||||
iOutputLineIncrement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void doSmap(
|
||||
Node n,
|
||||
int inLineCount,
|
||||
int outIncrement,
|
||||
int skippedLines) {
|
||||
Mark mark = n.getStart();
|
||||
if (mark == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String unqualifiedName = unqualify(mark.getFile());
|
||||
smap.addFile(unqualifiedName, mark.getFile());
|
||||
smap.addLineData(
|
||||
mark.getLineNumber() + skippedLines,
|
||||
mark.getFile(),
|
||||
inLineCount - skippedLines,
|
||||
n.getBeginJavaLine() + skippedLines,
|
||||
outIncrement);
|
||||
}
|
||||
|
||||
private void doSmap(Node n) {
|
||||
doSmap(n, 1, n.getEndJavaLine() - n.getBeginJavaLine(), 0);
|
||||
}
|
||||
|
||||
private void doSmapText(Node n) {
|
||||
String text = n.getText();
|
||||
int index = 0;
|
||||
int next = 0;
|
||||
int lineCount = 1;
|
||||
int skippedLines = 0;
|
||||
boolean slashStarSeen = false;
|
||||
boolean beginning = true;
|
||||
|
||||
// Count lines inside text, but skipping comment lines at the
|
||||
// beginning of the text.
|
||||
while ((next = text.indexOf('\n', index)) > -1) {
|
||||
if (beginning) {
|
||||
String line = text.substring(index, next).trim();
|
||||
if (!slashStarSeen && line.startsWith("/*")) {
|
||||
slashStarSeen = true;
|
||||
}
|
||||
if (slashStarSeen) {
|
||||
skippedLines++;
|
||||
int endIndex = line.indexOf("*/");
|
||||
if (endIndex >= 0) {
|
||||
// End of /* */ comment
|
||||
slashStarSeen = false;
|
||||
if (endIndex < line.length() - 2) {
|
||||
// Some executable code after comment
|
||||
skippedLines--;
|
||||
beginning = false;
|
||||
}
|
||||
}
|
||||
} else if (line.length() == 0 || line.startsWith("//")) {
|
||||
skippedLines++;
|
||||
} else {
|
||||
beginning = false;
|
||||
}
|
||||
}
|
||||
lineCount++;
|
||||
index = next + 1;
|
||||
}
|
||||
|
||||
doSmap(n, lineCount, 1, skippedLines);
|
||||
}
|
||||
}
|
||||
|
||||
private static class PreScanVisitor extends Node.Visitor {
|
||||
|
||||
HashMap map = new HashMap();
|
||||
|
||||
public void doVisit(Node n) {
|
||||
String inner = n.getInnerClassName();
|
||||
if (inner != null && !map.containsKey(inner)) {
|
||||
map.put(inner, new SmapStratum("JSP"));
|
||||
}
|
||||
}
|
||||
|
||||
HashMap getMap() {
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-116
@@ -1,116 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
public interface TagConstants {
|
||||
|
||||
public static final String JSP_URI = "http://java.sun.com/JSP/Page";
|
||||
|
||||
public static final String DIRECTIVE_ACTION = "directive.";
|
||||
|
||||
public static final String ROOT_ACTION = "root";
|
||||
public static final String JSP_ROOT_ACTION = "jsp:root";
|
||||
|
||||
public static final String PAGE_DIRECTIVE_ACTION = "directive.page";
|
||||
public static final String JSP_PAGE_DIRECTIVE_ACTION = "jsp:directive.page";
|
||||
|
||||
public static final String INCLUDE_DIRECTIVE_ACTION = "directive.include";
|
||||
public static final String JSP_INCLUDE_DIRECTIVE_ACTION = "jsp:directive.include";
|
||||
|
||||
public static final String DECLARATION_ACTION = "declaration";
|
||||
public static final String JSP_DECLARATION_ACTION = "jsp:declaration";
|
||||
|
||||
public static final String SCRIPTLET_ACTION = "scriptlet";
|
||||
public static final String JSP_SCRIPTLET_ACTION = "jsp:scriptlet";
|
||||
|
||||
public static final String EXPRESSION_ACTION = "expression";
|
||||
public static final String JSP_EXPRESSION_ACTION = "jsp:expression";
|
||||
|
||||
public static final String USE_BEAN_ACTION = "useBean";
|
||||
public static final String JSP_USE_BEAN_ACTION = "jsp:useBean";
|
||||
|
||||
public static final String SET_PROPERTY_ACTION = "setProperty";
|
||||
public static final String JSP_SET_PROPERTY_ACTION = "jsp:setProperty";
|
||||
|
||||
public static final String GET_PROPERTY_ACTION = "getProperty";
|
||||
public static final String JSP_GET_PROPERTY_ACTION = "jsp:getProperty";
|
||||
|
||||
public static final String INCLUDE_ACTION = "include";
|
||||
public static final String JSP_INCLUDE_ACTION = "jsp:include";
|
||||
|
||||
public static final String FORWARD_ACTION = "forward";
|
||||
public static final String JSP_FORWARD_ACTION = "jsp:forward";
|
||||
|
||||
public static final String PARAM_ACTION = "param";
|
||||
public static final String JSP_PARAM_ACTION = "jsp:param";
|
||||
|
||||
public static final String PARAMS_ACTION = "params";
|
||||
public static final String JSP_PARAMS_ACTION = "jsp:params";
|
||||
|
||||
public static final String PLUGIN_ACTION = "plugin";
|
||||
public static final String JSP_PLUGIN_ACTION = "jsp:plugin";
|
||||
|
||||
public static final String FALLBACK_ACTION = "fallback";
|
||||
public static final String JSP_FALLBACK_ACTION = "jsp:fallback";
|
||||
|
||||
public static final String TEXT_ACTION = "text";
|
||||
public static final String JSP_TEXT_ACTION = "jsp:text";
|
||||
public static final String JSP_TEXT_ACTION_END = "</jsp:text>";
|
||||
|
||||
public static final String ATTRIBUTE_ACTION = "attribute";
|
||||
public static final String JSP_ATTRIBUTE_ACTION = "jsp:attribute";
|
||||
|
||||
public static final String BODY_ACTION = "body";
|
||||
public static final String JSP_BODY_ACTION = "jsp:body";
|
||||
|
||||
public static final String ELEMENT_ACTION = "element";
|
||||
public static final String JSP_ELEMENT_ACTION = "jsp:element";
|
||||
|
||||
public static final String OUTPUT_ACTION = "output";
|
||||
public static final String JSP_OUTPUT_ACTION = "jsp:output";
|
||||
|
||||
public static final String TAGLIB_DIRECTIVE_ACTION = "taglib";
|
||||
public static final String JSP_TAGLIB_DIRECTIVE_ACTION = "jsp:taglib";
|
||||
|
||||
/*
|
||||
* Tag Files
|
||||
*/
|
||||
public static final String INVOKE_ACTION = "invoke";
|
||||
public static final String JSP_INVOKE_ACTION = "jsp:invoke";
|
||||
|
||||
public static final String DOBODY_ACTION = "doBody";
|
||||
public static final String JSP_DOBODY_ACTION = "jsp:doBody";
|
||||
|
||||
/*
|
||||
* Tag File Directives
|
||||
*/
|
||||
public static final String TAG_DIRECTIVE_ACTION = "directive.tag";
|
||||
public static final String JSP_TAG_DIRECTIVE_ACTION = "jsp:directive.tag";
|
||||
|
||||
public static final String ATTRIBUTE_DIRECTIVE_ACTION = "directive.attribute";
|
||||
public static final String JSP_ATTRIBUTE_DIRECTIVE_ACTION = "jsp:directive.attribute";
|
||||
|
||||
public static final String VARIABLE_DIRECTIVE_ACTION = "directive.variable";
|
||||
public static final String JSP_VARIABLE_DIRECTIVE_ACTION = "jsp:directive.variable";
|
||||
|
||||
/*
|
||||
* Directive attributes
|
||||
*/
|
||||
public static final String URN_JSPTAGDIR = "urn:jsptagdir:";
|
||||
public static final String URN_JSPTLD = "urn:jsptld:";
|
||||
}
|
||||
-726
@@ -1,726 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.el.MethodExpression;
|
||||
import javax.el.ValueExpression;
|
||||
import javax.servlet.jsp.tagext.TagAttributeInfo;
|
||||
import javax.servlet.jsp.tagext.TagExtraInfo;
|
||||
import javax.servlet.jsp.tagext.TagFileInfo;
|
||||
import javax.servlet.jsp.tagext.TagInfo;
|
||||
import javax.servlet.jsp.tagext.TagLibraryInfo;
|
||||
import javax.servlet.jsp.tagext.TagVariableInfo;
|
||||
import javax.servlet.jsp.tagext.VariableInfo;
|
||||
|
||||
import org.apache.jasper.JasperException;
|
||||
import org.apache.jasper.JspCompilationContext;
|
||||
import org.apache.jasper.servlet.JspServletWrapper;
|
||||
import org.apache.jasper.runtime.JspSourceDependent;
|
||||
|
||||
/**
|
||||
* 1. Processes and extracts the directive info in a tag file. 2. Compiles and
|
||||
* loads tag files used in a JSP file.
|
||||
*
|
||||
* @author Kin-man Chung
|
||||
*/
|
||||
|
||||
class TagFileProcessor {
|
||||
|
||||
private Vector tempVector;
|
||||
|
||||
/**
|
||||
* A visitor the tag file
|
||||
*/
|
||||
private static class TagFileDirectiveVisitor extends Node.Visitor {
|
||||
|
||||
private static final JspUtil.ValidAttribute[] tagDirectiveAttrs = {
|
||||
new JspUtil.ValidAttribute("display-name"),
|
||||
new JspUtil.ValidAttribute("body-content"),
|
||||
new JspUtil.ValidAttribute("dynamic-attributes"),
|
||||
new JspUtil.ValidAttribute("small-icon"),
|
||||
new JspUtil.ValidAttribute("large-icon"),
|
||||
new JspUtil.ValidAttribute("description"),
|
||||
new JspUtil.ValidAttribute("example"),
|
||||
new JspUtil.ValidAttribute("pageEncoding"),
|
||||
new JspUtil.ValidAttribute("language"),
|
||||
new JspUtil.ValidAttribute("import"),
|
||||
new JspUtil.ValidAttribute("deferredSyntaxAllowedAsLiteral"), // JSP 2.1
|
||||
new JspUtil.ValidAttribute("trimDirectiveWhitespaces"), // JSP 2.1
|
||||
new JspUtil.ValidAttribute("isELIgnored") };
|
||||
|
||||
private static final JspUtil.ValidAttribute[] attributeDirectiveAttrs = {
|
||||
new JspUtil.ValidAttribute("name", true),
|
||||
new JspUtil.ValidAttribute("required"),
|
||||
new JspUtil.ValidAttribute("fragment"),
|
||||
new JspUtil.ValidAttribute("rtexprvalue"),
|
||||
new JspUtil.ValidAttribute("type"),
|
||||
new JspUtil.ValidAttribute("deferredValue"), // JSP 2.1
|
||||
new JspUtil.ValidAttribute("deferredValueType"), // JSP 2.1
|
||||
new JspUtil.ValidAttribute("deferredMethod"), // JSP 2
|
||||
new JspUtil.ValidAttribute("deferredMethodSignature"), // JSP 21
|
||||
new JspUtil.ValidAttribute("description") };
|
||||
|
||||
private static final JspUtil.ValidAttribute[] variableDirectiveAttrs = {
|
||||
new JspUtil.ValidAttribute("name-given"),
|
||||
new JspUtil.ValidAttribute("name-from-attribute"),
|
||||
new JspUtil.ValidAttribute("alias"),
|
||||
new JspUtil.ValidAttribute("variable-class"),
|
||||
new JspUtil.ValidAttribute("scope"),
|
||||
new JspUtil.ValidAttribute("declare"),
|
||||
new JspUtil.ValidAttribute("description") };
|
||||
|
||||
private ErrorDispatcher err;
|
||||
|
||||
private TagLibraryInfo tagLibInfo;
|
||||
|
||||
private String name = null;
|
||||
|
||||
private String path = null;
|
||||
|
||||
private TagExtraInfo tei = null;
|
||||
|
||||
private String bodycontent = null;
|
||||
|
||||
private String description = null;
|
||||
|
||||
private String displayName = null;
|
||||
|
||||
private String smallIcon = null;
|
||||
|
||||
private String largeIcon = null;
|
||||
|
||||
private String dynamicAttrsMapName;
|
||||
|
||||
private String example = null;
|
||||
|
||||
private Vector attributeVector;
|
||||
|
||||
private Vector variableVector;
|
||||
|
||||
private static final String ATTR_NAME = "the name attribute of the attribute directive";
|
||||
|
||||
private static final String VAR_NAME_GIVEN = "the name-given attribute of the variable directive";
|
||||
|
||||
private static final String VAR_NAME_FROM = "the name-from-attribute attribute of the variable directive";
|
||||
|
||||
private static final String VAR_ALIAS = "the alias attribute of the variable directive";
|
||||
|
||||
private static final String TAG_DYNAMIC = "the dynamic-attributes attribute of the tag directive";
|
||||
|
||||
private HashMap nameTable = new HashMap();
|
||||
|
||||
private HashMap nameFromTable = new HashMap();
|
||||
|
||||
public TagFileDirectiveVisitor(Compiler compiler,
|
||||
TagLibraryInfo tagLibInfo, String name, String path) {
|
||||
err = compiler.getErrorDispatcher();
|
||||
this.tagLibInfo = tagLibInfo;
|
||||
this.name = name;
|
||||
this.path = path;
|
||||
attributeVector = new Vector();
|
||||
variableVector = new Vector();
|
||||
}
|
||||
|
||||
public void visit(Node.TagDirective n) throws JasperException {
|
||||
|
||||
JspUtil.checkAttributes("Tag directive", n, tagDirectiveAttrs, err);
|
||||
|
||||
bodycontent = checkConflict(n, bodycontent, "body-content");
|
||||
if (bodycontent != null
|
||||
&& !bodycontent
|
||||
.equalsIgnoreCase(TagInfo.BODY_CONTENT_EMPTY)
|
||||
&& !bodycontent
|
||||
.equalsIgnoreCase(TagInfo.BODY_CONTENT_TAG_DEPENDENT)
|
||||
&& !bodycontent
|
||||
.equalsIgnoreCase(TagInfo.BODY_CONTENT_SCRIPTLESS)) {
|
||||
err.jspError(n, "jsp.error.tagdirective.badbodycontent",
|
||||
bodycontent);
|
||||
}
|
||||
dynamicAttrsMapName = checkConflict(n, dynamicAttrsMapName,
|
||||
"dynamic-attributes");
|
||||
if (dynamicAttrsMapName != null) {
|
||||
checkUniqueName(dynamicAttrsMapName, TAG_DYNAMIC, n);
|
||||
}
|
||||
smallIcon = checkConflict(n, smallIcon, "small-icon");
|
||||
largeIcon = checkConflict(n, largeIcon, "large-icon");
|
||||
description = checkConflict(n, description, "description");
|
||||
displayName = checkConflict(n, displayName, "display-name");
|
||||
example = checkConflict(n, example, "example");
|
||||
}
|
||||
|
||||
private String checkConflict(Node n, String oldAttrValue, String attr)
|
||||
throws JasperException {
|
||||
|
||||
String result = oldAttrValue;
|
||||
String attrValue = n.getAttributeValue(attr);
|
||||
if (attrValue != null) {
|
||||
if (oldAttrValue != null && !oldAttrValue.equals(attrValue)) {
|
||||
err.jspError(n, "jsp.error.tag.conflict.attr", attr,
|
||||
oldAttrValue, attrValue);
|
||||
}
|
||||
result = attrValue;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void visit(Node.AttributeDirective n) throws JasperException {
|
||||
|
||||
JspUtil.checkAttributes("Attribute directive", n,
|
||||
attributeDirectiveAttrs, err);
|
||||
|
||||
// JSP 2.1 Table JSP.8-3
|
||||
// handle deferredValue and deferredValueType
|
||||
boolean deferredValue = false;
|
||||
boolean deferredValueSpecified = false;
|
||||
String deferredValueString = n.getAttributeValue("deferredValue");
|
||||
if (deferredValueString != null) {
|
||||
deferredValueSpecified = true;
|
||||
deferredValue = JspUtil.booleanValue(deferredValueString);
|
||||
}
|
||||
String deferredValueType = n.getAttributeValue("deferredValueType");
|
||||
if (deferredValueType != null) {
|
||||
if (deferredValueSpecified && !deferredValue) {
|
||||
err.jspError(n, "jsp.error.deferredvaluetypewithoutdeferredvalue");
|
||||
} else {
|
||||
deferredValue = true;
|
||||
}
|
||||
} else if (deferredValue) {
|
||||
deferredValueType = "java.lang.Object";
|
||||
} else {
|
||||
deferredValueType = "java.lang.String";
|
||||
}
|
||||
|
||||
// JSP 2.1 Table JSP.8-3
|
||||
// handle deferredMethod and deferredMethodSignature
|
||||
boolean deferredMethod = false;
|
||||
boolean deferredMethodSpecified = false;
|
||||
String deferredMethodString = n.getAttributeValue("deferredMethod");
|
||||
if (deferredMethodString != null) {
|
||||
deferredMethodSpecified = true;
|
||||
deferredMethod = JspUtil.booleanValue(deferredMethodString);
|
||||
}
|
||||
String deferredMethodSignature = n
|
||||
.getAttributeValue("deferredMethodSignature");
|
||||
if (deferredMethodSignature != null) {
|
||||
if (deferredMethodSpecified && !deferredMethod) {
|
||||
err.jspError(n, "jsp.error.deferredmethodsignaturewithoutdeferredmethod");
|
||||
} else {
|
||||
deferredMethod = true;
|
||||
}
|
||||
} else if (deferredMethod) {
|
||||
deferredMethodSignature = "void methodname()";
|
||||
}
|
||||
|
||||
if (deferredMethod && deferredValue) {
|
||||
err.jspError(n, "jsp.error.deferredmethodandvalue");
|
||||
}
|
||||
|
||||
String attrName = n.getAttributeValue("name");
|
||||
boolean required = JspUtil.booleanValue(n
|
||||
.getAttributeValue("required"));
|
||||
boolean rtexprvalue = true;
|
||||
String rtexprvalueString = n.getAttributeValue("rtexprvalue");
|
||||
if (rtexprvalueString != null) {
|
||||
rtexprvalue = JspUtil.booleanValue(rtexprvalueString);
|
||||
}
|
||||
boolean fragment = JspUtil.booleanValue(n
|
||||
.getAttributeValue("fragment"));
|
||||
String type = n.getAttributeValue("type");
|
||||
if (fragment) {
|
||||
// type is fixed to "JspFragment" and a translation error
|
||||
// must occur if specified.
|
||||
if (type != null) {
|
||||
err.jspError(n, "jsp.error.fragmentwithtype");
|
||||
}
|
||||
// rtexprvalue is fixed to "true" and a translation error
|
||||
// must occur if specified.
|
||||
rtexprvalue = true;
|
||||
if (rtexprvalueString != null) {
|
||||
err.jspError(n, "jsp.error.frgmentwithrtexprvalue");
|
||||
}
|
||||
} else {
|
||||
if (type == null)
|
||||
type = "java.lang.String";
|
||||
|
||||
if (deferredValue) {
|
||||
type = ValueExpression.class.getName();
|
||||
} else if (deferredMethod) {
|
||||
type = MethodExpression.class.getName();
|
||||
}
|
||||
}
|
||||
|
||||
if (("2.0".equals(tagLibInfo.getRequiredVersion()) || ("1.2".equals(tagLibInfo.getRequiredVersion())))
|
||||
&& (deferredMethodSpecified || deferredMethod
|
||||
|| deferredValueSpecified || deferredValue)) {
|
||||
err.jspError("jsp.error.invalid.version", path);
|
||||
}
|
||||
|
||||
TagAttributeInfo tagAttributeInfo = new TagAttributeInfo(attrName,
|
||||
required, type, rtexprvalue, fragment, null, deferredValue,
|
||||
deferredMethod, deferredValueType, deferredMethodSignature);
|
||||
attributeVector.addElement(tagAttributeInfo);
|
||||
checkUniqueName(attrName, ATTR_NAME, n, tagAttributeInfo);
|
||||
}
|
||||
|
||||
public void visit(Node.VariableDirective n) throws JasperException {
|
||||
|
||||
JspUtil.checkAttributes("Variable directive", n,
|
||||
variableDirectiveAttrs, err);
|
||||
|
||||
String nameGiven = n.getAttributeValue("name-given");
|
||||
String nameFromAttribute = n
|
||||
.getAttributeValue("name-from-attribute");
|
||||
if (nameGiven == null && nameFromAttribute == null) {
|
||||
err.jspError("jsp.error.variable.either.name");
|
||||
}
|
||||
|
||||
if (nameGiven != null && nameFromAttribute != null) {
|
||||
err.jspError("jsp.error.variable.both.name");
|
||||
}
|
||||
|
||||
String alias = n.getAttributeValue("alias");
|
||||
if (nameFromAttribute != null && alias == null
|
||||
|| nameFromAttribute == null && alias != null) {
|
||||
err.jspError("jsp.error.variable.alias");
|
||||
}
|
||||
|
||||
String className = n.getAttributeValue("variable-class");
|
||||
if (className == null)
|
||||
className = "java.lang.String";
|
||||
|
||||
String declareStr = n.getAttributeValue("declare");
|
||||
boolean declare = true;
|
||||
if (declareStr != null)
|
||||
declare = JspUtil.booleanValue(declareStr);
|
||||
|
||||
int scope = VariableInfo.NESTED;
|
||||
String scopeStr = n.getAttributeValue("scope");
|
||||
if (scopeStr != null) {
|
||||
if ("NESTED".equals(scopeStr)) {
|
||||
// Already the default
|
||||
} else if ("AT_BEGIN".equals(scopeStr)) {
|
||||
scope = VariableInfo.AT_BEGIN;
|
||||
} else if ("AT_END".equals(scopeStr)) {
|
||||
scope = VariableInfo.AT_END;
|
||||
}
|
||||
}
|
||||
|
||||
if (nameFromAttribute != null) {
|
||||
/*
|
||||
* An alias has been specified. We use 'nameGiven' to hold the
|
||||
* value of the alias, and 'nameFromAttribute' to hold the name
|
||||
* of the attribute whose value (at invocation-time) denotes the
|
||||
* name of the variable that is being aliased
|
||||
*/
|
||||
nameGiven = alias;
|
||||
checkUniqueName(nameFromAttribute, VAR_NAME_FROM, n);
|
||||
checkUniqueName(alias, VAR_ALIAS, n);
|
||||
} else {
|
||||
// name-given specified
|
||||
checkUniqueName(nameGiven, VAR_NAME_GIVEN, n);
|
||||
}
|
||||
|
||||
variableVector.addElement(new TagVariableInfo(nameGiven,
|
||||
nameFromAttribute, className, declare, scope));
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the vector of attributes corresponding to attribute
|
||||
* directives.
|
||||
*/
|
||||
public Vector getAttributesVector() {
|
||||
return attributeVector;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the vector of variables corresponding to variable directives.
|
||||
*/
|
||||
public Vector getVariablesVector() {
|
||||
return variableVector;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the value of the dynamic-attributes tag directive attribute.
|
||||
*/
|
||||
public String getDynamicAttributesMapName() {
|
||||
return dynamicAttrsMapName;
|
||||
}
|
||||
|
||||
public TagInfo getTagInfo() throws JasperException {
|
||||
|
||||
if (name == null) {
|
||||
// XXX Get it from tag file name
|
||||
}
|
||||
|
||||
if (bodycontent == null) {
|
||||
bodycontent = TagInfo.BODY_CONTENT_SCRIPTLESS;
|
||||
}
|
||||
|
||||
String tagClassName = JspUtil.getTagHandlerClassName(
|
||||
path, tagLibInfo.getReliableURN(), err);
|
||||
|
||||
TagVariableInfo[] tagVariableInfos = new TagVariableInfo[variableVector
|
||||
.size()];
|
||||
variableVector.copyInto(tagVariableInfos);
|
||||
|
||||
TagAttributeInfo[] tagAttributeInfo = new TagAttributeInfo[attributeVector
|
||||
.size()];
|
||||
attributeVector.copyInto(tagAttributeInfo);
|
||||
|
||||
return new JasperTagInfo(name, tagClassName, bodycontent,
|
||||
description, tagLibInfo, tei, tagAttributeInfo,
|
||||
displayName, smallIcon, largeIcon, tagVariableInfos,
|
||||
dynamicAttrsMapName);
|
||||
}
|
||||
|
||||
static class NameEntry {
|
||||
private String type;
|
||||
|
||||
private Node node;
|
||||
|
||||
private TagAttributeInfo attr;
|
||||
|
||||
NameEntry(String type, Node node, TagAttributeInfo attr) {
|
||||
this.type = type;
|
||||
this.node = node;
|
||||
this.attr = attr;
|
||||
}
|
||||
|
||||
String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
Node getNode() {
|
||||
return node;
|
||||
}
|
||||
|
||||
TagAttributeInfo getTagAttributeInfo() {
|
||||
return attr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports a translation error if names specified in attributes of
|
||||
* directives are not unique in this translation unit.
|
||||
*
|
||||
* The value of the following attributes must be unique. 1. 'name'
|
||||
* attribute of an attribute directive 2. 'name-given' attribute of a
|
||||
* variable directive 3. 'alias' attribute of variable directive 4.
|
||||
* 'dynamic-attributes' of a tag directive except that
|
||||
* 'dynamic-attributes' can (and must) have the same value when it
|
||||
* appears in multiple tag directives.
|
||||
*
|
||||
* Also, 'name-from' attribute of a variable directive cannot have the
|
||||
* same value as that from another variable directive.
|
||||
*/
|
||||
private void checkUniqueName(String name, String type, Node n)
|
||||
throws JasperException {
|
||||
checkUniqueName(name, type, n, null);
|
||||
}
|
||||
|
||||
private void checkUniqueName(String name, String type, Node n,
|
||||
TagAttributeInfo attr) throws JasperException {
|
||||
|
||||
HashMap table = (type == VAR_NAME_FROM) ? nameFromTable : nameTable;
|
||||
NameEntry nameEntry = (NameEntry) table.get(name);
|
||||
if (nameEntry != null) {
|
||||
if (type != TAG_DYNAMIC || nameEntry.getType() != TAG_DYNAMIC) {
|
||||
int line = nameEntry.getNode().getStart().getLineNumber();
|
||||
err.jspError(n, "jsp.error.tagfile.nameNotUnique", type,
|
||||
nameEntry.getType(), Integer.toString(line));
|
||||
}
|
||||
} else {
|
||||
table.put(name, new NameEntry(type, n, attr));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform miscellean checks after the nodes are visited.
|
||||
*/
|
||||
void postCheck() throws JasperException {
|
||||
// Check that var.name-from-attributes has valid values.
|
||||
Iterator iter = nameFromTable.keySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
String nameFrom = (String) iter.next();
|
||||
NameEntry nameEntry = (NameEntry) nameTable.get(nameFrom);
|
||||
NameEntry nameFromEntry = (NameEntry) nameFromTable
|
||||
.get(nameFrom);
|
||||
Node nameFromNode = nameFromEntry.getNode();
|
||||
if (nameEntry == null) {
|
||||
err.jspError(nameFromNode,
|
||||
"jsp.error.tagfile.nameFrom.noAttribute", nameFrom);
|
||||
} else {
|
||||
Node node = nameEntry.getNode();
|
||||
TagAttributeInfo tagAttr = nameEntry.getTagAttributeInfo();
|
||||
if (!"java.lang.String".equals(tagAttr.getTypeName())
|
||||
|| !tagAttr.isRequired()
|
||||
|| tagAttr.canBeRequestTime()) {
|
||||
err.jspError(nameFromNode,
|
||||
"jsp.error.tagfile.nameFrom.badAttribute",
|
||||
nameFrom, Integer.toString(node.getStart()
|
||||
.getLineNumber()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the tag file, and collects information on the directives included
|
||||
* in it. The method is used to obtain the info on the tag file, when the
|
||||
* handler that it represents is referenced. The tag file is not compiled
|
||||
* here.
|
||||
*
|
||||
* @param pc
|
||||
* the current ParserController used in this compilation
|
||||
* @param name
|
||||
* the tag name as specified in the TLD
|
||||
* @param tagfile
|
||||
* the path for the tagfile
|
||||
* @param tagLibInfo
|
||||
* the TagLibraryInfo object associated with this TagInfo
|
||||
* @return a TagInfo object assembled from the directives in the tag file.
|
||||
* @deprecated Use {@link TagFileProcessor#parseTagFileDirectives(
|
||||
* ParserController, String, String, URL, TagLibraryInfo)}
|
||||
* See https://issues.apache.org/bugzilla/show_bug.cgi?id=46471
|
||||
*/
|
||||
public static TagInfo parseTagFileDirectives(ParserController pc,
|
||||
String name, String path, TagLibraryInfo tagLibInfo)
|
||||
throws JasperException {
|
||||
return parseTagFileDirectives(pc, name, path,
|
||||
pc.getJspCompilationContext().getTagFileJarUrl(path),
|
||||
tagLibInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the tag file, and collects information on the directives included
|
||||
* in it. The method is used to obtain the info on the tag file, when the
|
||||
* handler that it represents is referenced. The tag file is not compiled
|
||||
* here.
|
||||
*
|
||||
* @param pc
|
||||
* the current ParserController used in this compilation
|
||||
* @param name
|
||||
* the tag name as specified in the TLD
|
||||
* @param tagfile
|
||||
* the path for the tagfile
|
||||
* @param tagFileJarUrl
|
||||
* the url for the Jar containign the tag file
|
||||
* @param tagLibInfo
|
||||
* the TagLibraryInfo object associated with this TagInfo
|
||||
* @return a TagInfo object assembled from the directives in the tag file.
|
||||
*/
|
||||
public static TagInfo parseTagFileDirectives(ParserController pc,
|
||||
String name, String path, URL tagFileJarUrl, TagLibraryInfo tagLibInfo)
|
||||
throws JasperException {
|
||||
|
||||
ErrorDispatcher err = pc.getCompiler().getErrorDispatcher();
|
||||
|
||||
Node.Nodes page = null;
|
||||
try {
|
||||
page = pc.parseTagFileDirectives(path, tagFileJarUrl);
|
||||
} catch (FileNotFoundException e) {
|
||||
err.jspError("jsp.error.file.not.found", path);
|
||||
} catch (IOException e) {
|
||||
err.jspError("jsp.error.file.not.found", path);
|
||||
}
|
||||
|
||||
TagFileDirectiveVisitor tagFileVisitor = new TagFileDirectiveVisitor(pc
|
||||
.getCompiler(), tagLibInfo, name, path);
|
||||
page.visit(tagFileVisitor);
|
||||
tagFileVisitor.postCheck();
|
||||
|
||||
return tagFileVisitor.getTagInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles and loads a tagfile.
|
||||
*/
|
||||
private Class loadTagFile(Compiler compiler, String tagFilePath,
|
||||
TagInfo tagInfo, PageInfo parentPageInfo) throws JasperException {
|
||||
|
||||
URL tagFileJarUrl = null;
|
||||
if (tagFilePath.startsWith("/META-INF/")) {
|
||||
try {
|
||||
tagFileJarUrl = new URL("jar:" +
|
||||
compiler.getCompilationContext().getTldLocation(
|
||||
tagInfo.getTagLibrary().getURI())[0] + "!/");
|
||||
} catch (MalformedURLException e) {
|
||||
// Ignore - tagFileJarUrl will be null
|
||||
}
|
||||
}
|
||||
String tagFileJarPath;
|
||||
if (tagFileJarUrl == null) {
|
||||
tagFileJarPath = "";
|
||||
} else {
|
||||
tagFileJarPath = tagFileJarUrl.toString();
|
||||
}
|
||||
|
||||
JspCompilationContext ctxt = compiler.getCompilationContext();
|
||||
JspRuntimeContext rctxt = ctxt.getRuntimeContext();
|
||||
JspServletWrapper wrapper = rctxt.getWrapper(tagFileJarPath + tagFilePath);
|
||||
|
||||
synchronized (rctxt) {
|
||||
if (wrapper == null) {
|
||||
wrapper = new JspServletWrapper(ctxt.getServletContext(), ctxt
|
||||
.getOptions(), tagFilePath, tagInfo, ctxt
|
||||
.getRuntimeContext(), tagFileJarUrl);
|
||||
rctxt.addWrapper(tagFileJarPath + tagFilePath, wrapper);
|
||||
|
||||
// Use same classloader and classpath for compiling tag files
|
||||
wrapper.getJspEngineContext().setClassLoader(
|
||||
(URLClassLoader) ctxt.getClassLoader());
|
||||
wrapper.getJspEngineContext().setClassPath(ctxt.getClassPath());
|
||||
} else {
|
||||
// Make sure that JspCompilationContext gets the latest TagInfo
|
||||
// for the tag file. TagInfo instance was created the last
|
||||
// time the tag file was scanned for directives, and the tag
|
||||
// file may have been modified since then.
|
||||
wrapper.getJspEngineContext().setTagInfo(tagInfo);
|
||||
}
|
||||
|
||||
Class tagClazz;
|
||||
int tripCount = wrapper.incTripCount();
|
||||
try {
|
||||
if (tripCount > 0) {
|
||||
// When tripCount is greater than zero, a circular
|
||||
// dependency exists. The circularily dependant tag
|
||||
// file is compiled in prototype mode, to avoid infinite
|
||||
// recursion.
|
||||
|
||||
JspServletWrapper tempWrapper = new JspServletWrapper(ctxt
|
||||
.getServletContext(), ctxt.getOptions(),
|
||||
tagFilePath, tagInfo, ctxt.getRuntimeContext(),
|
||||
ctxt.getTagFileJarUrl(tagFilePath));
|
||||
tagClazz = tempWrapper.loadTagFilePrototype();
|
||||
tempVector.add(tempWrapper.getJspEngineContext()
|
||||
.getCompiler());
|
||||
} else {
|
||||
tagClazz = wrapper.loadTagFile();
|
||||
}
|
||||
} finally {
|
||||
wrapper.decTripCount();
|
||||
}
|
||||
|
||||
// Add the dependants for this tag file to its parent's
|
||||
// dependant list. The only reliable dependency information
|
||||
// can only be obtained from the tag instance.
|
||||
try {
|
||||
Object tagIns = tagClazz.newInstance();
|
||||
if (tagIns instanceof JspSourceDependent) {
|
||||
Iterator iter = ((List) ((JspSourceDependent) tagIns)
|
||||
.getDependants()).iterator();
|
||||
while (iter.hasNext()) {
|
||||
parentPageInfo.addDependant((String) iter.next());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// ignore errors
|
||||
}
|
||||
|
||||
return tagClazz;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Visitor which scans the page and looks for tag handlers that are tag
|
||||
* files, compiling (if necessary) and loading them.
|
||||
*/
|
||||
private class TagFileLoaderVisitor extends Node.Visitor {
|
||||
|
||||
private Compiler compiler;
|
||||
|
||||
private PageInfo pageInfo;
|
||||
|
||||
TagFileLoaderVisitor(Compiler compiler) {
|
||||
|
||||
this.compiler = compiler;
|
||||
this.pageInfo = compiler.getPageInfo();
|
||||
}
|
||||
|
||||
public void visit(Node.CustomTag n) throws JasperException {
|
||||
TagFileInfo tagFileInfo = n.getTagFileInfo();
|
||||
if (tagFileInfo != null) {
|
||||
String tagFilePath = tagFileInfo.getPath();
|
||||
if (tagFilePath.startsWith("/META-INF/")) {
|
||||
// For tags in JARs, add the TLD and the tag as a dependency
|
||||
String[] location =
|
||||
compiler.getCompilationContext().getTldLocation(
|
||||
tagFileInfo.getTagInfo().getTagLibrary().getURI());
|
||||
// Add TLD
|
||||
pageInfo.addDependant("jar:" + location[0] + "!/" +
|
||||
location[1]);
|
||||
// Add Tag
|
||||
pageInfo.addDependant("jar:" + location[0] + "!" +
|
||||
tagFilePath);
|
||||
} else {
|
||||
pageInfo.addDependant(tagFilePath);
|
||||
}
|
||||
Class c = loadTagFile(compiler, tagFilePath, n.getTagInfo(),
|
||||
pageInfo);
|
||||
n.setTagHandlerClass(c);
|
||||
}
|
||||
visitBody(n);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a phase of the translation that compiles (if necessary) the
|
||||
* tag files used in a JSP files. The directives in the tag files are
|
||||
* assumed to have been proccessed and encapsulated as TagFileInfo in the
|
||||
* CustomTag nodes.
|
||||
*/
|
||||
public void loadTagFiles(Compiler compiler, Node.Nodes page)
|
||||
throws JasperException {
|
||||
|
||||
tempVector = new Vector();
|
||||
page.visit(new TagFileLoaderVisitor(compiler));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removed the java and class files for the tag prototype generated from the
|
||||
* current compilation.
|
||||
*
|
||||
* @param classFileName
|
||||
* If non-null, remove only the class file with with this name.
|
||||
*/
|
||||
public void removeProtoTypeFiles(String classFileName) {
|
||||
Iterator iter = tempVector.iterator();
|
||||
while (iter.hasNext()) {
|
||||
Compiler c = (Compiler) iter.next();
|
||||
if (classFileName == null) {
|
||||
c.removeGeneratedClassFiles();
|
||||
} else if (classFileName.equals(c.getCompilationContext()
|
||||
.getClassFileName())) {
|
||||
c.removeGeneratedClassFiles();
|
||||
tempVector.remove(c);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-768
@@ -1,768 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Vector;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
import javax.servlet.jsp.tagext.FunctionInfo;
|
||||
import javax.servlet.jsp.tagext.PageData;
|
||||
import javax.servlet.jsp.tagext.TagAttributeInfo;
|
||||
import javax.servlet.jsp.tagext.TagExtraInfo;
|
||||
import javax.servlet.jsp.tagext.TagFileInfo;
|
||||
import javax.servlet.jsp.tagext.TagInfo;
|
||||
import javax.servlet.jsp.tagext.TagLibraryInfo;
|
||||
import javax.servlet.jsp.tagext.TagLibraryValidator;
|
||||
import javax.servlet.jsp.tagext.TagVariableInfo;
|
||||
import javax.servlet.jsp.tagext.ValidationMessage;
|
||||
import javax.servlet.jsp.tagext.VariableInfo;
|
||||
|
||||
import org.apache.jasper.JasperException;
|
||||
import org.apache.jasper.JspCompilationContext;
|
||||
import org.apache.jasper.xmlparser.ParserUtils;
|
||||
import org.apache.jasper.xmlparser.TreeNode;
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Implementation of the TagLibraryInfo class from the JSP spec.
|
||||
*
|
||||
* @author Anil K. Vijendran
|
||||
* @author Mandar Raje
|
||||
* @author Pierre Delisle
|
||||
* @author Kin-man Chung
|
||||
* @author Jan Luehe
|
||||
*/
|
||||
class TagLibraryInfoImpl extends TagLibraryInfo implements TagConstants {
|
||||
|
||||
// Logger
|
||||
private Log log = LogFactory.getLog(TagLibraryInfoImpl.class);
|
||||
|
||||
private JspCompilationContext ctxt;
|
||||
|
||||
private PageInfo pi;
|
||||
|
||||
private ErrorDispatcher err;
|
||||
|
||||
private ParserController parserController;
|
||||
|
||||
private final void print(String name, String value, PrintWriter w) {
|
||||
if (value != null) {
|
||||
w.print(name + " = {\n\t");
|
||||
w.print(value);
|
||||
w.print("\n}\n");
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter out = new PrintWriter(sw);
|
||||
print("tlibversion", tlibversion, out);
|
||||
print("jspversion", jspversion, out);
|
||||
print("shortname", shortname, out);
|
||||
print("urn", urn, out);
|
||||
print("info", info, out);
|
||||
print("uri", uri, out);
|
||||
print("tagLibraryValidator", "" + tagLibraryValidator, out);
|
||||
|
||||
for (int i = 0; i < tags.length; i++)
|
||||
out.println(tags[i].toString());
|
||||
|
||||
for (int i = 0; i < tagFiles.length; i++)
|
||||
out.println(tagFiles[i].toString());
|
||||
|
||||
for (int i = 0; i < functions.length; i++)
|
||||
out.println(functions[i].toString());
|
||||
|
||||
return sw.toString();
|
||||
}
|
||||
|
||||
// XXX FIXME
|
||||
// resolveRelativeUri and/or getResourceAsStream don't seem to properly
|
||||
// handle relative paths when dealing when home and getDocBase are set
|
||||
// the following is a workaround until these problems are resolved.
|
||||
private InputStream getResourceAsStream(String uri)
|
||||
throws FileNotFoundException {
|
||||
try {
|
||||
// see if file exists on the filesystem first
|
||||
String real = ctxt.getRealPath(uri);
|
||||
if (real == null) {
|
||||
return ctxt.getResourceAsStream(uri);
|
||||
} else {
|
||||
return new FileInputStream(real);
|
||||
}
|
||||
} catch (FileNotFoundException ex) {
|
||||
// if file not found on filesystem, get the resource through
|
||||
// the context
|
||||
return ctxt.getResourceAsStream(uri);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public TagLibraryInfoImpl(JspCompilationContext ctxt, ParserController pc, PageInfo pi,
|
||||
String prefix, String uriIn, String[] location, ErrorDispatcher err)
|
||||
throws JasperException {
|
||||
super(prefix, uriIn);
|
||||
|
||||
this.ctxt = ctxt;
|
||||
this.parserController = pc;
|
||||
this.pi = pi;
|
||||
this.err = err;
|
||||
InputStream in = null;
|
||||
JarFile jarFile = null;
|
||||
|
||||
if (location == null) {
|
||||
// The URI points to the TLD itself or to a JAR file in which the
|
||||
// TLD is stored
|
||||
location = generateTLDLocation(uri, ctxt);
|
||||
}
|
||||
|
||||
try {
|
||||
if (!location[0].endsWith("jar")) {
|
||||
// Location points to TLD file
|
||||
try {
|
||||
in = getResourceAsStream(location[0]);
|
||||
if (in == null) {
|
||||
throw new FileNotFoundException(location[0]);
|
||||
}
|
||||
} catch (FileNotFoundException ex) {
|
||||
err.jspError("jsp.error.file.not.found", location[0]);
|
||||
}
|
||||
|
||||
parseTLD(ctxt, location[0], in, null);
|
||||
// Add TLD to dependency list
|
||||
PageInfo pageInfo = ctxt.createCompiler().getPageInfo();
|
||||
if (pageInfo != null) {
|
||||
pageInfo.addDependant(location[0]);
|
||||
}
|
||||
} else {
|
||||
// Tag library is packaged in JAR file
|
||||
try {
|
||||
URL jarFileUrl = new URL("jar:" + location[0] + "!/");
|
||||
JarURLConnection conn = (JarURLConnection) jarFileUrl
|
||||
.openConnection();
|
||||
conn.setUseCaches(false);
|
||||
conn.connect();
|
||||
jarFile = conn.getJarFile();
|
||||
ZipEntry jarEntry = jarFile.getEntry(location[1]);
|
||||
in = jarFile.getInputStream(jarEntry);
|
||||
parseTLD(ctxt, location[0], in, jarFileUrl);
|
||||
} catch (Exception ex) {
|
||||
err.jspError("jsp.error.tld.unable_to_read", location[0],
|
||||
location[1], ex.toString());
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (in != null) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (Throwable t) {
|
||||
}
|
||||
}
|
||||
if (jarFile != null) {
|
||||
try {
|
||||
jarFile.close();
|
||||
} catch (Throwable t) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public TagLibraryInfo[] getTagLibraryInfos() {
|
||||
Collection coll = pi.getTaglibs();
|
||||
return (TagLibraryInfo[]) coll.toArray(new TagLibraryInfo[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
* @param ctxt The JSP compilation context @param uri The TLD's uri @param
|
||||
* in The TLD's input stream @param jarFileUrl The JAR file containing the
|
||||
* TLD, or null if the tag library is not packaged in a JAR
|
||||
*/
|
||||
private void parseTLD(JspCompilationContext ctxt, String uri,
|
||||
InputStream in, URL jarFileUrl) throws JasperException {
|
||||
Vector tagVector = new Vector();
|
||||
Vector tagFileVector = new Vector();
|
||||
Hashtable functionTable = new Hashtable();
|
||||
|
||||
// Create an iterator over the child elements of our <taglib> element
|
||||
ParserUtils pu = new ParserUtils();
|
||||
TreeNode tld = pu.parseXMLDocument(uri, in);
|
||||
|
||||
// Check to see if the <taglib> root element contains a 'version'
|
||||
// attribute, which was added in JSP 2.0 to replace the <jsp-version>
|
||||
// subelement
|
||||
this.jspversion = tld.findAttribute("version");
|
||||
|
||||
// Process each child element of our <taglib> element
|
||||
Iterator list = tld.findChildren();
|
||||
|
||||
while (list.hasNext()) {
|
||||
TreeNode element = (TreeNode) list.next();
|
||||
String tname = element.getName();
|
||||
|
||||
if ("tlibversion".equals(tname) // JSP 1.1
|
||||
|| "tlib-version".equals(tname)) { // JSP 1.2
|
||||
this.tlibversion = element.getBody();
|
||||
} else if ("jspversion".equals(tname)
|
||||
|| "jsp-version".equals(tname)) {
|
||||
this.jspversion = element.getBody();
|
||||
} else if ("shortname".equals(tname) || "short-name".equals(tname))
|
||||
this.shortname = element.getBody();
|
||||
else if ("uri".equals(tname))
|
||||
this.urn = element.getBody();
|
||||
else if ("info".equals(tname) || "description".equals(tname))
|
||||
this.info = element.getBody();
|
||||
else if ("validator".equals(tname))
|
||||
this.tagLibraryValidator = createValidator(element);
|
||||
else if ("tag".equals(tname))
|
||||
tagVector.addElement(createTagInfo(element, jspversion));
|
||||
else if ("tag-file".equals(tname)) {
|
||||
TagFileInfo tagFileInfo = createTagFileInfo(element, uri,
|
||||
jarFileUrl);
|
||||
tagFileVector.addElement(tagFileInfo);
|
||||
} else if ("function".equals(tname)) { // JSP2.0
|
||||
FunctionInfo funcInfo = createFunctionInfo(element);
|
||||
String funcName = funcInfo.getName();
|
||||
if (functionTable.containsKey(funcName)) {
|
||||
err.jspError("jsp.error.tld.fn.duplicate.name", funcName,
|
||||
uri);
|
||||
|
||||
}
|
||||
functionTable.put(funcName, funcInfo);
|
||||
} else if ("display-name".equals(tname) || // Ignored elements
|
||||
"small-icon".equals(tname) || "large-icon".equals(tname)
|
||||
|| "listener".equals(tname)) {
|
||||
;
|
||||
} else if ("taglib-extension".equals(tname)) {
|
||||
// Recognized but ignored
|
||||
} else {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage(
|
||||
"jsp.warning.unknown.element.in.taglib", tname));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (tlibversion == null) {
|
||||
err.jspError("jsp.error.tld.mandatory.element.missing",
|
||||
"tlib-version");
|
||||
}
|
||||
if (jspversion == null) {
|
||||
err.jspError("jsp.error.tld.mandatory.element.missing",
|
||||
"jsp-version");
|
||||
}
|
||||
|
||||
this.tags = new TagInfo[tagVector.size()];
|
||||
tagVector.copyInto(this.tags);
|
||||
|
||||
this.tagFiles = new TagFileInfo[tagFileVector.size()];
|
||||
tagFileVector.copyInto(this.tagFiles);
|
||||
|
||||
this.functions = new FunctionInfo[functionTable.size()];
|
||||
int i = 0;
|
||||
Enumeration enumeration = functionTable.elements();
|
||||
while (enumeration.hasMoreElements()) {
|
||||
this.functions[i++] = (FunctionInfo) enumeration.nextElement();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @param uri The uri of the TLD @param ctxt The compilation context
|
||||
*
|
||||
* @return String array whose first element denotes the 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, which is hardcoded to
|
||||
* META-INF/taglib.tld.
|
||||
*/
|
||||
private String[] generateTLDLocation(String uri, JspCompilationContext ctxt)
|
||||
throws JasperException {
|
||||
|
||||
int uriType = TldLocationsCache.uriType(uri);
|
||||
if (uriType == TldLocationsCache.ABS_URI) {
|
||||
err.jspError("jsp.error.taglibDirective.absUriCannotBeResolved",
|
||||
uri);
|
||||
} else if (uriType == TldLocationsCache.NOROOT_REL_URI) {
|
||||
uri = ctxt.resolveRelativeUri(uri);
|
||||
}
|
||||
|
||||
String[] location = new String[2];
|
||||
location[0] = uri;
|
||||
if (location[0].endsWith("jar")) {
|
||||
URL url = null;
|
||||
try {
|
||||
url = ctxt.getResource(location[0]);
|
||||
} catch (Exception ex) {
|
||||
err.jspError("jsp.error.tld.unable_to_get_jar", location[0], ex
|
||||
.toString());
|
||||
}
|
||||
if (url == null) {
|
||||
err.jspError("jsp.error.tld.missing_jar", location[0]);
|
||||
}
|
||||
location[0] = url.toString();
|
||||
location[1] = "META-INF/taglib.tld";
|
||||
}
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
private TagInfo createTagInfo(TreeNode elem, String jspVersion)
|
||||
throws JasperException {
|
||||
|
||||
String tagName = null;
|
||||
String tagClassName = null;
|
||||
String teiClassName = null;
|
||||
|
||||
/*
|
||||
* Default body content for JSP 1.2 tag handlers (<body-content> has
|
||||
* become mandatory in JSP 2.0, because the default would be invalid for
|
||||
* simple tag handlers)
|
||||
*/
|
||||
String bodycontent = "JSP";
|
||||
|
||||
String info = null;
|
||||
String displayName = null;
|
||||
String smallIcon = null;
|
||||
String largeIcon = null;
|
||||
boolean dynamicAttributes = false;
|
||||
|
||||
Vector attributeVector = new Vector();
|
||||
Vector variableVector = new Vector();
|
||||
Iterator list = elem.findChildren();
|
||||
while (list.hasNext()) {
|
||||
TreeNode element = (TreeNode) list.next();
|
||||
String tname = element.getName();
|
||||
|
||||
if ("name".equals(tname)) {
|
||||
tagName = element.getBody();
|
||||
} else if ("tagclass".equals(tname) || "tag-class".equals(tname)) {
|
||||
tagClassName = element.getBody();
|
||||
} else if ("teiclass".equals(tname) || "tei-class".equals(tname)) {
|
||||
teiClassName = element.getBody();
|
||||
} else if ("bodycontent".equals(tname)
|
||||
|| "body-content".equals(tname)) {
|
||||
bodycontent = element.getBody();
|
||||
} else if ("display-name".equals(tname)) {
|
||||
displayName = element.getBody();
|
||||
} else if ("small-icon".equals(tname)) {
|
||||
smallIcon = element.getBody();
|
||||
} else if ("large-icon".equals(tname)) {
|
||||
largeIcon = element.getBody();
|
||||
} else if ("icon".equals(tname)) {
|
||||
TreeNode icon = element.findChild("small-icon");
|
||||
if (icon != null) {
|
||||
smallIcon = icon.getBody();
|
||||
}
|
||||
icon = element.findChild("large-icon");
|
||||
if (icon != null) {
|
||||
largeIcon = icon.getBody();
|
||||
}
|
||||
} else if ("info".equals(tname) || "description".equals(tname)) {
|
||||
info = element.getBody();
|
||||
} else if ("variable".equals(tname)) {
|
||||
variableVector.addElement(createVariable(element));
|
||||
} else if ("attribute".equals(tname)) {
|
||||
attributeVector
|
||||
.addElement(createAttribute(element, jspVersion));
|
||||
} else if ("dynamic-attributes".equals(tname)) {
|
||||
dynamicAttributes = JspUtil.booleanValue(element.getBody());
|
||||
} else if ("example".equals(tname)) {
|
||||
// Ignored elements
|
||||
} else if ("tag-extension".equals(tname)) {
|
||||
// Ignored
|
||||
} else {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage(
|
||||
"jsp.warning.unknown.element.in.tag", tname));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TagExtraInfo tei = null;
|
||||
if (teiClassName != null && !teiClassName.equals("")) {
|
||||
try {
|
||||
Class teiClass = ctxt.getClassLoader().loadClass(teiClassName);
|
||||
tei = (TagExtraInfo) teiClass.newInstance();
|
||||
} catch (Exception e) {
|
||||
err.jspError("jsp.error.teiclass.instantiation", teiClassName,
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
TagAttributeInfo[] tagAttributeInfo = new TagAttributeInfo[attributeVector
|
||||
.size()];
|
||||
attributeVector.copyInto(tagAttributeInfo);
|
||||
|
||||
TagVariableInfo[] tagVariableInfos = new TagVariableInfo[variableVector
|
||||
.size()];
|
||||
variableVector.copyInto(tagVariableInfos);
|
||||
|
||||
TagInfo taginfo = new TagInfo(tagName, tagClassName, bodycontent, info,
|
||||
this, tei, tagAttributeInfo, displayName, smallIcon, largeIcon,
|
||||
tagVariableInfos, dynamicAttributes);
|
||||
return taginfo;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parses the tag file directives of the given TagFile and turns them into a
|
||||
* TagInfo.
|
||||
*
|
||||
* @param elem The <tag-file> element in the TLD @param uri The location of
|
||||
* the TLD, in case the tag file is specified relative to it @param jarFile
|
||||
* The JAR file, in case the tag file is packaged in a JAR
|
||||
*
|
||||
* @return TagInfo correspoding to tag file directives
|
||||
*/
|
||||
private TagFileInfo createTagFileInfo(TreeNode elem, String uri,
|
||||
URL jarFileUrl) throws JasperException {
|
||||
|
||||
String name = null;
|
||||
String path = null;
|
||||
|
||||
Iterator list = elem.findChildren();
|
||||
while (list.hasNext()) {
|
||||
TreeNode child = (TreeNode) list.next();
|
||||
String tname = child.getName();
|
||||
if ("name".equals(tname)) {
|
||||
name = child.getBody();
|
||||
} else if ("path".equals(tname)) {
|
||||
path = child.getBody();
|
||||
} else if ("example".equals(tname)) {
|
||||
// Ignore <example> element: Bugzilla 33538
|
||||
} else if ("tag-extension".equals(tname)) {
|
||||
// Ignore <tag-extension> element: Bugzilla 33538
|
||||
} else if ("icon".equals(tname)
|
||||
|| "display-name".equals(tname)
|
||||
|| "description".equals(tname)) {
|
||||
// Ignore these elements: Bugzilla 38015
|
||||
} else {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage(
|
||||
"jsp.warning.unknown.element.in.tagfile", tname));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (path.startsWith("/META-INF/tags")) {
|
||||
// Tag file packaged in JAR
|
||||
// See https://issues.apache.org/bugzilla/show_bug.cgi?id=46471
|
||||
// This needs to be removed once all the broken code that depends on
|
||||
// it has been removed
|
||||
ctxt.setTagFileJarUrl(path, jarFileUrl);
|
||||
} else if (!path.startsWith("/WEB-INF/tags")) {
|
||||
err.jspError("jsp.error.tagfile.illegalPath", path);
|
||||
}
|
||||
|
||||
TagInfo tagInfo = TagFileProcessor.parseTagFileDirectives(
|
||||
parserController, name, path, jarFileUrl, this);
|
||||
return new TagFileInfo(name, path, tagInfo);
|
||||
}
|
||||
|
||||
TagAttributeInfo createAttribute(TreeNode elem, String jspVersion) {
|
||||
String name = null;
|
||||
String type = null;
|
||||
String expectedType = null;
|
||||
String methodSignature = null;
|
||||
boolean required = false, rtexprvalue = false, reqTime = false, isFragment = false, deferredValue = false, deferredMethod = false;
|
||||
|
||||
Iterator list = elem.findChildren();
|
||||
while (list.hasNext()) {
|
||||
TreeNode element = (TreeNode) list.next();
|
||||
String tname = element.getName();
|
||||
|
||||
if ("name".equals(tname)) {
|
||||
name = element.getBody();
|
||||
} else if ("required".equals(tname)) {
|
||||
String s = element.getBody();
|
||||
if (s != null)
|
||||
required = JspUtil.booleanValue(s);
|
||||
} else if ("rtexprvalue".equals(tname)) {
|
||||
String s = element.getBody();
|
||||
if (s != null)
|
||||
rtexprvalue = JspUtil.booleanValue(s);
|
||||
} else if ("type".equals(tname)) {
|
||||
type = element.getBody();
|
||||
if ("1.2".equals(jspVersion)
|
||||
&& (type.equals("Boolean") || type.equals("Byte")
|
||||
|| type.equals("Character")
|
||||
|| type.equals("Double")
|
||||
|| type.equals("Float")
|
||||
|| type.equals("Integer")
|
||||
|| type.equals("Long") || type.equals("Object")
|
||||
|| type.equals("Short") || type
|
||||
.equals("String"))) {
|
||||
type = "java.lang." + type;
|
||||
}
|
||||
} else if ("fragment".equals(tname)) {
|
||||
String s = element.getBody();
|
||||
if (s != null) {
|
||||
isFragment = JspUtil.booleanValue(s);
|
||||
}
|
||||
} else if ("deferred-value".equals(tname)) {
|
||||
deferredValue = true;
|
||||
type = "javax.el.ValueExpression";
|
||||
TreeNode child = element.findChild("type");
|
||||
if (child != null) {
|
||||
expectedType = child.getBody();
|
||||
if (expectedType != null) {
|
||||
expectedType = expectedType.trim();
|
||||
}
|
||||
} else {
|
||||
expectedType = "java.lang.Object";
|
||||
}
|
||||
} else if ("deferred-method".equals(tname)) {
|
||||
deferredMethod = true;
|
||||
type = "javax.el.MethodExpression";
|
||||
TreeNode child = element.findChild("method-signature");
|
||||
if (child != null) {
|
||||
methodSignature = child.getBody();
|
||||
if (methodSignature != null) {
|
||||
methodSignature = methodSignature.trim();
|
||||
}
|
||||
} else {
|
||||
methodSignature = "java.lang.Object method()";
|
||||
}
|
||||
} else if ("description".equals(tname) || // Ignored elements
|
||||
false) {
|
||||
;
|
||||
} else {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage(
|
||||
"jsp.warning.unknown.element.in.attribute", tname));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isFragment) {
|
||||
/*
|
||||
* According to JSP.C-3 ("TLD Schema Element Structure - tag"),
|
||||
* 'type' and 'rtexprvalue' must not be specified if 'fragment' has
|
||||
* been specified (this will be enforced by validating parser).
|
||||
* Also, if 'fragment' is TRUE, 'type' is fixed at
|
||||
* javax.servlet.jsp.tagext.JspFragment, and 'rtexprvalue' is fixed
|
||||
* at true. See also JSP.8.5.2.
|
||||
*/
|
||||
type = "javax.servlet.jsp.tagext.JspFragment";
|
||||
rtexprvalue = true;
|
||||
}
|
||||
|
||||
if (!rtexprvalue && type == null) {
|
||||
// According to JSP spec, for static values (those determined at
|
||||
// translation time) the type is fixed at java.lang.String.
|
||||
type = "java.lang.String";
|
||||
}
|
||||
|
||||
return new TagAttributeInfo(name, required, type, rtexprvalue,
|
||||
isFragment, null, deferredValue, deferredMethod, expectedType,
|
||||
methodSignature);
|
||||
}
|
||||
|
||||
TagVariableInfo createVariable(TreeNode elem) {
|
||||
String nameGiven = null;
|
||||
String nameFromAttribute = null;
|
||||
String className = "java.lang.String";
|
||||
boolean declare = true;
|
||||
int scope = VariableInfo.NESTED;
|
||||
|
||||
Iterator list = elem.findChildren();
|
||||
while (list.hasNext()) {
|
||||
TreeNode element = (TreeNode) list.next();
|
||||
String tname = element.getName();
|
||||
if ("name-given".equals(tname))
|
||||
nameGiven = element.getBody();
|
||||
else if ("name-from-attribute".equals(tname))
|
||||
nameFromAttribute = element.getBody();
|
||||
else if ("variable-class".equals(tname))
|
||||
className = element.getBody();
|
||||
else if ("declare".equals(tname)) {
|
||||
String s = element.getBody();
|
||||
if (s != null)
|
||||
declare = JspUtil.booleanValue(s);
|
||||
} else if ("scope".equals(tname)) {
|
||||
String s = element.getBody();
|
||||
if (s != null) {
|
||||
if ("NESTED".equals(s)) {
|
||||
scope = VariableInfo.NESTED;
|
||||
} else if ("AT_BEGIN".equals(s)) {
|
||||
scope = VariableInfo.AT_BEGIN;
|
||||
} else if ("AT_END".equals(s)) {
|
||||
scope = VariableInfo.AT_END;
|
||||
}
|
||||
}
|
||||
} else if ("description".equals(tname) || // Ignored elements
|
||||
false) {
|
||||
} else {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage(
|
||||
"jsp.warning.unknown.element.in.variable", tname));
|
||||
}
|
||||
}
|
||||
}
|
||||
return new TagVariableInfo(nameGiven, nameFromAttribute, className,
|
||||
declare, scope);
|
||||
}
|
||||
|
||||
private TagLibraryValidator createValidator(TreeNode elem)
|
||||
throws JasperException {
|
||||
|
||||
String validatorClass = null;
|
||||
Map initParams = new Hashtable();
|
||||
|
||||
Iterator list = elem.findChildren();
|
||||
while (list.hasNext()) {
|
||||
TreeNode element = (TreeNode) list.next();
|
||||
String tname = element.getName();
|
||||
if ("validator-class".equals(tname))
|
||||
validatorClass = element.getBody();
|
||||
else if ("init-param".equals(tname)) {
|
||||
String[] initParam = createInitParam(element);
|
||||
initParams.put(initParam[0], initParam[1]);
|
||||
} else if ("description".equals(tname) || // Ignored elements
|
||||
false) {
|
||||
} else {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage(
|
||||
"jsp.warning.unknown.element.in.validator", tname));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TagLibraryValidator tlv = null;
|
||||
if (validatorClass != null && !validatorClass.equals("")) {
|
||||
try {
|
||||
Class tlvClass = ctxt.getClassLoader()
|
||||
.loadClass(validatorClass);
|
||||
tlv = (TagLibraryValidator) tlvClass.newInstance();
|
||||
} catch (Exception e) {
|
||||
err.jspError("jsp.error.tlvclass.instantiation",
|
||||
validatorClass, e);
|
||||
}
|
||||
}
|
||||
if (tlv != null) {
|
||||
tlv.setInitParameters(initParams);
|
||||
}
|
||||
return tlv;
|
||||
}
|
||||
|
||||
String[] createInitParam(TreeNode elem) {
|
||||
String[] initParam = new String[2];
|
||||
|
||||
Iterator list = elem.findChildren();
|
||||
while (list.hasNext()) {
|
||||
TreeNode element = (TreeNode) list.next();
|
||||
String tname = element.getName();
|
||||
if ("param-name".equals(tname)) {
|
||||
initParam[0] = element.getBody();
|
||||
} else if ("param-value".equals(tname)) {
|
||||
initParam[1] = element.getBody();
|
||||
} else if ("description".equals(tname)) {
|
||||
// Do nothing
|
||||
} else {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage(
|
||||
"jsp.warning.unknown.element.in.initParam", tname));
|
||||
}
|
||||
}
|
||||
}
|
||||
return initParam;
|
||||
}
|
||||
|
||||
FunctionInfo createFunctionInfo(TreeNode elem) {
|
||||
|
||||
String name = null;
|
||||
String klass = null;
|
||||
String signature = null;
|
||||
|
||||
Iterator list = elem.findChildren();
|
||||
while (list.hasNext()) {
|
||||
TreeNode element = (TreeNode) list.next();
|
||||
String tname = element.getName();
|
||||
|
||||
if ("name".equals(tname)) {
|
||||
name = element.getBody();
|
||||
} else if ("function-class".equals(tname)) {
|
||||
klass = element.getBody();
|
||||
} else if ("function-signature".equals(tname)) {
|
||||
signature = element.getBody();
|
||||
} else if ("display-name".equals(tname) || // Ignored elements
|
||||
"small-icon".equals(tname) || "large-icon".equals(tname)
|
||||
|| "description".equals(tname) || "example".equals(tname)) {
|
||||
} else {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage(
|
||||
"jsp.warning.unknown.element.in.function", tname));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new FunctionInfo(name, klass, signature);
|
||||
}
|
||||
|
||||
// *********************************************************************
|
||||
// Until javax.servlet.jsp.tagext.TagLibraryInfo is fixed
|
||||
|
||||
/**
|
||||
* The instance (if any) for the TagLibraryValidator class.
|
||||
*
|
||||
* @return The TagLibraryValidator instance, if any.
|
||||
*/
|
||||
public TagLibraryValidator getTagLibraryValidator() {
|
||||
return tagLibraryValidator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translation-time validation of the XML document associated with the JSP
|
||||
* page. This is a convenience method on the associated TagLibraryValidator
|
||||
* class.
|
||||
*
|
||||
* @param thePage
|
||||
* The JSP page object
|
||||
* @return A string indicating whether the page is valid or not.
|
||||
*/
|
||||
public ValidationMessage[] validate(PageData thePage) {
|
||||
TagLibraryValidator tlv = getTagLibraryValidator();
|
||||
if (tlv == null)
|
||||
return null;
|
||||
|
||||
String uri = getURI();
|
||||
if (uri.startsWith("/")) {
|
||||
uri = URN_JSPTLD + uri;
|
||||
}
|
||||
|
||||
return tlv.validate(getPrefixString(), uri, thePage);
|
||||
}
|
||||
|
||||
protected TagLibraryValidator tagLibraryValidator;
|
||||
}
|
||||
-240
@@ -1,240 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.apache.jasper.JasperException;
|
||||
import org.apache.jasper.xmlparser.ParserUtils;
|
||||
import org.apache.jasper.xmlparser.TreeNode;
|
||||
import org.apache.jasper.compiler.tagplugin.TagPlugin;
|
||||
import org.apache.jasper.compiler.tagplugin.TagPluginContext;
|
||||
|
||||
/**
|
||||
* Manages tag plugin optimizations.
|
||||
* @author Kin-man Chung
|
||||
*/
|
||||
|
||||
public class TagPluginManager {
|
||||
|
||||
private static final String TAG_PLUGINS_XML = "/WEB-INF/tagPlugins.xml";
|
||||
private static final String TAG_PLUGINS_ROOT_ELEM = "tag-plugins";
|
||||
|
||||
private boolean initialized = false;
|
||||
private HashMap tagPlugins = null;
|
||||
private ServletContext ctxt;
|
||||
private PageInfo pageInfo;
|
||||
|
||||
public TagPluginManager(ServletContext ctxt) {
|
||||
this.ctxt = ctxt;
|
||||
}
|
||||
|
||||
public void apply(Node.Nodes page, ErrorDispatcher err, PageInfo pageInfo)
|
||||
throws JasperException {
|
||||
|
||||
init(err);
|
||||
if (tagPlugins == null || tagPlugins.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.pageInfo = pageInfo;
|
||||
|
||||
page.visit(new Node.Visitor() {
|
||||
public void visit(Node.CustomTag n)
|
||||
throws JasperException {
|
||||
invokePlugin(n);
|
||||
visitBody(n);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void init(ErrorDispatcher err) throws JasperException {
|
||||
if (initialized)
|
||||
return;
|
||||
|
||||
InputStream is = ctxt.getResourceAsStream(TAG_PLUGINS_XML);
|
||||
if (is == null)
|
||||
return;
|
||||
|
||||
TreeNode root = (new ParserUtils()).parseXMLDocument(TAG_PLUGINS_XML,
|
||||
is);
|
||||
if (root == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TAG_PLUGINS_ROOT_ELEM.equals(root.getName())) {
|
||||
err.jspError("jsp.error.plugin.wrongRootElement", TAG_PLUGINS_XML,
|
||||
TAG_PLUGINS_ROOT_ELEM);
|
||||
}
|
||||
|
||||
tagPlugins = new HashMap();
|
||||
Iterator pluginList = root.findChildren("tag-plugin");
|
||||
while (pluginList.hasNext()) {
|
||||
TreeNode pluginNode = (TreeNode) pluginList.next();
|
||||
TreeNode tagClassNode = pluginNode.findChild("tag-class");
|
||||
if (tagClassNode == null) {
|
||||
// Error
|
||||
return;
|
||||
}
|
||||
String tagClass = tagClassNode.getBody().trim();
|
||||
TreeNode pluginClassNode = pluginNode.findChild("plugin-class");
|
||||
if (pluginClassNode == null) {
|
||||
// Error
|
||||
return;
|
||||
}
|
||||
|
||||
String pluginClassStr = pluginClassNode.getBody();
|
||||
TagPlugin tagPlugin = null;
|
||||
try {
|
||||
Class pluginClass = Class.forName(pluginClassStr);
|
||||
tagPlugin = (TagPlugin) pluginClass.newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new JasperException(e);
|
||||
}
|
||||
if (tagPlugin == null) {
|
||||
return;
|
||||
}
|
||||
tagPlugins.put(tagClass, tagPlugin);
|
||||
}
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke tag plugin for the given custom tag, if a plugin exists for
|
||||
* the custom tag's tag handler.
|
||||
*
|
||||
* The given custom tag node will be manipulated by the plugin.
|
||||
*/
|
||||
private void invokePlugin(Node.CustomTag n) {
|
||||
TagPlugin tagPlugin = (TagPlugin)
|
||||
tagPlugins.get(n.getTagHandlerClass().getName());
|
||||
if (tagPlugin == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
TagPluginContext tagPluginContext = new TagPluginContextImpl(n, pageInfo);
|
||||
n.setTagPluginContext(tagPluginContext);
|
||||
tagPlugin.doTag(tagPluginContext);
|
||||
}
|
||||
|
||||
static class TagPluginContextImpl implements TagPluginContext {
|
||||
private Node.CustomTag node;
|
||||
private Node.Nodes curNodes;
|
||||
private PageInfo pageInfo;
|
||||
private HashMap pluginAttributes;
|
||||
|
||||
TagPluginContextImpl(Node.CustomTag n, PageInfo pageInfo) {
|
||||
this.node = n;
|
||||
this.pageInfo = pageInfo;
|
||||
curNodes = new Node.Nodes();
|
||||
n.setAtETag(curNodes);
|
||||
curNodes = new Node.Nodes();
|
||||
n.setAtSTag(curNodes);
|
||||
n.setUseTagPlugin(true);
|
||||
pluginAttributes = new HashMap();
|
||||
}
|
||||
|
||||
public TagPluginContext getParentContext() {
|
||||
Node parent = node.getParent();
|
||||
if (! (parent instanceof Node.CustomTag)) {
|
||||
return null;
|
||||
}
|
||||
return ((Node.CustomTag) parent).getTagPluginContext();
|
||||
}
|
||||
|
||||
public void setPluginAttribute(String key, Object value) {
|
||||
pluginAttributes.put(key, value);
|
||||
}
|
||||
|
||||
public Object getPluginAttribute(String key) {
|
||||
return pluginAttributes.get(key);
|
||||
}
|
||||
|
||||
public boolean isScriptless() {
|
||||
return node.getChildInfo().isScriptless();
|
||||
}
|
||||
|
||||
public boolean isConstantAttribute(String attribute) {
|
||||
Node.JspAttribute attr = getNodeAttribute(attribute);
|
||||
if (attr == null)
|
||||
return false;
|
||||
return attr.isLiteral();
|
||||
}
|
||||
|
||||
public String getConstantAttribute(String attribute) {
|
||||
Node.JspAttribute attr = getNodeAttribute(attribute);
|
||||
if (attr == null)
|
||||
return null;
|
||||
return attr.getValue();
|
||||
}
|
||||
|
||||
public boolean isAttributeSpecified(String attribute) {
|
||||
return getNodeAttribute(attribute) != null;
|
||||
}
|
||||
|
||||
public String getTemporaryVariableName() {
|
||||
return node.getRoot().nextTemporaryVariableName();
|
||||
}
|
||||
|
||||
public void generateImport(String imp) {
|
||||
pageInfo.addImport(imp);
|
||||
}
|
||||
|
||||
public void generateDeclaration(String id, String text) {
|
||||
if (pageInfo.isPluginDeclared(id)) {
|
||||
return;
|
||||
}
|
||||
curNodes.add(new Node.Declaration(text, node.getStart(), null));
|
||||
}
|
||||
|
||||
public void generateJavaSource(String sourceCode) {
|
||||
curNodes.add(new Node.Scriptlet(sourceCode, node.getStart(),
|
||||
null));
|
||||
}
|
||||
|
||||
public void generateAttribute(String attributeName) {
|
||||
curNodes.add(new Node.AttributeGenerator(node.getStart(),
|
||||
attributeName,
|
||||
node));
|
||||
}
|
||||
|
||||
public void dontUseTagPlugin() {
|
||||
node.setUseTagPlugin(false);
|
||||
}
|
||||
|
||||
public void generateBody() {
|
||||
// Since we'll generate the body anyway, this is really a nop,
|
||||
// except for the fact that it lets us put the Java sources the
|
||||
// plugins produce in the correct order (w.r.t the body).
|
||||
curNodes = node.getAtETag();
|
||||
}
|
||||
|
||||
private Node.JspAttribute getNodeAttribute(String attribute) {
|
||||
Node.JspAttribute[] attrs = node.getJspAttributes();
|
||||
for (int i=0; attrs != null && i < attrs.length; i++) {
|
||||
if (attrs[i].getName().equals(attribute)) {
|
||||
return attrs[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
-115
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import org.apache.jasper.JasperException;
|
||||
import org.apache.jasper.Options;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class TextOptimizer {
|
||||
|
||||
/**
|
||||
* A visitor to concatenate contiguous template texts.
|
||||
*/
|
||||
static class TextCatVisitor extends Node.Visitor {
|
||||
|
||||
private Options options;
|
||||
private PageInfo pageInfo;
|
||||
private int textNodeCount = 0;
|
||||
private Node.TemplateText firstTextNode = null;
|
||||
private StringBuffer textBuffer;
|
||||
private final String emptyText = new String("");
|
||||
|
||||
public TextCatVisitor(Compiler compiler) {
|
||||
options = compiler.getCompilationContext().getOptions();
|
||||
pageInfo = compiler.getPageInfo();
|
||||
}
|
||||
|
||||
public void doVisit(Node n) throws JasperException {
|
||||
collectText();
|
||||
}
|
||||
|
||||
/*
|
||||
* The following directis are ignored in text concatenation
|
||||
*/
|
||||
|
||||
public void visit(Node.PageDirective n) throws JasperException {
|
||||
}
|
||||
|
||||
public void visit(Node.TagDirective n) throws JasperException {
|
||||
}
|
||||
|
||||
public void visit(Node.TaglibDirective n) throws JasperException {
|
||||
}
|
||||
|
||||
public void visit(Node.AttributeDirective n) throws JasperException {
|
||||
}
|
||||
|
||||
public void visit(Node.VariableDirective n) throws JasperException {
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't concatenate text across body boundaries
|
||||
*/
|
||||
public void visitBody(Node n) throws JasperException {
|
||||
super.visitBody(n);
|
||||
collectText();
|
||||
}
|
||||
|
||||
public void visit(Node.TemplateText n) throws JasperException {
|
||||
if ((options.getTrimSpaces() || pageInfo.isTrimDirectiveWhitespaces())
|
||||
&& n.isAllSpace()) {
|
||||
n.setText(emptyText);
|
||||
return;
|
||||
}
|
||||
|
||||
if (textNodeCount++ == 0) {
|
||||
firstTextNode = n;
|
||||
textBuffer = new StringBuffer(n.getText());
|
||||
} else {
|
||||
// Append text to text buffer
|
||||
textBuffer.append(n.getText());
|
||||
n.setText(emptyText);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method breaks concatenation mode. As a side effect it copies
|
||||
* the concatenated string to the first text node
|
||||
*/
|
||||
private void collectText() {
|
||||
|
||||
if (textNodeCount > 1) {
|
||||
// Copy the text in buffer into the first template text node.
|
||||
firstTextNode.setText(textBuffer.toString());
|
||||
}
|
||||
textNodeCount = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void concatenate(Compiler compiler, Node.Nodes page)
|
||||
throws JasperException {
|
||||
|
||||
TextCatVisitor v = new TextCatVisitor(compiler);
|
||||
page.visit(v);
|
||||
|
||||
// Cleanup, in case the page ends with a template text
|
||||
v.collectText();
|
||||
}
|
||||
}
|
||||
-549
@@ -1,549 +0,0 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.apache.jasper.Constants;
|
||||
import org.apache.jasper.JasperException;
|
||||
import org.apache.jasper.xmlparser.ParserUtils;
|
||||
import org.apache.jasper.xmlparser.TreeNode;
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* A container for all tag libraries that are defined "globally"
|
||||
* for the web application.
|
||||
*
|
||||
* Tag Libraries can be defined globally in one of two ways:
|
||||
* 1. Via <taglib> elements in web.xml:
|
||||
* the uri and location of the tag-library are specified in
|
||||
* the <taglib> element.
|
||||
* 2. Via packaged jar files that contain .tld files
|
||||
* within the META-INF directory, or some subdirectory
|
||||
* of it. The taglib is 'global' if it has the <uri>
|
||||
* element defined.
|
||||
*
|
||||
* A mapping between the taglib URI and its associated TaglibraryInfoImpl
|
||||
* is maintained in this container.
|
||||
* Actually, that's what we'd like to do. However, because of the
|
||||
* way the classes TagLibraryInfo and TagInfo have been defined,
|
||||
* it is not currently possible to share an instance of TagLibraryInfo
|
||||
* across page invocations. A bug has been submitted to the spec lead.
|
||||
* In the mean time, all we do is save the 'location' where the
|
||||
* TLD associated with a taglib URI can be found.
|
||||
*
|
||||
* When a JSP page has a taglib directive, the mappings in this container
|
||||
* are first searched (see method getLocation()).
|
||||
* If a mapping is found, then the location of the TLD is returned.
|
||||
* If no mapping is found, then the uri specified
|
||||
* in the taglib directive is to be interpreted as the location for
|
||||
* the TLD of this tag library.
|
||||
*
|
||||
* @author Pierre Delisle
|
||||
* @author Jan Luehe
|
||||
*/
|
||||
|
||||
public class TldLocationsCache {
|
||||
|
||||
// Logger
|
||||
private Log log = LogFactory.getLog(TldLocationsCache.class);
|
||||
|
||||
/**
|
||||
* The types of URI one may specify for a tag library
|
||||
*/
|
||||
public static final int ABS_URI = 0;
|
||||
public static final int ROOT_REL_URI = 1;
|
||||
public static final int NOROOT_REL_URI = 2;
|
||||
|
||||
private static final String WEB_XML = "/WEB-INF/web.xml";
|
||||
private static final String FILE_PROTOCOL = "file:";
|
||||
private static final String JAR_FILE_SUFFIX = ".jar";
|
||||
|
||||
// Names of JARs that are known not to contain any TLDs
|
||||
private static HashSet<String> noTldJars;
|
||||
|
||||
/**
|
||||
* The mapping of the 'global' tag library URI to the location (resource
|
||||
* path) of the TLD associated with that tag library. The location is
|
||||
* returned as a String array:
|
||||
* [0] The location
|
||||
* [1] If the location is a jar file, this is the location of the tld.
|
||||
*/
|
||||
private Hashtable mappings;
|
||||
|
||||
private boolean initialized;
|
||||
private ServletContext ctxt;
|
||||
private boolean redeployMode;
|
||||
|
||||
//*********************************************************************
|
||||
// Constructor and Initilizations
|
||||
|
||||
/*
|
||||
* Initializes the set of JARs that are known not to contain any TLDs
|
||||
*/
|
||||
static {
|
||||
noTldJars = new HashSet<String>();
|
||||
// Bootstrap JARs
|
||||
noTldJars.add("bootstrap.jar");
|
||||
noTldJars.add("commons-daemon.jar");
|
||||
noTldJars.add("tomcat-juli.jar");
|
||||
// Main JARs
|
||||
noTldJars.add("annotations-api.jar");
|
||||
noTldJars.add("catalina.jar");
|
||||
noTldJars.add("catalina-ant.jar");
|
||||
noTldJars.add("catalina-ha.jar");
|
||||
noTldJars.add("catalina-tribes.jar");
|
||||
noTldJars.add("el-api.jar");
|
||||
noTldJars.add("jasper.jar");
|
||||
noTldJars.add("jasper-el.jar");
|
||||
noTldJars.add("jasper-jdt.jar");
|
||||
noTldJars.add("jsp-api.jar");
|
||||
noTldJars.add("servlet-api.jar");
|
||||
noTldJars.add("tomcat-coyote.jar");
|
||||
noTldJars.add("tomcat-dbcp.jar");
|
||||
// i18n JARs
|
||||
noTldJars.add("tomcat-i18n-en.jar");
|
||||
noTldJars.add("tomcat-i18n-es.jar");
|
||||
noTldJars.add("tomcat-i18n-fr.jar");
|
||||
noTldJars.add("tomcat-i18n-ja.jar");
|
||||
// Misc JARs not included with Tomcat
|
||||
noTldJars.add("ant.jar");
|
||||
noTldJars.add("commons-dbcp.jar");
|
||||
noTldJars.add("commons-beanutils.jar");
|
||||
noTldJars.add("commons-fileupload-1.0.jar");
|
||||
noTldJars.add("commons-pool.jar");
|
||||
noTldJars.add("commons-digester.jar");
|
||||
noTldJars.add("commons-logging.jar");
|
||||
noTldJars.add("commons-collections.jar");
|
||||
noTldJars.add("jmx.jar");
|
||||
noTldJars.add("jmx-tools.jar");
|
||||
noTldJars.add("xercesImpl.jar");
|
||||
noTldJars.add("xmlParserAPIs.jar");
|
||||
noTldJars.add("xml-apis.jar");
|
||||
// JARs from J2SE runtime
|
||||
noTldJars.add("sunjce_provider.jar");
|
||||
noTldJars.add("ldapsec.jar");
|
||||
noTldJars.add("localedata.jar");
|
||||
noTldJars.add("dnsns.jar");
|
||||
noTldJars.add("tools.jar");
|
||||
noTldJars.add("sunpkcs11.jar");
|
||||
}
|
||||
|
||||
public TldLocationsCache(ServletContext ctxt) {
|
||||
this(ctxt, true);
|
||||
}
|
||||
|
||||
/** Constructor.
|
||||
*
|
||||
* @param ctxt the servlet context of the web application in which Jasper
|
||||
* is running
|
||||
* @param redeployMode if true, then the compiler will allow redeploying
|
||||
* a tag library from the same jar, at the expense of slowing down the
|
||||
* server a bit. Note that this may only work on JDK 1.3.1_01a and later,
|
||||
* because of JDK bug 4211817 fixed in this release.
|
||||
* If redeployMode is false, a faster but less capable mode will be used.
|
||||
*/
|
||||
public TldLocationsCache(ServletContext ctxt, boolean redeployMode) {
|
||||
this.ctxt = ctxt;
|
||||
this.redeployMode = redeployMode;
|
||||
mappings = new Hashtable();
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the list of JARs that are known not to contain any TLDs.
|
||||
*
|
||||
* @param jarNames List of comma-separated names of JAR files that are
|
||||
* known not to contain any TLDs
|
||||
*/
|
||||
public static void setNoTldJars(String jarNames) {
|
||||
if (jarNames != null) {
|
||||
noTldJars.clear();
|
||||
StringTokenizer tokenizer = new StringTokenizer(jarNames, ",");
|
||||
while (tokenizer.hasMoreElements()) {
|
||||
noTldJars.add(tokenizer.nextToken());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the 'location' of the TLD associated with the given taglib 'uri'.
|
||||
*
|
||||
* Returns null if the uri is not associated with any tag library 'exposed'
|
||||
* in the web application. A tag library is 'exposed' either explicitly in
|
||||
* web.xml or implicitly via the uri tag in the TLD of a taglib deployed
|
||||
* in a jar file (WEB-INF/lib).
|
||||
*
|
||||
* @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 uri is not associated with any tag library 'exposed'
|
||||
* in the web application.
|
||||
*/
|
||||
public String[] getLocation(String uri) throws JasperException {
|
||||
if (!initialized) {
|
||||
init();
|
||||
}
|
||||
return (String[]) mappings.get(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of a URI:
|
||||
* ABS_URI
|
||||
* ROOT_REL_URI
|
||||
* NOROOT_REL_URI
|
||||
*/
|
||||
public static int uriType(String uri) {
|
||||
if (uri.indexOf(':') != -1) {
|
||||
return ABS_URI;
|
||||
} else if (uri.startsWith("/")) {
|
||||
return ROOT_REL_URI;
|
||||
} else {
|
||||
return NOROOT_REL_URI;
|
||||
}
|
||||
}
|
||||
|
||||
private void init() throws JasperException {
|
||||
if (initialized) return;
|
||||
try {
|
||||
processWebDotXml();
|
||||
scanJars();
|
||||
processTldsInFileSystem("/WEB-INF/");
|
||||
initialized = true;
|
||||
} catch (Exception ex) {
|
||||
throw new JasperException(Localizer.getMessage(
|
||||
"jsp.error.internal.tldinit", ex.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Populates taglib map described in web.xml.
|
||||
*/
|
||||
private void processWebDotXml() throws Exception {
|
||||
|
||||
InputStream is = null;
|
||||
|
||||
try {
|
||||
// Acquire input stream to web application deployment descriptor
|
||||
String altDDName = (String)ctxt.getAttribute(
|
||||
Constants.ALT_DD_ATTR);
|
||||
URL uri = null;
|
||||
if (altDDName != null) {
|
||||
try {
|
||||
uri = new URL(FILE_PROTOCOL+altDDName.replace('\\', '/'));
|
||||
} catch (MalformedURLException e) {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage(
|
||||
"jsp.error.internal.filenotfound",
|
||||
altDDName));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uri = ctxt.getResource(WEB_XML);
|
||||
if (uri == null && log.isWarnEnabled()) {
|
||||
log.warn(Localizer.getMessage(
|
||||
"jsp.error.internal.filenotfound",
|
||||
WEB_XML));
|
||||
}
|
||||
}
|
||||
|
||||
if (uri == null) {
|
||||
return;
|
||||
}
|
||||
is = uri.openStream();
|
||||
InputSource ip = new InputSource(is);
|
||||
ip.setSystemId(uri.toExternalForm());
|
||||
|
||||
// Parse the web application deployment descriptor
|
||||
TreeNode webtld = null;
|
||||
// altDDName is the absolute path of the DD
|
||||
if (altDDName != null) {
|
||||
webtld = new ParserUtils().parseXMLDocument(altDDName, ip);
|
||||
} else {
|
||||
webtld = new ParserUtils().parseXMLDocument(WEB_XML, ip);
|
||||
}
|
||||
|
||||
// Allow taglib to be an element of the root or jsp-config (JSP2.0)
|
||||
TreeNode jspConfig = webtld.findChild("jsp-config");
|
||||
if (jspConfig != null) {
|
||||
webtld = jspConfig;
|
||||
}
|
||||
Iterator taglibs = webtld.findChildren("taglib");
|
||||
while (taglibs.hasNext()) {
|
||||
|
||||
// Parse the next <taglib> element
|
||||
TreeNode taglib = (TreeNode) taglibs.next();
|
||||
String tagUri = null;
|
||||
String tagLoc = null;
|
||||
TreeNode child = taglib.findChild("taglib-uri");
|
||||
if (child != null)
|
||||
tagUri = child.getBody();
|
||||
child = taglib.findChild("taglib-location");
|
||||
if (child != null)
|
||||
tagLoc = child.getBody();
|
||||
|
||||
// Save this location if appropriate
|
||||
if (tagLoc == null)
|
||||
continue;
|
||||
if (uriType(tagLoc) == NOROOT_REL_URI)
|
||||
tagLoc = "/WEB-INF/" + tagLoc;
|
||||
String tagLoc2 = null;
|
||||
if (tagLoc.endsWith(JAR_FILE_SUFFIX)) {
|
||||
tagLoc = ctxt.getResource(tagLoc).toString();
|
||||
tagLoc2 = "META-INF/taglib.tld";
|
||||
}
|
||||
mappings.put(tagUri, new String[] { tagLoc, tagLoc2 });
|
||||
}
|
||||
} finally {
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch (Throwable t) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans the given JarURLConnection for TLD files located in META-INF
|
||||
* (or a subdirectory of it), adding an implicit map entry to the taglib
|
||||
* map for any TLD that has a <uri> element.
|
||||
*
|
||||
* @param conn The JarURLConnection to the JAR file to scan
|
||||
* @param ignore true if any exceptions raised when processing the given
|
||||
* JAR should be ignored, false otherwise
|
||||
*/
|
||||
private void scanJar(JarURLConnection conn, boolean ignore)
|
||||
throws JasperException {
|
||||
|
||||
JarFile jarFile = null;
|
||||
String resourcePath = conn.getJarFileURL().toString();
|
||||
try {
|
||||
if (redeployMode) {
|
||||
conn.setUseCaches(false);
|
||||
}
|
||||
jarFile = conn.getJarFile();
|
||||
Enumeration entries = jarFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
JarEntry entry = (JarEntry) entries.nextElement();
|
||||
String name = entry.getName();
|
||||
if (!name.startsWith("META-INF/")) continue;
|
||||
if (!name.endsWith(".tld")) continue;
|
||||
InputStream stream = jarFile.getInputStream(entry);
|
||||
try {
|
||||
String uri = getUriFromTld(resourcePath, stream);
|
||||
// Add implicit map entry only if its uri is not already
|
||||
// present in the map
|
||||
if (uri != null && mappings.get(uri) == null) {
|
||||
mappings.put(uri, new String[]{ resourcePath, name });
|
||||
}
|
||||
} finally {
|
||||
if (stream != null) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (Throwable t) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
if (!redeployMode) {
|
||||
// if not in redeploy mode, close the jar in case of an error
|
||||
if (jarFile != null) {
|
||||
try {
|
||||
jarFile.close();
|
||||
} catch (Throwable t) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ignore) {
|
||||
throw new JasperException(ex);
|
||||
}
|
||||
} finally {
|
||||
if (redeployMode) {
|
||||
// if in redeploy mode, always close the jar
|
||||
if (jarFile != null) {
|
||||
try {
|
||||
jarFile.close();
|
||||
} catch (Throwable t) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Searches the filesystem under /WEB-INF for any TLD files, and adds
|
||||
* an implicit map entry to the taglib map for any TLD that has a <uri>
|
||||
* element.
|
||||
*/
|
||||
private void processTldsInFileSystem(String startPath)
|
||||
throws Exception {
|
||||
|
||||
Set dirList = ctxt.getResourcePaths(startPath);
|
||||
if (dirList != null) {
|
||||
Iterator it = dirList.iterator();
|
||||
while (it.hasNext()) {
|
||||
String path = (String) it.next();
|
||||
if (path.endsWith("/")) {
|
||||
processTldsInFileSystem(path);
|
||||
}
|
||||
if (!path.endsWith(".tld")) {
|
||||
continue;
|
||||
}
|
||||
InputStream stream = ctxt.getResourceAsStream(path);
|
||||
String uri = null;
|
||||
try {
|
||||
uri = getUriFromTld(path, stream);
|
||||
} finally {
|
||||
if (stream != null) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (Throwable t) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add implicit map entry only if its uri is not already
|
||||
// present in the map
|
||||
if (uri != null && mappings.get(uri) == null) {
|
||||
mappings.put(uri, new String[] { path, null });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the value of the uri element of the given TLD, or null if the
|
||||
* given TLD does not contain any such element.
|
||||
*/
|
||||
private String getUriFromTld(String resourcePath, InputStream in)
|
||||
throws JasperException
|
||||
{
|
||||
// Parse the tag library descriptor at the specified resource path
|
||||
TreeNode tld = new ParserUtils().parseXMLDocument(resourcePath, in);
|
||||
TreeNode uri = tld.findChild("uri");
|
||||
if (uri != null) {
|
||||
String body = uri.getBody();
|
||||
if (body != null)
|
||||
return body;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scans all JARs accessible to the webapp's classloader and its
|
||||
* parent classloaders for TLDs.
|
||||
*
|
||||
* The list of JARs always includes the JARs under WEB-INF/lib, as well as
|
||||
* all shared JARs in the classloader delegation chain of the webapp's
|
||||
* classloader.
|
||||
*
|
||||
* Considering JARs in the classloader delegation chain constitutes a
|
||||
* Tomcat-specific extension to the TLD search
|
||||
* order defined in the JSP spec. It allows tag libraries packaged as JAR
|
||||
* files to be shared by web applications by simply dropping them in a
|
||||
* location that all web applications have access to (e.g.,
|
||||
* <CATALINA_HOME>/common/lib).
|
||||
*
|
||||
* The set of shared JARs to be scanned for TLDs is narrowed down by
|
||||
* the <tt>noTldJars</tt> class variable, which contains the names of JARs
|
||||
* that are known not to contain any TLDs.
|
||||
*/
|
||||
private void scanJars() throws Exception {
|
||||
|
||||
ClassLoader webappLoader
|
||||
= Thread.currentThread().getContextClassLoader();
|
||||
ClassLoader loader = webappLoader;
|
||||
|
||||
while (loader != null) {
|
||||
if (loader instanceof URLClassLoader) {
|
||||
URL[] urls = ((URLClassLoader) loader).getURLs();
|
||||
for (int i=0; i<urls.length; i++) {
|
||||
URLConnection conn = urls[i].openConnection();
|
||||
if (conn instanceof JarURLConnection) {
|
||||
if (needScanJar(loader, webappLoader,
|
||||
((JarURLConnection) conn).getJarFile().getName())) {
|
||||
scanJar((JarURLConnection) conn, true);
|
||||
}
|
||||
} else {
|
||||
String urlStr = urls[i].toString();
|
||||
if (urlStr.startsWith(FILE_PROTOCOL)
|
||||
&& urlStr.endsWith(JAR_FILE_SUFFIX)
|
||||
&& needScanJar(loader, webappLoader, urlStr)) {
|
||||
URL jarURL = new URL("jar:" + urlStr + "!/");
|
||||
scanJar((JarURLConnection) jarURL.openConnection(),
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loader = loader.getParent();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Determines if the JAR file with the given <tt>jarPath</tt> needs to be
|
||||
* scanned for TLDs.
|
||||
*
|
||||
* @param loader The current classloader in the parent chain
|
||||
* @param webappLoader The webapp classloader
|
||||
* @param jarPath The JAR file path
|
||||
*
|
||||
* @return TRUE if the JAR file identified by <tt>jarPath</tt> needs to be
|
||||
* scanned for TLDs, FALSE otherwise
|
||||
*/
|
||||
private boolean needScanJar(ClassLoader loader, ClassLoader webappLoader,
|
||||
String jarPath) {
|
||||
if (loader == webappLoader) {
|
||||
// JARs under WEB-INF/lib must be scanned unconditionally according
|
||||
// to the spec.
|
||||
return true;
|
||||
} else {
|
||||
String jarName = jarPath;
|
||||
int slash = jarPath.lastIndexOf('/');
|
||||
if (slash >= 0) {
|
||||
jarName = jarPath.substring(slash + 1);
|
||||
}
|
||||
return (!noTldJars.contains(jarName));
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
-37
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* 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.compiler.tagplugin;
|
||||
|
||||
/**
|
||||
* This interface is to be implemented by the plugin author, to supply
|
||||
* an alternate implementation of the tag handlers. It can be used to
|
||||
* specify the Java codes to be generated when a tag is invoked.
|
||||
*
|
||||
* An implementation of this interface must be registered in a file
|
||||
* named "tagPlugins.xml" under WEB-INF.
|
||||
*/
|
||||
|
||||
public interface TagPlugin {
|
||||
|
||||
/**
|
||||
* Generate codes for a custom tag.
|
||||
* @param ctxt a TagPluginContext for accessing Jasper functions
|
||||
*/
|
||||
void doTag(TagPluginContext ctxt);
|
||||
}
|
||||
|
||||
-124
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* 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.compiler.tagplugin;
|
||||
|
||||
|
||||
/**
|
||||
* This interface allows the plugin author to make inqueries about the
|
||||
* properties of the current tag, and to use Jasper resources to generate
|
||||
* direct Java codes in place of tag handler invocations.
|
||||
*/
|
||||
|
||||
public interface TagPluginContext {
|
||||
/**
|
||||
* @return true if the body of the tag is scriptless.
|
||||
*/
|
||||
boolean isScriptless();
|
||||
|
||||
/**
|
||||
* @param attribute Name of the attribute
|
||||
* @return true if the attribute is specified in the tag
|
||||
*/
|
||||
boolean isAttributeSpecified(String attribute);
|
||||
|
||||
/**
|
||||
* @return An unique temporary variable name that the plugin can use.
|
||||
*/
|
||||
String getTemporaryVariableName();
|
||||
|
||||
/**
|
||||
* Generate an import statement
|
||||
* @param s Name of the import class, '*' allowed.
|
||||
*/
|
||||
void generateImport(String s);
|
||||
|
||||
/**
|
||||
* Generate a declaration in the of the generated class. This can be
|
||||
* used to declare an innter class, a method, or a class variable.
|
||||
* @param id An unique ID identifying the declaration. It is not
|
||||
* part of the declaration, and is used to ensure that the
|
||||
* declaration will only appear once. If this method is
|
||||
* invoked with the same id more than once in the translation
|
||||
* unit, only the first declaration will be taken.
|
||||
* @param text The text of the declaration.
|
||||
**/
|
||||
void generateDeclaration(String id, String text);
|
||||
|
||||
/**
|
||||
* Generate Java source codes
|
||||
*/
|
||||
void generateJavaSource(String s);
|
||||
|
||||
/**
|
||||
* @return true if the attribute is specified and its value is a
|
||||
* translation-time constant.
|
||||
*/
|
||||
boolean isConstantAttribute(String attribute);
|
||||
|
||||
/**
|
||||
* @return A string that is the value of a constant attribute. Undefined
|
||||
* if the attribute is not a (translation-time) constant.
|
||||
* null if the attribute is not specified.
|
||||
*/
|
||||
String getConstantAttribute(String attribute);
|
||||
|
||||
/**
|
||||
* Generate codesto evaluate value of a attribute in the custom tag
|
||||
* The codes is a Java expression.
|
||||
* NOTE: Currently cannot handle attributes that are fragments.
|
||||
* @param attribute The specified attribute
|
||||
*/
|
||||
void generateAttribute(String attribute);
|
||||
|
||||
/**
|
||||
* Generate codes for the body of the custom tag
|
||||
*/
|
||||
void generateBody();
|
||||
|
||||
/**
|
||||
* Abandon optimization for this tag handler, and instruct
|
||||
* Jasper to generate the tag handler calls, as usual.
|
||||
* Should be invoked if errors are detected, or when the tag body
|
||||
* is deemed too compilicated for optimization.
|
||||
*/
|
||||
void dontUseTagPlugin();
|
||||
|
||||
/**
|
||||
* Get the PluginContext for the parent of this custom tag. NOTE:
|
||||
* The operations available for PluginContext so obtained is limited
|
||||
* to getPluginAttribute and setPluginAttribute, and queries (e.g.
|
||||
* isScriptless(). There should be no calls to generate*().
|
||||
* @return The pluginContext for the parent node.
|
||||
* null if the parent is not a custom tag, or if the pluginConxt
|
||||
* if not available (because useTagPlugin is false, e.g).
|
||||
*/
|
||||
TagPluginContext getParentContext();
|
||||
|
||||
/**
|
||||
* Associate the attribute with a value in the current tagplugin context.
|
||||
* The plugin attributes can be used for communication among tags that
|
||||
* must work together as a group. See <c:when> for an example.
|
||||
*/
|
||||
void setPluginAttribute(String attr, Object value);
|
||||
|
||||
/**
|
||||
* Get the value of an attribute in the current tagplugin context.
|
||||
*/
|
||||
Object getPluginAttribute(String attr);
|
||||
}
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
* 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.el;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.el.ELContext;
|
||||
import javax.el.ELResolver;
|
||||
import javax.el.FunctionMapper;
|
||||
import javax.el.ValueExpression;
|
||||
import javax.el.VariableMapper;
|
||||
|
||||
/**
|
||||
* Implementation of ELContext
|
||||
*
|
||||
* @author Jacob Hookom
|
||||
*/
|
||||
public final class ELContextImpl extends ELContext {
|
||||
|
||||
private final static FunctionMapper NullFunctionMapper = new FunctionMapper() {
|
||||
public Method resolveFunction(String prefix, String localName) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
private final static class VariableMapperImpl extends VariableMapper {
|
||||
|
||||
private Map<String, ValueExpression> vars;
|
||||
|
||||
public ValueExpression resolveVariable(String variable) {
|
||||
if (vars == null) {
|
||||
return null;
|
||||
}
|
||||
return vars.get(variable);
|
||||
}
|
||||
|
||||
public ValueExpression setVariable(String variable,
|
||||
ValueExpression expression) {
|
||||
if (vars == null)
|
||||
vars = new HashMap<String, ValueExpression>();
|
||||
return vars.put(variable, expression);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final ELResolver resolver;
|
||||
|
||||
private FunctionMapper functionMapper = NullFunctionMapper; // immutable
|
||||
|
||||
private VariableMapper variableMapper;
|
||||
|
||||
public ELContextImpl() {
|
||||
this(ELResolverImpl.DefaultResolver);
|
||||
}
|
||||
|
||||
public ELContextImpl(ELResolver resolver) {
|
||||
this.resolver = resolver;
|
||||
}
|
||||
|
||||
public ELResolver getELResolver() {
|
||||
return this.resolver;
|
||||
}
|
||||
|
||||
public FunctionMapper getFunctionMapper() {
|
||||
return this.functionMapper;
|
||||
}
|
||||
|
||||
public VariableMapper getVariableMapper() {
|
||||
if (this.variableMapper == null) {
|
||||
this.variableMapper = new VariableMapperImpl();
|
||||
}
|
||||
return this.variableMapper;
|
||||
}
|
||||
|
||||
public void setFunctionMapper(FunctionMapper functionMapper) {
|
||||
this.functionMapper = functionMapper;
|
||||
}
|
||||
|
||||
public void setVariableMapper(VariableMapper variableMapper) {
|
||||
this.variableMapper = variableMapper;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* 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.el;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.el.ELContext;
|
||||
import javax.el.ELResolver;
|
||||
import javax.el.FunctionMapper;
|
||||
import javax.el.VariableMapper;
|
||||
|
||||
/**
|
||||
* Simple ELContextWrapper for runtime evaluation of EL w/ dynamic FunctionMappers
|
||||
*
|
||||
* @author jhook
|
||||
*/
|
||||
public final class ELContextWrapper extends ELContext {
|
||||
|
||||
private final ELContext target;
|
||||
private final FunctionMapper fnMapper;
|
||||
|
||||
public ELContextWrapper(ELContext target, FunctionMapper fnMapper) {
|
||||
this.target = target;
|
||||
this.fnMapper = fnMapper;
|
||||
}
|
||||
|
||||
public ELResolver getELResolver() {
|
||||
return this.target.getELResolver();
|
||||
}
|
||||
|
||||
public FunctionMapper getFunctionMapper() {
|
||||
if (this.fnMapper != null) return this.fnMapper;
|
||||
return this.target.getFunctionMapper();
|
||||
}
|
||||
|
||||
public VariableMapper getVariableMapper() {
|
||||
return this.target.getVariableMapper();
|
||||
}
|
||||
|
||||
public Object getContext(Class key) {
|
||||
return this.target.getContext(key);
|
||||
}
|
||||
|
||||
public Locale getLocale() {
|
||||
return this.target.getLocale();
|
||||
}
|
||||
|
||||
public boolean isPropertyResolved() {
|
||||
return this.target.isPropertyResolved();
|
||||
}
|
||||
|
||||
public void putContext(Class key, Object contextObject) throws NullPointerException {
|
||||
this.target.putContext(key, contextObject);
|
||||
}
|
||||
|
||||
public void setLocale(Locale locale) {
|
||||
this.target.setLocale(locale);
|
||||
}
|
||||
|
||||
public void setPropertyResolved(boolean resolved) {
|
||||
this.target.setPropertyResolved(resolved);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
/*
|
||||
* 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.el;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.el.ArrayELResolver;
|
||||
import javax.el.BeanELResolver;
|
||||
import javax.el.CompositeELResolver;
|
||||
import javax.el.ELContext;
|
||||
import javax.el.ELException;
|
||||
import javax.el.ELResolver;
|
||||
import javax.el.ListELResolver;
|
||||
import javax.el.MapELResolver;
|
||||
import javax.el.PropertyNotFoundException;
|
||||
import javax.el.PropertyNotWritableException;
|
||||
import javax.el.ResourceBundleELResolver;
|
||||
import javax.servlet.jsp.el.VariableResolver;
|
||||
|
||||
public final class ELResolverImpl extends ELResolver {
|
||||
|
||||
public final static ELResolver DefaultResolver = new CompositeELResolver();
|
||||
|
||||
static {
|
||||
((CompositeELResolver) DefaultResolver).add(new MapELResolver());
|
||||
((CompositeELResolver) DefaultResolver).add(new ResourceBundleELResolver());
|
||||
((CompositeELResolver) DefaultResolver).add(new ListELResolver());
|
||||
((CompositeELResolver) DefaultResolver).add(new ArrayELResolver());
|
||||
((CompositeELResolver) DefaultResolver).add(new BeanELResolver());
|
||||
}
|
||||
|
||||
private final VariableResolver variableResolver;
|
||||
|
||||
public ELResolverImpl(VariableResolver variableResolver) {
|
||||
this.variableResolver = variableResolver;
|
||||
}
|
||||
|
||||
public Object getValue(ELContext context, Object base, Object property)
|
||||
throws NullPointerException, PropertyNotFoundException, ELException {
|
||||
if (context == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
if (base == null) {
|
||||
context.setPropertyResolved(true);
|
||||
if (property != null) {
|
||||
try {
|
||||
return this.variableResolver.resolveVariable(property
|
||||
.toString());
|
||||
} catch (javax.servlet.jsp.el.ELException e) {
|
||||
throw new ELException(e.getMessage(), e.getCause());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!context.isPropertyResolved()) {
|
||||
return DefaultResolver.getValue(context, base, property);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Class<?> getType(ELContext context, Object base, Object property)
|
||||
throws NullPointerException, PropertyNotFoundException, ELException {
|
||||
if (context == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
if (base == null) {
|
||||
context.setPropertyResolved(true);
|
||||
if (property != null) {
|
||||
try {
|
||||
Object obj = this.variableResolver.resolveVariable(property
|
||||
.toString());
|
||||
return (obj != null) ? obj.getClass() : null;
|
||||
} catch (javax.servlet.jsp.el.ELException e) {
|
||||
throw new ELException(e.getMessage(), e.getCause());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!context.isPropertyResolved()) {
|
||||
return DefaultResolver.getType(context, base, property);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setValue(ELContext context, Object base, Object property,
|
||||
Object value) throws NullPointerException,
|
||||
PropertyNotFoundException, PropertyNotWritableException,
|
||||
ELException {
|
||||
if (context == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
if (base == null) {
|
||||
context.setPropertyResolved(true);
|
||||
throw new PropertyNotWritableException(
|
||||
"Legacy VariableResolver wrapped, not writable");
|
||||
}
|
||||
|
||||
if (!context.isPropertyResolved()) {
|
||||
DefaultResolver.setValue(context, base, property, value);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isReadOnly(ELContext context, Object base, Object property)
|
||||
throws NullPointerException, PropertyNotFoundException, ELException {
|
||||
if (context == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
if (base == null) {
|
||||
context.setPropertyResolved(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
return DefaultResolver.isReadOnly(context, base, property);
|
||||
}
|
||||
|
||||
public Iterator<java.beans.FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
|
||||
return DefaultResolver.getFeatureDescriptors(context, base);
|
||||
}
|
||||
|
||||
public Class<?> getCommonPropertyType(ELContext context, Object base) {
|
||||
if (base == null) {
|
||||
return String.class;
|
||||
}
|
||||
return DefaultResolver.getCommonPropertyType(context, base);
|
||||
}
|
||||
|
||||
}
|
||||
-58
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* 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.el;
|
||||
|
||||
import javax.el.ELContext;
|
||||
import javax.el.ExpressionFactory;
|
||||
import javax.el.ValueExpression;
|
||||
import javax.servlet.jsp.el.ELException;
|
||||
import javax.servlet.jsp.el.ELParseException;
|
||||
import javax.servlet.jsp.el.Expression;
|
||||
import javax.servlet.jsp.el.ExpressionEvaluator;
|
||||
import javax.servlet.jsp.el.FunctionMapper;
|
||||
import javax.servlet.jsp.el.VariableResolver;
|
||||
|
||||
|
||||
public final class ExpressionEvaluatorImpl extends ExpressionEvaluator {
|
||||
|
||||
private final ExpressionFactory factory;
|
||||
|
||||
public ExpressionEvaluatorImpl(ExpressionFactory factory) {
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
public Expression parseExpression(String expression, Class expectedType,
|
||||
FunctionMapper fMapper) throws ELException {
|
||||
try {
|
||||
ELContextImpl ctx = new ELContextImpl(ELResolverImpl.DefaultResolver);
|
||||
if (fMapper != null) {
|
||||
ctx.setFunctionMapper(new FunctionMapperImpl(fMapper));
|
||||
}
|
||||
ValueExpression ve = this.factory.createValueExpression(ctx, expression, expectedType);
|
||||
return new ExpressionImpl(ve);
|
||||
} catch (javax.el.ELException e) {
|
||||
throw new ELParseException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public Object evaluate(String expression, Class expectedType,
|
||||
VariableResolver vResolver, FunctionMapper fMapper)
|
||||
throws ELException {
|
||||
return this.parseExpression(expression, expectedType, fMapper).evaluate(vResolver);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* 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.el;
|
||||
|
||||
import javax.el.ELContext;
|
||||
import javax.el.ValueExpression;
|
||||
import javax.servlet.jsp.el.ELException;
|
||||
import javax.servlet.jsp.el.Expression;
|
||||
import javax.servlet.jsp.el.VariableResolver;
|
||||
|
||||
public final class ExpressionImpl extends Expression {
|
||||
|
||||
private final ValueExpression ve;
|
||||
|
||||
public ExpressionImpl(ValueExpression ve) {
|
||||
this.ve = ve;
|
||||
}
|
||||
|
||||
public Object evaluate(VariableResolver vResolver) throws ELException {
|
||||
ELContext ctx = new ELContextImpl(new ELResolverImpl(vResolver));
|
||||
return ve.getValue(ctx);
|
||||
}
|
||||
|
||||
}
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* 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.el;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.servlet.jsp.el.FunctionMapper;
|
||||
|
||||
public final class FunctionMapperImpl extends javax.el.FunctionMapper {
|
||||
|
||||
private final FunctionMapper fnMapper;
|
||||
|
||||
public FunctionMapperImpl(FunctionMapper fnMapper) {
|
||||
this.fnMapper = fnMapper;
|
||||
}
|
||||
|
||||
public Method resolveFunction(String prefix, String localName) {
|
||||
return this.fnMapper.resolveFunction(prefix, localName);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* 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.el;
|
||||
|
||||
import javax.el.ELException;
|
||||
|
||||
public class JspELException extends ELException {
|
||||
|
||||
public JspELException(String mark, ELException e) {
|
||||
super(mark + " " + e.getMessage(), e.getCause());
|
||||
}
|
||||
}
|
||||
-108
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* 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.el;
|
||||
|
||||
import java.io.Externalizable;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
|
||||
import javax.el.ELContext;
|
||||
import javax.el.ELException;
|
||||
import javax.el.MethodExpression;
|
||||
import javax.el.MethodInfo;
|
||||
import javax.el.MethodNotFoundException;
|
||||
import javax.el.PropertyNotFoundException;
|
||||
|
||||
public final class JspMethodExpression extends MethodExpression implements
|
||||
Externalizable {
|
||||
|
||||
private String mark;
|
||||
|
||||
private MethodExpression target;
|
||||
|
||||
public JspMethodExpression() {
|
||||
super();
|
||||
}
|
||||
|
||||
public JspMethodExpression(String mark, MethodExpression target) {
|
||||
this.target = target;
|
||||
this.mark = mark;
|
||||
}
|
||||
|
||||
public MethodInfo getMethodInfo(ELContext context)
|
||||
throws NullPointerException, PropertyNotFoundException,
|
||||
MethodNotFoundException, ELException {
|
||||
try {
|
||||
return this.target.getMethodInfo(context);
|
||||
} catch (MethodNotFoundException e) {
|
||||
if (e instanceof JspMethodNotFoundException) throw e;
|
||||
throw new JspMethodNotFoundException(this.mark, e);
|
||||
} catch (PropertyNotFoundException e) {
|
||||
if (e instanceof JspPropertyNotFoundException) throw e;
|
||||
throw new JspPropertyNotFoundException(this.mark, e);
|
||||
} catch (ELException e) {
|
||||
if (e instanceof JspELException) throw e;
|
||||
throw new JspELException(this.mark, e);
|
||||
}
|
||||
}
|
||||
|
||||
public Object invoke(ELContext context, Object[] params)
|
||||
throws NullPointerException, PropertyNotFoundException,
|
||||
MethodNotFoundException, ELException {
|
||||
try {
|
||||
return this.target.invoke(context, params);
|
||||
} catch (MethodNotFoundException e) {
|
||||
if (e instanceof JspMethodNotFoundException) throw e;
|
||||
throw new JspMethodNotFoundException(this.mark, e);
|
||||
} catch (PropertyNotFoundException e) {
|
||||
if (e instanceof JspPropertyNotFoundException) throw e;
|
||||
throw new JspPropertyNotFoundException(this.mark, e);
|
||||
} catch (ELException e) {
|
||||
if (e instanceof JspELException) throw e;
|
||||
throw new JspELException(this.mark, e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
return this.target.equals(obj);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.target.hashCode();
|
||||
}
|
||||
|
||||
public String getExpressionString() {
|
||||
return this.target.getExpressionString();
|
||||
}
|
||||
|
||||
public boolean isLiteralText() {
|
||||
return this.target.isLiteralText();
|
||||
}
|
||||
|
||||
public void writeExternal(ObjectOutput out) throws IOException {
|
||||
out.writeUTF(this.mark);
|
||||
out.writeObject(this.target);
|
||||
}
|
||||
|
||||
public void readExternal(ObjectInput in) throws IOException,
|
||||
ClassNotFoundException {
|
||||
this.mark = in.readUTF();
|
||||
this.target = (MethodExpression) in.readObject();
|
||||
}
|
||||
|
||||
}
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* 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.el;
|
||||
|
||||
import javax.el.MethodNotFoundException;
|
||||
|
||||
public class JspMethodNotFoundException extends MethodNotFoundException {
|
||||
|
||||
public JspMethodNotFoundException(String mark, MethodNotFoundException e) {
|
||||
super(mark + " " + e.getMessage(), e.getCause());
|
||||
}
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* 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.el;
|
||||
|
||||
import javax.el.PropertyNotFoundException;
|
||||
|
||||
public final class JspPropertyNotFoundException extends
|
||||
PropertyNotFoundException {
|
||||
|
||||
public JspPropertyNotFoundException(String mark, PropertyNotFoundException e) {
|
||||
super(mark + " " + e.getMessage(), e.getCause());
|
||||
}
|
||||
|
||||
}
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* 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.el;
|
||||
|
||||
import javax.el.PropertyNotWritableException;
|
||||
|
||||
public class JspPropertyNotWritableException extends
|
||||
PropertyNotWritableException {
|
||||
|
||||
public JspPropertyNotWritableException(String mark, PropertyNotWritableException e) {
|
||||
super(mark + " " + e.getMessage(), e.getCause());
|
||||
}
|
||||
}
|
||||
-137
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
* 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.el;
|
||||
|
||||
import java.io.Externalizable;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
|
||||
import javax.el.ELContext;
|
||||
import javax.el.ELException;
|
||||
import javax.el.PropertyNotFoundException;
|
||||
import javax.el.PropertyNotWritableException;
|
||||
import javax.el.ValueExpression;
|
||||
|
||||
/**
|
||||
* Wrapper for providing context to ValueExpressions
|
||||
*
|
||||
* @author Jacob Hookom
|
||||
*/
|
||||
public final class JspValueExpression extends ValueExpression implements
|
||||
Externalizable {
|
||||
|
||||
private ValueExpression target;
|
||||
|
||||
private String mark;
|
||||
|
||||
public JspValueExpression() {
|
||||
super();
|
||||
}
|
||||
|
||||
public JspValueExpression(String mark, ValueExpression target) {
|
||||
this.target = target;
|
||||
this.mark = mark;
|
||||
}
|
||||
|
||||
public Class<?> getExpectedType() {
|
||||
return this.target.getExpectedType();
|
||||
}
|
||||
|
||||
public Class<?> getType(ELContext context) throws NullPointerException,
|
||||
PropertyNotFoundException, ELException {
|
||||
try {
|
||||
return this.target.getType(context);
|
||||
} catch (PropertyNotFoundException e) {
|
||||
if (e instanceof JspPropertyNotFoundException) throw e;
|
||||
throw new JspPropertyNotFoundException(this.mark, e);
|
||||
} catch (ELException e) {
|
||||
if (e instanceof JspELException) throw e;
|
||||
throw new JspELException(this.mark, e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isReadOnly(ELContext context) throws NullPointerException,
|
||||
PropertyNotFoundException, ELException {
|
||||
try {
|
||||
return this.target.isReadOnly(context);
|
||||
} catch (PropertyNotFoundException e) {
|
||||
if (e instanceof JspPropertyNotFoundException) throw e;
|
||||
throw new JspPropertyNotFoundException(this.mark, e);
|
||||
} catch (ELException e) {
|
||||
if (e instanceof JspELException) throw e;
|
||||
throw new JspELException(this.mark, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setValue(ELContext context, Object value)
|
||||
throws NullPointerException, PropertyNotFoundException,
|
||||
PropertyNotWritableException, ELException {
|
||||
try {
|
||||
this.target.setValue(context, value);
|
||||
} catch (PropertyNotWritableException e) {
|
||||
if (e instanceof JspPropertyNotWritableException) throw e;
|
||||
throw new JspPropertyNotWritableException(this.mark, e);
|
||||
} catch (PropertyNotFoundException e) {
|
||||
if (e instanceof JspPropertyNotFoundException) throw e;
|
||||
throw new JspPropertyNotFoundException(this.mark, e);
|
||||
} catch (ELException e) {
|
||||
if (e instanceof JspELException) throw e;
|
||||
throw new JspELException(this.mark, e);
|
||||
}
|
||||
}
|
||||
|
||||
public Object getValue(ELContext context) throws NullPointerException,
|
||||
PropertyNotFoundException, ELException {
|
||||
try {
|
||||
return this.target.getValue(context);
|
||||
} catch (PropertyNotFoundException e) {
|
||||
if (e instanceof JspPropertyNotFoundException) throw e;
|
||||
throw new JspPropertyNotFoundException(this.mark, e);
|
||||
} catch (ELException e) {
|
||||
if (e instanceof JspELException) throw e;
|
||||
throw new JspELException(this.mark, e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
return this.target.equals(obj);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.target.hashCode();
|
||||
}
|
||||
|
||||
public String getExpressionString() {
|
||||
return this.target.getExpressionString();
|
||||
}
|
||||
|
||||
public boolean isLiteralText() {
|
||||
return this.target.isLiteralText();
|
||||
}
|
||||
|
||||
public void writeExternal(ObjectOutput out) throws IOException {
|
||||
out.writeUTF(this.mark);
|
||||
out.writeObject(this.target);
|
||||
}
|
||||
|
||||
public void readExternal(ObjectInput in) throws IOException,
|
||||
ClassNotFoundException {
|
||||
this.mark = in.readUTF();
|
||||
this.target = (ValueExpression) in.readObject();
|
||||
}
|
||||
}
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* 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.el;
|
||||
|
||||
import javax.el.ELContext;
|
||||
import javax.servlet.jsp.el.ELException;
|
||||
import javax.servlet.jsp.el.VariableResolver;
|
||||
|
||||
public final class VariableResolverImpl implements VariableResolver {
|
||||
|
||||
private final ELContext ctx;
|
||||
|
||||
public VariableResolverImpl(ELContext ctx) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
public Object resolveVariable(String pName) throws ELException {
|
||||
return this.ctx.getELResolver().getValue(this.ctx, null, pName);
|
||||
}
|
||||
|
||||
}
|
||||
-61
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* 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.runtime;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
|
||||
import org.apache.AnnotationProcessor;
|
||||
|
||||
|
||||
/**
|
||||
* Verify the annotation and Process it.
|
||||
*
|
||||
* @author Fabien Carrion
|
||||
* @author Remy Maucherat
|
||||
* @version $Revision: 467222 $, $Date: 2006-10-24 05:17:11 +0200 (Tue, 24 Oct 2006) $
|
||||
*/
|
||||
public class AnnotationHelper {
|
||||
|
||||
|
||||
/**
|
||||
* Call postConstruct method on the specified instance. Note: In Jasper, this
|
||||
* calls naming resources injection as well.
|
||||
*/
|
||||
public static void postConstruct(AnnotationProcessor processor, Object instance)
|
||||
throws IllegalAccessException, InvocationTargetException, NamingException {
|
||||
if (processor != null) {
|
||||
processor.processAnnotations(instance);
|
||||
processor.postConstruct(instance);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call preDestroy method on the specified instance.
|
||||
*/
|
||||
public static void preDestroy(AnnotationProcessor processor, Object instance)
|
||||
throws IllegalAccessException, InvocationTargetException {
|
||||
if (processor != null) {
|
||||
processor.preDestroy(instance);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
-604
@@ -1,604 +0,0 @@
|
||||
/*
|
||||
* 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.runtime;
|
||||
|
||||
import java.io.CharArrayReader;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
|
||||
import javax.servlet.jsp.JspWriter;
|
||||
import javax.servlet.jsp.tagext.BodyContent;
|
||||
|
||||
import org.apache.jasper.Constants;
|
||||
|
||||
/**
|
||||
* Write text to a character-output stream, buffering characters so as
|
||||
* to provide for the efficient writing of single characters, arrays,
|
||||
* and strings.
|
||||
*
|
||||
* Provide support for discarding for the output that has been buffered.
|
||||
*
|
||||
* @author Rajiv Mordani
|
||||
* @author Jan Luehe
|
||||
*/
|
||||
public class BodyContentImpl extends BodyContent {
|
||||
|
||||
private static final String LINE_SEPARATOR =
|
||||
System.getProperty("line.separator");
|
||||
private static final boolean LIMIT_BUFFER =
|
||||
Boolean.valueOf(System.getProperty("org.apache.jasper.runtime.BodyContentImpl.LIMIT_BUFFER", "false")).booleanValue();
|
||||
|
||||
private char[] cb;
|
||||
private int nextChar;
|
||||
private boolean closed;
|
||||
|
||||
// Enclosed writer to which any output is written
|
||||
private Writer writer;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public BodyContentImpl(JspWriter enclosingWriter) {
|
||||
super(enclosingWriter);
|
||||
bufferSize = Constants.DEFAULT_TAG_BUFFER_SIZE;
|
||||
cb = new char[bufferSize];
|
||||
nextChar = 0;
|
||||
closed = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a single character.
|
||||
*/
|
||||
public void write(int c) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(c);
|
||||
} else {
|
||||
ensureOpen();
|
||||
if (nextChar >= bufferSize) {
|
||||
reAllocBuff (1);
|
||||
}
|
||||
cb[nextChar++] = (char) c;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a portion of an array of characters.
|
||||
*
|
||||
* <p> Ordinarily this method stores characters from the given array into
|
||||
* this stream's buffer, flushing the buffer to the underlying stream as
|
||||
* needed. If the requested length is at least as large as the buffer,
|
||||
* however, then this method will flush the buffer and write the characters
|
||||
* directly to the underlying stream. Thus redundant
|
||||
* <code>DiscardableBufferedWriter</code>s will not copy data
|
||||
* unnecessarily.
|
||||
*
|
||||
* @param cbuf A character array
|
||||
* @param off Offset from which to start reading characters
|
||||
* @param len Number of characters to write
|
||||
*/
|
||||
public void write(char[] cbuf, int off, int len) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(cbuf, off, len);
|
||||
} else {
|
||||
ensureOpen();
|
||||
|
||||
if ((off < 0) || (off > cbuf.length) || (len < 0) ||
|
||||
((off + len) > cbuf.length) || ((off + len) < 0)) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
} else if (len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (len >= bufferSize - nextChar)
|
||||
reAllocBuff (len);
|
||||
|
||||
System.arraycopy(cbuf, off, cb, nextChar, len);
|
||||
nextChar+=len;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an array of characters. This method cannot be inherited from the
|
||||
* Writer class because it must suppress I/O exceptions.
|
||||
*/
|
||||
public void write(char[] buf) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(buf);
|
||||
} else {
|
||||
write(buf, 0, buf.length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a portion of a String.
|
||||
*
|
||||
* @param s String to be written
|
||||
* @param off Offset from which to start reading characters
|
||||
* @param len Number of characters to be written
|
||||
*/
|
||||
public void write(String s, int off, int len) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(s, off, len);
|
||||
} else {
|
||||
ensureOpen();
|
||||
if (len >= bufferSize - nextChar)
|
||||
reAllocBuff(len);
|
||||
|
||||
s.getChars(off, off + len, cb, nextChar);
|
||||
nextChar += len;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a string. This method cannot be inherited from the Writer class
|
||||
* because it must suppress I/O exceptions.
|
||||
*/
|
||||
public void write(String s) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(s);
|
||||
} else {
|
||||
write(s, 0, s.length());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a line separator. The line separator string is defined by the
|
||||
* system property <tt>line.separator</tt>, and is not necessarily a single
|
||||
* newline ('\n') character.
|
||||
*
|
||||
* @throws IOException If an I/O error occurs
|
||||
*/
|
||||
public void newLine() throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(LINE_SEPARATOR);
|
||||
} else {
|
||||
write(LINE_SEPARATOR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a boolean value. The string produced by <code>{@link
|
||||
* java.lang.String#valueOf(boolean)}</code> is translated into bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the <code>{@link
|
||||
* #write(int)}</code> method.
|
||||
*
|
||||
* @param b The <code>boolean</code> to be printed
|
||||
* @throws IOException
|
||||
*/
|
||||
public void print(boolean b) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(b ? "true" : "false");
|
||||
} else {
|
||||
write(b ? "true" : "false");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a character. The character is translated into one or more bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the <code>{@link
|
||||
* #write(int)}</code> method.
|
||||
*
|
||||
* @param c The <code>char</code> to be printed
|
||||
* @throws IOException
|
||||
*/
|
||||
public void print(char c) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(String.valueOf(c));
|
||||
} else {
|
||||
write(String.valueOf(c));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an integer. The string produced by <code>{@link
|
||||
* java.lang.String#valueOf(int)}</code> is translated into bytes according
|
||||
* to the platform's default character encoding, and these bytes are
|
||||
* written in exactly the manner of the <code>{@link #write(int)}</code>
|
||||
* method.
|
||||
*
|
||||
* @param i The <code>int</code> to be printed
|
||||
* @throws IOException
|
||||
*/
|
||||
public void print(int i) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(String.valueOf(i));
|
||||
} else {
|
||||
write(String.valueOf(i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a long integer. The string produced by <code>{@link
|
||||
* java.lang.String#valueOf(long)}</code> is translated into bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the
|
||||
* <code>{@link #write(int)}</code> method.
|
||||
*
|
||||
* @param l The <code>long</code> to be printed
|
||||
* @throws IOException
|
||||
*/
|
||||
public void print(long l) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(String.valueOf(l));
|
||||
} else {
|
||||
write(String.valueOf(l));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a floating-point number. The string produced by <code>{@link
|
||||
* java.lang.String#valueOf(float)}</code> is translated into bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the
|
||||
* <code>{@link #write(int)}</code> method.
|
||||
*
|
||||
* @param f The <code>float</code> to be printed
|
||||
* @throws IOException
|
||||
*/
|
||||
public void print(float f) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(String.valueOf(f));
|
||||
} else {
|
||||
write(String.valueOf(f));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a double-precision floating-point number. The string produced by
|
||||
* <code>{@link java.lang.String#valueOf(double)}</code> is translated into
|
||||
* bytes according to the platform's default character encoding, and these
|
||||
* bytes are written in exactly the manner of the <code>{@link
|
||||
* #write(int)}</code> method.
|
||||
*
|
||||
* @param d The <code>double</code> to be printed
|
||||
* @throws IOException
|
||||
*/
|
||||
public void print(double d) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(String.valueOf(d));
|
||||
} else {
|
||||
write(String.valueOf(d));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an array of characters. The characters are converted into bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the
|
||||
* <code>{@link #write(int)}</code> method.
|
||||
*
|
||||
* @param s The array of chars to be printed
|
||||
*
|
||||
* @throws NullPointerException If <code>s</code> is <code>null</code>
|
||||
* @throws IOException
|
||||
*/
|
||||
public void print(char[] s) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(s);
|
||||
} else {
|
||||
write(s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a string. If the argument is <code>null</code> then the string
|
||||
* <code>"null"</code> is printed. Otherwise, the string's characters are
|
||||
* converted into bytes according to the platform's default character
|
||||
* encoding, and these bytes are written in exactly the manner of the
|
||||
* <code>{@link #write(int)}</code> method.
|
||||
*
|
||||
* @param s The <code>String</code> to be printed
|
||||
* @throws IOException
|
||||
*/
|
||||
public void print(String s) throws IOException {
|
||||
if (s == null) s = "null";
|
||||
if (writer != null) {
|
||||
writer.write(s);
|
||||
} else {
|
||||
write(s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an object. The string produced by the <code>{@link
|
||||
* java.lang.String#valueOf(Object)}</code> method is translated into bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the
|
||||
* <code>{@link #write(int)}</code> method.
|
||||
*
|
||||
* @param obj The <code>Object</code> to be printed
|
||||
* @throws IOException
|
||||
*/
|
||||
public void print(Object obj) throws IOException {
|
||||
if (writer != null) {
|
||||
writer.write(String.valueOf(obj));
|
||||
} else {
|
||||
write(String.valueOf(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminate the current line by writing the line separator string. The
|
||||
* line separator string is defined by the system property
|
||||
* <code>line.separator</code>, and is not necessarily a single newline
|
||||
* character (<code>'\n'</code>).
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void println() throws IOException {
|
||||
newLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a boolean value and then terminate the line. This method behaves
|
||||
* as though it invokes <code>{@link #print(boolean)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void println(boolean x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a character and then terminate the line. This method behaves as
|
||||
* though it invokes <code>{@link #print(char)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void println(char x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an integer and then terminate the line. This method behaves as
|
||||
* though it invokes <code>{@link #print(int)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void println(int x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a long integer and then terminate the line. This method behaves
|
||||
* as though it invokes <code>{@link #print(long)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void println(long x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a floating-point number and then terminate the line. This method
|
||||
* behaves as though it invokes <code>{@link #print(float)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void println(float x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a double-precision floating-point number and then terminate the
|
||||
* line. This method behaves as though it invokes <code>{@link
|
||||
* #print(double)}</code> and then <code>{@link #println()}</code>.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void println(double x) throws IOException{
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an array of characters and then terminate the line. This method
|
||||
* behaves as though it invokes <code>{@link #print(char[])}</code> and
|
||||
* then <code>{@link #println()}</code>.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void println(char x[]) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a String and then terminate the line. This method behaves as
|
||||
* though it invokes <code>{@link #print(String)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void println(String x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an Object and then terminate the line. This method behaves as
|
||||
* though it invokes <code>{@link #print(Object)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void println(Object x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the contents of the buffer. If the buffer has been already
|
||||
* been flushed then the clear operation shall throw an IOException
|
||||
* to signal the fact that some data has already been irrevocably
|
||||
* written to the client response stream.
|
||||
*
|
||||
* @throws IOException If an I/O error occurs
|
||||
*/
|
||||
public void clear() throws IOException {
|
||||
if (writer != null) {
|
||||
throw new IOException();
|
||||
} else {
|
||||
nextChar = 0;
|
||||
if (LIMIT_BUFFER && (cb.length > Constants.DEFAULT_TAG_BUFFER_SIZE)) {
|
||||
bufferSize = Constants.DEFAULT_TAG_BUFFER_SIZE;
|
||||
cb = new char[bufferSize];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the current contents of the buffer. Unlike clear(), this
|
||||
* mehtod will not throw an IOException if the buffer has already been
|
||||
* flushed. It merely clears the current content of the buffer and
|
||||
* returns.
|
||||
*
|
||||
* @throws IOException If an I/O error occurs
|
||||
*/
|
||||
public void clearBuffer() throws IOException {
|
||||
if (writer == null) {
|
||||
this.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the stream, flushing it first. Once a stream has been closed,
|
||||
* further write() or flush() invocations will cause an IOException to be
|
||||
* thrown. Closing a previously-closed stream, however, has no effect.
|
||||
*
|
||||
* @throws IOException If an I/O error occurs
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
if (writer != null) {
|
||||
writer.close();
|
||||
} else {
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the size of the buffer used by the JspWriter.
|
||||
*
|
||||
* @return the size of the buffer in bytes, or 0 is unbuffered.
|
||||
*/
|
||||
public int getBufferSize() {
|
||||
// According to the spec, the JspWriter returned by
|
||||
// JspContext.pushBody(java.io.Writer writer) must behave as
|
||||
// though it were unbuffered. This means that its getBufferSize()
|
||||
// must always return 0.
|
||||
return (writer == null) ? bufferSize : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of bytes unused in the buffer
|
||||
*/
|
||||
public int getRemaining() {
|
||||
return (writer == null) ? bufferSize-nextChar : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value of this BodyJspWriter as a Reader.
|
||||
* Note: this is after evaluation!! There are no scriptlets,
|
||||
* etc in this stream.
|
||||
*
|
||||
* @return the value of this BodyJspWriter as a Reader
|
||||
*/
|
||||
public Reader getReader() {
|
||||
return (writer == null) ? new CharArrayReader (cb, 0, nextChar) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value of the BodyJspWriter as a String.
|
||||
* Note: this is after evaluation!! There are no scriptlets,
|
||||
* etc in this stream.
|
||||
*
|
||||
* @return the value of the BodyJspWriter as a String
|
||||
*/
|
||||
public String getString() {
|
||||
return (writer == null) ? new String(cb, 0, nextChar) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the contents of this BodyJspWriter into a Writer.
|
||||
* Subclasses are likely to do interesting things with the
|
||||
* implementation so some things are extra efficient.
|
||||
*
|
||||
* @param out The writer into which to place the contents of this body
|
||||
* evaluation
|
||||
*/
|
||||
public void writeOut(Writer out) throws IOException {
|
||||
if (writer == null) {
|
||||
out.write(cb, 0, nextChar);
|
||||
// Flush not called as the writer passed could be a BodyContent and
|
||||
// it doesn't allow to flush.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the writer to which all output is written.
|
||||
*/
|
||||
void setWriter(Writer writer) {
|
||||
this.writer = writer;
|
||||
closed = false;
|
||||
if (writer == null) {
|
||||
clearBody();
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureOpen() throws IOException {
|
||||
if (closed) throw new IOException("Stream closed");
|
||||
}
|
||||
|
||||
/**
|
||||
* Reallocates buffer since the spec requires it to be unbounded.
|
||||
*/
|
||||
private void reAllocBuff(int len) {
|
||||
|
||||
if (bufferSize + len <= cb.length) {
|
||||
bufferSize = cb.length;
|
||||
return;
|
||||
}
|
||||
|
||||
if (len < cb.length) {
|
||||
len = cb.length;
|
||||
}
|
||||
|
||||
bufferSize = cb.length + len;
|
||||
char[] tmp = new char[bufferSize];
|
||||
|
||||
System.arraycopy(cb, 0, tmp, 0, cb.length);
|
||||
cb = tmp;
|
||||
tmp = null;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* 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.runtime;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.jsp.HttpJspPage;
|
||||
import javax.servlet.jsp.JspFactory;
|
||||
|
||||
import org.apache.jasper.compiler.Localizer;
|
||||
|
||||
/**
|
||||
* This is the super class of all JSP-generated servlets.
|
||||
*
|
||||
* @author Anil K. Vijendran
|
||||
*/
|
||||
public abstract class HttpJspBase
|
||||
extends HttpServlet
|
||||
implements HttpJspPage
|
||||
|
||||
|
||||
{
|
||||
|
||||
protected HttpJspBase() {
|
||||
}
|
||||
|
||||
public final void init(ServletConfig config)
|
||||
throws ServletException
|
||||
{
|
||||
super.init(config);
|
||||
jspInit();
|
||||
_jspInit();
|
||||
}
|
||||
|
||||
public String getServletInfo() {
|
||||
return Localizer.getMessage("jsp.engine.info");
|
||||
}
|
||||
|
||||
public final void destroy() {
|
||||
jspDestroy();
|
||||
_jspDestroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Entry point into service.
|
||||
*/
|
||||
public final void service(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException
|
||||
{
|
||||
_jspService(request, response);
|
||||
}
|
||||
|
||||
public void jspInit() {
|
||||
}
|
||||
|
||||
public void _jspInit() {
|
||||
}
|
||||
|
||||
public void jspDestroy() {
|
||||
}
|
||||
|
||||
protected void _jspDestroy() {
|
||||
}
|
||||
|
||||
public abstract void _jspService(HttpServletRequest request,
|
||||
HttpServletResponse response)
|
||||
throws ServletException, IOException;
|
||||
}
|
||||
-138
@@ -1,138 +0,0 @@
|
||||
/*
|
||||
* 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.runtime;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.el.ArrayELResolver;
|
||||
import javax.el.BeanELResolver;
|
||||
import javax.el.CompositeELResolver;
|
||||
import javax.el.ELContextEvent;
|
||||
import javax.el.ELContextListener;
|
||||
import javax.el.ELResolver;
|
||||
import javax.el.ExpressionFactory;
|
||||
import javax.el.ListELResolver;
|
||||
import javax.el.MapELResolver;
|
||||
import javax.el.ResourceBundleELResolver;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.jsp.JspApplicationContext;
|
||||
import javax.servlet.jsp.JspContext;
|
||||
import javax.servlet.jsp.el.ImplicitObjectELResolver;
|
||||
import javax.servlet.jsp.el.ScopedAttributeELResolver;
|
||||
|
||||
import org.apache.el.ExpressionFactoryImpl;
|
||||
import org.apache.jasper.el.ELContextImpl;
|
||||
|
||||
/**
|
||||
* Implementation of JspApplicationContext
|
||||
*
|
||||
* @author Jacob Hookom
|
||||
*/
|
||||
public class JspApplicationContextImpl implements JspApplicationContext {
|
||||
|
||||
private final static String KEY = JspApplicationContextImpl.class.getName();
|
||||
|
||||
private final static ExpressionFactory expressionFactory = new ExpressionFactoryImpl();
|
||||
|
||||
private final List<ELContextListener> contextListeners = new ArrayList<ELContextListener>();
|
||||
|
||||
private final List<ELResolver> resolvers = new ArrayList<ELResolver>();
|
||||
|
||||
private boolean instantiated = false;
|
||||
|
||||
private ELResolver resolver;
|
||||
|
||||
public JspApplicationContextImpl() {
|
||||
|
||||
}
|
||||
|
||||
public void addELContextListener(ELContextListener listener) {
|
||||
if (listener == null) {
|
||||
throw new IllegalArgumentException("ELConextListener was null");
|
||||
}
|
||||
this.contextListeners.add(listener);
|
||||
}
|
||||
|
||||
public static JspApplicationContextImpl getInstance(ServletContext context) {
|
||||
if (context == null) {
|
||||
throw new IllegalArgumentException("ServletContext was null");
|
||||
}
|
||||
JspApplicationContextImpl impl = (JspApplicationContextImpl) context
|
||||
.getAttribute(KEY);
|
||||
if (impl == null) {
|
||||
impl = new JspApplicationContextImpl();
|
||||
context.setAttribute(KEY, impl);
|
||||
}
|
||||
return impl;
|
||||
}
|
||||
|
||||
public ELContextImpl createELContext(JspContext context) {
|
||||
if (context == null) {
|
||||
throw new IllegalArgumentException("JspContext was null");
|
||||
}
|
||||
|
||||
// create ELContext for JspContext
|
||||
ELResolver r = this.createELResolver();
|
||||
ELContextImpl ctx = new ELContextImpl(r);
|
||||
ctx.putContext(JspContext.class, context);
|
||||
|
||||
// alert all ELContextListeners
|
||||
ELContextEvent event = new ELContextEvent(ctx);
|
||||
for (int i = 0; i < this.contextListeners.size(); i++) {
|
||||
this.contextListeners.get(i).contextCreated(event);
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
private ELResolver createELResolver() {
|
||||
this.instantiated = true;
|
||||
if (this.resolver == null) {
|
||||
CompositeELResolver r = new CompositeELResolver();
|
||||
r.add(new ImplicitObjectELResolver());
|
||||
for (Iterator itr = this.resolvers.iterator(); itr.hasNext();) {
|
||||
r.add((ELResolver) itr.next());
|
||||
}
|
||||
r.add(new MapELResolver());
|
||||
r.add(new ResourceBundleELResolver());
|
||||
r.add(new ListELResolver());
|
||||
r.add(new ArrayELResolver());
|
||||
r.add(new BeanELResolver());
|
||||
r.add(new ScopedAttributeELResolver());
|
||||
this.resolver = r;
|
||||
}
|
||||
return this.resolver;
|
||||
}
|
||||
|
||||
public void addELResolver(ELResolver resolver) throws IllegalStateException {
|
||||
if (resolver == null) {
|
||||
throw new IllegalArgumentException("ELResolver was null");
|
||||
}
|
||||
if (this.instantiated) {
|
||||
throw new IllegalStateException(
|
||||
"cannot call addELResolver after the first request has been made");
|
||||
}
|
||||
this.resolvers.add(resolver);
|
||||
}
|
||||
|
||||
public ExpressionFactory getExpressionFactory() {
|
||||
return expressionFactory;
|
||||
}
|
||||
|
||||
}
|
||||
-462
@@ -1,462 +0,0 @@
|
||||
/*
|
||||
* 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.runtime;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.el.ELContext;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import javax.servlet.jsp.JspContext;
|
||||
import javax.servlet.jsp.JspWriter;
|
||||
import javax.servlet.jsp.PageContext;
|
||||
import javax.servlet.jsp.el.ELException;
|
||||
import javax.servlet.jsp.el.ExpressionEvaluator;
|
||||
import javax.servlet.jsp.el.VariableResolver;
|
||||
import javax.servlet.jsp.tagext.BodyContent;
|
||||
import javax.servlet.jsp.tagext.VariableInfo;
|
||||
|
||||
import org.apache.jasper.compiler.Localizer;
|
||||
import org.apache.jasper.util.Enumerator;
|
||||
|
||||
/**
|
||||
* Implementation of a JSP Context Wrapper.
|
||||
*
|
||||
* The JSP Context Wrapper is a JspContext created and maintained by a tag
|
||||
* handler implementation. It wraps the Invoking JSP Context, that is, the
|
||||
* JspContext instance passed to the tag handler by the invoking page via
|
||||
* setJspContext().
|
||||
*
|
||||
* @author Kin-man Chung
|
||||
* @author Jan Luehe
|
||||
* @author Jacob Hookom
|
||||
*/
|
||||
public class JspContextWrapper extends PageContext implements VariableResolver {
|
||||
|
||||
// Invoking JSP context
|
||||
private PageContext invokingJspCtxt;
|
||||
|
||||
private transient HashMap<String, Object> pageAttributes;
|
||||
|
||||
// ArrayList of NESTED scripting variables
|
||||
private ArrayList nestedVars;
|
||||
|
||||
// ArrayList of AT_BEGIN scripting variables
|
||||
private ArrayList atBeginVars;
|
||||
|
||||
// ArrayList of AT_END scripting variables
|
||||
private ArrayList atEndVars;
|
||||
|
||||
private Map aliases;
|
||||
|
||||
private HashMap<String, Object> originalNestedVars;
|
||||
|
||||
public JspContextWrapper(JspContext jspContext, ArrayList nestedVars,
|
||||
ArrayList atBeginVars, ArrayList atEndVars, Map aliases) {
|
||||
this.invokingJspCtxt = (PageContext) jspContext;
|
||||
this.nestedVars = nestedVars;
|
||||
this.atBeginVars = atBeginVars;
|
||||
this.atEndVars = atEndVars;
|
||||
this.pageAttributes = new HashMap<String, Object>(16);
|
||||
this.aliases = aliases;
|
||||
|
||||
if (nestedVars != null) {
|
||||
this.originalNestedVars = new HashMap<String, Object>(nestedVars.size());
|
||||
}
|
||||
syncBeginTagFile();
|
||||
}
|
||||
|
||||
public void initialize(Servlet servlet, ServletRequest request,
|
||||
ServletResponse response, String errorPageURL,
|
||||
boolean needsSession, int bufferSize, boolean autoFlush)
|
||||
throws IOException, IllegalStateException, IllegalArgumentException {
|
||||
}
|
||||
|
||||
public Object getAttribute(String name) {
|
||||
|
||||
if (name == null) {
|
||||
throw new NullPointerException(Localizer
|
||||
.getMessage("jsp.error.attribute.null_name"));
|
||||
}
|
||||
|
||||
return pageAttributes.get(name);
|
||||
}
|
||||
|
||||
public Object getAttribute(String name, int scope) {
|
||||
|
||||
if (name == null) {
|
||||
throw new NullPointerException(Localizer
|
||||
.getMessage("jsp.error.attribute.null_name"));
|
||||
}
|
||||
|
||||
if (scope == PAGE_SCOPE) {
|
||||
return pageAttributes.get(name);
|
||||
}
|
||||
|
||||
return invokingJspCtxt.getAttribute(name, scope);
|
||||
}
|
||||
|
||||
public void setAttribute(String name, Object value) {
|
||||
|
||||
if (name == null) {
|
||||
throw new NullPointerException(Localizer
|
||||
.getMessage("jsp.error.attribute.null_name"));
|
||||
}
|
||||
|
||||
if (value != null) {
|
||||
pageAttributes.put(name, value);
|
||||
} else {
|
||||
removeAttribute(name, PAGE_SCOPE);
|
||||
}
|
||||
}
|
||||
|
||||
public void setAttribute(String name, Object value, int scope) {
|
||||
|
||||
if (name == null) {
|
||||
throw new NullPointerException(Localizer
|
||||
.getMessage("jsp.error.attribute.null_name"));
|
||||
}
|
||||
|
||||
if (scope == PAGE_SCOPE) {
|
||||
if (value != null) {
|
||||
pageAttributes.put(name, value);
|
||||
} else {
|
||||
removeAttribute(name, PAGE_SCOPE);
|
||||
}
|
||||
} else {
|
||||
invokingJspCtxt.setAttribute(name, value, scope);
|
||||
}
|
||||
}
|
||||
|
||||
public Object findAttribute(String name) {
|
||||
|
||||
if (name == null) {
|
||||
throw new NullPointerException(Localizer
|
||||
.getMessage("jsp.error.attribute.null_name"));
|
||||
}
|
||||
|
||||
Object o = pageAttributes.get(name);
|
||||
if (o == null) {
|
||||
o = invokingJspCtxt.getAttribute(name, REQUEST_SCOPE);
|
||||
if (o == null) {
|
||||
if (getSession() != null) {
|
||||
o = invokingJspCtxt.getAttribute(name, SESSION_SCOPE);
|
||||
}
|
||||
if (o == null) {
|
||||
o = invokingJspCtxt.getAttribute(name, APPLICATION_SCOPE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
public void removeAttribute(String name) {
|
||||
|
||||
if (name == null) {
|
||||
throw new NullPointerException(Localizer
|
||||
.getMessage("jsp.error.attribute.null_name"));
|
||||
}
|
||||
|
||||
pageAttributes.remove(name);
|
||||
invokingJspCtxt.removeAttribute(name, REQUEST_SCOPE);
|
||||
if (getSession() != null) {
|
||||
invokingJspCtxt.removeAttribute(name, SESSION_SCOPE);
|
||||
}
|
||||
invokingJspCtxt.removeAttribute(name, APPLICATION_SCOPE);
|
||||
}
|
||||
|
||||
public void removeAttribute(String name, int scope) {
|
||||
|
||||
if (name == null) {
|
||||
throw new NullPointerException(Localizer
|
||||
.getMessage("jsp.error.attribute.null_name"));
|
||||
}
|
||||
|
||||
if (scope == PAGE_SCOPE) {
|
||||
pageAttributes.remove(name);
|
||||
} else {
|
||||
invokingJspCtxt.removeAttribute(name, scope);
|
||||
}
|
||||
}
|
||||
|
||||
public int getAttributesScope(String name) {
|
||||
|
||||
if (name == null) {
|
||||
throw new NullPointerException(Localizer
|
||||
.getMessage("jsp.error.attribute.null_name"));
|
||||
}
|
||||
|
||||
if (pageAttributes.get(name) != null) {
|
||||
return PAGE_SCOPE;
|
||||
} else {
|
||||
return invokingJspCtxt.getAttributesScope(name);
|
||||
}
|
||||
}
|
||||
|
||||
public Enumeration<String> getAttributeNamesInScope(int scope) {
|
||||
if (scope == PAGE_SCOPE) {
|
||||
return new Enumerator(pageAttributes.keySet().iterator());
|
||||
}
|
||||
|
||||
return invokingJspCtxt.getAttributeNamesInScope(scope);
|
||||
}
|
||||
|
||||
public void release() {
|
||||
invokingJspCtxt.release();
|
||||
}
|
||||
|
||||
public JspWriter getOut() {
|
||||
return invokingJspCtxt.getOut();
|
||||
}
|
||||
|
||||
public HttpSession getSession() {
|
||||
return invokingJspCtxt.getSession();
|
||||
}
|
||||
|
||||
public Object getPage() {
|
||||
return invokingJspCtxt.getPage();
|
||||
}
|
||||
|
||||
public ServletRequest getRequest() {
|
||||
return invokingJspCtxt.getRequest();
|
||||
}
|
||||
|
||||
public ServletResponse getResponse() {
|
||||
return invokingJspCtxt.getResponse();
|
||||
}
|
||||
|
||||
public Exception getException() {
|
||||
return invokingJspCtxt.getException();
|
||||
}
|
||||
|
||||
public ServletConfig getServletConfig() {
|
||||
return invokingJspCtxt.getServletConfig();
|
||||
}
|
||||
|
||||
public ServletContext getServletContext() {
|
||||
return invokingJspCtxt.getServletContext();
|
||||
}
|
||||
|
||||
public void forward(String relativeUrlPath) throws ServletException,
|
||||
IOException {
|
||||
invokingJspCtxt.forward(relativeUrlPath);
|
||||
}
|
||||
|
||||
public void include(String relativeUrlPath) throws ServletException,
|
||||
IOException {
|
||||
invokingJspCtxt.include(relativeUrlPath);
|
||||
}
|
||||
|
||||
public void include(String relativeUrlPath, boolean flush)
|
||||
throws ServletException, IOException {
|
||||
invokingJspCtxt.include(relativeUrlPath, false);
|
||||
}
|
||||
|
||||
public VariableResolver getVariableResolver() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public BodyContent pushBody() {
|
||||
return invokingJspCtxt.pushBody();
|
||||
}
|
||||
|
||||
public JspWriter pushBody(Writer writer) {
|
||||
return invokingJspCtxt.pushBody(writer);
|
||||
}
|
||||
|
||||
public JspWriter popBody() {
|
||||
return invokingJspCtxt.popBody();
|
||||
}
|
||||
|
||||
public ExpressionEvaluator getExpressionEvaluator() {
|
||||
return invokingJspCtxt.getExpressionEvaluator();
|
||||
}
|
||||
|
||||
public void handlePageException(Exception ex) throws IOException,
|
||||
ServletException {
|
||||
// Should never be called since handleException() called with a
|
||||
// Throwable in the generated servlet.
|
||||
handlePageException((Throwable) ex);
|
||||
}
|
||||
|
||||
public void handlePageException(Throwable t) throws IOException,
|
||||
ServletException {
|
||||
invokingJspCtxt.handlePageException(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* VariableResolver interface
|
||||
*/
|
||||
public Object resolveVariable(String pName) throws ELException {
|
||||
ELContext ctx = this.getELContext();
|
||||
return ctx.getELResolver().getValue(ctx, null, pName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronize variables at begin of tag file
|
||||
*/
|
||||
public void syncBeginTagFile() {
|
||||
saveNestedVariables();
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronize variables before fragment invokation
|
||||
*/
|
||||
public void syncBeforeInvoke() {
|
||||
copyTagToPageScope(VariableInfo.NESTED);
|
||||
copyTagToPageScope(VariableInfo.AT_BEGIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronize variables at end of tag file
|
||||
*/
|
||||
public void syncEndTagFile() {
|
||||
copyTagToPageScope(VariableInfo.AT_BEGIN);
|
||||
copyTagToPageScope(VariableInfo.AT_END);
|
||||
restoreNestedVariables();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the variables of the given scope from the virtual page scope of
|
||||
* this JSP context wrapper to the page scope of the invoking JSP context.
|
||||
*
|
||||
* @param scope
|
||||
* variable scope (one of NESTED, AT_BEGIN, or AT_END)
|
||||
*/
|
||||
private void copyTagToPageScope(int scope) {
|
||||
Iterator iter = null;
|
||||
|
||||
switch (scope) {
|
||||
case VariableInfo.NESTED:
|
||||
if (nestedVars != null) {
|
||||
iter = nestedVars.iterator();
|
||||
}
|
||||
break;
|
||||
case VariableInfo.AT_BEGIN:
|
||||
if (atBeginVars != null) {
|
||||
iter = atBeginVars.iterator();
|
||||
}
|
||||
break;
|
||||
case VariableInfo.AT_END:
|
||||
if (atEndVars != null) {
|
||||
iter = atEndVars.iterator();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
while ((iter != null) && iter.hasNext()) {
|
||||
String varName = (String) iter.next();
|
||||
Object obj = getAttribute(varName);
|
||||
varName = findAlias(varName);
|
||||
if (obj != null) {
|
||||
invokingJspCtxt.setAttribute(varName, obj);
|
||||
} else {
|
||||
invokingJspCtxt.removeAttribute(varName, PAGE_SCOPE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the values of any NESTED variables that are present in the invoking
|
||||
* JSP context, so they can later be restored.
|
||||
*/
|
||||
private void saveNestedVariables() {
|
||||
if (nestedVars != null) {
|
||||
Iterator iter = nestedVars.iterator();
|
||||
while (iter.hasNext()) {
|
||||
String varName = (String) iter.next();
|
||||
varName = findAlias(varName);
|
||||
Object obj = invokingJspCtxt.getAttribute(varName);
|
||||
if (obj != null) {
|
||||
originalNestedVars.put(varName, obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the values of any NESTED variables in the invoking JSP context.
|
||||
*/
|
||||
private void restoreNestedVariables() {
|
||||
if (nestedVars != null) {
|
||||
Iterator iter = nestedVars.iterator();
|
||||
while (iter.hasNext()) {
|
||||
String varName = (String) iter.next();
|
||||
varName = findAlias(varName);
|
||||
Object obj = originalNestedVars.get(varName);
|
||||
if (obj != null) {
|
||||
invokingJspCtxt.setAttribute(varName, obj);
|
||||
} else {
|
||||
invokingJspCtxt.removeAttribute(varName, PAGE_SCOPE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the given variable name is used as an alias, and if so,
|
||||
* returns the variable name for which it is used as an alias.
|
||||
*
|
||||
* @param varName
|
||||
* The variable name to check
|
||||
* @return The variable name for which varName is used as an alias, or
|
||||
* varName if it is not being used as an alias
|
||||
*/
|
||||
private String findAlias(String varName) {
|
||||
|
||||
if (aliases == null)
|
||||
return varName;
|
||||
|
||||
String alias = (String) aliases.get(varName);
|
||||
if (alias == null) {
|
||||
return varName;
|
||||
}
|
||||
return alias;
|
||||
}
|
||||
|
||||
//private ELContextImpl elContext;
|
||||
|
||||
public ELContext getELContext() {
|
||||
// instead decorate!!!
|
||||
|
||||
return this.invokingJspCtxt.getELContext();
|
||||
|
||||
/*
|
||||
if (this.elContext != null) {
|
||||
JspFactory jspFact = JspFactory.getDefaultFactory();
|
||||
ServletContext servletContext = this.getServletContext();
|
||||
JspApplicationContextImpl jspCtx = (JspApplicationContextImpl) jspFact
|
||||
.getJspApplicationContext(servletContext);
|
||||
this.elContext = jspCtx.createELContext(this);
|
||||
}
|
||||
return this.elContext;
|
||||
*/
|
||||
}
|
||||
}
|
||||
-202
@@ -1,202 +0,0 @@
|
||||
/*
|
||||
* 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.runtime;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.jsp.JspApplicationContext;
|
||||
import javax.servlet.jsp.JspEngineInfo;
|
||||
import javax.servlet.jsp.JspFactory;
|
||||
import javax.servlet.jsp.PageContext;
|
||||
|
||||
import org.apache.jasper.Constants;
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Implementation of JspFactory.
|
||||
*
|
||||
* @author Anil K. Vijendran
|
||||
*/
|
||||
public class JspFactoryImpl extends JspFactory {
|
||||
|
||||
// Logger
|
||||
private Log log = LogFactory.getLog(JspFactoryImpl.class);
|
||||
|
||||
private static final String SPEC_VERSION = "2.1";
|
||||
private static final boolean USE_POOL =
|
||||
Boolean.valueOf(System.getProperty("org.apache.jasper.runtime.JspFactoryImpl.USE_POOL", "true")).booleanValue();
|
||||
private static final int POOL_SIZE =
|
||||
Integer.valueOf(System.getProperty("org.apache.jasper.runtime.JspFactoryImpl.POOL_SIZE", "8")).intValue();
|
||||
|
||||
private ThreadLocal<PageContextPool> localPool = new ThreadLocal<PageContextPool>();
|
||||
|
||||
public PageContext getPageContext(Servlet servlet, ServletRequest request,
|
||||
ServletResponse response, String errorPageURL, boolean needsSession,
|
||||
int bufferSize, boolean autoflush) {
|
||||
|
||||
if( Constants.IS_SECURITY_ENABLED ) {
|
||||
PrivilegedGetPageContext dp = new PrivilegedGetPageContext(
|
||||
(JspFactoryImpl)this, servlet, request, response, errorPageURL,
|
||||
needsSession, bufferSize, autoflush);
|
||||
return (PageContext)AccessController.doPrivileged(dp);
|
||||
} else {
|
||||
return internalGetPageContext(servlet, request, response,
|
||||
errorPageURL, needsSession,
|
||||
bufferSize, autoflush);
|
||||
}
|
||||
}
|
||||
|
||||
public void releasePageContext(PageContext pc) {
|
||||
if( pc == null )
|
||||
return;
|
||||
if( Constants.IS_SECURITY_ENABLED ) {
|
||||
PrivilegedReleasePageContext dp = new PrivilegedReleasePageContext(
|
||||
(JspFactoryImpl)this,pc);
|
||||
AccessController.doPrivileged(dp);
|
||||
} else {
|
||||
internalReleasePageContext(pc);
|
||||
}
|
||||
}
|
||||
|
||||
public JspEngineInfo getEngineInfo() {
|
||||
return new JspEngineInfo() {
|
||||
public String getSpecificationVersion() {
|
||||
return SPEC_VERSION;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private PageContext internalGetPageContext(Servlet servlet, ServletRequest request,
|
||||
ServletResponse response, String errorPageURL, boolean needsSession,
|
||||
int bufferSize, boolean autoflush) {
|
||||
try {
|
||||
PageContext pc;
|
||||
if (USE_POOL) {
|
||||
PageContextPool pool = localPool.get();
|
||||
if (pool == null) {
|
||||
pool = new PageContextPool();
|
||||
localPool.set(pool);
|
||||
}
|
||||
pc = pool.get();
|
||||
if (pc == null) {
|
||||
pc = new PageContextImpl();
|
||||
}
|
||||
} else {
|
||||
pc = new PageContextImpl();
|
||||
}
|
||||
pc.initialize(servlet, request, response, errorPageURL,
|
||||
needsSession, bufferSize, autoflush);
|
||||
return pc;
|
||||
} catch (Throwable ex) {
|
||||
/* FIXME: need to do something reasonable here!! */
|
||||
log.fatal("Exception initializing page context", ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void internalReleasePageContext(PageContext pc) {
|
||||
pc.release();
|
||||
if (USE_POOL && (pc instanceof PageContextImpl)) {
|
||||
localPool.get().put(pc);
|
||||
}
|
||||
}
|
||||
|
||||
private class PrivilegedGetPageContext implements PrivilegedAction {
|
||||
|
||||
private JspFactoryImpl factory;
|
||||
private Servlet servlet;
|
||||
private ServletRequest request;
|
||||
private ServletResponse response;
|
||||
private String errorPageURL;
|
||||
private boolean needsSession;
|
||||
private int bufferSize;
|
||||
private boolean autoflush;
|
||||
|
||||
PrivilegedGetPageContext(JspFactoryImpl factory, Servlet servlet,
|
||||
ServletRequest request, ServletResponse response, String errorPageURL,
|
||||
boolean needsSession, int bufferSize, boolean autoflush) {
|
||||
this.factory = factory;
|
||||
this.servlet = servlet;
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
this.errorPageURL = errorPageURL;
|
||||
this.needsSession = needsSession;
|
||||
this.bufferSize = bufferSize;
|
||||
this.autoflush = autoflush;
|
||||
}
|
||||
|
||||
public Object run() {
|
||||
return factory.internalGetPageContext(servlet, request, response,
|
||||
errorPageURL, needsSession, bufferSize, autoflush);
|
||||
}
|
||||
}
|
||||
|
||||
private class PrivilegedReleasePageContext implements PrivilegedAction {
|
||||
|
||||
private JspFactoryImpl factory;
|
||||
private PageContext pageContext;
|
||||
|
||||
PrivilegedReleasePageContext(JspFactoryImpl factory,
|
||||
PageContext pageContext) {
|
||||
this.factory = factory;
|
||||
this.pageContext = pageContext;
|
||||
}
|
||||
|
||||
public Object run() {
|
||||
factory.internalReleasePageContext(pageContext);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected final class PageContextPool {
|
||||
|
||||
private PageContext[] pool;
|
||||
|
||||
private int current = -1;
|
||||
|
||||
public PageContextPool() {
|
||||
this.pool = new PageContext[POOL_SIZE];
|
||||
}
|
||||
|
||||
public void put(PageContext o) {
|
||||
if (current < (POOL_SIZE - 1)) {
|
||||
current++;
|
||||
pool[current] = o;
|
||||
}
|
||||
}
|
||||
|
||||
public PageContext get() {
|
||||
PageContext item = null;
|
||||
if (current >= 0) {
|
||||
item = pool[current];
|
||||
current--;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public JspApplicationContext getJspApplicationContext(ServletContext context) {
|
||||
return JspApplicationContextImpl.getInstance(context);
|
||||
}
|
||||
}
|
||||
-65
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* 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.runtime;
|
||||
|
||||
import javax.servlet.jsp.JspContext;
|
||||
import javax.servlet.jsp.PageContext;
|
||||
import javax.servlet.jsp.tagext.JspFragment;
|
||||
import javax.servlet.jsp.tagext.JspTag;
|
||||
|
||||
/**
|
||||
* Helper class from which all Jsp Fragment helper classes extend.
|
||||
* This class allows for the emulation of numerous fragments within
|
||||
* a single class, which in turn reduces the load on the class loader
|
||||
* since there are potentially many JspFragments in a single page.
|
||||
* <p>
|
||||
* The class also provides various utility methods for JspFragment
|
||||
* implementations.
|
||||
*
|
||||
* @author Mark Roth
|
||||
*/
|
||||
public abstract class JspFragmentHelper
|
||||
extends JspFragment
|
||||
{
|
||||
|
||||
protected int discriminator;
|
||||
protected JspContext jspContext;
|
||||
protected PageContext _jspx_page_context;
|
||||
protected JspTag parentTag;
|
||||
|
||||
public JspFragmentHelper( int discriminator, JspContext jspContext,
|
||||
JspTag parentTag )
|
||||
{
|
||||
this.discriminator = discriminator;
|
||||
this.jspContext = jspContext;
|
||||
this._jspx_page_context = null;
|
||||
if( jspContext instanceof PageContext ) {
|
||||
_jspx_page_context = (PageContext)jspContext;
|
||||
}
|
||||
this.parentTag = parentTag;
|
||||
}
|
||||
|
||||
public JspContext getJspContext() {
|
||||
return this.jspContext;
|
||||
}
|
||||
|
||||
public JspTag getParentTag() {
|
||||
return this.parentTag;
|
||||
}
|
||||
|
||||
}
|
||||
-1047
File diff suppressed because it is too large
Load Diff
-39
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* 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.runtime;
|
||||
|
||||
/**
|
||||
* Interface for tracking the source files dependencies, for the purpose
|
||||
* of compiling out of date pages. This is used for
|
||||
* 1) files that are included by page directives
|
||||
* 2) files that are included by include-prelude and include-coda in jsp:config
|
||||
* 3) files that are tag files and referenced
|
||||
* 4) TLDs referenced
|
||||
*/
|
||||
|
||||
public interface JspSourceDependent {
|
||||
|
||||
/**
|
||||
* Returns a list of files names that the current page has a source
|
||||
* dependency on.
|
||||
*/
|
||||
// FIXME: Type used is Object due to very weird behavior
|
||||
// with Eclipse JDT 3.1 in Java 5 mode
|
||||
public Object getDependants();
|
||||
|
||||
}
|
||||
-590
@@ -1,590 +0,0 @@
|
||||
/*
|
||||
* 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.runtime;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.jsp.JspWriter;
|
||||
|
||||
import org.apache.jasper.Constants;
|
||||
import org.apache.jasper.compiler.Localizer;
|
||||
import org.apache.jasper.security.SecurityUtil;
|
||||
|
||||
/**
|
||||
* Write text to a character-output stream, buffering characters so as
|
||||
* to provide for the efficient writing of single characters, arrays,
|
||||
* and strings.
|
||||
*
|
||||
* Provide support for discarding for the output that has been
|
||||
* buffered.
|
||||
*
|
||||
* This needs revisiting when the buffering problems in the JSP spec
|
||||
* are fixed -akv
|
||||
*
|
||||
* @author Anil K. Vijendran
|
||||
*/
|
||||
public class JspWriterImpl extends JspWriter {
|
||||
|
||||
private Writer out;
|
||||
private ServletResponse response;
|
||||
private char cb[];
|
||||
private int nextChar;
|
||||
private boolean flushed = false;
|
||||
private boolean closed = false;
|
||||
|
||||
public JspWriterImpl() {
|
||||
super( Constants.DEFAULT_BUFFER_SIZE, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a buffered character-output stream that uses a default-sized
|
||||
* output buffer.
|
||||
*
|
||||
* @param response A Servlet Response
|
||||
*/
|
||||
public JspWriterImpl(ServletResponse response) {
|
||||
this(response, Constants.DEFAULT_BUFFER_SIZE, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new buffered character-output stream that uses an output
|
||||
* buffer of the given size.
|
||||
*
|
||||
* @param response A Servlet Response
|
||||
* @param sz Output-buffer size, a positive integer
|
||||
*
|
||||
* @exception IllegalArgumentException If sz is <= 0
|
||||
*/
|
||||
public JspWriterImpl(ServletResponse response, int sz,
|
||||
boolean autoFlush) {
|
||||
super(sz, autoFlush);
|
||||
if (sz < 0)
|
||||
throw new IllegalArgumentException("Buffer size <= 0");
|
||||
this.response = response;
|
||||
cb = sz == 0 ? null : new char[sz];
|
||||
nextChar = 0;
|
||||
}
|
||||
|
||||
void init( ServletResponse response, int sz, boolean autoFlush ) {
|
||||
this.response= response;
|
||||
if( sz > 0 && ( cb == null || sz > cb.length ) )
|
||||
cb=new char[sz];
|
||||
nextChar = 0;
|
||||
this.autoFlush=autoFlush;
|
||||
this.bufferSize=sz;
|
||||
}
|
||||
|
||||
/** Package-level access
|
||||
*/
|
||||
void recycle() {
|
||||
flushed = false;
|
||||
closed = false;
|
||||
out = null;
|
||||
nextChar = 0;
|
||||
response = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the output buffer to the underlying character stream, without
|
||||
* flushing the stream itself. This method is non-private only so that it
|
||||
* may be invoked by PrintStream.
|
||||
*/
|
||||
protected final void flushBuffer() throws IOException {
|
||||
if (bufferSize == 0)
|
||||
return;
|
||||
flushed = true;
|
||||
ensureOpen();
|
||||
if (nextChar == 0)
|
||||
return;
|
||||
initOut();
|
||||
out.write(cb, 0, nextChar);
|
||||
nextChar = 0;
|
||||
}
|
||||
|
||||
private void initOut() throws IOException {
|
||||
if (out == null) {
|
||||
out = response.getWriter();
|
||||
}
|
||||
}
|
||||
|
||||
private String getLocalizeMessage(final String message){
|
||||
if (SecurityUtil.isPackageProtectionEnabled()){
|
||||
return (String)AccessController.doPrivileged(new PrivilegedAction(){
|
||||
public Object run(){
|
||||
return Localizer.getMessage(message);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return Localizer.getMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Discard the output buffer.
|
||||
*/
|
||||
public final void clear() throws IOException {
|
||||
if ((bufferSize == 0) && (out != null))
|
||||
// clear() is illegal after any unbuffered output (JSP.5.5)
|
||||
throw new IllegalStateException(
|
||||
getLocalizeMessage("jsp.error.ise_on_clear"));
|
||||
if (flushed)
|
||||
throw new IOException(
|
||||
getLocalizeMessage("jsp.error.attempt_to_clear_flushed_buffer"));
|
||||
ensureOpen();
|
||||
nextChar = 0;
|
||||
}
|
||||
|
||||
public void clearBuffer() throws IOException {
|
||||
if (bufferSize == 0)
|
||||
throw new IllegalStateException(
|
||||
getLocalizeMessage("jsp.error.ise_on_clear"));
|
||||
ensureOpen();
|
||||
nextChar = 0;
|
||||
}
|
||||
|
||||
private final void bufferOverflow() throws IOException {
|
||||
throw new IOException(getLocalizeMessage("jsp.error.overflow"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the stream.
|
||||
*
|
||||
*/
|
||||
public void flush() throws IOException {
|
||||
flushBuffer();
|
||||
if (out != null) {
|
||||
out.flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the stream.
|
||||
*
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
if (response == null || closed)
|
||||
// multiple calls to close is OK
|
||||
return;
|
||||
flush();
|
||||
if (out != null)
|
||||
out.close();
|
||||
out = null;
|
||||
closed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of bytes unused in the buffer
|
||||
*/
|
||||
public int getRemaining() {
|
||||
return bufferSize - nextChar;
|
||||
}
|
||||
|
||||
/** check to make sure that the stream has not been closed */
|
||||
private void ensureOpen() throws IOException {
|
||||
if (response == null || closed)
|
||||
throw new IOException("Stream closed");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write a single character.
|
||||
*/
|
||||
public void write(int c) throws IOException {
|
||||
ensureOpen();
|
||||
if (bufferSize == 0) {
|
||||
initOut();
|
||||
out.write(c);
|
||||
}
|
||||
else {
|
||||
if (nextChar >= bufferSize)
|
||||
if (autoFlush)
|
||||
flushBuffer();
|
||||
else
|
||||
bufferOverflow();
|
||||
cb[nextChar++] = (char) c;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Our own little min method, to avoid loading java.lang.Math if we've run
|
||||
* out of file descriptors and we're trying to print a stack trace.
|
||||
*/
|
||||
private int min(int a, int b) {
|
||||
if (a < b) return a;
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a portion of an array of characters.
|
||||
*
|
||||
* <p> Ordinarily this method stores characters from the given array into
|
||||
* this stream's buffer, flushing the buffer to the underlying stream as
|
||||
* needed. If the requested length is at least as large as the buffer,
|
||||
* however, then this method will flush the buffer and write the characters
|
||||
* directly to the underlying stream. Thus redundant
|
||||
* <code>DiscardableBufferedWriter</code>s will not copy data unnecessarily.
|
||||
*
|
||||
* @param cbuf A character array
|
||||
* @param off Offset from which to start reading characters
|
||||
* @param len Number of characters to write
|
||||
*/
|
||||
public void write(char cbuf[], int off, int len)
|
||||
throws IOException
|
||||
{
|
||||
ensureOpen();
|
||||
|
||||
if (bufferSize == 0) {
|
||||
initOut();
|
||||
out.write(cbuf, off, len);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((off < 0) || (off > cbuf.length) || (len < 0) ||
|
||||
((off + len) > cbuf.length) || ((off + len) < 0)) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
} else if (len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (len >= bufferSize) {
|
||||
/* If the request length exceeds the size of the output buffer,
|
||||
flush the buffer and then write the data directly. In this
|
||||
way buffered streams will cascade harmlessly. */
|
||||
if (autoFlush)
|
||||
flushBuffer();
|
||||
else
|
||||
bufferOverflow();
|
||||
initOut();
|
||||
out.write(cbuf, off, len);
|
||||
return;
|
||||
}
|
||||
|
||||
int b = off, t = off + len;
|
||||
while (b < t) {
|
||||
int d = min(bufferSize - nextChar, t - b);
|
||||
System.arraycopy(cbuf, b, cb, nextChar, d);
|
||||
b += d;
|
||||
nextChar += d;
|
||||
if (nextChar >= bufferSize)
|
||||
if (autoFlush)
|
||||
flushBuffer();
|
||||
else
|
||||
bufferOverflow();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an array of characters. This method cannot be inherited from the
|
||||
* Writer class because it must suppress I/O exceptions.
|
||||
*/
|
||||
public void write(char buf[]) throws IOException {
|
||||
write(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a portion of a String.
|
||||
*
|
||||
* @param s String to be written
|
||||
* @param off Offset from which to start reading characters
|
||||
* @param len Number of characters to be written
|
||||
*/
|
||||
public void write(String s, int off, int len) throws IOException {
|
||||
ensureOpen();
|
||||
if (bufferSize == 0) {
|
||||
initOut();
|
||||
out.write(s, off, len);
|
||||
return;
|
||||
}
|
||||
int b = off, t = off + len;
|
||||
while (b < t) {
|
||||
int d = min(bufferSize - nextChar, t - b);
|
||||
s.getChars(b, b + d, cb, nextChar);
|
||||
b += d;
|
||||
nextChar += d;
|
||||
if (nextChar >= bufferSize)
|
||||
if (autoFlush)
|
||||
flushBuffer();
|
||||
else
|
||||
bufferOverflow();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a string. This method cannot be inherited from the Writer class
|
||||
* because it must suppress I/O exceptions.
|
||||
*/
|
||||
public void write(String s) throws IOException {
|
||||
// Simple fix for Bugzilla 35410
|
||||
// Calling the other write function so as to init the buffer anyways
|
||||
if(s == null) {
|
||||
write(s, 0, 0);
|
||||
} else {
|
||||
write(s, 0, s.length());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static String lineSeparator = System.getProperty("line.separator");
|
||||
|
||||
/**
|
||||
* Write a line separator. The line separator string is defined by the
|
||||
* system property <tt>line.separator</tt>, and is not necessarily a single
|
||||
* newline ('\n') character.
|
||||
*
|
||||
* @exception IOException If an I/O error occurs
|
||||
*/
|
||||
|
||||
public void newLine() throws IOException {
|
||||
write(lineSeparator);
|
||||
}
|
||||
|
||||
|
||||
/* Methods that do not terminate lines */
|
||||
|
||||
/**
|
||||
* Print a boolean value. The string produced by <code>{@link
|
||||
* java.lang.String#valueOf(boolean)}</code> is translated into bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the <code>{@link
|
||||
* #write(int)}</code> method.
|
||||
*
|
||||
* @param b The <code>boolean</code> to be printed
|
||||
*/
|
||||
public void print(boolean b) throws IOException {
|
||||
write(b ? "true" : "false");
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a character. The character is translated into one or more bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the <code>{@link
|
||||
* #write(int)}</code> method.
|
||||
*
|
||||
* @param c The <code>char</code> to be printed
|
||||
*/
|
||||
public void print(char c) throws IOException {
|
||||
write(String.valueOf(c));
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an integer. The string produced by <code>{@link
|
||||
* java.lang.String#valueOf(int)}</code> is translated into bytes according
|
||||
* to the platform's default character encoding, and these bytes are
|
||||
* written in exactly the manner of the <code>{@link #write(int)}</code>
|
||||
* method.
|
||||
*
|
||||
* @param i The <code>int</code> to be printed
|
||||
*/
|
||||
public void print(int i) throws IOException {
|
||||
write(String.valueOf(i));
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a long integer. The string produced by <code>{@link
|
||||
* java.lang.String#valueOf(long)}</code> is translated into bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the <code>{@link #write(int)}</code>
|
||||
* method.
|
||||
*
|
||||
* @param l The <code>long</code> to be printed
|
||||
*/
|
||||
public void print(long l) throws IOException {
|
||||
write(String.valueOf(l));
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a floating-point number. The string produced by <code>{@link
|
||||
* java.lang.String#valueOf(float)}</code> is translated into bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the <code>{@link #write(int)}</code>
|
||||
* method.
|
||||
*
|
||||
* @param f The <code>float</code> to be printed
|
||||
*/
|
||||
public void print(float f) throws IOException {
|
||||
write(String.valueOf(f));
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a double-precision floating-point number. The string produced by
|
||||
* <code>{@link java.lang.String#valueOf(double)}</code> is translated into
|
||||
* bytes according to the platform's default character encoding, and these
|
||||
* bytes are written in exactly the manner of the <code>{@link
|
||||
* #write(int)}</code> method.
|
||||
*
|
||||
* @param d The <code>double</code> to be printed
|
||||
*/
|
||||
public void print(double d) throws IOException {
|
||||
write(String.valueOf(d));
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an array of characters. The characters are converted into bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the <code>{@link #write(int)}</code>
|
||||
* method.
|
||||
*
|
||||
* @param s The array of chars to be printed
|
||||
*
|
||||
* @throws NullPointerException If <code>s</code> is <code>null</code>
|
||||
*/
|
||||
public void print(char s[]) throws IOException {
|
||||
write(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a string. If the argument is <code>null</code> then the string
|
||||
* <code>"null"</code> is printed. Otherwise, the string's characters are
|
||||
* converted into bytes according to the platform's default character
|
||||
* encoding, and these bytes are written in exactly the manner of the
|
||||
* <code>{@link #write(int)}</code> method.
|
||||
*
|
||||
* @param s The <code>String</code> to be printed
|
||||
*/
|
||||
public void print(String s) throws IOException {
|
||||
if (s == null) {
|
||||
s = "null";
|
||||
}
|
||||
write(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an object. The string produced by the <code>{@link
|
||||
* java.lang.String#valueOf(Object)}</code> method is translated into bytes
|
||||
* according to the platform's default character encoding, and these bytes
|
||||
* are written in exactly the manner of the <code>{@link #write(int)}</code>
|
||||
* method.
|
||||
*
|
||||
* @param obj The <code>Object</code> to be printed
|
||||
*/
|
||||
public void print(Object obj) throws IOException {
|
||||
write(String.valueOf(obj));
|
||||
}
|
||||
|
||||
/* Methods that do terminate lines */
|
||||
|
||||
/**
|
||||
* Terminate the current line by writing the line separator string. The
|
||||
* line separator string is defined by the system property
|
||||
* <code>line.separator</code>, and is not necessarily a single newline
|
||||
* character (<code>'\n'</code>).
|
||||
*
|
||||
* Need to change this from PrintWriter because the default
|
||||
* println() writes to the sink directly instead of through the
|
||||
* write method...
|
||||
*/
|
||||
public void println() throws IOException {
|
||||
newLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a boolean value and then terminate the line. This method behaves
|
||||
* as though it invokes <code>{@link #print(boolean)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*/
|
||||
public void println(boolean x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a character and then terminate the line. This method behaves as
|
||||
* though it invokes <code>{@link #print(char)}</code> and then <code>{@link
|
||||
* #println()}</code>.
|
||||
*/
|
||||
public void println(char x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an integer and then terminate the line. This method behaves as
|
||||
* though it invokes <code>{@link #print(int)}</code> and then <code>{@link
|
||||
* #println()}</code>.
|
||||
*/
|
||||
public void println(int x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a long integer and then terminate the line. This method behaves
|
||||
* as though it invokes <code>{@link #print(long)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*/
|
||||
public void println(long x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a floating-point number and then terminate the line. This method
|
||||
* behaves as though it invokes <code>{@link #print(float)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*/
|
||||
public void println(float x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a double-precision floating-point number and then terminate the
|
||||
* line. This method behaves as though it invokes <code>{@link
|
||||
* #print(double)}</code> and then <code>{@link #println()}</code>.
|
||||
*/
|
||||
public void println(double x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an array of characters and then terminate the line. This method
|
||||
* behaves as though it invokes <code>{@link #print(char[])}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*/
|
||||
public void println(char x[]) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a String and then terminate the line. This method behaves as
|
||||
* though it invokes <code>{@link #print(String)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*/
|
||||
public void println(String x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print an Object and then terminate the line. This method behaves as
|
||||
* though it invokes <code>{@link #print(Object)}</code> and then
|
||||
* <code>{@link #println()}</code>.
|
||||
*/
|
||||
public void println(Object x) throws IOException {
|
||||
print(x);
|
||||
println();
|
||||
}
|
||||
|
||||
}
|
||||
-951
@@ -1,951 +0,0 @@
|
||||
/*
|
||||
* 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.runtime;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.el.ELContext;
|
||||
import javax.el.ExpressionFactory;
|
||||
import javax.el.ValueExpression;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import javax.servlet.jsp.JspException;
|
||||
import javax.servlet.jsp.JspFactory;
|
||||
import javax.servlet.jsp.JspWriter;
|
||||
import javax.servlet.jsp.PageContext;
|
||||
import javax.servlet.jsp.el.ELException;
|
||||
import javax.servlet.jsp.el.ExpressionEvaluator;
|
||||
import javax.servlet.jsp.el.VariableResolver;
|
||||
import javax.servlet.jsp.tagext.BodyContent;
|
||||
|
||||
import org.apache.jasper.Constants;
|
||||
import org.apache.jasper.compiler.Localizer;
|
||||
import org.apache.jasper.el.ELContextImpl;
|
||||
import org.apache.jasper.el.ExpressionEvaluatorImpl;
|
||||
import org.apache.jasper.el.FunctionMapperImpl;
|
||||
import org.apache.jasper.el.VariableResolverImpl;
|
||||
import org.apache.jasper.security.SecurityUtil;
|
||||
import org.apache.jasper.util.Enumerator;
|
||||
|
||||
/**
|
||||
* Implementation of the PageContext class from the JSP spec. Also doubles as a
|
||||
* VariableResolver for the EL.
|
||||
*
|
||||
* @author Anil K. Vijendran
|
||||
* @author Larry Cable
|
||||
* @author Hans Bergsten
|
||||
* @author Pierre Delisle
|
||||
* @author Mark Roth
|
||||
* @author Jan Luehe
|
||||
* @author Jacob Hookom
|
||||
*/
|
||||
public class PageContextImpl extends PageContext {
|
||||
|
||||
private static final JspFactory jspf = JspFactory.getDefaultFactory();
|
||||
|
||||
private BodyContentImpl[] outs;
|
||||
|
||||
private int depth;
|
||||
|
||||
// per-servlet state
|
||||
private Servlet servlet;
|
||||
|
||||
private ServletConfig config;
|
||||
|
||||
private ServletContext context;
|
||||
|
||||
private JspApplicationContextImpl applicationContext;
|
||||
|
||||
private String errorPageURL;
|
||||
|
||||
// page-scope attributes
|
||||
private transient HashMap<String, Object> attributes;
|
||||
|
||||
// per-request state
|
||||
private transient ServletRequest request;
|
||||
|
||||
private transient ServletResponse response;
|
||||
|
||||
private transient HttpSession session;
|
||||
|
||||
private transient ELContextImpl elContext;
|
||||
|
||||
private boolean isIncluded;
|
||||
|
||||
|
||||
// initial output stream
|
||||
private transient JspWriter out;
|
||||
|
||||
private transient JspWriterImpl baseOut;
|
||||
|
||||
/*
|
||||
* Constructor.
|
||||
*/
|
||||
PageContextImpl() {
|
||||
this.outs = new BodyContentImpl[0];
|
||||
this.attributes = new HashMap<String, Object>(16);
|
||||
this.depth = -1;
|
||||
}
|
||||
|
||||
public void initialize(Servlet servlet, ServletRequest request,
|
||||
ServletResponse response, String errorPageURL,
|
||||
boolean needsSession, int bufferSize, boolean autoFlush)
|
||||
throws IOException {
|
||||
|
||||
_initialize(servlet, request, response, errorPageURL, needsSession,
|
||||
bufferSize, autoFlush);
|
||||
}
|
||||
|
||||
private void _initialize(Servlet servlet, ServletRequest request,
|
||||
ServletResponse response, String errorPageURL,
|
||||
boolean needsSession, int bufferSize, boolean autoFlush)
|
||||
throws IOException {
|
||||
|
||||
// initialize state
|
||||
this.servlet = servlet;
|
||||
this.config = servlet.getServletConfig();
|
||||
this.context = config.getServletContext();
|
||||
this.errorPageURL = errorPageURL;
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
|
||||
// initialize application context
|
||||
this.applicationContext = JspApplicationContextImpl.getInstance(context);
|
||||
|
||||
// Setup session (if required)
|
||||
if (request instanceof HttpServletRequest && needsSession)
|
||||
this.session = ((HttpServletRequest) request).getSession();
|
||||
if (needsSession && session == null)
|
||||
throw new IllegalStateException(
|
||||
"Page needs a session and none is available");
|
||||
|
||||
// initialize the initial out ...
|
||||
depth = -1;
|
||||
if (this.baseOut == null) {
|
||||
this.baseOut = new JspWriterImpl(response, bufferSize, autoFlush);
|
||||
} else {
|
||||
this.baseOut.init(response, bufferSize, autoFlush);
|
||||
}
|
||||
this.out = baseOut;
|
||||
|
||||
// register names/values as per spec
|
||||
setAttribute(OUT, this.out);
|
||||
setAttribute(REQUEST, request);
|
||||
setAttribute(RESPONSE, response);
|
||||
|
||||
if (session != null)
|
||||
setAttribute(SESSION, session);
|
||||
|
||||
setAttribute(PAGE, servlet);
|
||||
setAttribute(CONFIG, config);
|
||||
setAttribute(PAGECONTEXT, this);
|
||||
setAttribute(APPLICATION, context);
|
||||
|
||||
isIncluded = request.getAttribute("javax.servlet.include.servlet_path") != null;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
out = baseOut;
|
||||
try {
|
||||
if (isIncluded) {
|
||||
((JspWriterImpl) out).flushBuffer();
|
||||
// push it into the including jspWriter
|
||||
} else {
|
||||
// Old code:
|
||||
// out.flush();
|
||||
// Do not flush the buffer even if we're not included (i.e.
|
||||
// we are the main page. The servlet will flush it and close
|
||||
// the stream.
|
||||
((JspWriterImpl) out).flushBuffer();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
IllegalStateException ise = new IllegalStateException(Localizer.getMessage("jsp.error.flush"), ex);
|
||||
throw ise;
|
||||
} finally {
|
||||
servlet = null;
|
||||
config = null;
|
||||
context = null;
|
||||
applicationContext = null;
|
||||
elContext = null;
|
||||
errorPageURL = null;
|
||||
request = null;
|
||||
response = null;
|
||||
depth = -1;
|
||||
baseOut.recycle();
|
||||
session = null;
|
||||
attributes.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public Object getAttribute(final String name) {
|
||||
|
||||
if (name == null) {
|
||||
throw new NullPointerException(Localizer
|
||||
.getMessage("jsp.error.attribute.null_name"));
|
||||
}
|
||||
|
||||
if (SecurityUtil.isPackageProtectionEnabled()) {
|
||||
return AccessController.doPrivileged(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
return doGetAttribute(name);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return doGetAttribute(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Object doGetAttribute(String name) {
|
||||
return attributes.get(name);
|
||||
}
|
||||
|
||||
public Object getAttribute(final String name, final int scope) {
|
||||
|
||||
if (name == null) {
|
||||
throw new NullPointerException(Localizer
|
||||
.getMessage("jsp.error.attribute.null_name"));
|
||||
}
|
||||
|
||||
if (SecurityUtil.isPackageProtectionEnabled()) {
|
||||
return AccessController.doPrivileged(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
return doGetAttribute(name, scope);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return doGetAttribute(name, scope);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Object doGetAttribute(String name, int scope) {
|
||||
switch (scope) {
|
||||
case PAGE_SCOPE:
|
||||
return attributes.get(name);
|
||||
|
||||
case REQUEST_SCOPE:
|
||||
return request.getAttribute(name);
|
||||
|
||||
case SESSION_SCOPE:
|
||||
if (session == null) {
|
||||
throw new IllegalStateException(Localizer
|
||||
.getMessage("jsp.error.page.noSession"));
|
||||
}
|
||||
return session.getAttribute(name);
|
||||
|
||||
case APPLICATION_SCOPE:
|
||||
return context.getAttribute(name);
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid scope");
|
||||
}
|
||||
}
|
||||
|
||||
public void setAttribute(final String name, final Object attribute) {
|
||||
|
||||
if (name == null) {
|
||||
throw new NullPointerException(Localizer
|
||||
.getMessage("jsp.error.attribute.null_name"));
|
||||
}
|
||||
|
||||
if (SecurityUtil.isPackageProtectionEnabled()) {
|
||||
AccessController.doPrivileged(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
doSetAttribute(name, attribute);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
doSetAttribute(name, attribute);
|
||||
}
|
||||
}
|
||||
|
||||
private void doSetAttribute(String name, Object attribute) {
|
||||
if (attribute != null) {
|
||||
attributes.put(name, attribute);
|
||||
} else {
|
||||
removeAttribute(name, PAGE_SCOPE);
|
||||
}
|
||||
}
|
||||
|
||||
public void setAttribute(final String name, final Object o, final int scope) {
|
||||
|
||||
if (name == null) {
|
||||
throw new NullPointerException(Localizer
|
||||
.getMessage("jsp.error.attribute.null_name"));
|
||||
}
|
||||
|
||||
if (SecurityUtil.isPackageProtectionEnabled()) {
|
||||
AccessController.doPrivileged(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
doSetAttribute(name, o, scope);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
doSetAttribute(name, o, scope);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void doSetAttribute(String name, Object o, int scope) {
|
||||
if (o != null) {
|
||||
switch (scope) {
|
||||
case PAGE_SCOPE:
|
||||
attributes.put(name, o);
|
||||
break;
|
||||
|
||||
case REQUEST_SCOPE:
|
||||
request.setAttribute(name, o);
|
||||
break;
|
||||
|
||||
case SESSION_SCOPE:
|
||||
if (session == null) {
|
||||
throw new IllegalStateException(Localizer
|
||||
.getMessage("jsp.error.page.noSession"));
|
||||
}
|
||||
session.setAttribute(name, o);
|
||||
break;
|
||||
|
||||
case APPLICATION_SCOPE:
|
||||
context.setAttribute(name, o);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid scope");
|
||||
}
|
||||
} else {
|
||||
removeAttribute(name, scope);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAttribute(final String name, final int scope) {
|
||||
|
||||
if (name == null) {
|
||||
throw new NullPointerException(Localizer
|
||||
.getMessage("jsp.error.attribute.null_name"));
|
||||
}
|
||||
if (SecurityUtil.isPackageProtectionEnabled()) {
|
||||
AccessController.doPrivileged(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
doRemoveAttribute(name, scope);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
doRemoveAttribute(name, scope);
|
||||
}
|
||||
}
|
||||
|
||||
private void doRemoveAttribute(String name, int scope) {
|
||||
switch (scope) {
|
||||
case PAGE_SCOPE:
|
||||
attributes.remove(name);
|
||||
break;
|
||||
|
||||
case REQUEST_SCOPE:
|
||||
request.removeAttribute(name);
|
||||
break;
|
||||
|
||||
case SESSION_SCOPE:
|
||||
if (session == null) {
|
||||
throw new IllegalStateException(Localizer
|
||||
.getMessage("jsp.error.page.noSession"));
|
||||
}
|
||||
session.removeAttribute(name);
|
||||
break;
|
||||
|
||||
case APPLICATION_SCOPE:
|
||||
context.removeAttribute(name);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid scope");
|
||||
}
|
||||
}
|
||||
|
||||
public int getAttributesScope(final String name) {
|
||||
|
||||
if (name == null) {
|
||||
throw new NullPointerException(Localizer
|
||||
.getMessage("jsp.error.attribute.null_name"));
|
||||
}
|
||||
|
||||
if (SecurityUtil.isPackageProtectionEnabled()) {
|
||||
return ((Integer) AccessController
|
||||
.doPrivileged(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
return new Integer(doGetAttributeScope(name));
|
||||
}
|
||||
})).intValue();
|
||||
} else {
|
||||
return doGetAttributeScope(name);
|
||||
}
|
||||
}
|
||||
|
||||
private int doGetAttributeScope(String name) {
|
||||
if (attributes.get(name) != null)
|
||||
return PAGE_SCOPE;
|
||||
|
||||
if (request.getAttribute(name) != null)
|
||||
return REQUEST_SCOPE;
|
||||
|
||||
if (session != null) {
|
||||
try {
|
||||
if (session.getAttribute(name) != null)
|
||||
return SESSION_SCOPE;
|
||||
} catch(IllegalStateException ise) {
|
||||
// Session has been invalidated.
|
||||
// Ignore and fall through to application scope.
|
||||
}
|
||||
}
|
||||
|
||||
if (context.getAttribute(name) != null)
|
||||
return APPLICATION_SCOPE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public Object findAttribute(final String name) {
|
||||
if (SecurityUtil.isPackageProtectionEnabled()) {
|
||||
return AccessController.doPrivileged(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
if (name == null) {
|
||||
throw new NullPointerException(Localizer
|
||||
.getMessage("jsp.error.attribute.null_name"));
|
||||
}
|
||||
|
||||
return doFindAttribute(name);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (name == null) {
|
||||
throw new NullPointerException(Localizer
|
||||
.getMessage("jsp.error.attribute.null_name"));
|
||||
}
|
||||
|
||||
return doFindAttribute(name);
|
||||
}
|
||||
}
|
||||
|
||||
private Object doFindAttribute(String name) {
|
||||
|
||||
Object o = attributes.get(name);
|
||||
if (o != null)
|
||||
return o;
|
||||
|
||||
o = request.getAttribute(name);
|
||||
if (o != null)
|
||||
return o;
|
||||
|
||||
if (session != null) {
|
||||
try {
|
||||
o = session.getAttribute(name);
|
||||
} catch(IllegalStateException ise) {
|
||||
// Session has been invalidated.
|
||||
// Ignore and fall through to application scope.
|
||||
}
|
||||
if (o != null)
|
||||
return o;
|
||||
}
|
||||
|
||||
return context.getAttribute(name);
|
||||
}
|
||||
|
||||
public Enumeration<String> getAttributeNamesInScope(final int scope) {
|
||||
if (SecurityUtil.isPackageProtectionEnabled()) {
|
||||
return (Enumeration) AccessController
|
||||
.doPrivileged(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
return doGetAttributeNamesInScope(scope);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return doGetAttributeNamesInScope(scope);
|
||||
}
|
||||
}
|
||||
|
||||
private Enumeration doGetAttributeNamesInScope(int scope) {
|
||||
switch (scope) {
|
||||
case PAGE_SCOPE:
|
||||
return new Enumerator(attributes.keySet().iterator());
|
||||
|
||||
case REQUEST_SCOPE:
|
||||
return request.getAttributeNames();
|
||||
|
||||
case SESSION_SCOPE:
|
||||
if (session == null) {
|
||||
throw new IllegalStateException(Localizer
|
||||
.getMessage("jsp.error.page.noSession"));
|
||||
}
|
||||
return session.getAttributeNames();
|
||||
|
||||
case APPLICATION_SCOPE:
|
||||
return context.getAttributeNames();
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid scope");
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAttribute(final String name) {
|
||||
|
||||
if (name == null) {
|
||||
throw new NullPointerException(Localizer
|
||||
.getMessage("jsp.error.attribute.null_name"));
|
||||
}
|
||||
|
||||
if (SecurityUtil.isPackageProtectionEnabled()) {
|
||||
AccessController.doPrivileged(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
doRemoveAttribute(name);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
doRemoveAttribute(name);
|
||||
}
|
||||
}
|
||||
|
||||
private void doRemoveAttribute(String name) {
|
||||
removeAttribute(name, PAGE_SCOPE);
|
||||
removeAttribute(name, REQUEST_SCOPE);
|
||||
if( session != null ) {
|
||||
try {
|
||||
removeAttribute(name, SESSION_SCOPE);
|
||||
} catch(IllegalStateException ise) {
|
||||
// Session has been invalidated.
|
||||
// Ignore and fall throw to application scope.
|
||||
}
|
||||
}
|
||||
removeAttribute(name, APPLICATION_SCOPE);
|
||||
}
|
||||
|
||||
public JspWriter getOut() {
|
||||
return out;
|
||||
}
|
||||
|
||||
public HttpSession getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
public Servlet getServlet() {
|
||||
return servlet;
|
||||
}
|
||||
|
||||
public ServletConfig getServletConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public ServletContext getServletContext() {
|
||||
return config.getServletContext();
|
||||
}
|
||||
|
||||
public ServletRequest getRequest() {
|
||||
return request;
|
||||
}
|
||||
|
||||
public ServletResponse getResponse() {
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exception associated with this page context, if any. <p/>
|
||||
* Added wrapping for Throwables to avoid ClassCastException: see Bugzilla
|
||||
* 31171 for details.
|
||||
*
|
||||
* @return The Exception associated with this page context, if any.
|
||||
*/
|
||||
public Exception getException() {
|
||||
Throwable t = JspRuntimeLibrary.getThrowable(request);
|
||||
|
||||
// Only wrap if needed
|
||||
if ((t != null) && (!(t instanceof Exception))) {
|
||||
t = new JspException(t);
|
||||
}
|
||||
|
||||
return (Exception) t;
|
||||
}
|
||||
|
||||
public Object getPage() {
|
||||
return servlet;
|
||||
}
|
||||
|
||||
private final String getAbsolutePathRelativeToContext(String relativeUrlPath) {
|
||||
String path = relativeUrlPath;
|
||||
|
||||
if (!path.startsWith("/")) {
|
||||
String uri = (String) request
|
||||
.getAttribute("javax.servlet.include.servlet_path");
|
||||
if (uri == null)
|
||||
uri = ((HttpServletRequest) request).getServletPath();
|
||||
String baseURI = uri.substring(0, uri.lastIndexOf('/'));
|
||||
path = baseURI + '/' + path;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
public void include(String relativeUrlPath) throws ServletException,
|
||||
IOException {
|
||||
JspRuntimeLibrary
|
||||
.include(request, response, relativeUrlPath, out, true);
|
||||
}
|
||||
|
||||
public void include(final String relativeUrlPath, final boolean flush)
|
||||
throws ServletException, IOException {
|
||||
if (SecurityUtil.isPackageProtectionEnabled()) {
|
||||
try {
|
||||
AccessController.doPrivileged(new PrivilegedExceptionAction() {
|
||||
public Object run() throws Exception {
|
||||
doInclude(relativeUrlPath, flush);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} catch (PrivilegedActionException e) {
|
||||
Exception ex = e.getException();
|
||||
if (ex instanceof IOException) {
|
||||
throw (IOException) ex;
|
||||
} else {
|
||||
throw (ServletException) ex;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
doInclude(relativeUrlPath, flush);
|
||||
}
|
||||
}
|
||||
|
||||
private void doInclude(String relativeUrlPath, boolean flush)
|
||||
throws ServletException, IOException {
|
||||
JspRuntimeLibrary.include(request, response, relativeUrlPath, out,
|
||||
flush);
|
||||
}
|
||||
|
||||
public VariableResolver getVariableResolver() {
|
||||
return new VariableResolverImpl(this.getELContext());
|
||||
}
|
||||
|
||||
public void forward(final String relativeUrlPath) throws ServletException,
|
||||
IOException {
|
||||
if (SecurityUtil.isPackageProtectionEnabled()) {
|
||||
try {
|
||||
AccessController.doPrivileged(new PrivilegedExceptionAction() {
|
||||
public Object run() throws Exception {
|
||||
doForward(relativeUrlPath);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} catch (PrivilegedActionException e) {
|
||||
Exception ex = e.getException();
|
||||
if (ex instanceof IOException) {
|
||||
throw (IOException) ex;
|
||||
} else {
|
||||
throw (ServletException) ex;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
doForward(relativeUrlPath);
|
||||
}
|
||||
}
|
||||
|
||||
private void doForward(String relativeUrlPath) throws ServletException,
|
||||
IOException {
|
||||
|
||||
// JSP.4.5 If the buffer was flushed, throw IllegalStateException
|
||||
try {
|
||||
out.clear();
|
||||
} catch (IOException ex) {
|
||||
IllegalStateException ise = new IllegalStateException(Localizer
|
||||
.getMessage("jsp.error.attempt_to_clear_flushed_buffer"));
|
||||
ise.initCause(ex);
|
||||
throw ise;
|
||||
}
|
||||
|
||||
// Make sure that the response object is not the wrapper for include
|
||||
while (response instanceof ServletResponseWrapperInclude) {
|
||||
response = ((ServletResponseWrapperInclude) response).getResponse();
|
||||
}
|
||||
|
||||
final String path = getAbsolutePathRelativeToContext(relativeUrlPath);
|
||||
String includeUri = (String) request
|
||||
.getAttribute(Constants.INC_SERVLET_PATH);
|
||||
|
||||
if (includeUri != null)
|
||||
request.removeAttribute(Constants.INC_SERVLET_PATH);
|
||||
try {
|
||||
context.getRequestDispatcher(path).forward(request, response);
|
||||
} finally {
|
||||
if (includeUri != null)
|
||||
request.setAttribute(Constants.INC_SERVLET_PATH, includeUri);
|
||||
}
|
||||
}
|
||||
|
||||
public BodyContent pushBody() {
|
||||
return (BodyContent) pushBody(null);
|
||||
}
|
||||
|
||||
public JspWriter pushBody(Writer writer) {
|
||||
depth++;
|
||||
if (depth >= outs.length) {
|
||||
BodyContentImpl[] newOuts = new BodyContentImpl[depth + 1];
|
||||
for (int i = 0; i < outs.length; i++) {
|
||||
newOuts[i] = outs[i];
|
||||
}
|
||||
newOuts[depth] = new BodyContentImpl(out);
|
||||
outs = newOuts;
|
||||
}
|
||||
|
||||
outs[depth].setWriter(writer);
|
||||
out = outs[depth];
|
||||
|
||||
// Update the value of the "out" attribute in the page scope
|
||||
// attribute namespace of this PageContext
|
||||
setAttribute(OUT, out);
|
||||
|
||||
return outs[depth];
|
||||
}
|
||||
|
||||
public JspWriter popBody() {
|
||||
depth--;
|
||||
if (depth >= 0) {
|
||||
out = outs[depth];
|
||||
} else {
|
||||
out = baseOut;
|
||||
}
|
||||
|
||||
// Update the value of the "out" attribute in the page scope
|
||||
// attribute namespace of this PageContext
|
||||
setAttribute(OUT, out);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides programmatic access to the ExpressionEvaluator. The JSP
|
||||
* Container must return a valid instance of an ExpressionEvaluator that can
|
||||
* parse EL expressions.
|
||||
*/
|
||||
public ExpressionEvaluator getExpressionEvaluator() {
|
||||
return new ExpressionEvaluatorImpl(this.applicationContext.getExpressionFactory());
|
||||
}
|
||||
|
||||
public void handlePageException(Exception ex) throws IOException,
|
||||
ServletException {
|
||||
// Should never be called since handleException() called with a
|
||||
// Throwable in the generated servlet.
|
||||
handlePageException((Throwable) ex);
|
||||
}
|
||||
|
||||
public void handlePageException(final Throwable t) throws IOException,
|
||||
ServletException {
|
||||
if (t == null)
|
||||
throw new NullPointerException("null Throwable");
|
||||
|
||||
if (SecurityUtil.isPackageProtectionEnabled()) {
|
||||
try {
|
||||
AccessController.doPrivileged(new PrivilegedExceptionAction() {
|
||||
public Object run() throws Exception {
|
||||
doHandlePageException(t);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} catch (PrivilegedActionException e) {
|
||||
Exception ex = e.getException();
|
||||
if (ex instanceof IOException) {
|
||||
throw (IOException) ex;
|
||||
} else {
|
||||
throw (ServletException) ex;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
doHandlePageException(t);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void doHandlePageException(Throwable t) throws IOException,
|
||||
ServletException {
|
||||
|
||||
if (errorPageURL != null && !errorPageURL.equals("")) {
|
||||
|
||||
/*
|
||||
* Set request attributes. Do not set the
|
||||
* javax.servlet.error.exception attribute here (instead, set in the
|
||||
* generated servlet code for the error page) in order to prevent
|
||||
* the ErrorReportValve, which is invoked as part of forwarding the
|
||||
* request to the error page, from throwing it if the response has
|
||||
* not been committed (the response will have been committed if the
|
||||
* error page is a JSP page).
|
||||
*/
|
||||
request.setAttribute("javax.servlet.jsp.jspException", t);
|
||||
request.setAttribute("javax.servlet.error.status_code",
|
||||
new Integer(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
|
||||
request.setAttribute("javax.servlet.error.request_uri",
|
||||
((HttpServletRequest) request).getRequestURI());
|
||||
request.setAttribute("javax.servlet.error.servlet_name", config
|
||||
.getServletName());
|
||||
try {
|
||||
forward(errorPageURL);
|
||||
} catch (IllegalStateException ise) {
|
||||
include(errorPageURL);
|
||||
}
|
||||
|
||||
// The error page could be inside an include.
|
||||
|
||||
Object newException = request
|
||||
.getAttribute("javax.servlet.error.exception");
|
||||
|
||||
// t==null means the attribute was not set.
|
||||
if ((newException != null) && (newException == t)) {
|
||||
request.removeAttribute("javax.servlet.error.exception");
|
||||
}
|
||||
|
||||
// now clear the error code - to prevent double handling.
|
||||
request.removeAttribute("javax.servlet.error.status_code");
|
||||
request.removeAttribute("javax.servlet.error.request_uri");
|
||||
request.removeAttribute("javax.servlet.error.status_code");
|
||||
request.removeAttribute("javax.servlet.jsp.jspException");
|
||||
|
||||
} else {
|
||||
// Otherwise throw the exception wrapped inside a ServletException.
|
||||
// Set the exception as the root cause in the ServletException
|
||||
// to get a stack trace for the real problem
|
||||
if (t instanceof IOException)
|
||||
throw (IOException) t;
|
||||
if (t instanceof ServletException)
|
||||
throw (ServletException) t;
|
||||
if (t instanceof RuntimeException)
|
||||
throw (RuntimeException) t;
|
||||
|
||||
Throwable rootCause = null;
|
||||
if (t instanceof JspException) {
|
||||
rootCause = ((JspException) t).getRootCause();
|
||||
} else if (t instanceof ELException) {
|
||||
rootCause = ((ELException) t).getRootCause();
|
||||
}
|
||||
|
||||
if (rootCause != null) {
|
||||
throw new ServletException(t.getClass().getName() + ": "
|
||||
+ t.getMessage(), rootCause);
|
||||
}
|
||||
|
||||
throw new ServletException(t);
|
||||
}
|
||||
}
|
||||
|
||||
private static String XmlEscape(String s) {
|
||||
if (s == null)
|
||||
return null;
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char c = s.charAt(i);
|
||||
if (c == '<') {
|
||||
sb.append("<");
|
||||
} else if (c == '>') {
|
||||
sb.append(">");
|
||||
} else if (c == '\'') {
|
||||
sb.append("'"); // '
|
||||
} else if (c == '&') {
|
||||
sb.append("&");
|
||||
} else if (c == '"') {
|
||||
sb.append("""); // "
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Proprietary method to evaluate EL expressions. XXX - This method should
|
||||
* go away once the EL interpreter moves out of JSTL and into its own
|
||||
* project. For now, this is necessary because the standard machinery is too
|
||||
* slow.
|
||||
*
|
||||
* @param expression
|
||||
* The expression to be evaluated
|
||||
* @param expectedType
|
||||
* The expected resulting type
|
||||
* @param pageContext
|
||||
* The page context
|
||||
* @param functionMap
|
||||
* Maps prefix and name to Method
|
||||
* @return The result of the evaluation
|
||||
*/
|
||||
public static Object proprietaryEvaluate(final String expression,
|
||||
final Class expectedType, final PageContext pageContext,
|
||||
final ProtectedFunctionMapper functionMap, final boolean escape)
|
||||
throws ELException {
|
||||
Object retValue;
|
||||
final ExpressionFactory exprFactory = jspf.getJspApplicationContext(pageContext.getServletContext()).getExpressionFactory();
|
||||
if (SecurityUtil.isPackageProtectionEnabled()) {
|
||||
try {
|
||||
retValue = AccessController
|
||||
.doPrivileged(new PrivilegedExceptionAction() {
|
||||
|
||||
public Object run() throws Exception {
|
||||
ELContextImpl ctx = (ELContextImpl) pageContext.getELContext();
|
||||
ctx.setFunctionMapper(new FunctionMapperImpl(functionMap));
|
||||
ValueExpression ve = exprFactory.createValueExpression(ctx, expression, expectedType);
|
||||
return ve.getValue(ctx);
|
||||
}
|
||||
});
|
||||
} catch (PrivilegedActionException ex) {
|
||||
Exception realEx = ex.getException();
|
||||
if (realEx instanceof ELException) {
|
||||
throw (ELException) realEx;
|
||||
} else {
|
||||
throw new ELException(realEx);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ELContextImpl ctx = (ELContextImpl) pageContext.getELContext();
|
||||
ctx.setFunctionMapper(new FunctionMapperImpl(functionMap));
|
||||
ValueExpression ve = exprFactory.createValueExpression(ctx, expression, expectedType);
|
||||
retValue = ve.getValue(ctx);
|
||||
}
|
||||
if (escape && retValue != null) {
|
||||
retValue = XmlEscape(retValue.toString());
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
public ELContext getELContext() {
|
||||
if (this.elContext == null) {
|
||||
this.elContext = this.applicationContext.createELContext(this);
|
||||
}
|
||||
return this.elContext;
|
||||
}
|
||||
|
||||
}
|
||||
-134
@@ -1,134 +0,0 @@
|
||||
/*
|
||||
* 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.runtime;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.jsp.JspException;
|
||||
import javax.servlet.jsp.tagext.Tag;
|
||||
|
||||
import org.apache.jasper.Constants;
|
||||
|
||||
/**
|
||||
* Thread-local based pool of tag handlers that can be reused.
|
||||
*
|
||||
* @author Jan Luehe
|
||||
* @author Costin Manolache
|
||||
*/
|
||||
public class PerThreadTagHandlerPool extends TagHandlerPool {
|
||||
|
||||
private int maxSize;
|
||||
|
||||
// For cleanup
|
||||
private Vector perThreadDataVector;
|
||||
|
||||
private ThreadLocal perThread;
|
||||
|
||||
private static class PerThreadData {
|
||||
Tag handlers[];
|
||||
int current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a tag handler pool with the default capacity.
|
||||
*/
|
||||
public PerThreadTagHandlerPool() {
|
||||
super();
|
||||
perThreadDataVector = new Vector();
|
||||
}
|
||||
|
||||
protected void init(ServletConfig config) {
|
||||
maxSize = Constants.MAX_POOL_SIZE;
|
||||
String maxSizeS = getOption(config, OPTION_MAXSIZE, null);
|
||||
if (maxSizeS != null) {
|
||||
maxSize = Integer.parseInt(maxSizeS);
|
||||
if (maxSize < 0) {
|
||||
maxSize = Constants.MAX_POOL_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
perThread = new ThreadLocal() {
|
||||
protected Object initialValue() {
|
||||
PerThreadData ptd = new PerThreadData();
|
||||
ptd.handlers = new Tag[maxSize];
|
||||
ptd.current = -1;
|
||||
perThreadDataVector.addElement(ptd);
|
||||
return ptd;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next available tag handler from this tag handler pool,
|
||||
* instantiating one if this tag handler pool is empty.
|
||||
*
|
||||
* @param handlerClass Tag handler class
|
||||
*
|
||||
* @return Reused or newly instantiated tag handler
|
||||
*
|
||||
* @throws JspException if a tag handler cannot be instantiated
|
||||
*/
|
||||
public Tag get(Class handlerClass) throws JspException {
|
||||
PerThreadData ptd = (PerThreadData)perThread.get();
|
||||
if(ptd.current >=0 ) {
|
||||
return ptd.handlers[ptd.current--];
|
||||
} else {
|
||||
try {
|
||||
return (Tag) handlerClass.newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new JspException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given tag handler to this tag handler pool, unless this tag
|
||||
* handler pool has already reached its capacity, in which case the tag
|
||||
* handler's release() method is called.
|
||||
*
|
||||
* @param handler Tag handler to add to this tag handler pool
|
||||
*/
|
||||
public void reuse(Tag handler) {
|
||||
PerThreadData ptd=(PerThreadData)perThread.get();
|
||||
if (ptd.current < (ptd.handlers.length - 1)) {
|
||||
ptd.handlers[++ptd.current] = handler;
|
||||
} else {
|
||||
handler.release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the release() method of all tag handlers in this tag handler pool.
|
||||
*/
|
||||
public void release() {
|
||||
Enumeration enumeration = perThreadDataVector.elements();
|
||||
while (enumeration.hasMoreElements()) {
|
||||
PerThreadData ptd = (PerThreadData)enumeration.nextElement();
|
||||
if (ptd.handlers != null) {
|
||||
for (int i=ptd.current; i>=0; i--) {
|
||||
if (ptd.handlers[i] != null) {
|
||||
ptd.handlers[i].release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-196
@@ -1,196 +0,0 @@
|
||||
/*
|
||||
* 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.runtime;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.lang.reflect.Method;
|
||||
import javax.servlet.jsp.el.FunctionMapper;
|
||||
|
||||
import org.apache.jasper.security.SecurityUtil;
|
||||
|
||||
/**
|
||||
* Maps EL functions to their Java method counterparts. Keeps the actual Method
|
||||
* objects protected so that JSP pages can't indirectly do reflection.
|
||||
*
|
||||
* @author Mark Roth
|
||||
* @author Kin-man Chung
|
||||
*/
|
||||
public final class ProtectedFunctionMapper extends javax.el.FunctionMapper
|
||||
implements FunctionMapper {
|
||||
|
||||
/**
|
||||
* Maps "prefix:name" to java.lang.Method objects.
|
||||
*/
|
||||
private HashMap fnmap = null;
|
||||
|
||||
/**
|
||||
* If there is only one function in the map, this is the Method for it.
|
||||
*/
|
||||
private Method theMethod = null;
|
||||
|
||||
/**
|
||||
* Constructor has protected access.
|
||||
*/
|
||||
private ProtectedFunctionMapper() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generated Servlet and Tag Handler implementations call this method to
|
||||
* retrieve an instance of the ProtectedFunctionMapper. This is necessary
|
||||
* since generated code does not have access to create instances of classes
|
||||
* in this package.
|
||||
*
|
||||
* @return A new protected function mapper.
|
||||
*/
|
||||
public static ProtectedFunctionMapper getInstance() {
|
||||
ProtectedFunctionMapper funcMapper;
|
||||
if (SecurityUtil.isPackageProtectionEnabled()) {
|
||||
funcMapper = (ProtectedFunctionMapper) AccessController
|
||||
.doPrivileged(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
return new ProtectedFunctionMapper();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
funcMapper = new ProtectedFunctionMapper();
|
||||
}
|
||||
funcMapper.fnmap = new java.util.HashMap();
|
||||
return funcMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a mapping from the given EL function prefix and name to the given
|
||||
* Java method.
|
||||
*
|
||||
* @param fnQName
|
||||
* The EL function qualified name (including prefix)
|
||||
* @param c
|
||||
* The class containing the Java method
|
||||
* @param methodName
|
||||
* The name of the Java method
|
||||
* @param args
|
||||
* The arguments of the Java method
|
||||
* @throws RuntimeException
|
||||
* if no method with the given signature could be found.
|
||||
*/
|
||||
public void mapFunction(String fnQName, final Class c,
|
||||
final String methodName, final Class[] args) {
|
||||
java.lang.reflect.Method method;
|
||||
if (SecurityUtil.isPackageProtectionEnabled()) {
|
||||
try {
|
||||
method = (java.lang.reflect.Method) AccessController
|
||||
.doPrivileged(new PrivilegedExceptionAction() {
|
||||
|
||||
public Object run() throws Exception {
|
||||
return c.getDeclaredMethod(methodName, args);
|
||||
}
|
||||
});
|
||||
} catch (PrivilegedActionException ex) {
|
||||
throw new RuntimeException(
|
||||
"Invalid function mapping - no such method: "
|
||||
+ ex.getException().getMessage());
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
method = c.getDeclaredMethod(methodName, args);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(
|
||||
"Invalid function mapping - no such method: "
|
||||
+ e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
this.fnmap.put(fnQName, method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance for this class, and stores the Method for the given
|
||||
* EL function prefix and name. This method is used for the case when there
|
||||
* is only one function in the EL expression.
|
||||
*
|
||||
* @param fnQName
|
||||
* The EL function qualified name (including prefix)
|
||||
* @param c
|
||||
* The class containing the Java method
|
||||
* @param methodName
|
||||
* The name of the Java method
|
||||
* @param args
|
||||
* The arguments of the Java method
|
||||
* @throws RuntimeException
|
||||
* if no method with the given signature could be found.
|
||||
*/
|
||||
public static ProtectedFunctionMapper getMapForFunction(String fnQName,
|
||||
final Class c, final String methodName, final Class[] args) {
|
||||
java.lang.reflect.Method method;
|
||||
ProtectedFunctionMapper funcMapper;
|
||||
if (SecurityUtil.isPackageProtectionEnabled()) {
|
||||
funcMapper = (ProtectedFunctionMapper) AccessController
|
||||
.doPrivileged(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
return new ProtectedFunctionMapper();
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
method = (java.lang.reflect.Method) AccessController
|
||||
.doPrivileged(new PrivilegedExceptionAction() {
|
||||
|
||||
public Object run() throws Exception {
|
||||
return c.getDeclaredMethod(methodName, args);
|
||||
}
|
||||
});
|
||||
} catch (PrivilegedActionException ex) {
|
||||
throw new RuntimeException(
|
||||
"Invalid function mapping - no such method: "
|
||||
+ ex.getException().getMessage());
|
||||
}
|
||||
} else {
|
||||
funcMapper = new ProtectedFunctionMapper();
|
||||
try {
|
||||
method = c.getDeclaredMethod(methodName, args);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(
|
||||
"Invalid function mapping - no such method: "
|
||||
+ e.getMessage());
|
||||
}
|
||||
}
|
||||
funcMapper.theMethod = method;
|
||||
return funcMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the specified local name and prefix into a Java.lang.Method.
|
||||
* Returns null if the prefix and local name are not found.
|
||||
*
|
||||
* @param prefix
|
||||
* the prefix of the function
|
||||
* @param localName
|
||||
* the short name of the function
|
||||
* @return the result of the method mapping. Null means no entry found.
|
||||
*/
|
||||
public Method resolveFunction(String prefix, String localName) {
|
||||
if (this.fnmap != null) {
|
||||
return (Method) this.fnmap.get(prefix + ":" + localName);
|
||||
}
|
||||
return theMethod;
|
||||
}
|
||||
}
|
||||
-76
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* 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.runtime;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletResponseWrapper;
|
||||
import javax.servlet.jsp.JspWriter;
|
||||
|
||||
/**
|
||||
* ServletResponseWrapper used by the JSP 'include' action.
|
||||
*
|
||||
* This wrapper response object is passed to RequestDispatcher.include(), so
|
||||
* that the output of the included resource is appended to that of the
|
||||
* including page.
|
||||
*
|
||||
* @author Pierre Delisle
|
||||
*/
|
||||
|
||||
public class ServletResponseWrapperInclude extends HttpServletResponseWrapper {
|
||||
|
||||
/**
|
||||
* PrintWriter which appends to the JspWriter of the including page.
|
||||
*/
|
||||
private PrintWriter printWriter;
|
||||
|
||||
private JspWriter jspWriter;
|
||||
|
||||
public ServletResponseWrapperInclude(ServletResponse response,
|
||||
JspWriter jspWriter) {
|
||||
super((HttpServletResponse)response);
|
||||
this.printWriter = new PrintWriter(jspWriter);
|
||||
this.jspWriter = jspWriter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a wrapper around the JspWriter of the including page.
|
||||
*/
|
||||
public PrintWriter getWriter() throws IOException {
|
||||
return printWriter;
|
||||
}
|
||||
|
||||
public ServletOutputStream getOutputStream() throws IOException {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the output buffer of the JspWriter associated with the including
|
||||
* page.
|
||||
*/
|
||||
public void resetBuffer() {
|
||||
try {
|
||||
jspWriter.clearBuffer();
|
||||
} catch (IOException ioe) {
|
||||
}
|
||||
}
|
||||
}
|
||||
-191
@@ -1,191 +0,0 @@
|
||||
/*
|
||||
* 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.runtime;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.jsp.JspException;
|
||||
import javax.servlet.jsp.tagext.Tag;
|
||||
|
||||
import org.apache.AnnotationProcessor;
|
||||
import org.apache.jasper.Constants;
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Pool of tag handlers that can be reused.
|
||||
*
|
||||
* @author Jan Luehe
|
||||
*/
|
||||
public class TagHandlerPool {
|
||||
|
||||
private Tag[] handlers;
|
||||
|
||||
public static String OPTION_TAGPOOL="tagpoolClassName";
|
||||
public static String OPTION_MAXSIZE="tagpoolMaxSize";
|
||||
|
||||
private Log log = LogFactory.getLog(TagHandlerPool.class);
|
||||
|
||||
// index of next available tag handler
|
||||
private int current;
|
||||
protected AnnotationProcessor annotationProcessor = null;
|
||||
|
||||
public static TagHandlerPool getTagHandlerPool( ServletConfig config) {
|
||||
TagHandlerPool result=null;
|
||||
|
||||
String tpClassName=getOption( config, OPTION_TAGPOOL, null);
|
||||
if( tpClassName != null ) {
|
||||
try {
|
||||
Class c=Class.forName( tpClassName );
|
||||
result=(TagHandlerPool)c.newInstance();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
result=null;
|
||||
}
|
||||
}
|
||||
if( result==null ) result=new TagHandlerPool();
|
||||
result.init(config);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void init( ServletConfig config ) {
|
||||
int maxSize=-1;
|
||||
String maxSizeS=getOption(config, OPTION_MAXSIZE, null);
|
||||
if( maxSizeS != null ) {
|
||||
try {
|
||||
maxSize=Integer.parseInt(maxSizeS);
|
||||
} catch( Exception ex) {
|
||||
maxSize=-1;
|
||||
}
|
||||
}
|
||||
if( maxSize <0 ) {
|
||||
maxSize=Constants.MAX_POOL_SIZE;
|
||||
}
|
||||
this.handlers = new Tag[maxSize];
|
||||
this.current = -1;
|
||||
this.annotationProcessor =
|
||||
(AnnotationProcessor) config.getServletContext().getAttribute(AnnotationProcessor.class.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a tag handler pool with the default capacity.
|
||||
*/
|
||||
public TagHandlerPool() {
|
||||
// Nothing - jasper generated servlets call the other constructor,
|
||||
// this should be used in future + init .
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a tag handler pool with the given capacity.
|
||||
*
|
||||
* @param capacity Tag handler pool capacity
|
||||
* @deprecated Use static getTagHandlerPool
|
||||
*/
|
||||
public TagHandlerPool(int capacity) {
|
||||
this.handlers = new Tag[capacity];
|
||||
this.current = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next available tag handler from this tag handler pool,
|
||||
* instantiating one if this tag handler pool is empty.
|
||||
*
|
||||
* @param handlerClass Tag handler class
|
||||
*
|
||||
* @return Reused or newly instantiated tag handler
|
||||
*
|
||||
* @throws JspException if a tag handler cannot be instantiated
|
||||
*/
|
||||
public Tag get(Class handlerClass) throws JspException {
|
||||
Tag handler = null;
|
||||
synchronized( this ) {
|
||||
if (current >= 0) {
|
||||
handler = handlers[current--];
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
|
||||
// Out of sync block - there is no need for other threads to
|
||||
// wait for us to construct a tag for this thread.
|
||||
try {
|
||||
Tag instance = (Tag) handlerClass.newInstance();
|
||||
AnnotationHelper.postConstruct(annotationProcessor, instance);
|
||||
return instance;
|
||||
} catch (Exception e) {
|
||||
throw new JspException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given tag handler to this tag handler pool, unless this tag
|
||||
* handler pool has already reached its capacity, in which case the tag
|
||||
* handler's release() method is called.
|
||||
*
|
||||
* @param handler Tag handler to add to this tag handler pool
|
||||
*/
|
||||
public void reuse(Tag handler) {
|
||||
synchronized( this ) {
|
||||
if (current < (handlers.length - 1)) {
|
||||
handlers[++current] = handler;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// There is no need for other threads to wait for us to release
|
||||
handler.release();
|
||||
if (annotationProcessor != null) {
|
||||
try {
|
||||
AnnotationHelper.preDestroy(annotationProcessor, handler);
|
||||
} catch (Exception e) {
|
||||
log.warn("Error processing preDestroy on tag instance of "
|
||||
+ handler.getClass().getName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the release() method of all available tag handlers in this tag
|
||||
* handler pool.
|
||||
*/
|
||||
public synchronized void release() {
|
||||
for (int i = current; i >= 0; i--) {
|
||||
handlers[i].release();
|
||||
if (annotationProcessor != null) {
|
||||
try {
|
||||
AnnotationHelper.preDestroy(annotationProcessor, handlers[i]);
|
||||
} catch (Exception e) {
|
||||
log.warn("Error processing preDestroy on tag instance of "
|
||||
+ handlers[i].getClass().getName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static String getOption( ServletConfig config, String name, String defaultV) {
|
||||
if( config == null ) return defaultV;
|
||||
|
||||
String value=config.getInitParameter(name);
|
||||
if( value != null ) return value;
|
||||
if( config.getServletContext() ==null )
|
||||
return defaultV;
|
||||
value=config.getServletContext().getInitParameter(name);
|
||||
if( value!=null ) return value;
|
||||
return defaultV;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-111
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* 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.security;
|
||||
|
||||
/**
|
||||
* Static class used to preload java classes when using the
|
||||
* Java SecurityManager so that the defineClassInPackage
|
||||
* RuntimePermission does not trigger an AccessControlException.
|
||||
*
|
||||
* @author Jean-Francois Arcand
|
||||
*/
|
||||
|
||||
public final class SecurityClassLoad {
|
||||
|
||||
private static org.apache.juli.logging.Log log=
|
||||
org.apache.juli.logging.LogFactory.getLog( SecurityClassLoad.class );
|
||||
|
||||
public static void securityClassLoad(ClassLoader loader){
|
||||
|
||||
if( System.getSecurityManager() == null ){
|
||||
return;
|
||||
}
|
||||
|
||||
String basePackage = "org.apache.jasper.";
|
||||
try {
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.JspFactoryImpl$PrivilegedGetPageContext");
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.JspFactoryImpl$PrivilegedReleasePageContext");
|
||||
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.JspRuntimeLibrary");
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.JspRuntimeLibrary$PrivilegedIntrospectHelper");
|
||||
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.ServletResponseWrapperInclude");
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.TagHandlerPool");
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.JspFragmentHelper");
|
||||
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.ProtectedFunctionMapper");
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.ProtectedFunctionMapper$1");
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.ProtectedFunctionMapper$2");
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.ProtectedFunctionMapper$3");
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.ProtectedFunctionMapper$4");
|
||||
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.PageContextImpl");
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.PageContextImpl$1");
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.PageContextImpl$2");
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.PageContextImpl$3");
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.PageContextImpl$4");
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.PageContextImpl$5");
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.PageContextImpl$6");
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.PageContextImpl$7");
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.PageContextImpl$8");
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.PageContextImpl$9");
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.PageContextImpl$10");
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.PageContextImpl$11");
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.PageContextImpl$12");
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.PageContextImpl$13");
|
||||
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.JspContextWrapper");
|
||||
|
||||
loader.loadClass( basePackage +
|
||||
"servlet.JspServletWrapper");
|
||||
|
||||
loader.loadClass( basePackage +
|
||||
"runtime.JspWriterImpl$1");
|
||||
} catch (ClassNotFoundException ex) {
|
||||
log.error("SecurityClassLoad", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
-81
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* 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.security;
|
||||
|
||||
import org.apache.jasper.Constants;
|
||||
|
||||
/**
|
||||
* Util class for Security related operations.
|
||||
*
|
||||
* @author Jean-Francois Arcand
|
||||
*/
|
||||
|
||||
public final class SecurityUtil{
|
||||
|
||||
private static boolean packageDefinitionEnabled =
|
||||
System.getProperty("package.definition") == null ? false : true;
|
||||
|
||||
/**
|
||||
* Return the <code>SecurityManager</code> only if Security is enabled AND
|
||||
* package protection mechanism is enabled.
|
||||
*/
|
||||
public static boolean isPackageProtectionEnabled(){
|
||||
if (packageDefinitionEnabled && Constants.IS_SECURITY_ENABLED){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Filter the specified message string for characters that are sensitive
|
||||
* in HTML. This avoids potential attacks caused by including JavaScript
|
||||
* codes in the request URL that is often reported in error messages.
|
||||
*
|
||||
* @param message The message string to be filtered
|
||||
*/
|
||||
public static String filter(String message) {
|
||||
|
||||
if (message == null)
|
||||
return (null);
|
||||
|
||||
char content[] = new char[message.length()];
|
||||
message.getChars(0, message.length(), content, 0);
|
||||
StringBuffer result = new StringBuffer(content.length + 50);
|
||||
for (int i = 0; i < content.length; i++) {
|
||||
switch (content[i]) {
|
||||
case '<':
|
||||
result.append("<");
|
||||
break;
|
||||
case '>':
|
||||
result.append(">");
|
||||
break;
|
||||
case '&':
|
||||
result.append("&");
|
||||
break;
|
||||
case '"':
|
||||
result.append(""");
|
||||
break;
|
||||
default:
|
||||
result.append(content[i]);
|
||||
}
|
||||
}
|
||||
return (result.toString());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-172
@@ -1,172 +0,0 @@
|
||||
/*
|
||||
* 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.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.security.CodeSource;
|
||||
import java.security.PermissionCollection;
|
||||
|
||||
import org.apache.jasper.Constants;
|
||||
|
||||
/**
|
||||
* Class loader for loading servlet class files (corresponding to JSP files)
|
||||
* and tag handler class files (corresponding to tag files).
|
||||
*
|
||||
* @author Anil K. Vijendran
|
||||
* @author Harish Prabandham
|
||||
* @author Jean-Francois Arcand
|
||||
*/
|
||||
public class JasperLoader extends URLClassLoader {
|
||||
|
||||
private PermissionCollection permissionCollection;
|
||||
private CodeSource codeSource;
|
||||
private String className;
|
||||
private ClassLoader parent;
|
||||
private SecurityManager securityManager;
|
||||
|
||||
public JasperLoader(URL[] urls, ClassLoader parent,
|
||||
PermissionCollection permissionCollection,
|
||||
CodeSource codeSource) {
|
||||
super(urls, parent);
|
||||
this.permissionCollection = permissionCollection;
|
||||
this.codeSource = codeSource;
|
||||
this.parent = parent;
|
||||
this.securityManager = System.getSecurityManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the class with the specified name. This method searches for
|
||||
* classes in the same manner as <code>loadClass(String, boolean)</code>
|
||||
* with <code>false</code> as the second argument.
|
||||
*
|
||||
* @param name Name of the class to be loaded
|
||||
*
|
||||
* @exception ClassNotFoundException if the class was not found
|
||||
*/
|
||||
public Class loadClass(String name) throws ClassNotFoundException {
|
||||
|
||||
return (loadClass(name, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the class with the specified name, searching using the following
|
||||
* algorithm until it finds and returns the class. If the class cannot
|
||||
* be found, returns <code>ClassNotFoundException</code>.
|
||||
* <ul>
|
||||
* <li>Call <code>findLoadedClass(String)</code> to check if the
|
||||
* class has already been loaded. If it has, the same
|
||||
* <code>Class</code> object is returned.</li>
|
||||
* <li>If the <code>delegate</code> property is set to <code>true</code>,
|
||||
* call the <code>loadClass()</code> method of the parent class
|
||||
* loader, if any.</li>
|
||||
* <li>Call <code>findClass()</code> to find this class in our locally
|
||||
* defined repositories.</li>
|
||||
* <li>Call the <code>loadClass()</code> method of our parent
|
||||
* class loader, if any.</li>
|
||||
* </ul>
|
||||
* If the class was found using the above steps, and the
|
||||
* <code>resolve</code> flag is <code>true</code>, this method will then
|
||||
* call <code>resolveClass(Class)</code> on the resulting Class object.
|
||||
*
|
||||
* @param name Name of the class to be loaded
|
||||
* @param resolve If <code>true</code> then resolve the class
|
||||
*
|
||||
* @exception ClassNotFoundException if the class was not found
|
||||
*/
|
||||
public Class loadClass(final String name, boolean resolve)
|
||||
throws ClassNotFoundException {
|
||||
|
||||
Class clazz = null;
|
||||
|
||||
// (0) Check our previously loaded class cache
|
||||
clazz = findLoadedClass(name);
|
||||
if (clazz != null) {
|
||||
if (resolve)
|
||||
resolveClass(clazz);
|
||||
return (clazz);
|
||||
}
|
||||
|
||||
// (.5) Permission to access this class when using a SecurityManager
|
||||
if (securityManager != null) {
|
||||
int dot = name.lastIndexOf('.');
|
||||
if (dot >= 0) {
|
||||
try {
|
||||
// Do not call the security manager since by default, we grant that package.
|
||||
if (!"org.apache.jasper.runtime".equalsIgnoreCase(name.substring(0,dot))){
|
||||
securityManager.checkPackageAccess(name.substring(0,dot));
|
||||
}
|
||||
} catch (SecurityException se) {
|
||||
String error = "Security Violation, attempt to use " +
|
||||
"Restricted Class: " + name;
|
||||
se.printStackTrace();
|
||||
throw new ClassNotFoundException(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !name.startsWith(Constants.JSP_PACKAGE_NAME + '.') ) {
|
||||
// Class is not in org.apache.jsp, therefore, have our
|
||||
// parent load it
|
||||
clazz = parent.loadClass(name);
|
||||
if( resolve )
|
||||
resolveClass(clazz);
|
||||
return clazz;
|
||||
}
|
||||
|
||||
return findClass(name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delegate to parent
|
||||
*
|
||||
* @see java.lang.ClassLoader#getResourceAsStream(java.lang.String)
|
||||
*/
|
||||
public InputStream getResourceAsStream(String name) {
|
||||
InputStream is = parent.getResourceAsStream(name);
|
||||
if (is == null) {
|
||||
URL url = findResource(name);
|
||||
if (url != null) {
|
||||
try {
|
||||
is = url.openStream();
|
||||
} catch (IOException e) {
|
||||
is = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the Permissions for a CodeSource.
|
||||
*
|
||||
* Since this ClassLoader is only used for a JSP page in
|
||||
* a web application context, we just return our preset
|
||||
* PermissionCollection for the web app context.
|
||||
*
|
||||
* @param codeSource Code source where the code was loaded from
|
||||
* @return PermissionCollection for CodeSource
|
||||
*/
|
||||
public final PermissionCollection getPermissions(CodeSource codeSource) {
|
||||
return permissionCollection;
|
||||
}
|
||||
}
|
||||
-441
@@ -1,441 +0,0 @@
|
||||
/*
|
||||
* 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.servlet;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Set;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
|
||||
/**
|
||||
* Simple <code>ServletContext</code> implementation without
|
||||
* HTTP-specific methods.
|
||||
*
|
||||
* @author Peter Rossbach (pr@webapp.de)
|
||||
*/
|
||||
|
||||
public class JspCServletContext implements ServletContext {
|
||||
|
||||
|
||||
// ----------------------------------------------------- Instance Variables
|
||||
|
||||
|
||||
/**
|
||||
* Servlet context attributes.
|
||||
*/
|
||||
protected Hashtable myAttributes;
|
||||
|
||||
|
||||
/**
|
||||
* The log writer we will write log messages to.
|
||||
*/
|
||||
protected PrintWriter myLogWriter;
|
||||
|
||||
|
||||
/**
|
||||
* The base URL (document root) for this context.
|
||||
*/
|
||||
protected URL myResourceBaseURL;
|
||||
|
||||
|
||||
// ----------------------------------------------------------- Constructors
|
||||
|
||||
|
||||
/**
|
||||
* Create a new instance of this ServletContext implementation.
|
||||
*
|
||||
* @param aLogWriter PrintWriter which is used for <code>log()</code> calls
|
||||
* @param aResourceBaseURL Resource base URL
|
||||
*/
|
||||
public JspCServletContext(PrintWriter aLogWriter, URL aResourceBaseURL) {
|
||||
|
||||
myAttributes = new Hashtable();
|
||||
myLogWriter = aLogWriter;
|
||||
myResourceBaseURL = aResourceBaseURL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------- Public Methods
|
||||
|
||||
|
||||
/**
|
||||
* Return the specified context attribute, if any.
|
||||
*
|
||||
* @param name Name of the requested attribute
|
||||
*/
|
||||
public Object getAttribute(String name) {
|
||||
|
||||
return (myAttributes.get(name));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return an enumeration of context attribute names.
|
||||
*/
|
||||
public Enumeration getAttributeNames() {
|
||||
|
||||
return (myAttributes.keys());
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the servlet context for the specified path.
|
||||
*
|
||||
* @param uripath Server-relative path starting with '/'
|
||||
*/
|
||||
public ServletContext getContext(String uripath) {
|
||||
|
||||
return (null);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the context path.
|
||||
*/
|
||||
public String getContextPath() {
|
||||
|
||||
return (null);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the specified context initialization parameter.
|
||||
*
|
||||
* @param name Name of the requested parameter
|
||||
*/
|
||||
public String getInitParameter(String name) {
|
||||
|
||||
return (null);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return an enumeration of the names of context initialization
|
||||
* parameters.
|
||||
*/
|
||||
public Enumeration getInitParameterNames() {
|
||||
|
||||
return (new Vector().elements());
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the Servlet API major version number.
|
||||
*/
|
||||
public int getMajorVersion() {
|
||||
|
||||
return (2);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the MIME type for the specified filename.
|
||||
*
|
||||
* @param file Filename whose MIME type is requested
|
||||
*/
|
||||
public String getMimeType(String file) {
|
||||
|
||||
return (null);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the Servlet API minor version number.
|
||||
*/
|
||||
public int getMinorVersion() {
|
||||
|
||||
return (3);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a request dispatcher for the specified servlet name.
|
||||
*
|
||||
* @param name Name of the requested servlet
|
||||
*/
|
||||
public RequestDispatcher getNamedDispatcher(String name) {
|
||||
|
||||
return (null);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the real path for the specified context-relative
|
||||
* virtual path.
|
||||
*
|
||||
* @param path The context-relative virtual path to resolve
|
||||
*/
|
||||
public String getRealPath(String path) {
|
||||
|
||||
if (!myResourceBaseURL.getProtocol().equals("file"))
|
||||
return (null);
|
||||
if (!path.startsWith("/"))
|
||||
return (null);
|
||||
try {
|
||||
return
|
||||
(getResource(path).getFile().replace('/', File.separatorChar));
|
||||
} catch (Throwable t) {
|
||||
return (null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a request dispatcher for the specified context-relative path.
|
||||
*
|
||||
* @param path Context-relative path for which to acquire a dispatcher
|
||||
*/
|
||||
public RequestDispatcher getRequestDispatcher(String path) {
|
||||
|
||||
return (null);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a URL object of a resource that is mapped to the
|
||||
* specified context-relative path.
|
||||
*
|
||||
* @param path Context-relative path of the desired resource
|
||||
*
|
||||
* @exception MalformedURLException if the resource path is
|
||||
* not properly formed
|
||||
*/
|
||||
public URL getResource(String path) throws MalformedURLException {
|
||||
|
||||
if (!path.startsWith("/"))
|
||||
throw new MalformedURLException("Path '" + path +
|
||||
"' does not start with '/'");
|
||||
URL url = new URL(myResourceBaseURL, path.substring(1));
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = url.openStream();
|
||||
} catch (Throwable t) {
|
||||
url = null;
|
||||
} finally {
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch (Throwable t2) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
return url;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return an InputStream allowing access to the resource at the
|
||||
* specified context-relative path.
|
||||
*
|
||||
* @param path Context-relative path of the desired resource
|
||||
*/
|
||||
public InputStream getResourceAsStream(String path) {
|
||||
|
||||
try {
|
||||
return (getResource(path).openStream());
|
||||
} catch (Throwable t) {
|
||||
return (null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the set of resource paths for the "directory" at the
|
||||
* specified context path.
|
||||
*
|
||||
* @param path Context-relative base path
|
||||
*/
|
||||
public Set getResourcePaths(String path) {
|
||||
|
||||
Set thePaths = new HashSet();
|
||||
if (!path.endsWith("/"))
|
||||
path += "/";
|
||||
String basePath = getRealPath(path);
|
||||
if (basePath == null)
|
||||
return (thePaths);
|
||||
File theBaseDir = new File(basePath);
|
||||
if (!theBaseDir.exists() || !theBaseDir.isDirectory())
|
||||
return (thePaths);
|
||||
String theFiles[] = theBaseDir.list();
|
||||
for (int i = 0; i < theFiles.length; i++) {
|
||||
File testFile = new File(basePath + File.separator + theFiles[i]);
|
||||
if (testFile.isFile())
|
||||
thePaths.add(path + theFiles[i]);
|
||||
else if (testFile.isDirectory())
|
||||
thePaths.add(path + theFiles[i] + "/");
|
||||
}
|
||||
return (thePaths);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return descriptive information about this server.
|
||||
*/
|
||||
public String getServerInfo() {
|
||||
|
||||
return ("JspCServletContext/1.0");
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a null reference for the specified servlet name.
|
||||
*
|
||||
* @param name Name of the requested servlet
|
||||
*
|
||||
* @deprecated This method has been deprecated with no replacement
|
||||
*/
|
||||
public Servlet getServlet(String name) throws ServletException {
|
||||
|
||||
return (null);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the name of this servlet context.
|
||||
*/
|
||||
public String getServletContextName() {
|
||||
|
||||
return (getServerInfo());
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return an empty enumeration of servlet names.
|
||||
*
|
||||
* @deprecated This method has been deprecated with no replacement
|
||||
*/
|
||||
public Enumeration getServletNames() {
|
||||
|
||||
return (new Vector().elements());
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return an empty enumeration of servlets.
|
||||
*
|
||||
* @deprecated This method has been deprecated with no replacement
|
||||
*/
|
||||
public Enumeration getServlets() {
|
||||
|
||||
return (new Vector().elements());
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log the specified message.
|
||||
*
|
||||
* @param message The message to be logged
|
||||
*/
|
||||
public void log(String message) {
|
||||
|
||||
myLogWriter.println(message);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log the specified message and exception.
|
||||
*
|
||||
* @param exception The exception to be logged
|
||||
* @param message The message to be logged
|
||||
*
|
||||
* @deprecated Use log(String,Throwable) instead
|
||||
*/
|
||||
public void log(Exception exception, String message) {
|
||||
|
||||
log(message, exception);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log the specified message and exception.
|
||||
*
|
||||
* @param message The message to be logged
|
||||
* @param exception The exception to be logged
|
||||
*/
|
||||
public void log(String message, Throwable exception) {
|
||||
|
||||
myLogWriter.println(message);
|
||||
exception.printStackTrace(myLogWriter);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove the specified context attribute.
|
||||
*
|
||||
* @param name Name of the attribute to remove
|
||||
*/
|
||||
public void removeAttribute(String name) {
|
||||
|
||||
myAttributes.remove(name);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set or replace the specified context attribute.
|
||||
*
|
||||
* @param name Name of the context attribute to set
|
||||
* @param value Corresponding attribute value
|
||||
*/
|
||||
public void setAttribute(String name, Object value) {
|
||||
|
||||
myAttributes.put(name, value);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,347 +0,0 @@
|
||||
/*
|
||||
* 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.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.PeriodicEventListener;
|
||||
|
||||
import org.apache.jasper.Constants;
|
||||
import org.apache.jasper.EmbeddedServletOptions;
|
||||
import org.apache.jasper.Options;
|
||||
import org.apache.jasper.compiler.JspRuntimeContext;
|
||||
import org.apache.jasper.compiler.Localizer;
|
||||
import org.apache.jasper.security.SecurityUtil;
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* The JSP engine (a.k.a Jasper).
|
||||
*
|
||||
* The servlet container is responsible for providing a
|
||||
* URLClassLoader for the web application context Jasper
|
||||
* is being used in. Jasper will try get the Tomcat
|
||||
* ServletContext attribute for its ServletContext class
|
||||
* loader, if that fails, it uses the parent class loader.
|
||||
* In either case, it must be a URLClassLoader.
|
||||
*
|
||||
* @author Anil K. Vijendran
|
||||
* @author Harish Prabandham
|
||||
* @author Remy Maucherat
|
||||
* @author Kin-man Chung
|
||||
* @author Glenn Nielsen
|
||||
*/
|
||||
public class JspServlet extends HttpServlet implements PeriodicEventListener {
|
||||
|
||||
// Logger
|
||||
private Log log = LogFactory.getLog(JspServlet.class);
|
||||
|
||||
private ServletContext context;
|
||||
private ServletConfig config;
|
||||
private Options options;
|
||||
private JspRuntimeContext rctxt;
|
||||
|
||||
|
||||
/*
|
||||
* Initializes this JspServlet.
|
||||
*/
|
||||
public void init(ServletConfig config) throws ServletException {
|
||||
|
||||
super.init(config);
|
||||
this.config = config;
|
||||
this.context = config.getServletContext();
|
||||
|
||||
// Initialize the JSP Runtime Context
|
||||
// Check for a custom Options implementation
|
||||
String engineOptionsName =
|
||||
config.getInitParameter("engineOptionsClass");
|
||||
if (engineOptionsName != null) {
|
||||
// Instantiate the indicated Options implementation
|
||||
try {
|
||||
ClassLoader loader = Thread.currentThread()
|
||||
.getContextClassLoader();
|
||||
Class engineOptionsClass = loader.loadClass(engineOptionsName);
|
||||
Class[] ctorSig = { ServletConfig.class, ServletContext.class };
|
||||
Constructor ctor = engineOptionsClass.getConstructor(ctorSig);
|
||||
Object[] args = { config, context };
|
||||
options = (Options) ctor.newInstance(args);
|
||||
} catch (Throwable e) {
|
||||
// Need to localize this.
|
||||
log.warn("Failed to load engineOptionsClass", e);
|
||||
// Use the default Options implementation
|
||||
options = new EmbeddedServletOptions(config, context);
|
||||
}
|
||||
} else {
|
||||
// Use the default Options implementation
|
||||
options = new EmbeddedServletOptions(config, context);
|
||||
}
|
||||
rctxt = new JspRuntimeContext(context, options);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(Localizer.getMessage("jsp.message.scratch.dir.is",
|
||||
options.getScratchDir().toString()));
|
||||
log.debug(Localizer.getMessage("jsp.message.dont.modify.servlets"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of JSPs for which JspServletWrappers exist, i.e.,
|
||||
* the number of JSPs that have been loaded into the webapp with which
|
||||
* this JspServlet is associated.
|
||||
*
|
||||
* <p>This info may be used for monitoring purposes.
|
||||
*
|
||||
* @return The number of JSPs that have been loaded into the webapp with
|
||||
* which this JspServlet is associated
|
||||
*/
|
||||
public int getJspCount() {
|
||||
return this.rctxt.getJspCount();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resets the JSP reload counter.
|
||||
*
|
||||
* @param count Value to which to reset the JSP reload counter
|
||||
*/
|
||||
public void setJspReloadCount(int count) {
|
||||
this.rctxt.setJspReloadCount(count);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of JSPs that have been reloaded.
|
||||
*
|
||||
* <p>This info may be used for monitoring purposes.
|
||||
*
|
||||
* @return The number of JSPs (in the webapp with which this JspServlet is
|
||||
* associated) that have been reloaded
|
||||
*/
|
||||
public int getJspReloadCount() {
|
||||
return this.rctxt.getJspReloadCount();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Look for a <em>precompilation request</em> as described in
|
||||
* Section 8.4.2 of the JSP 1.2 Specification. <strong>WARNING</strong> -
|
||||
* we cannot use <code>request.getParameter()</code> for this, because
|
||||
* that will trigger parsing all of the request parameters, and not give
|
||||
* a servlet the opportunity to call
|
||||
* <code>request.setCharacterEncoding()</code> first.</p>
|
||||
*
|
||||
* @param request The servlet requset we are processing
|
||||
*
|
||||
* @exception ServletException if an invalid parameter value for the
|
||||
* <code>jsp_precompile</code> parameter name is specified
|
||||
*/
|
||||
boolean preCompile(HttpServletRequest request) throws ServletException {
|
||||
|
||||
String queryString = request.getQueryString();
|
||||
if (queryString == null) {
|
||||
return (false);
|
||||
}
|
||||
int start = queryString.indexOf(Constants.PRECOMPILE);
|
||||
if (start < 0) {
|
||||
return (false);
|
||||
}
|
||||
queryString =
|
||||
queryString.substring(start + Constants.PRECOMPILE.length());
|
||||
if (queryString.length() == 0) {
|
||||
return (true); // ?jsp_precompile
|
||||
}
|
||||
if (queryString.startsWith("&")) {
|
||||
return (true); // ?jsp_precompile&foo=bar...
|
||||
}
|
||||
if (!queryString.startsWith("=")) {
|
||||
return (false); // part of some other name or value
|
||||
}
|
||||
int limit = queryString.length();
|
||||
int ampersand = queryString.indexOf("&");
|
||||
if (ampersand > 0) {
|
||||
limit = ampersand;
|
||||
}
|
||||
String value = queryString.substring(1, limit);
|
||||
if (value.equals("true")) {
|
||||
return (true); // ?jsp_precompile=true
|
||||
} else if (value.equals("false")) {
|
||||
// Spec says if jsp_precompile=false, the request should not
|
||||
// be delivered to the JSP page; the easiest way to implement
|
||||
// this is to set the flag to true, and precompile the page anyway.
|
||||
// This still conforms to the spec, since it says the
|
||||
// precompilation request can be ignored.
|
||||
return (true); // ?jsp_precompile=false
|
||||
} else {
|
||||
throw new ServletException("Cannot have request parameter " +
|
||||
Constants.PRECOMPILE + " set to " +
|
||||
value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void service (HttpServletRequest request,
|
||||
HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
|
||||
String jspUri = null;
|
||||
|
||||
String jspFile = (String) request.getAttribute(Constants.JSP_FILE);
|
||||
if (jspFile != null) {
|
||||
// JSP is specified via <jsp-file> in <servlet> declaration
|
||||
jspUri = jspFile;
|
||||
} else {
|
||||
/*
|
||||
* Check to see if the requested JSP has been the target of a
|
||||
* RequestDispatcher.include()
|
||||
*/
|
||||
jspUri = (String) request.getAttribute(Constants.INC_SERVLET_PATH);
|
||||
if (jspUri != null) {
|
||||
/*
|
||||
* Requested JSP has been target of
|
||||
* RequestDispatcher.include(). Its path is assembled from the
|
||||
* relevant javax.servlet.include.* request attributes
|
||||
*/
|
||||
String pathInfo = (String) request.getAttribute(
|
||||
"javax.servlet.include.path_info");
|
||||
if (pathInfo != null) {
|
||||
jspUri += pathInfo;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Requested JSP has not been the target of a
|
||||
* RequestDispatcher.include(). Reconstruct its path from the
|
||||
* request's getServletPath() and getPathInfo()
|
||||
*/
|
||||
jspUri = request.getServletPath();
|
||||
String pathInfo = request.getPathInfo();
|
||||
if (pathInfo != null) {
|
||||
jspUri += pathInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("JspEngine --> " + jspUri);
|
||||
log.debug("\t ServletPath: " + request.getServletPath());
|
||||
log.debug("\t PathInfo: " + request.getPathInfo());
|
||||
log.debug("\t RealPath: " + context.getRealPath(jspUri));
|
||||
log.debug("\t RequestURI: " + request.getRequestURI());
|
||||
log.debug("\t QueryString: " + request.getQueryString());
|
||||
log.debug("\t Request Params: ");
|
||||
Enumeration e = request.getParameterNames();
|
||||
while (e.hasMoreElements()) {
|
||||
String name = (String) e.nextElement();
|
||||
log.debug("\t\t " + name + " = "
|
||||
+ request.getParameter(name));
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
boolean precompile = preCompile(request);
|
||||
serviceJspFile(request, response, jspUri, null, precompile);
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (ServletException e) {
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
} catch (Throwable e) {
|
||||
throw new ServletException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("JspServlet.destroy()");
|
||||
}
|
||||
|
||||
rctxt.destroy();
|
||||
}
|
||||
|
||||
|
||||
public void periodicEvent() {
|
||||
rctxt.checkCompile();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------- Private Methods
|
||||
|
||||
private void serviceJspFile(HttpServletRequest request,
|
||||
HttpServletResponse response, String jspUri,
|
||||
Throwable exception, boolean precompile)
|
||||
throws ServletException, IOException {
|
||||
|
||||
JspServletWrapper wrapper =
|
||||
(JspServletWrapper) rctxt.getWrapper(jspUri);
|
||||
if (wrapper == null) {
|
||||
synchronized(this) {
|
||||
wrapper = (JspServletWrapper) rctxt.getWrapper(jspUri);
|
||||
if (wrapper == null) {
|
||||
// Check if the requested JSP page exists, to avoid
|
||||
// creating unnecessary directories and files.
|
||||
if (null == context.getResource(jspUri)) {
|
||||
String includeRequestUri = (String)
|
||||
request.getAttribute(
|
||||
"javax.servlet.include.request_uri");
|
||||
if (includeRequestUri != null) {
|
||||
// This file was included. Throw an exception as
|
||||
// a response.sendError() will be ignored
|
||||
String msg = Localizer.getMessage(
|
||||
"jsp.error.file.not.found",jspUri);
|
||||
// Strictly, filtering this is an application
|
||||
// responsibility but just in case...
|
||||
throw new ServletException(
|
||||
SecurityUtil.filter(msg));
|
||||
} else {
|
||||
try {
|
||||
response.sendError(
|
||||
HttpServletResponse.SC_NOT_FOUND,
|
||||
request.getRequestURI());
|
||||
} catch (IllegalStateException ise) {
|
||||
log.error(Localizer.getMessage(
|
||||
"jsp.error.file.not.found",
|
||||
jspUri));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
boolean isErrorPage = exception != null;
|
||||
wrapper = new JspServletWrapper(config, options, jspUri,
|
||||
isErrorPage, rctxt);
|
||||
rctxt.addWrapper(jspUri,wrapper);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wrapper.service(request, response, precompile);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
-527
@@ -1,527 +0,0 @@
|
||||
/*
|
||||
* 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.servlet;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.SingleThreadModel;
|
||||
import javax.servlet.UnavailableException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.jsp.tagext.TagInfo;
|
||||
|
||||
import org.apache.AnnotationProcessor;
|
||||
import org.apache.jasper.JasperException;
|
||||
import org.apache.jasper.JspCompilationContext;
|
||||
import org.apache.jasper.Options;
|
||||
import org.apache.jasper.compiler.ErrorDispatcher;
|
||||
import org.apache.jasper.compiler.JavacErrorDetail;
|
||||
import org.apache.jasper.compiler.JspRuntimeContext;
|
||||
import org.apache.jasper.compiler.Localizer;
|
||||
import org.apache.jasper.runtime.JspSourceDependent;
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* The JSP engine (a.k.a Jasper).
|
||||
*
|
||||
* The servlet container is responsible for providing a
|
||||
* URLClassLoader for the web application context Jasper
|
||||
* is being used in. Jasper will try get the Tomcat
|
||||
* ServletContext attribute for its ServletContext class
|
||||
* loader, if that fails, it uses the parent class loader.
|
||||
* In either case, it must be a URLClassLoader.
|
||||
*
|
||||
* @author Anil K. Vijendran
|
||||
* @author Harish Prabandham
|
||||
* @author Remy Maucherat
|
||||
* @author Kin-man Chung
|
||||
* @author Glenn Nielsen
|
||||
* @author Tim Fennell
|
||||
*/
|
||||
|
||||
public class JspServletWrapper {
|
||||
|
||||
// Logger
|
||||
private Log log = LogFactory.getLog(JspServletWrapper.class);
|
||||
|
||||
private Servlet theServlet;
|
||||
private String jspUri;
|
||||
private Class servletClass;
|
||||
private Class tagHandlerClass;
|
||||
private JspCompilationContext ctxt;
|
||||
private long available = 0L;
|
||||
private ServletConfig config;
|
||||
private Options options;
|
||||
private boolean firstTime = true;
|
||||
private boolean reload = true;
|
||||
private boolean isTagFile;
|
||||
private int tripCount;
|
||||
private JasperException compileException;
|
||||
private long servletClassLastModifiedTime;
|
||||
private long lastModificationTest = 0L;
|
||||
|
||||
/*
|
||||
* JspServletWrapper for JSP pages.
|
||||
*/
|
||||
public JspServletWrapper(ServletConfig config, Options options, String jspUri,
|
||||
boolean isErrorPage, JspRuntimeContext rctxt)
|
||||
throws JasperException {
|
||||
|
||||
this.isTagFile = false;
|
||||
this.config = config;
|
||||
this.options = options;
|
||||
this.jspUri = jspUri;
|
||||
ctxt = new JspCompilationContext(jspUri, isErrorPage, options,
|
||||
config.getServletContext(),
|
||||
this, rctxt);
|
||||
}
|
||||
|
||||
/*
|
||||
* JspServletWrapper for tag files.
|
||||
*/
|
||||
public JspServletWrapper(ServletContext servletContext,
|
||||
Options options,
|
||||
String tagFilePath,
|
||||
TagInfo tagInfo,
|
||||
JspRuntimeContext rctxt,
|
||||
URL tagFileJarUrl)
|
||||
throws JasperException {
|
||||
|
||||
this.isTagFile = true;
|
||||
this.config = null; // not used
|
||||
this.options = options;
|
||||
this.jspUri = tagFilePath;
|
||||
this.tripCount = 0;
|
||||
ctxt = new JspCompilationContext(jspUri, tagInfo, options,
|
||||
servletContext, this, rctxt,
|
||||
tagFileJarUrl);
|
||||
}
|
||||
|
||||
public JspCompilationContext getJspEngineContext() {
|
||||
return ctxt;
|
||||
}
|
||||
|
||||
public void setReload(boolean reload) {
|
||||
this.reload = reload;
|
||||
}
|
||||
|
||||
public Servlet getServlet()
|
||||
throws ServletException, IOException, FileNotFoundException
|
||||
{
|
||||
if (reload) {
|
||||
synchronized (this) {
|
||||
// Synchronizing on jsw enables simultaneous loading
|
||||
// of different pages, but not the same page.
|
||||
if (reload) {
|
||||
// This is to maintain the original protocol.
|
||||
destroy();
|
||||
|
||||
Servlet servlet = null;
|
||||
|
||||
try {
|
||||
servletClass = ctxt.load();
|
||||
servlet = (Servlet) servletClass.newInstance();
|
||||
AnnotationProcessor annotationProcessor = (AnnotationProcessor) config.getServletContext().getAttribute(AnnotationProcessor.class.getName());
|
||||
if (annotationProcessor != null) {
|
||||
annotationProcessor.processAnnotations(servlet);
|
||||
annotationProcessor.postConstruct(servlet);
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new JasperException(e);
|
||||
} catch (InstantiationException e) {
|
||||
throw new JasperException(e);
|
||||
} catch (Exception e) {
|
||||
throw new JasperException(e);
|
||||
}
|
||||
|
||||
servlet.init(config);
|
||||
|
||||
if (!firstTime) {
|
||||
ctxt.getRuntimeContext().incrementJspReloadCount();
|
||||
}
|
||||
|
||||
theServlet = servlet;
|
||||
reload = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return theServlet;
|
||||
}
|
||||
|
||||
public ServletContext getServletContext() {
|
||||
return config.getServletContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the compilation exception for this JspServletWrapper.
|
||||
*
|
||||
* @param je The compilation exception
|
||||
*/
|
||||
public void setCompilationException(JasperException je) {
|
||||
this.compileException = je;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the last-modified time of the servlet class file associated with
|
||||
* this JspServletWrapper.
|
||||
*
|
||||
* @param lastModified Last-modified time of servlet class
|
||||
*/
|
||||
public void setServletClassLastModifiedTime(long lastModified) {
|
||||
if (this.servletClassLastModifiedTime < lastModified) {
|
||||
synchronized (this) {
|
||||
if (this.servletClassLastModifiedTime < lastModified) {
|
||||
this.servletClassLastModifiedTime = lastModified;
|
||||
reload = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile (if needed) and load a tag file
|
||||
*/
|
||||
public Class loadTagFile() throws JasperException {
|
||||
|
||||
try {
|
||||
if (ctxt.isRemoved()) {
|
||||
throw new FileNotFoundException(jspUri);
|
||||
}
|
||||
if (options.getDevelopment() || firstTime ) {
|
||||
synchronized (this) {
|
||||
firstTime = false;
|
||||
ctxt.compile();
|
||||
}
|
||||
} else {
|
||||
if (compileException != null) {
|
||||
throw compileException;
|
||||
}
|
||||
}
|
||||
|
||||
if (reload) {
|
||||
tagHandlerClass = ctxt.load();
|
||||
reload = false;
|
||||
}
|
||||
} catch (FileNotFoundException ex) {
|
||||
throw new JasperException(ex);
|
||||
}
|
||||
|
||||
return tagHandlerClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile and load a prototype for the Tag file. This is needed
|
||||
* when compiling tag files with circular dependencies. A prototpe
|
||||
* (skeleton) with no dependencies on other other tag files is
|
||||
* generated and compiled.
|
||||
*/
|
||||
public Class loadTagFilePrototype() throws JasperException {
|
||||
|
||||
ctxt.setPrototypeMode(true);
|
||||
try {
|
||||
return loadTagFile();
|
||||
} finally {
|
||||
ctxt.setPrototypeMode(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of files that the current page has source dependency on.
|
||||
*/
|
||||
public java.util.List getDependants() {
|
||||
try {
|
||||
Object target;
|
||||
if (isTagFile) {
|
||||
if (reload) {
|
||||
tagHandlerClass = ctxt.load();
|
||||
reload = false;
|
||||
}
|
||||
target = tagHandlerClass.newInstance();
|
||||
} else {
|
||||
target = getServlet();
|
||||
}
|
||||
if (target != null && target instanceof JspSourceDependent) {
|
||||
return ((java.util.List) ((JspSourceDependent) target).getDependants());
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isTagFile() {
|
||||
return this.isTagFile;
|
||||
}
|
||||
|
||||
public int incTripCount() {
|
||||
return tripCount++;
|
||||
}
|
||||
|
||||
public int decTripCount() {
|
||||
return tripCount--;
|
||||
}
|
||||
|
||||
public void service(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
boolean precompile)
|
||||
throws ServletException, IOException, FileNotFoundException {
|
||||
|
||||
try {
|
||||
|
||||
if (ctxt.isRemoved()) {
|
||||
throw new FileNotFoundException(jspUri);
|
||||
}
|
||||
|
||||
if ((available > 0L) && (available < Long.MAX_VALUE)) {
|
||||
if (available > System.currentTimeMillis()) {
|
||||
response.setDateHeader("Retry-After", available);
|
||||
response.sendError
|
||||
(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
|
||||
Localizer.getMessage("jsp.error.unavailable"));
|
||||
return;
|
||||
} else {
|
||||
// Wait period has expired. Reset.
|
||||
available = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (1) Compile
|
||||
*/
|
||||
if (options.getDevelopment() || firstTime ) {
|
||||
synchronized (this) {
|
||||
firstTime = false;
|
||||
|
||||
// The following sets reload to true, if necessary
|
||||
ctxt.compile();
|
||||
}
|
||||
} else {
|
||||
if (compileException != null) {
|
||||
// Throw cached compilation exception
|
||||
throw compileException;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (2) (Re)load servlet class file
|
||||
*/
|
||||
getServlet();
|
||||
|
||||
// If a page is to be precompiled only, return.
|
||||
if (precompile) {
|
||||
return;
|
||||
}
|
||||
|
||||
} catch (ServletException ex) {
|
||||
if (options.getDevelopment()) {
|
||||
throw handleJspException(ex);
|
||||
} else {
|
||||
throw ex;
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
if (options.getDevelopment()) {
|
||||
throw handleJspException(ex);
|
||||
} else {
|
||||
throw ex;
|
||||
}
|
||||
} catch (IllegalStateException ex) {
|
||||
if (options.getDevelopment()) {
|
||||
throw handleJspException(ex);
|
||||
} else {
|
||||
throw ex;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
if (options.getDevelopment()) {
|
||||
throw handleJspException(ex);
|
||||
} else {
|
||||
throw new JasperException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
/*
|
||||
* (3) Service request
|
||||
*/
|
||||
if (theServlet instanceof SingleThreadModel) {
|
||||
// sync on the wrapper so that the freshness
|
||||
// of the page is determined right before servicing
|
||||
synchronized (this) {
|
||||
theServlet.service(request, response);
|
||||
}
|
||||
} else {
|
||||
theServlet.service(request, response);
|
||||
}
|
||||
|
||||
} catch (UnavailableException ex) {
|
||||
String includeRequestUri = (String)
|
||||
request.getAttribute("javax.servlet.include.request_uri");
|
||||
if (includeRequestUri != null) {
|
||||
// This file was included. Throw an exception as
|
||||
// a response.sendError() will be ignored by the
|
||||
// servlet engine.
|
||||
throw ex;
|
||||
} else {
|
||||
int unavailableSeconds = ex.getUnavailableSeconds();
|
||||
if (unavailableSeconds <= 0) {
|
||||
unavailableSeconds = 60; // Arbitrary default
|
||||
}
|
||||
available = System.currentTimeMillis() +
|
||||
(unavailableSeconds * 1000L);
|
||||
response.sendError
|
||||
(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
|
||||
ex.getMessage());
|
||||
}
|
||||
} catch (ServletException ex) {
|
||||
if(options.getDevelopment()) {
|
||||
throw handleJspException(ex);
|
||||
} else {
|
||||
throw ex;
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
if(options.getDevelopment()) {
|
||||
throw handleJspException(ex);
|
||||
} else {
|
||||
throw ex;
|
||||
}
|
||||
} catch (IllegalStateException ex) {
|
||||
if(options.getDevelopment()) {
|
||||
throw handleJspException(ex);
|
||||
} else {
|
||||
throw ex;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
if(options.getDevelopment()) {
|
||||
throw handleJspException(ex);
|
||||
} else {
|
||||
throw new JasperException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
if (theServlet != null) {
|
||||
theServlet.destroy();
|
||||
AnnotationProcessor annotationProcessor = (AnnotationProcessor) config.getServletContext().getAttribute(AnnotationProcessor.class.getName());
|
||||
if (annotationProcessor != null) {
|
||||
try {
|
||||
annotationProcessor.preDestroy(theServlet);
|
||||
} catch (Exception e) {
|
||||
// Log any exception, since it can't be passed along
|
||||
log.error(Localizer.getMessage("jsp.error.file.not.found",
|
||||
e.getMessage()), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the lastModificationTest.
|
||||
*/
|
||||
public long getLastModificationTest() {
|
||||
return lastModificationTest;
|
||||
}
|
||||
/**
|
||||
* @param lastModificationTest The lastModificationTest to set.
|
||||
*/
|
||||
public void setLastModificationTest(long lastModificationTest) {
|
||||
this.lastModificationTest = lastModificationTest;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Attempts to construct a JasperException that contains helpful information
|
||||
* about what went wrong. Uses the JSP compiler system to translate the line
|
||||
* number in the generated servlet that originated the exception to a line
|
||||
* number in the JSP. Then constructs an exception containing that
|
||||
* information, and a snippet of the JSP to help debugging.
|
||||
* Please see http://issues.apache.org/bugzilla/show_bug.cgi?id=37062 and
|
||||
* http://www.tfenne.com/jasper/ for more details.
|
||||
*</p>
|
||||
*
|
||||
* @param ex the exception that was the cause of the problem.
|
||||
* @return a JasperException with more detailed information
|
||||
*/
|
||||
protected JasperException handleJspException(Exception ex) {
|
||||
try {
|
||||
Throwable realException = ex;
|
||||
if (ex instanceof ServletException) {
|
||||
realException = ((ServletException) ex).getRootCause();
|
||||
}
|
||||
|
||||
// First identify the stack frame in the trace that represents the JSP
|
||||
StackTraceElement[] frames = realException.getStackTrace();
|
||||
StackTraceElement jspFrame = null;
|
||||
|
||||
for (int i=0; i<frames.length; ++i) {
|
||||
if ( frames[i].getClassName().equals(this.getServlet().getClass().getName()) ) {
|
||||
jspFrame = frames[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (jspFrame == null) {
|
||||
// If we couldn't find a frame in the stack trace corresponding
|
||||
// to the generated servlet class, we can't really add anything
|
||||
return new JasperException(ex);
|
||||
}
|
||||
else {
|
||||
int javaLineNumber = jspFrame.getLineNumber();
|
||||
JavacErrorDetail detail = ErrorDispatcher.createJavacError(
|
||||
jspFrame.getMethodName(),
|
||||
this.ctxt.getCompiler().getPageNodes(),
|
||||
null,
|
||||
javaLineNumber,
|
||||
ctxt);
|
||||
|
||||
// If the line number is less than one we couldn't find out
|
||||
// where in the JSP things went wrong
|
||||
int jspLineNumber = detail.getJspBeginLineNumber();
|
||||
if (jspLineNumber < 1) {
|
||||
throw new JasperException(ex);
|
||||
}
|
||||
|
||||
if (options.getDisplaySourceFragment()) {
|
||||
return new JasperException(Localizer.getMessage
|
||||
("jsp.exception", detail.getJspFileName(),
|
||||
"" + jspLineNumber) +
|
||||
"\n\n" + detail.getJspExtract() +
|
||||
"\n\nStacktrace:", ex);
|
||||
|
||||
} else {
|
||||
return new JasperException(Localizer.getMessage
|
||||
("jsp.exception", detail.getJspFileName(),
|
||||
"" + jspLineNumber), ex);
|
||||
}
|
||||
}
|
||||
} catch (Exception je) {
|
||||
// If anything goes wrong, just revert to the original behaviour
|
||||
if (ex instanceof JasperException) {
|
||||
return (JasperException) ex;
|
||||
} else {
|
||||
return new JasperException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<mbeans-descriptors>
|
||||
|
||||
<mbean name="JspMonitor"
|
||||
description="JSP Monitoring"
|
||||
domain="Catalina"
|
||||
group="Monitoring"
|
||||
type="org.apache.jasper.servlet.JspServlet">
|
||||
|
||||
<attribute name="jspCount"
|
||||
description="The number of JSPs that have been loaded into a webapp"
|
||||
type="int"/>
|
||||
|
||||
<attribute name="jspReloadCount"
|
||||
description="The number of JSPs that have been reloaded"
|
||||
type="int"/>
|
||||
|
||||
</mbean>
|
||||
|
||||
</mbeans-descriptors>
|
||||
-328
@@ -1,328 +0,0 @@
|
||||
/*
|
||||
* 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.tagplugins.jstl;
|
||||
|
||||
import org.apache.jasper.Constants;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletResponseWrapper;
|
||||
import javax.servlet.jsp.JspException;
|
||||
import javax.servlet.jsp.JspTagException;
|
||||
import javax.servlet.jsp.PageContext;
|
||||
|
||||
/**
|
||||
* Util contains some often used consts, static methods and embedded class
|
||||
* to support the JSTL tag plugin.
|
||||
*/
|
||||
|
||||
public class Util {
|
||||
|
||||
public static final String VALID_SCHEME_CHAR =
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+.-";
|
||||
|
||||
public static final String DEFAULT_ENCODING =
|
||||
"ISO-8859-1";
|
||||
|
||||
public static final int HIGHEST_SPECIAL = '>';
|
||||
|
||||
public static char[][] specialCharactersRepresentation = new char[HIGHEST_SPECIAL + 1][];
|
||||
|
||||
static {
|
||||
specialCharactersRepresentation['&'] = "&".toCharArray();
|
||||
specialCharactersRepresentation['<'] = "<".toCharArray();
|
||||
specialCharactersRepresentation['>'] = ">".toCharArray();
|
||||
specialCharactersRepresentation['"'] = """.toCharArray();
|
||||
specialCharactersRepresentation['\''] = "'".toCharArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given string description of a scope to the corresponding
|
||||
* PageContext constant.
|
||||
*
|
||||
* The validity of the given scope has already been checked by the
|
||||
* appropriate TLV.
|
||||
*
|
||||
* @param scope String description of scope
|
||||
*
|
||||
* @return PageContext constant corresponding to given scope description
|
||||
*
|
||||
* taken from org.apache.taglibs.standard.tag.common.core.Util
|
||||
*/
|
||||
public static int getScope(String scope){
|
||||
int ret = PageContext.PAGE_SCOPE;
|
||||
|
||||
if("request".equalsIgnoreCase(scope)){
|
||||
ret = PageContext.REQUEST_SCOPE;
|
||||
}else if("session".equalsIgnoreCase(scope)){
|
||||
ret = PageContext.SESSION_SCOPE;
|
||||
}else if("application".equalsIgnoreCase(scope)){
|
||||
ret = PageContext.APPLICATION_SCOPE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if our current URL is absolute,
|
||||
* <tt>false</tt> otherwise.
|
||||
* taken from org.apache.taglibs.standard.tag.common.core.ImportSupport
|
||||
*/
|
||||
public static boolean isAbsoluteUrl(String url){
|
||||
if(url == null){
|
||||
return false;
|
||||
}
|
||||
|
||||
int colonPos = url.indexOf(":");
|
||||
if(colonPos == -1){
|
||||
return false;
|
||||
}
|
||||
|
||||
for(int i=0;i<colonPos;i++){
|
||||
if(VALID_SCHEME_CHAR.indexOf(url.charAt(i)) == -1){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value associated with a content-type attribute.
|
||||
* Syntax defined in RFC 2045, section 5.1.
|
||||
* taken from org.apache.taglibs.standard.tag.common.core.Util
|
||||
*/
|
||||
public static String getContentTypeAttribute(String input, String name) {
|
||||
int begin;
|
||||
int end;
|
||||
int index = input.toUpperCase().indexOf(name.toUpperCase());
|
||||
if (index == -1) return null;
|
||||
index = index + name.length(); // positioned after the attribute name
|
||||
index = input.indexOf('=', index); // positioned at the '='
|
||||
if (index == -1) return null;
|
||||
index += 1; // positioned after the '='
|
||||
input = input.substring(index).trim();
|
||||
|
||||
if (input.charAt(0) == '"') {
|
||||
// attribute value is a quoted string
|
||||
begin = 1;
|
||||
end = input.indexOf('"', begin);
|
||||
if (end == -1) return null;
|
||||
} else {
|
||||
begin = 0;
|
||||
end = input.indexOf(';');
|
||||
if (end == -1) end = input.indexOf(' ');
|
||||
if (end == -1) end = input.length();
|
||||
}
|
||||
return input.substring(begin, end).trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips a servlet session ID from <tt>url</tt>. The session ID
|
||||
* is encoded as a URL "path parameter" beginning with "jsessionid=".
|
||||
* We thus remove anything we find between ";jsessionid=" (inclusive)
|
||||
* and either EOS or a subsequent ';' (exclusive).
|
||||
*
|
||||
* taken from org.apache.taglibs.standard.tag.common.core.ImportSupport
|
||||
*/
|
||||
public static String stripSession(String url) {
|
||||
StringBuffer u = new StringBuffer(url);
|
||||
int sessionStart;
|
||||
while ((sessionStart = u.toString().indexOf(";" + Constants.SESSION_PARAMETER_NAME + "=")) != -1) {
|
||||
int sessionEnd = u.toString().indexOf(";", sessionStart + 1);
|
||||
if (sessionEnd == -1)
|
||||
sessionEnd = u.toString().indexOf("?", sessionStart + 1);
|
||||
if (sessionEnd == -1) // still
|
||||
sessionEnd = u.length();
|
||||
u.delete(sessionStart, sessionEnd);
|
||||
}
|
||||
return u.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Performs the following substring replacements
|
||||
* (to facilitate output to XML/HTML pages):
|
||||
*
|
||||
* & -> &
|
||||
* < -> <
|
||||
* > -> >
|
||||
* " -> "
|
||||
* ' -> '
|
||||
*
|
||||
* See also OutSupport.writeEscapedXml().
|
||||
*
|
||||
* taken from org.apache.taglibs.standard.tag.common.core.Util
|
||||
*/
|
||||
public static String escapeXml(String buffer) {
|
||||
int start = 0;
|
||||
int length = buffer.length();
|
||||
char[] arrayBuffer = buffer.toCharArray();
|
||||
StringBuffer escapedBuffer = null;
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
char c = arrayBuffer[i];
|
||||
if (c <= HIGHEST_SPECIAL) {
|
||||
char[] escaped = specialCharactersRepresentation[c];
|
||||
if (escaped != null) {
|
||||
// create StringBuffer to hold escaped xml string
|
||||
if (start == 0) {
|
||||
escapedBuffer = new StringBuffer(length + 5);
|
||||
}
|
||||
// add unescaped portion
|
||||
if (start < i) {
|
||||
escapedBuffer.append(arrayBuffer,start,i-start);
|
||||
}
|
||||
start = i + 1;
|
||||
// add escaped xml
|
||||
escapedBuffer.append(escaped);
|
||||
}
|
||||
}
|
||||
}
|
||||
// no xml escaping was necessary
|
||||
if (start == 0) {
|
||||
return buffer;
|
||||
}
|
||||
// add rest of unescaped portion
|
||||
if (start < length) {
|
||||
escapedBuffer.append(arrayBuffer,start,length-start);
|
||||
}
|
||||
return escapedBuffer.toString();
|
||||
}
|
||||
|
||||
/** Utility methods
|
||||
* taken from org.apache.taglibs.standard.tag.common.core.UrlSupport
|
||||
*/
|
||||
public static String resolveUrl(
|
||||
String url, String context, PageContext pageContext)
|
||||
throws JspException {
|
||||
// don't touch absolute URLs
|
||||
if (isAbsoluteUrl(url))
|
||||
return url;
|
||||
|
||||
// normalize relative URLs against a context root
|
||||
HttpServletRequest request =
|
||||
(HttpServletRequest) pageContext.getRequest();
|
||||
if (context == null) {
|
||||
if (url.startsWith("/"))
|
||||
return (request.getContextPath() + url);
|
||||
else
|
||||
return url;
|
||||
} else {
|
||||
if (!context.startsWith("/") || !url.startsWith("/")) {
|
||||
throw new JspTagException(
|
||||
"In URL tags, when the \"context\" attribute is specified, values of both \"context\" and \"url\" must start with \"/\".");
|
||||
}
|
||||
if (context.equals("/")) {
|
||||
// Don't produce string starting with '//', many
|
||||
// browsers interpret this as host name, not as
|
||||
// path on same host.
|
||||
return url;
|
||||
} else {
|
||||
return (context + url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Wraps responses to allow us to retrieve results as Strings.
|
||||
* mainly taken from org.apache.taglibs.standard.tag.common.core.importSupport
|
||||
*/
|
||||
public static class ImportResponseWrapper extends HttpServletResponseWrapper{
|
||||
|
||||
private StringWriter sw = new StringWriter();
|
||||
private ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
private ServletOutputStream sos = new ServletOutputStream() {
|
||||
public void write(int b) throws IOException {
|
||||
bos.write(b);
|
||||
}
|
||||
};
|
||||
private boolean isWriterUsed;
|
||||
private boolean isStreamUsed;
|
||||
private int status = 200;
|
||||
private String charEncoding;
|
||||
|
||||
public ImportResponseWrapper(HttpServletResponse arg0) {
|
||||
super(arg0);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public PrintWriter getWriter() {
|
||||
if (isStreamUsed)
|
||||
throw new IllegalStateException("Unexpected internal error during <import>: " +
|
||||
"Target servlet called getWriter(), then getOutputStream()");
|
||||
isWriterUsed = true;
|
||||
return new PrintWriter(sw);
|
||||
}
|
||||
|
||||
public ServletOutputStream getOutputStream() {
|
||||
if (isWriterUsed)
|
||||
throw new IllegalStateException("Unexpected internal error during <import>: " +
|
||||
"Target servlet called getOutputStream(), then getWriter()");
|
||||
isStreamUsed = true;
|
||||
return sos;
|
||||
}
|
||||
|
||||
/** Has no effect. */
|
||||
public void setContentType(String x) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/** Has no effect. */
|
||||
public void setLocale(Locale x) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
public void setStatus(int status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public String getCharEncoding(){
|
||||
return this.charEncoding;
|
||||
}
|
||||
|
||||
public void setCharEncoding(String ce){
|
||||
this.charEncoding = ce;
|
||||
}
|
||||
|
||||
public String getString() throws UnsupportedEncodingException {
|
||||
if (isWriterUsed)
|
||||
return sw.toString();
|
||||
else if (isStreamUsed) {
|
||||
if (this.charEncoding != null && !this.charEncoding.equals(""))
|
||||
return bos.toString(charEncoding);
|
||||
else
|
||||
return bos.toString("ISO-8859-1");
|
||||
} else
|
||||
return ""; // target didn't write anything
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-72
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* 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.tagplugins.jstl.core;
|
||||
|
||||
import org.apache.jasper.compiler.tagplugin.TagPlugin;
|
||||
import org.apache.jasper.compiler.tagplugin.TagPluginContext;
|
||||
|
||||
public class Catch implements TagPlugin {
|
||||
|
||||
public void doTag(TagPluginContext ctxt) {
|
||||
|
||||
//flag for the existence of the var attribute
|
||||
boolean hasVar = ctxt.isAttributeSpecified("var");
|
||||
|
||||
//temp name for exception and caught
|
||||
String exceptionName = ctxt.getTemporaryVariableName();
|
||||
String caughtName = ctxt.getTemporaryVariableName();
|
||||
|
||||
//main part to generate code
|
||||
ctxt.generateJavaSource("boolean " + caughtName + " = false;");
|
||||
ctxt.generateJavaSource("try{");
|
||||
ctxt.generateBody();
|
||||
ctxt.generateJavaSource("}");
|
||||
|
||||
//do catch
|
||||
ctxt.generateJavaSource("catch(Throwable " + exceptionName + "){");
|
||||
|
||||
//if the var specified, the exception object should
|
||||
//be set to the attribute "var" defines in page scope
|
||||
if(hasVar){
|
||||
String strVar = ctxt.getConstantAttribute("var");
|
||||
ctxt.generateJavaSource(" pageContext.setAttribute(\"" + strVar + "\", "
|
||||
+ exceptionName + ", PageContext.PAGE_SCOPE);");
|
||||
}
|
||||
|
||||
//whenever there's exception caught,
|
||||
//the flag caught should be set true;
|
||||
ctxt.generateJavaSource(" " + caughtName + " = true;");
|
||||
ctxt.generateJavaSource("}");
|
||||
|
||||
//do finally
|
||||
ctxt.generateJavaSource("finally{");
|
||||
|
||||
//if var specified, the attribute it defines
|
||||
//in page scope should be removed
|
||||
if(hasVar){
|
||||
String strVar = ctxt.getConstantAttribute("var");
|
||||
ctxt.generateJavaSource(" if(!" + caughtName + "){");
|
||||
ctxt.generateJavaSource(" pageContext.removeAttribute(\"" + strVar + "\", PageContext.PAGE_SCOPE);");
|
||||
ctxt.generateJavaSource(" }");
|
||||
}
|
||||
|
||||
ctxt.generateJavaSource("}");
|
||||
}
|
||||
|
||||
}
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* 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.tagplugins.jstl.core;
|
||||
|
||||
import org.apache.jasper.compiler.tagplugin.*;
|
||||
|
||||
public final class Choose implements TagPlugin {
|
||||
|
||||
public void doTag(TagPluginContext ctxt) {
|
||||
|
||||
// Not much to do here, much of the work will be done in the
|
||||
// containing tags, <c:when> and <c:otherwise>.
|
||||
|
||||
ctxt.generateBody();
|
||||
// See comments in When.java for the reason "}" is generated here.
|
||||
ctxt.generateJavaSource("}");
|
||||
}
|
||||
}
|
||||
-344
@@ -1,344 +0,0 @@
|
||||
/*
|
||||
* 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.tagplugins.jstl.core;
|
||||
|
||||
import org.apache.jasper.compiler.tagplugin.*;
|
||||
|
||||
public final class ForEach implements TagPlugin {
|
||||
|
||||
private boolean hasVar, hasBegin, hasEnd, hasStep;
|
||||
|
||||
public void doTag(TagPluginContext ctxt) {
|
||||
|
||||
String index = null;
|
||||
|
||||
boolean hasVarStatus = ctxt.isAttributeSpecified("varStatus");
|
||||
if (hasVarStatus) {
|
||||
ctxt.dontUseTagPlugin();
|
||||
return;
|
||||
}
|
||||
|
||||
hasVar = ctxt.isAttributeSpecified("var");
|
||||
hasBegin = ctxt.isAttributeSpecified("begin");
|
||||
hasEnd = ctxt.isAttributeSpecified("end");
|
||||
hasStep = ctxt.isAttributeSpecified("step");
|
||||
|
||||
boolean hasItems = ctxt.isAttributeSpecified("items");
|
||||
if (hasItems) {
|
||||
doCollection(ctxt);
|
||||
return;
|
||||
}
|
||||
|
||||
// We must have a begin and end attributes
|
||||
index = ctxt.getTemporaryVariableName();
|
||||
ctxt.generateJavaSource("for (int " + index + " = ");
|
||||
ctxt.generateAttribute("begin");
|
||||
ctxt.generateJavaSource("; " + index + " <= ");
|
||||
ctxt.generateAttribute("end");
|
||||
if (hasStep) {
|
||||
ctxt.generateJavaSource("; " + index + "+=");
|
||||
ctxt.generateAttribute("step");
|
||||
ctxt.generateJavaSource(") {");
|
||||
}
|
||||
else {
|
||||
ctxt.generateJavaSource("; " + index + "++) {");
|
||||
}
|
||||
|
||||
// If var is specified and the body contains an EL, then sycn
|
||||
// the var attribute
|
||||
if (hasVar /* && ctxt.hasEL() */) {
|
||||
ctxt.generateJavaSource("_jspx_page_context.setAttribute(");
|
||||
ctxt.generateAttribute("var");
|
||||
ctxt.generateJavaSource(", String.valueOf(" + index + "));");
|
||||
}
|
||||
ctxt.generateBody();
|
||||
ctxt.generateJavaSource("}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate codes for Collections
|
||||
* The pseudo code is:
|
||||
*/
|
||||
private void doCollection(TagPluginContext ctxt) {
|
||||
|
||||
ctxt.generateImport("java.util.*");
|
||||
generateIterators(ctxt);
|
||||
|
||||
String itemsV = ctxt.getTemporaryVariableName();
|
||||
ctxt.generateJavaSource("Object " + itemsV + "= ");
|
||||
ctxt.generateAttribute("items");
|
||||
ctxt.generateJavaSource(";");
|
||||
|
||||
String indexV=null, beginV=null, endV=null, stepV=null;
|
||||
if (hasBegin) {
|
||||
beginV = ctxt.getTemporaryVariableName();
|
||||
ctxt.generateJavaSource("int " + beginV + " = ");
|
||||
ctxt.generateAttribute("begin");
|
||||
ctxt.generateJavaSource(";");
|
||||
}
|
||||
if (hasEnd) {
|
||||
indexV = ctxt.getTemporaryVariableName();
|
||||
ctxt.generateJavaSource("int " + indexV + " = 0;");
|
||||
endV = ctxt.getTemporaryVariableName();
|
||||
ctxt.generateJavaSource("int " + endV + " = ");
|
||||
ctxt.generateAttribute("end");
|
||||
ctxt.generateJavaSource(";");
|
||||
}
|
||||
if (hasStep) {
|
||||
stepV = ctxt.getTemporaryVariableName();
|
||||
ctxt.generateJavaSource("int " + stepV + " = ");
|
||||
ctxt.generateAttribute("step");
|
||||
ctxt.generateJavaSource(";");
|
||||
}
|
||||
|
||||
String iterV = ctxt.getTemporaryVariableName();
|
||||
ctxt.generateJavaSource("Iterator " + iterV + " = null;");
|
||||
// Object[]
|
||||
ctxt.generateJavaSource("if (" + itemsV + " instanceof Object[])");
|
||||
ctxt.generateJavaSource(iterV + "=toIterator((Object[])" + itemsV + ");");
|
||||
// boolean[]
|
||||
ctxt.generateJavaSource("else if (" + itemsV + " instanceof boolean[])");
|
||||
ctxt.generateJavaSource(iterV + "=toIterator((boolean[])" + itemsV + ");");
|
||||
// byte[]
|
||||
ctxt.generateJavaSource("else if (" + itemsV + " instanceof byte[])");
|
||||
ctxt.generateJavaSource(iterV + "=toIterator((byte[])" + itemsV + ");");
|
||||
// char[]
|
||||
ctxt.generateJavaSource("else if (" + itemsV + " instanceof char[])");
|
||||
ctxt.generateJavaSource(iterV + "=toIterator((char[])" + itemsV + ");");
|
||||
// short[]
|
||||
ctxt.generateJavaSource("else if (" + itemsV + " instanceof short[])");
|
||||
ctxt.generateJavaSource(iterV + "=toIterator((short[])" + itemsV + ");");
|
||||
// int[]
|
||||
ctxt.generateJavaSource("else if (" + itemsV + " instanceof int[])");
|
||||
ctxt.generateJavaSource(iterV + "=toIterator((int[])" + itemsV + ");");
|
||||
// long[]
|
||||
ctxt.generateJavaSource("else if (" + itemsV + " instanceof long[])");
|
||||
ctxt.generateJavaSource(iterV + "=toIterator((long[])" + itemsV + ");");
|
||||
// float[]
|
||||
ctxt.generateJavaSource("else if (" + itemsV + " instanceof float[])");
|
||||
ctxt.generateJavaSource(iterV + "=toIterator((float[])" + itemsV + ");");
|
||||
// double[]
|
||||
ctxt.generateJavaSource("else if (" + itemsV + " instanceof double[])");
|
||||
ctxt.generateJavaSource(iterV + "=toIterator((double[])" + itemsV + ");");
|
||||
|
||||
// Collection
|
||||
ctxt.generateJavaSource("else if (" + itemsV + " instanceof Collection)");
|
||||
ctxt.generateJavaSource(iterV + "=((Collection)" + itemsV + ").iterator();");
|
||||
|
||||
// Iterator
|
||||
ctxt.generateJavaSource("else if (" + itemsV + " instanceof Iterator)");
|
||||
ctxt.generateJavaSource(iterV + "=(Iterator)" + itemsV + ";");
|
||||
|
||||
// Enumeration
|
||||
ctxt.generateJavaSource("else if (" + itemsV + " instanceof Enumeration)");
|
||||
ctxt.generateJavaSource(iterV + "=toIterator((Enumeration)" + itemsV + ");");
|
||||
|
||||
// Map
|
||||
ctxt.generateJavaSource("else if (" + itemsV + " instanceof Map)");
|
||||
ctxt.generateJavaSource(iterV + "=((Map)" + itemsV + ").entrySet().iterator();");
|
||||
|
||||
if (hasBegin) {
|
||||
String tV = ctxt.getTemporaryVariableName();
|
||||
ctxt.generateJavaSource("for (int " + tV + "=" + beginV + ";" +
|
||||
tV + ">0 && " + iterV + ".hasNext(); " +
|
||||
tV + "--)");
|
||||
ctxt.generateJavaSource(iterV + ".next();");
|
||||
}
|
||||
|
||||
ctxt.generateJavaSource("while (" + iterV + ".hasNext()){");
|
||||
if (hasVar) {
|
||||
ctxt.generateJavaSource("_jspx_page_context.setAttribute(");
|
||||
ctxt.generateAttribute("var");
|
||||
ctxt.generateJavaSource(", " + iterV + ".next());");
|
||||
}
|
||||
|
||||
ctxt.generateBody();
|
||||
|
||||
if (hasStep) {
|
||||
String tV = ctxt.getTemporaryVariableName();
|
||||
ctxt.generateJavaSource("for (int " + tV + "=" + stepV + "-1;" +
|
||||
tV + ">0 && " + iterV + ".hasNext(); " +
|
||||
tV + "--)");
|
||||
ctxt.generateJavaSource(iterV + ".next();");
|
||||
}
|
||||
if (hasEnd) {
|
||||
if (hasStep) {
|
||||
ctxt.generateJavaSource(indexV + "+=" + stepV + ";");
|
||||
}
|
||||
else {
|
||||
ctxt.generateJavaSource(indexV + "++;");
|
||||
}
|
||||
if (hasBegin) {
|
||||
ctxt.generateJavaSource("if(" + beginV + "+" + indexV +
|
||||
">"+ endV + ")");
|
||||
}
|
||||
else {
|
||||
ctxt.generateJavaSource("if(" + indexV + ">" + endV + ")");
|
||||
}
|
||||
ctxt.generateJavaSource("break;");
|
||||
}
|
||||
ctxt.generateJavaSource("}"); // while
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate iterators for data types supported in items
|
||||
*/
|
||||
private void generateIterators(TagPluginContext ctxt) {
|
||||
|
||||
// Object[]
|
||||
ctxt.generateDeclaration("ObjectArrayIterator",
|
||||
"private Iterator toIterator(final Object[] a){\n" +
|
||||
" return (new Iterator() {\n" +
|
||||
" int index=0;\n" +
|
||||
" public boolean hasNext() {\n" +
|
||||
" return index < a.length;}\n" +
|
||||
" public Object next() {\n" +
|
||||
" return a[index++];}\n" +
|
||||
" public void remove() {}\n" +
|
||||
" });\n" +
|
||||
"}"
|
||||
);
|
||||
|
||||
// boolean[]
|
||||
ctxt.generateDeclaration("booleanArrayIterator",
|
||||
"private Iterator toIterator(final boolean[] a){\n" +
|
||||
" return (new Iterator() {\n" +
|
||||
" int index=0;\n" +
|
||||
" public boolean hasNext() {\n" +
|
||||
" return index < a.length;}\n" +
|
||||
" public Object next() {\n" +
|
||||
" return new Boolean(a[index++]);}\n" +
|
||||
" public void remove() {}\n" +
|
||||
" });\n" +
|
||||
"}"
|
||||
);
|
||||
|
||||
// byte[]
|
||||
ctxt.generateDeclaration("byteArrayIterator",
|
||||
"private Iterator toIterator(final byte[] a){\n" +
|
||||
" return (new Iterator() {\n" +
|
||||
" int index=0;\n" +
|
||||
" public boolean hasNext() {\n" +
|
||||
" return index < a.length;}\n" +
|
||||
" public Object next() {\n" +
|
||||
" return new Byte(a[index++]);}\n" +
|
||||
" public void remove() {}\n" +
|
||||
" });\n" +
|
||||
"}"
|
||||
);
|
||||
|
||||
// char[]
|
||||
ctxt.generateDeclaration("charArrayIterator",
|
||||
"private Iterator toIterator(final char[] a){\n" +
|
||||
" return (new Iterator() {\n" +
|
||||
" int index=0;\n" +
|
||||
" public boolean hasNext() {\n" +
|
||||
" return index < a.length;}\n" +
|
||||
" public Object next() {\n" +
|
||||
" return new Character(a[index++]);}\n" +
|
||||
" public void remove() {}\n" +
|
||||
" });\n" +
|
||||
"}"
|
||||
);
|
||||
|
||||
// short[]
|
||||
ctxt.generateDeclaration("shortArrayIterator",
|
||||
"private Iterator toIterator(final short[] a){\n" +
|
||||
" return (new Iterator() {\n" +
|
||||
" int index=0;\n" +
|
||||
" public boolean hasNext() {\n" +
|
||||
" return index < a.length;}\n" +
|
||||
" public Object next() {\n" +
|
||||
" return new Short(a[index++]);}\n" +
|
||||
" public void remove() {}\n" +
|
||||
" });\n" +
|
||||
"}"
|
||||
);
|
||||
|
||||
// int[]
|
||||
ctxt.generateDeclaration("intArrayIterator",
|
||||
"private Iterator toIterator(final int[] a){\n" +
|
||||
" return (new Iterator() {\n" +
|
||||
" int index=0;\n" +
|
||||
" public boolean hasNext() {\n" +
|
||||
" return index < a.length;}\n" +
|
||||
" public Object next() {\n" +
|
||||
" return new Integer(a[index++]);}\n" +
|
||||
" public void remove() {}\n" +
|
||||
" });\n" +
|
||||
"}"
|
||||
);
|
||||
|
||||
// long[]
|
||||
ctxt.generateDeclaration("longArrayIterator",
|
||||
"private Iterator toIterator(final long[] a){\n" +
|
||||
" return (new Iterator() {\n" +
|
||||
" int index=0;\n" +
|
||||
" public boolean hasNext() {\n" +
|
||||
" return index < a.length;}\n" +
|
||||
" public Object next() {\n" +
|
||||
" return new Long(a[index++]);}\n" +
|
||||
" public void remove() {}\n" +
|
||||
" });\n" +
|
||||
"}"
|
||||
);
|
||||
|
||||
// float[]
|
||||
ctxt.generateDeclaration("floatArrayIterator",
|
||||
"private Iterator toIterator(final float[] a){\n" +
|
||||
" return (new Iterator() {\n" +
|
||||
" int index=0;\n" +
|
||||
" public boolean hasNext() {\n" +
|
||||
" return index < a.length;}\n" +
|
||||
" public Object next() {\n" +
|
||||
" return new Float(a[index++]);}\n" +
|
||||
" public void remove() {}\n" +
|
||||
" });\n" +
|
||||
"}"
|
||||
);
|
||||
|
||||
// double[]
|
||||
ctxt.generateDeclaration("doubleArrayIterator",
|
||||
"private Iterator toIterator(final double[] a){\n" +
|
||||
" return (new Iterator() {\n" +
|
||||
" int index=0;\n" +
|
||||
" public boolean hasNext() {\n" +
|
||||
" return index < a.length;}\n" +
|
||||
" public Object next() {\n" +
|
||||
" return new Double(a[index++]);}\n" +
|
||||
" public void remove() {}\n" +
|
||||
" });\n" +
|
||||
"}"
|
||||
);
|
||||
|
||||
// Enumeration
|
||||
ctxt.generateDeclaration("enumIterator",
|
||||
"private Iterator toIterator(final Enumeration e){\n" +
|
||||
" return (new Iterator() {\n" +
|
||||
" public boolean hasNext() {\n" +
|
||||
" return e.hasMoreElements();}\n" +
|
||||
" public Object next() {\n" +
|
||||
" return e.nextElement();}\n" +
|
||||
" public void remove() {}\n" +
|
||||
" });\n" +
|
||||
"}"
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
-119
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* 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.tagplugins.jstl.core;
|
||||
|
||||
import org.apache.jasper.compiler.tagplugin.TagPlugin;
|
||||
import org.apache.jasper.compiler.tagplugin.TagPluginContext;
|
||||
|
||||
public class ForTokens implements TagPlugin {
|
||||
|
||||
public void doTag(TagPluginContext ctxt) {
|
||||
boolean hasVar, hasVarStatus, hasBegin, hasEnd, hasStep;
|
||||
|
||||
//init the flags
|
||||
hasVar = ctxt.isAttributeSpecified("var");
|
||||
hasVarStatus = ctxt.isAttributeSpecified("varStatus");
|
||||
hasBegin = ctxt.isAttributeSpecified("begin");
|
||||
hasEnd = ctxt.isAttributeSpecified("end");
|
||||
hasStep = ctxt.isAttributeSpecified("step");
|
||||
|
||||
if(hasVarStatus){
|
||||
ctxt.dontUseTagPlugin();
|
||||
return;
|
||||
}
|
||||
|
||||
//define all the temp variables' names
|
||||
String itemsName = ctxt.getTemporaryVariableName();
|
||||
String delimsName = ctxt.getTemporaryVariableName();
|
||||
String stName = ctxt.getTemporaryVariableName();
|
||||
String beginName = ctxt.getTemporaryVariableName();
|
||||
String endName = ctxt.getTemporaryVariableName();
|
||||
String stepName = ctxt.getTemporaryVariableName();
|
||||
String index = ctxt.getTemporaryVariableName();
|
||||
String temp = ctxt.getTemporaryVariableName();
|
||||
String tokensCountName = ctxt.getTemporaryVariableName();
|
||||
|
||||
//get the value of the "items" attribute
|
||||
ctxt.generateJavaSource("String " + itemsName + " = (String)");
|
||||
ctxt.generateAttribute("items");
|
||||
ctxt.generateJavaSource(";");
|
||||
|
||||
//get the value of the "delim" attribute
|
||||
ctxt.generateJavaSource("String " + delimsName + " = (String)");
|
||||
ctxt.generateAttribute("delims");
|
||||
ctxt.generateJavaSource(";");
|
||||
|
||||
//new a StringTokenizer Object according to the "items" and the "delim"
|
||||
ctxt.generateJavaSource("java.util.StringTokenizer " + stName + " = " +
|
||||
"new java.util.StringTokenizer(" + itemsName + ", " + delimsName + ");");
|
||||
|
||||
//if "begin" specified, move the token to the "begin" place
|
||||
//and record the begin index. default begin place is 0.
|
||||
ctxt.generateJavaSource("int " + tokensCountName + " = " + stName + ".countTokens();");
|
||||
if(hasBegin){
|
||||
ctxt.generateJavaSource("int " + beginName + " = " );
|
||||
ctxt.generateAttribute("begin");
|
||||
ctxt.generateJavaSource(";");
|
||||
ctxt.generateJavaSource("for(int " + index + " = 0; " + index + " < " + beginName + " && " + stName + ".hasMoreTokens(); " + index + "++, " + stName + ".nextToken()){}");
|
||||
}else{
|
||||
ctxt.generateJavaSource("int " + beginName + " = 0;");
|
||||
}
|
||||
|
||||
//when "end" is specified, if the "end" is more than the last index,
|
||||
//record the end place as the last index, otherwise, record it as "end";
|
||||
//default end place is the last index
|
||||
if(hasEnd){
|
||||
ctxt.generateJavaSource("int " + endName + " = 0;" );
|
||||
ctxt.generateJavaSource("if((" + tokensCountName + " - 1) < ");
|
||||
ctxt.generateAttribute("end");
|
||||
ctxt.generateJavaSource("){");
|
||||
ctxt.generateJavaSource(" " + endName + " = " + tokensCountName + " - 1;");
|
||||
ctxt.generateJavaSource("}else{");
|
||||
ctxt.generateJavaSource(" " + endName + " = ");
|
||||
ctxt.generateAttribute("end");
|
||||
ctxt.generateJavaSource(";}");
|
||||
}else{
|
||||
ctxt.generateJavaSource("int " + endName + " = " + tokensCountName + " - 1;");
|
||||
}
|
||||
|
||||
//get the step value from "step" if specified.
|
||||
//default step value is 1.
|
||||
if(hasStep){
|
||||
ctxt.generateJavaSource("int " + stepName + " = " );
|
||||
ctxt.generateAttribute("step");
|
||||
ctxt.generateJavaSource(";");
|
||||
}else{
|
||||
ctxt.generateJavaSource("int " + stepName + " = 1;");
|
||||
}
|
||||
|
||||
//the loop
|
||||
ctxt.generateJavaSource("for(int " + index + " = " + beginName + "; " + index + " <= " + endName + "; " + index + "++){");
|
||||
ctxt.generateJavaSource(" String " + temp + " = " + stName + ".nextToken();");
|
||||
ctxt.generateJavaSource(" if(((" + index + " - " + beginName + ") % " + stepName + ") == 0){");
|
||||
//if var specified, put the current token into the attribute "var" defines.
|
||||
if(hasVar){
|
||||
String strVar = ctxt.getConstantAttribute("var");
|
||||
ctxt.generateJavaSource(" pageContext.setAttribute(\"" + strVar + "\", " + temp + ");");
|
||||
}
|
||||
ctxt.generateBody();
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource("}");
|
||||
}
|
||||
|
||||
}
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* 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.tagplugins.jstl.core;
|
||||
|
||||
import org.apache.jasper.compiler.tagplugin.*;
|
||||
|
||||
public final class If implements TagPlugin {
|
||||
|
||||
public void doTag(TagPluginContext ctxt) {
|
||||
String condV = ctxt.getTemporaryVariableName();
|
||||
ctxt.generateJavaSource("boolean " + condV + "=");
|
||||
ctxt.generateAttribute("test");
|
||||
ctxt.generateJavaSource(";");
|
||||
if (ctxt.isAttributeSpecified("var")) {
|
||||
String scope = "PageContext.PAGE_SCOPE";
|
||||
if (ctxt.isAttributeSpecified("scope")) {
|
||||
String scopeStr = ctxt.getConstantAttribute("scope");
|
||||
if ("request".equals(scopeStr)) {
|
||||
scope = "PageContext.REQUEST_SCOPE";
|
||||
} else if ("session".equals(scopeStr)) {
|
||||
scope = "PageContext.SESSION_SCOPE";
|
||||
} else if ("application".equals(scopeStr)) {
|
||||
scope = "PageContext.APPLICATION_SCOPE";
|
||||
}
|
||||
}
|
||||
ctxt.generateJavaSource("_jspx_page_context.setAttribute(");
|
||||
ctxt.generateAttribute("var");
|
||||
ctxt.generateJavaSource(", new Boolean(" + condV + ")," + scope + ");");
|
||||
}
|
||||
ctxt.generateJavaSource("if (" + condV + "){");
|
||||
ctxt.generateBody();
|
||||
ctxt.generateJavaSource("}");
|
||||
}
|
||||
}
|
||||
-382
@@ -1,382 +0,0 @@
|
||||
/*
|
||||
* 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.tagplugins.jstl.core;
|
||||
|
||||
import org.apache.jasper.compiler.tagplugin.TagPlugin;
|
||||
import org.apache.jasper.compiler.tagplugin.TagPluginContext;
|
||||
import org.apache.jasper.tagplugins.jstl.Util;
|
||||
|
||||
public class Import implements TagPlugin {
|
||||
|
||||
public void doTag(TagPluginContext ctxt) {
|
||||
boolean hasContext, hasVar, hasScope, hasVarReader, hasCharEncoding;
|
||||
|
||||
//flags
|
||||
hasContext = ctxt.isAttributeSpecified("context");
|
||||
hasVar = ctxt.isAttributeSpecified("var");
|
||||
hasScope = ctxt.isAttributeSpecified("scope");
|
||||
hasVarReader = ctxt.isAttributeSpecified("varReader");
|
||||
hasCharEncoding = ctxt.isAttributeSpecified("charEncoding");
|
||||
|
||||
//variables' names
|
||||
String urlName = ctxt.getTemporaryVariableName();
|
||||
String contextName = ctxt.getTemporaryVariableName();
|
||||
String iauName = ctxt.getTemporaryVariableName(); // is absolute url
|
||||
String urlObjName = ctxt.getTemporaryVariableName(); //URL object
|
||||
String ucName = ctxt.getTemporaryVariableName(); //URLConnection
|
||||
String inputStreamName = ctxt.getTemporaryVariableName();
|
||||
String tempReaderName = ctxt.getTemporaryVariableName();
|
||||
String tempReaderName2 = ctxt.getTemporaryVariableName();
|
||||
String charSetName = ctxt.getTemporaryVariableName();
|
||||
String charEncodingName = ctxt.getTemporaryVariableName();
|
||||
String contentTypeName = ctxt.getTemporaryVariableName();
|
||||
String varReaderName = ctxt.getTemporaryVariableName();
|
||||
String servletContextName = ctxt.getTemporaryVariableName();
|
||||
String servletPathName = ctxt.getTemporaryVariableName();
|
||||
String requestDispatcherName = ctxt.getTemporaryVariableName();
|
||||
String irwName = ctxt.getTemporaryVariableName(); //ImportResponseWrapper name
|
||||
String brName = ctxt.getTemporaryVariableName(); //BufferedReader name
|
||||
String sbName = ctxt.getTemporaryVariableName(); //StringBuffer name
|
||||
String tempStringName = ctxt.getTemporaryVariableName();
|
||||
|
||||
//is absolute url
|
||||
ctxt.generateJavaSource("boolean " + iauName + ";");
|
||||
|
||||
//get the url value
|
||||
ctxt.generateJavaSource("String " + urlName + " = ");
|
||||
ctxt.generateAttribute("url");
|
||||
ctxt.generateJavaSource(";");
|
||||
|
||||
//validate the url
|
||||
ctxt.generateJavaSource("if(" + urlName + " == null || " + urlName + ".equals(\"\")){");
|
||||
ctxt.generateJavaSource(" throw new JspTagException(\"The \\\"url\\\" attribute " +
|
||||
"illegally evaluated to \\\"null\\\" or \\\"\\\" in <import>\");");
|
||||
ctxt.generateJavaSource("}");
|
||||
|
||||
//initialize the is_absolute_url
|
||||
ctxt.generateJavaSource(iauName + " = " +
|
||||
"org.apache.jasper.tagplugins.jstl.Util.isAbsoluteUrl(" + urlName + ");");
|
||||
|
||||
//validate the context
|
||||
if(hasContext){
|
||||
|
||||
ctxt.generateJavaSource("String " + contextName + " = ");
|
||||
ctxt.generateAttribute("context");
|
||||
ctxt.generateJavaSource(";");
|
||||
|
||||
ctxt.generateJavaSource("if((!" + contextName + ".startsWith(\"/\")) " +
|
||||
"|| (!" + urlName + ".startsWith(\"/\"))){");
|
||||
ctxt.generateJavaSource(" throw new JspTagException" +
|
||||
"(\"In URL tags, when the \\\"context\\\" attribute is specified, " +
|
||||
"values of both \\\"context\\\" and \\\"url\\\" must start with \\\"/\\\".\");");
|
||||
ctxt.generateJavaSource("}");
|
||||
|
||||
}
|
||||
|
||||
//define charset
|
||||
ctxt.generateJavaSource("String " + charSetName + " = null;");
|
||||
|
||||
//if the charEncoding attribute is specified
|
||||
if(hasCharEncoding){
|
||||
|
||||
//initialize the charEncoding
|
||||
ctxt.generateJavaSource("String " + charEncodingName + " = ");
|
||||
ctxt.generateAttribute("charEncoding");
|
||||
ctxt.generateJavaSource(";");
|
||||
|
||||
//assign appropriate value tp the charset
|
||||
ctxt.generateJavaSource("if(null != " + charEncodingName + " " +
|
||||
"&& !" + charEncodingName + ".equals(\"\")){");
|
||||
ctxt.generateJavaSource(" " + charSetName + " = "
|
||||
+ charEncodingName + ";");
|
||||
ctxt.generateJavaSource("}");
|
||||
}
|
||||
|
||||
//reshape the url string
|
||||
ctxt.generateJavaSource("if(!"+iauName+"){");
|
||||
ctxt.generateJavaSource(" if(!" + urlName + ".startsWith(\"/\")){");
|
||||
ctxt.generateJavaSource(" String " + servletPathName + " = " +
|
||||
"((HttpServletRequest)pageContext.getRequest()).getServletPath();");
|
||||
ctxt.generateJavaSource(" " + urlName + " = "
|
||||
+ servletPathName + ".substring(0," + servletPathName + ".lastIndexOf('/')) + '/' + " + urlName + ";");
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource("}");
|
||||
|
||||
//if the varReader attribute specified
|
||||
if(hasVarReader){
|
||||
|
||||
//get the String value of varReader
|
||||
ctxt.generateJavaSource("String " + varReaderName + " = ");
|
||||
ctxt.generateAttribute("varReader");
|
||||
ctxt.generateJavaSource(";");
|
||||
|
||||
//if the url is absolute url
|
||||
ctxt.generateJavaSource("if(" + iauName + "){");
|
||||
|
||||
//get the content of the target
|
||||
ctxt.generateJavaSource(" java.net.URL " + urlObjName + " = new java.net.URL(" + urlName + ");");
|
||||
ctxt.generateJavaSource(" java.net.URLConnection " + ucName + " = "
|
||||
+ urlObjName + ".openConnection();");
|
||||
ctxt.generateJavaSource(" java.io.InputStream " + inputStreamName + " = "
|
||||
+ ucName + ".getInputStream();");
|
||||
|
||||
ctxt.generateJavaSource(" if(" + charSetName + " == null){");
|
||||
ctxt.generateJavaSource(" String " + contentTypeName + " = "
|
||||
+ ucName + ".getContentType();");
|
||||
ctxt.generateJavaSource(" if(null != " + contentTypeName + "){");
|
||||
ctxt.generateJavaSource(" " + charSetName + " = " +
|
||||
"org.apache.jasper.tagplugins.jstl.Util.getContentTypeAttribute(" + contentTypeName + ", \"charset\");");
|
||||
ctxt.generateJavaSource(" if(" + charSetName + " == null) "
|
||||
+ charSetName + " = org.apache.jasper.tagplugins.jstl.Util.DEFAULT_ENCODING;");
|
||||
ctxt.generateJavaSource(" }else{");
|
||||
ctxt.generateJavaSource(" " + charSetName + " = org.apache.jasper.tagplugins.jstl.Util.DEFAULT_ENCODING;");
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource(" }");
|
||||
|
||||
if(!hasCharEncoding){
|
||||
ctxt.generateJavaSource(" String " + contentTypeName + " = " + ucName + ".getContentType();");
|
||||
}
|
||||
|
||||
//define the Reader
|
||||
ctxt.generateJavaSource(" java.io.Reader " + tempReaderName + " = null;");
|
||||
|
||||
//initialize the Reader object
|
||||
ctxt.generateJavaSource(" try{");
|
||||
ctxt.generateJavaSource(" " + tempReaderName + " = new java.io.InputStreamReader(" + inputStreamName + ", " + charSetName + ");");
|
||||
ctxt.generateJavaSource(" }catch(Exception ex){");
|
||||
ctxt.generateJavaSource(" " + tempReaderName + " = new java.io.InputStreamReader(" + inputStreamName + ", org.apache.jasper.tagplugins.jstl.Util.DEFAULT_ENCODING);");
|
||||
ctxt.generateJavaSource(" }");
|
||||
|
||||
//validate the response
|
||||
ctxt.generateJavaSource(" if(" + ucName + " instanceof java.net.HttpURLConnection){");
|
||||
ctxt.generateJavaSource(" int status = ((java.net.HttpURLConnection) " + ucName + ").getResponseCode();");
|
||||
ctxt.generateJavaSource(" if(status < 200 || status > 299){");
|
||||
ctxt.generateJavaSource(" throw new JspTagException(status + \" \" + " + urlName + ");");
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource(" }");
|
||||
|
||||
//set attribute in the page context scope
|
||||
ctxt.generateJavaSource(" pageContext.setAttribute(" + varReaderName + ", " + tempReaderName + ");");
|
||||
|
||||
//if the url is relative
|
||||
ctxt.generateJavaSource("}else{");
|
||||
|
||||
//if the url is relative, http request is needed
|
||||
ctxt.generateJavaSource(" if (!(pageContext.getRequest() instanceof HttpServletRequest " +
|
||||
"&& pageContext.getResponse() instanceof HttpServletResponse)){");
|
||||
ctxt.generateJavaSource(" throw new JspTagException(\"Relative <import> from non-HTTP request not allowed\");");
|
||||
ctxt.generateJavaSource(" }");
|
||||
|
||||
//get the servlet context of the context defined in the context attribute
|
||||
ctxt.generateJavaSource(" ServletContext " + servletContextName + " = null;");
|
||||
if(hasContext){
|
||||
ctxt.generateJavaSource(" if(null != " + contextName + "){");
|
||||
ctxt.generateJavaSource(" " + servletContextName + " = pageContext.getServletContext().getContext(" + contextName + ");" );
|
||||
ctxt.generateJavaSource(" }else{");
|
||||
ctxt.generateJavaSource(" " + servletContextName + " = pageContext.getServletContext();");
|
||||
ctxt.generateJavaSource(" }");
|
||||
}else{
|
||||
ctxt.generateJavaSource(" " + servletContextName + " = pageContext.getServletContext();");
|
||||
}
|
||||
|
||||
//
|
||||
ctxt.generateJavaSource(" if(" + servletContextName + " == null){");
|
||||
if(hasContext){
|
||||
ctxt.generateJavaSource(" throw new JspTagException(\"Unable to get RequestDispatcher for Context: \\\" \"+" + contextName + "+\" \\\" and URL: \\\" \" +" + urlName + "+ \" \\\". Verify values and/or enable cross context access.\");");
|
||||
}else{
|
||||
ctxt.generateJavaSource(" throw new JspTagException(\"Unable to get RequestDispatcher for URL: \\\" \" +" + urlName + "+ \" \\\". Verify values and/or enable cross context access.\");");
|
||||
}
|
||||
ctxt.generateJavaSource(" }");
|
||||
|
||||
//get the request dispatcher
|
||||
ctxt.generateJavaSource(" RequestDispatcher " + requestDispatcherName + " = " + servletContextName + ".getRequestDispatcher(org.apache.jasper.tagplugins.jstl.Util.stripSession("+urlName+"));");
|
||||
ctxt.generateJavaSource(" if(" + requestDispatcherName + " == null) throw new JspTagException(org.apache.jasper.tagplugins.jstl.Util.stripSession("+urlName+"));");
|
||||
|
||||
//initialize a ImportResponseWrapper to include the resource
|
||||
ctxt.generateJavaSource(" org.apache.jasper.tagplugins.jstl.Util.ImportResponseWrapper " + irwName + " = new org.apache.jasper.tagplugins.jstl.Util.ImportResponseWrapper((HttpServletResponse) pageContext.getResponse());");
|
||||
ctxt.generateJavaSource(" if(" + charSetName + " == null){");
|
||||
ctxt.generateJavaSource(" " + charSetName + " = org.apache.jasper.tagplugins.jstl.Util.DEFAULT_ENCODING;");
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource(" " + irwName + ".setCharEncoding(" + charSetName + ");");
|
||||
ctxt.generateJavaSource(" try{");
|
||||
ctxt.generateJavaSource(" " + requestDispatcherName + ".include(pageContext.getRequest(), " + irwName + ");");
|
||||
ctxt.generateJavaSource(" }catch(java.io.IOException ex){");
|
||||
ctxt.generateJavaSource(" throw new JspException(ex);");
|
||||
ctxt.generateJavaSource(" }catch(RuntimeException ex){");
|
||||
ctxt.generateJavaSource(" throw new JspException(ex);");
|
||||
ctxt.generateJavaSource(" }catch(ServletException ex){");
|
||||
ctxt.generateJavaSource(" Throwable rc = ex.getRootCause();");
|
||||
ctxt.generateJavaSource(" if (rc == null)");
|
||||
ctxt.generateJavaSource(" throw new JspException(ex);");
|
||||
ctxt.generateJavaSource(" else");
|
||||
ctxt.generateJavaSource(" throw new JspException(rc);");
|
||||
ctxt.generateJavaSource(" }");
|
||||
|
||||
//validate the response status
|
||||
ctxt.generateJavaSource(" if(" + irwName + ".getStatus() < 200 || " + irwName + ".getStatus() > 299){");
|
||||
ctxt.generateJavaSource(" throw new JspTagException(" + irwName + ".getStatus()+\" \" + org.apache.jasper.tagplugins.jstl.Util.stripSession(" + urlName + "));");
|
||||
ctxt.generateJavaSource(" }");
|
||||
|
||||
//push in the page context
|
||||
ctxt.generateJavaSource(" java.io.Reader " + tempReaderName + " = new java.io.StringReader(" + irwName + ".getString());");
|
||||
ctxt.generateJavaSource(" pageContext.setAttribute(" + varReaderName + ", " + tempReaderName + ");");
|
||||
|
||||
ctxt.generateJavaSource("}");
|
||||
|
||||
//execute the body action
|
||||
ctxt.generateBody();
|
||||
|
||||
//close the reader
|
||||
ctxt.generateJavaSource("java.io.Reader " + tempReaderName2 + " = (java.io.Reader)pageContext.getAttribute(" + varReaderName + ");");
|
||||
ctxt.generateJavaSource("if(" + tempReaderName2 + " != null) " + tempReaderName2 + ".close();");
|
||||
ctxt.generateJavaSource("pageContext.removeAttribute(" + varReaderName + ",1);");
|
||||
}
|
||||
|
||||
//if the varReader is not specified
|
||||
else{
|
||||
|
||||
ctxt.generateJavaSource("pageContext.setAttribute(\"url_without_param\"," + urlName + ");");
|
||||
ctxt.generateBody();
|
||||
ctxt.generateJavaSource(urlName + " = (String)pageContext.getAttribute(\"url_without_param\");");
|
||||
ctxt.generateJavaSource("pageContext.removeAttribute(\"url_without_param\");");
|
||||
String strScope = "page";
|
||||
if(hasScope){
|
||||
strScope = ctxt.getConstantAttribute("scope");
|
||||
}
|
||||
int iScope = Util.getScope(strScope);
|
||||
|
||||
ctxt.generateJavaSource("String " + tempStringName + " = null;");
|
||||
|
||||
ctxt.generateJavaSource("if(" + iauName + "){");
|
||||
|
||||
//get the content of the target
|
||||
ctxt.generateJavaSource(" java.net.URL " + urlObjName + " = new java.net.URL(" + urlName + ");");
|
||||
ctxt.generateJavaSource(" java.net.URLConnection " + ucName + " = " + urlObjName + ".openConnection();");
|
||||
ctxt.generateJavaSource(" java.io.InputStream " + inputStreamName + " = " + ucName + ".getInputStream();");
|
||||
ctxt.generateJavaSource(" java.io.Reader " + tempReaderName + " = null;");
|
||||
|
||||
ctxt.generateJavaSource(" if(" + charSetName + " == null){");
|
||||
ctxt.generateJavaSource(" String " + contentTypeName + " = "
|
||||
+ ucName + ".getContentType();");
|
||||
ctxt.generateJavaSource(" if(null != " + contentTypeName + "){");
|
||||
ctxt.generateJavaSource(" " + charSetName + " = " +
|
||||
"org.apache.jasper.tagplugins.jstl.Util.getContentTypeAttribute(" + contentTypeName + ", \"charset\");");
|
||||
ctxt.generateJavaSource(" if(" + charSetName + " == null) "
|
||||
+ charSetName + " = org.apache.jasper.tagplugins.jstl.Util.DEFAULT_ENCODING;");
|
||||
ctxt.generateJavaSource(" }else{");
|
||||
ctxt.generateJavaSource(" " + charSetName + " = org.apache.jasper.tagplugins.jstl.Util.DEFAULT_ENCODING;");
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource(" }");
|
||||
|
||||
ctxt.generateJavaSource(" try{");
|
||||
ctxt.generateJavaSource(" " + tempReaderName + " = new java.io.InputStreamReader(" + inputStreamName + "," + charSetName + ");");
|
||||
ctxt.generateJavaSource(" }catch(Exception ex){");
|
||||
//ctxt.generateJavaSource(" throw new JspTagException(ex.toString());");
|
||||
ctxt.generateJavaSource(" " + tempReaderName + " = new java.io.InputStreamReader(" + inputStreamName + ",org.apache.jasper.tagplugins.jstl.Util.DEFAULT_ENCODING);");
|
||||
ctxt.generateJavaSource(" }");
|
||||
|
||||
//validate the response
|
||||
ctxt.generateJavaSource(" if(" + ucName + " instanceof java.net.HttpURLConnection){");
|
||||
ctxt.generateJavaSource(" int status = ((java.net.HttpURLConnection) " + ucName + ").getResponseCode();");
|
||||
ctxt.generateJavaSource(" if(status < 200 || status > 299){");
|
||||
ctxt.generateJavaSource(" throw new JspTagException(status + \" \" + " + urlName + ");");
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource(" }");
|
||||
|
||||
ctxt.generateJavaSource(" java.io.BufferedReader " + brName + " = new java.io.BufferedReader(" + tempReaderName + ");");
|
||||
ctxt.generateJavaSource(" StringBuffer " + sbName + " = new StringBuffer();");
|
||||
String index = ctxt.getTemporaryVariableName();
|
||||
ctxt.generateJavaSource(" int " + index + ";");
|
||||
ctxt.generateJavaSource(" while(("+index+" = "+brName+".read()) != -1) "+sbName+".append((char)"+index+");");
|
||||
ctxt.generateJavaSource(" " + tempStringName + " = " +sbName + ".toString();");
|
||||
|
||||
ctxt.generateJavaSource("}else{");
|
||||
|
||||
//if the url is relative, http request is needed.
|
||||
ctxt.generateJavaSource(" if (!(pageContext.getRequest() instanceof HttpServletRequest " +
|
||||
"&& pageContext.getResponse() instanceof HttpServletResponse)){");
|
||||
ctxt.generateJavaSource(" throw new JspTagException(\"Relative <import> from non-HTTP request not allowed\");");
|
||||
ctxt.generateJavaSource(" }");
|
||||
|
||||
//get the servlet context of the context defined in the context attribute
|
||||
ctxt.generateJavaSource(" ServletContext " + servletContextName + " = null;");
|
||||
if(hasContext){
|
||||
ctxt.generateJavaSource(" if(null != " + contextName + "){");
|
||||
ctxt.generateJavaSource(" " + servletContextName + " = pageContext.getServletContext().getContext(" + contextName + ");" );
|
||||
ctxt.generateJavaSource(" }else{");
|
||||
ctxt.generateJavaSource(" " + servletContextName + " = pageContext.getServletContext();");
|
||||
ctxt.generateJavaSource(" }");
|
||||
}else{
|
||||
ctxt.generateJavaSource(" " + servletContextName + " = pageContext.getServletContext();");
|
||||
}
|
||||
|
||||
//
|
||||
ctxt.generateJavaSource(" if(" + servletContextName + " == null){");
|
||||
if(hasContext){
|
||||
ctxt.generateJavaSource(" throw new JspTagException(\"Unable to get RequestDispatcher for Context: \\\" \" +" + contextName + "+ \" \\\" and URL: \\\" \" +" + urlName + "+ \" \\\". Verify values and/or enable cross context access.\");");
|
||||
}else{
|
||||
ctxt.generateJavaSource(" throw new JspTagException(\"Unable to get RequestDispatcher for URL: \\\" \" +" + urlName + "+ \" \\\". Verify values and/or enable cross context access.\");");
|
||||
}
|
||||
ctxt.generateJavaSource(" }");
|
||||
|
||||
//get the request dispatcher
|
||||
ctxt.generateJavaSource(" RequestDispatcher " + requestDispatcherName + " = " + servletContextName + ".getRequestDispatcher(org.apache.jasper.tagplugins.jstl.Util.stripSession("+urlName+"));");
|
||||
ctxt.generateJavaSource(" if(" + requestDispatcherName + " == null) throw new JspTagException(org.apache.jasper.tagplugins.jstl.Util.stripSession("+urlName+"));");
|
||||
|
||||
//initialize a ImportResponseWrapper to include the resource
|
||||
ctxt.generateJavaSource(" org.apache.jasper.tagplugins.jstl.Util.ImportResponseWrapper " + irwName + " = new org.apache.jasper.tagplugins.jstl.Util.ImportResponseWrapper((HttpServletResponse) pageContext.getResponse());");
|
||||
ctxt.generateJavaSource(" if(" + charSetName + " == null){");
|
||||
ctxt.generateJavaSource(" " + charSetName + " = org.apache.jasper.tagplugins.jstl.Util.DEFAULT_ENCODING;");
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource(" " + irwName + ".setCharEncoding(" + charSetName + ");");
|
||||
ctxt.generateJavaSource(" try{");
|
||||
ctxt.generateJavaSource(" " + requestDispatcherName + ".include(pageContext.getRequest(), " + irwName + ");");
|
||||
ctxt.generateJavaSource(" }catch(java.io.IOException ex){");
|
||||
ctxt.generateJavaSource(" throw new JspException(ex);");
|
||||
ctxt.generateJavaSource(" }catch(RuntimeException ex){");
|
||||
ctxt.generateJavaSource(" throw new JspException(ex);");
|
||||
ctxt.generateJavaSource(" }catch(ServletException ex){");
|
||||
ctxt.generateJavaSource(" Throwable rc = ex.getRootCause();");
|
||||
ctxt.generateJavaSource(" if (rc == null)");
|
||||
ctxt.generateJavaSource(" throw new JspException(ex);");
|
||||
ctxt.generateJavaSource(" else");
|
||||
ctxt.generateJavaSource(" throw new JspException(rc);");
|
||||
ctxt.generateJavaSource(" }");
|
||||
|
||||
//validate the response status
|
||||
ctxt.generateJavaSource(" if(" + irwName + ".getStatus() < 200 || " + irwName + ".getStatus() > 299){");
|
||||
ctxt.generateJavaSource(" throw new JspTagException(" + irwName + ".getStatus()+\" \" + org.apache.jasper.tagplugins.jstl.Util.stripSession(" + urlName + "));");
|
||||
ctxt.generateJavaSource(" }");
|
||||
|
||||
ctxt.generateJavaSource(" " + tempStringName + " = " + irwName + ".getString();");
|
||||
|
||||
ctxt.generateJavaSource("}");
|
||||
|
||||
if(hasVar){
|
||||
String strVar = ctxt.getConstantAttribute("var");
|
||||
ctxt.generateJavaSource("pageContext.setAttribute(\""+strVar+"\"," + tempStringName + "," + iScope + ");");
|
||||
}else{
|
||||
ctxt.generateJavaSource("pageContext.getOut().print(" + tempStringName + ");");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* 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.tagplugins.jstl.core;
|
||||
|
||||
import org.apache.jasper.compiler.tagplugin.*;
|
||||
|
||||
public final class Otherwise implements TagPlugin {
|
||||
|
||||
public void doTag(TagPluginContext ctxt) {
|
||||
|
||||
// See When.java for the reason whey "}" is need at the beginng and
|
||||
// not at the end.
|
||||
ctxt.generateJavaSource("} else {");
|
||||
ctxt.generateBody();
|
||||
}
|
||||
}
|
||||
-90
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* 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.tagplugins.jstl.core;
|
||||
|
||||
import org.apache.jasper.compiler.tagplugin.TagPlugin;
|
||||
import org.apache.jasper.compiler.tagplugin.TagPluginContext;
|
||||
|
||||
|
||||
public final class Out implements TagPlugin {
|
||||
|
||||
public void doTag(TagPluginContext ctxt) {
|
||||
|
||||
//these two data member are to indicate
|
||||
//whether the corresponding attribute is specified
|
||||
boolean hasDefault=false, hasEscapeXml=false;
|
||||
hasDefault = ctxt.isAttributeSpecified("default");
|
||||
hasEscapeXml = ctxt.isAttributeSpecified("escapeXml");
|
||||
|
||||
//strValName, strEscapeXmlName & strDefName are two variables' name
|
||||
//standing for value, escapeXml and default attribute
|
||||
String strValName = ctxt.getTemporaryVariableName();
|
||||
String strDefName = ctxt.getTemporaryVariableName();
|
||||
String strEscapeXmlName = ctxt.getTemporaryVariableName();
|
||||
|
||||
//according to the tag file, the value attribute is mandatory.
|
||||
ctxt.generateJavaSource("String " + strValName + " = null;");
|
||||
ctxt.generateJavaSource("if(");
|
||||
ctxt.generateAttribute("value");
|
||||
ctxt.generateJavaSource("!=null){");
|
||||
ctxt.generateJavaSource(" " + strValName + " = (");
|
||||
ctxt.generateAttribute("value");
|
||||
ctxt.generateJavaSource(").toString();");
|
||||
ctxt.generateJavaSource("}");
|
||||
|
||||
//initiate the strDefName with null.
|
||||
//if the default has been specified, then assign the value to it;
|
||||
ctxt.generateJavaSource("String " + strDefName + " = null;\n");
|
||||
if(hasDefault){
|
||||
ctxt.generateJavaSource("if(");
|
||||
ctxt.generateAttribute("default");
|
||||
ctxt.generateJavaSource(" != null){");
|
||||
ctxt.generateJavaSource(strDefName + " = (");
|
||||
ctxt.generateAttribute("default");
|
||||
ctxt.generateJavaSource(").toString();");
|
||||
ctxt.generateJavaSource("}");
|
||||
}
|
||||
|
||||
//initiate the strEscapeXmlName with true;
|
||||
//if the escapeXml is specified, assign the value to it;
|
||||
ctxt.generateJavaSource("boolean " + strEscapeXmlName + " = true;");
|
||||
if(hasEscapeXml){
|
||||
ctxt.generateJavaSource(strEscapeXmlName + " = Boolean.parseBoolean((");
|
||||
ctxt.generateAttribute("default");
|
||||
ctxt.generateJavaSource(").toString());");
|
||||
}
|
||||
|
||||
//main part.
|
||||
ctxt.generateJavaSource("if(null != " + strValName +"){");
|
||||
ctxt.generateJavaSource(" if(" + strEscapeXmlName + "){");
|
||||
ctxt.generateJavaSource(" " + strValName + " = org.apache.jasper.tagplugins.jstl.Util.escapeXml(" + strValName + ");");
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource(" out.write(" + strValName + ");");
|
||||
ctxt.generateJavaSource("}else{");
|
||||
ctxt.generateJavaSource(" if(null != " + strDefName + "){");
|
||||
ctxt.generateJavaSource(" if(" + strEscapeXmlName + "){");
|
||||
ctxt.generateJavaSource(" " + strDefName + " = org.apache.jasper.tagplugins.jstl.Util.escapeXml(" + strDefName + ");");
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource(" out.write(" + strDefName + ");");
|
||||
ctxt.generateJavaSource(" }else{");
|
||||
ctxt.generateBody();
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource("}");
|
||||
}
|
||||
}
|
||||
-77
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* 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.tagplugins.jstl.core;
|
||||
|
||||
import org.apache.jasper.compiler.tagplugin.TagPlugin;
|
||||
import org.apache.jasper.compiler.tagplugin.TagPluginContext;
|
||||
|
||||
public class Param implements TagPlugin {
|
||||
|
||||
public void doTag(TagPluginContext ctxt) {
|
||||
|
||||
//don't support the body content
|
||||
|
||||
//define names of all the temp variables
|
||||
String nameName = ctxt.getTemporaryVariableName();
|
||||
String valueName = ctxt.getTemporaryVariableName();
|
||||
String urlName = ctxt.getTemporaryVariableName();
|
||||
String encName = ctxt.getTemporaryVariableName();
|
||||
String index = ctxt.getTemporaryVariableName();
|
||||
|
||||
//if the param tag has no parents, throw a exception
|
||||
TagPluginContext parent = ctxt.getParentContext();
|
||||
if(parent == null){
|
||||
ctxt.generateJavaSource(" throw new JspTagExcption" +
|
||||
"(\"<param> outside <import> or <urlEncode>\");");
|
||||
return;
|
||||
}
|
||||
|
||||
//get the url string before adding this param
|
||||
ctxt.generateJavaSource("String " + urlName + " = " +
|
||||
"(String)pageContext.getAttribute(\"url_without_param\");");
|
||||
|
||||
//get the value of "name"
|
||||
ctxt.generateJavaSource("String " + nameName + " = ");
|
||||
ctxt.generateAttribute("name");
|
||||
ctxt.generateJavaSource(";");
|
||||
|
||||
//if the "name" is null then do nothing.
|
||||
//else add such string "name=value" to the url.
|
||||
//and the url should be encoded
|
||||
ctxt.generateJavaSource("if(" + nameName + " != null && !" + nameName + ".equals(\"\")){");
|
||||
ctxt.generateJavaSource(" String " + valueName + " = ");
|
||||
ctxt.generateAttribute("value");
|
||||
ctxt.generateJavaSource(";");
|
||||
ctxt.generateJavaSource(" if(" + valueName + " == null) " + valueName + " = \"\";");
|
||||
ctxt.generateJavaSource(" String " + encName + " = pageContext.getResponse().getCharacterEncoding();");
|
||||
ctxt.generateJavaSource(" " + nameName + " = java.net.URLEncoder.encode(" + nameName + ", " + encName + ");");
|
||||
ctxt.generateJavaSource(" " + valueName + " = java.net.URLEncoder.encode(" + valueName + ", " + encName + ");");
|
||||
ctxt.generateJavaSource(" int " + index + ";");
|
||||
ctxt.generateJavaSource(" " + index + " = " + urlName + ".indexOf(\'?\');");
|
||||
//if the current param is the first one, add a "?" ahead of it
|
||||
//else add a "&" ahead of it
|
||||
ctxt.generateJavaSource(" if(" + index + " == -1){");
|
||||
ctxt.generateJavaSource(" " + urlName + " = " + urlName + " + \"?\" + " + nameName + " + \"=\" + " + valueName + ";");
|
||||
ctxt.generateJavaSource(" }else{");
|
||||
ctxt.generateJavaSource(" " + urlName + " = " + urlName + " + \"&\" + " + nameName + " + \"=\" + " + valueName + ";");
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource(" pageContext.setAttribute(\"url_without_param\"," + urlName + ");");
|
||||
ctxt.generateJavaSource("}");
|
||||
}
|
||||
}
|
||||
-83
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* 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.tagplugins.jstl.core;
|
||||
|
||||
import org.apache.jasper.compiler.tagplugin.TagPlugin;
|
||||
import org.apache.jasper.compiler.tagplugin.TagPluginContext;
|
||||
|
||||
public class Redirect implements TagPlugin {
|
||||
|
||||
public void doTag(TagPluginContext ctxt) {
|
||||
|
||||
//flag for the existence of the "context"
|
||||
boolean hasContext = ctxt.isAttributeSpecified("context");
|
||||
|
||||
//names of the temp variables
|
||||
String urlName = ctxt.getTemporaryVariableName();
|
||||
String contextName = ctxt.getTemporaryVariableName();
|
||||
String baseUrlName = ctxt.getTemporaryVariableName();
|
||||
String resultName = ctxt.getTemporaryVariableName();
|
||||
String responseName = ctxt.getTemporaryVariableName();
|
||||
|
||||
//get context
|
||||
ctxt.generateJavaSource("String " + contextName + " = null;");
|
||||
if(hasContext){
|
||||
ctxt.generateJavaSource(contextName + " = ");
|
||||
ctxt.generateAttribute("context");
|
||||
ctxt.generateJavaSource(";");
|
||||
}
|
||||
|
||||
//get the url
|
||||
ctxt.generateJavaSource("String " + urlName + " = ");
|
||||
ctxt.generateAttribute("url");
|
||||
ctxt.generateJavaSource(";");
|
||||
|
||||
//get the raw url according to "url" and "context"
|
||||
ctxt.generateJavaSource("String " + baseUrlName + " = " +
|
||||
"org.apache.jasper.tagplugins.jstl.Util.resolveUrl(" + urlName + ", " + contextName + ", pageContext);");
|
||||
ctxt.generateJavaSource("pageContext.setAttribute" +
|
||||
"(\"url_without_param\", " + baseUrlName + ");");
|
||||
|
||||
//add params
|
||||
ctxt.generateBody();
|
||||
|
||||
ctxt.generateJavaSource("String " + resultName + " = " +
|
||||
"(String)pageContext.getAttribute(\"url_without_param\");");
|
||||
ctxt.generateJavaSource("pageContext.removeAttribute" +
|
||||
"(\"url_without_param\");");
|
||||
|
||||
//get the response object
|
||||
ctxt.generateJavaSource("HttpServletResponse " + responseName + " = " +
|
||||
"((HttpServletResponse) pageContext.getResponse());");
|
||||
|
||||
//if the url is relative, encode it
|
||||
ctxt.generateJavaSource("if(!org.apache.jasper.tagplugins.jstl.Util.isAbsoluteUrl(" + resultName + ")){");
|
||||
ctxt.generateJavaSource(" " + resultName + " = "
|
||||
+ responseName + ".encodeRedirectURL(" + resultName + ");");
|
||||
ctxt.generateJavaSource("}");
|
||||
|
||||
//do redirect
|
||||
ctxt.generateJavaSource("try{");
|
||||
ctxt.generateJavaSource(" " + responseName + ".sendRedirect(" + resultName + ");");
|
||||
ctxt.generateJavaSource("}catch(java.io.IOException ex){");
|
||||
ctxt.generateJavaSource(" throw new JspTagException(ex.toString(), ex);");
|
||||
ctxt.generateJavaSource("}");
|
||||
}
|
||||
|
||||
}
|
||||
-45
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* 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.tagplugins.jstl.core;
|
||||
|
||||
import org.apache.jasper.compiler.tagplugin.TagPlugin;
|
||||
import org.apache.jasper.compiler.tagplugin.TagPluginContext;
|
||||
import org.apache.jasper.tagplugins.jstl.Util;
|
||||
|
||||
public class Remove implements TagPlugin {
|
||||
|
||||
public void doTag(TagPluginContext ctxt) {
|
||||
|
||||
//scope flag
|
||||
boolean hasScope = ctxt.isAttributeSpecified("scope");
|
||||
|
||||
//the value of the "var"
|
||||
String strVar = ctxt.getConstantAttribute("var");
|
||||
|
||||
//remove attribute from certain scope.
|
||||
//default scope is "page".
|
||||
if(hasScope){
|
||||
int iScope = Util.getScope(ctxt.getConstantAttribute("scope"));
|
||||
ctxt.generateJavaSource("pageContext.removeAttribute(\"" + strVar + "\"," + iScope + ");");
|
||||
}else{
|
||||
ctxt.generateJavaSource("pageContext.removeAttribute(\"" + strVar + "\");");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-167
@@ -1,167 +0,0 @@
|
||||
/*
|
||||
* 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.tagplugins.jstl.core;
|
||||
|
||||
import org.apache.jasper.compiler.tagplugin.TagPlugin;
|
||||
import org.apache.jasper.compiler.tagplugin.TagPluginContext;
|
||||
import org.apache.jasper.tagplugins.jstl.Util;
|
||||
|
||||
public class Set implements TagPlugin {
|
||||
|
||||
public void doTag(TagPluginContext ctxt) {
|
||||
|
||||
//the flags to indicate whether the attributes have been specified
|
||||
boolean hasValue = false, hasVar = false, hasScope = false,
|
||||
hasTarget = false;
|
||||
|
||||
//the scope name
|
||||
String strScope;
|
||||
//the id of the scope
|
||||
int iScope;
|
||||
|
||||
//initialize the flags
|
||||
hasValue = ctxt.isAttributeSpecified("value");
|
||||
hasVar = ctxt.isAttributeSpecified("var");
|
||||
hasScope = ctxt.isAttributeSpecified("scope");
|
||||
hasTarget = ctxt.isAttributeSpecified("target");
|
||||
|
||||
//the temp variables name
|
||||
String resultName = ctxt.getTemporaryVariableName();
|
||||
String targetName = ctxt.getTemporaryVariableName();
|
||||
String propertyName = ctxt.getTemporaryVariableName();
|
||||
|
||||
//initialize the "result" which will be assigned to the var or target.property
|
||||
ctxt.generateJavaSource("Object " + resultName + " = null;");
|
||||
if(hasValue){
|
||||
ctxt.generateJavaSource(resultName + " = ");
|
||||
ctxt.generateAttribute("value");
|
||||
ctxt.generateJavaSource(";");
|
||||
}else{
|
||||
ctxt.dontUseTagPlugin();
|
||||
return;
|
||||
}
|
||||
|
||||
//initialize the strScope
|
||||
if(hasScope){
|
||||
strScope = ctxt.getConstantAttribute("scope");
|
||||
}else{
|
||||
strScope = "page";
|
||||
}
|
||||
|
||||
//get the iScope according to the strScope
|
||||
iScope = Util.getScope(strScope);
|
||||
|
||||
//if the attribute var has been specified then assign the result to the var;
|
||||
if(hasVar){
|
||||
String strVar = ctxt.getConstantAttribute("var");
|
||||
ctxt.generateJavaSource("if(null != " + resultName + "){");
|
||||
ctxt.generateJavaSource(" pageContext.setAttribute(\"" + strVar + "\"," + resultName + "," + iScope + ");");
|
||||
ctxt.generateJavaSource("} else {");
|
||||
if(hasScope){
|
||||
ctxt.generateJavaSource(" pageContext.removeAttribute(\"" + strVar + "\"," + iScope + ");");
|
||||
}else{
|
||||
ctxt.generateJavaSource(" pageContext.removeAttribute(\"" + strVar + "\");");
|
||||
}
|
||||
ctxt.generateJavaSource("}");
|
||||
|
||||
//else assign the result to the target.property
|
||||
}else if(hasTarget){
|
||||
|
||||
//generate the temp variable name
|
||||
String pdName = ctxt.getTemporaryVariableName();
|
||||
String successFlagName = ctxt.getTemporaryVariableName();
|
||||
String index = ctxt.getTemporaryVariableName();
|
||||
String methodName = ctxt.getTemporaryVariableName();
|
||||
|
||||
//initialize the property
|
||||
ctxt.generateJavaSource("String " + propertyName + " = null;");
|
||||
ctxt.generateJavaSource("if(");
|
||||
ctxt.generateAttribute("property");
|
||||
ctxt.generateJavaSource(" != null){");
|
||||
ctxt.generateJavaSource(" " + propertyName + " = (");
|
||||
ctxt.generateAttribute("property");
|
||||
ctxt.generateJavaSource(").toString();");
|
||||
ctxt.generateJavaSource("}");
|
||||
|
||||
//initialize the target
|
||||
ctxt.generateJavaSource("Object " + targetName + " = ");
|
||||
ctxt.generateAttribute("target");
|
||||
ctxt.generateJavaSource(";");
|
||||
|
||||
//the target is ok
|
||||
ctxt.generateJavaSource("if(" + targetName + " != null){");
|
||||
|
||||
//if the target is a map, then put the result into the map with the key property
|
||||
ctxt.generateJavaSource(" if(" + targetName + " instanceof java.util.Map){");
|
||||
ctxt.generateJavaSource(" if(null != " + resultName + "){");
|
||||
ctxt.generateJavaSource(" ((java.util.Map) " + targetName + ").put(" + propertyName + "," + resultName + ");");
|
||||
ctxt.generateJavaSource(" }else{");
|
||||
ctxt.generateJavaSource(" ((java.util.Map) " + targetName + ").remove(" + propertyName + ");");
|
||||
ctxt.generateJavaSource(" }");
|
||||
|
||||
//else assign the result to the target.property
|
||||
ctxt.generateJavaSource(" }else{");
|
||||
ctxt.generateJavaSource(" try{");
|
||||
|
||||
//get all the property of the target
|
||||
ctxt.generateJavaSource(" java.beans.PropertyDescriptor " + pdName + "[] = java.beans.Introspector.getBeanInfo(" + targetName + ".getClass()).getPropertyDescriptors();");
|
||||
|
||||
//the success flag is to imply whether the assign is successful
|
||||
ctxt.generateJavaSource(" boolean " + successFlagName + " = false;");
|
||||
|
||||
//find the right property
|
||||
ctxt.generateJavaSource(" for(int " + index + "=0;" + index + "<" + pdName + ".length;" + index + "++){");
|
||||
ctxt.generateJavaSource(" if(" + pdName + "[" + index + "].getName().equals(" + propertyName + ")){");
|
||||
|
||||
//get the "set" method;
|
||||
ctxt.generateJavaSource(" java.lang.reflect.Method " + methodName + " = " + pdName + "[" + index + "].getWriteMethod();");
|
||||
ctxt.generateJavaSource(" if(null == " + methodName + "){");
|
||||
ctxt.generateJavaSource(" throw new JspException(\"No setter method in <set> for property \"+" + propertyName + ");");
|
||||
ctxt.generateJavaSource(" }");
|
||||
|
||||
//invoke the method through the reflection
|
||||
ctxt.generateJavaSource(" if(" + resultName + " != null){");
|
||||
ctxt.generateJavaSource(" " + methodName + ".invoke(" + targetName + ", new Object[]{(" + methodName + ".getParameterTypes()[0]).cast(" + resultName + ")});");
|
||||
ctxt.generateJavaSource(" }else{");
|
||||
ctxt.generateJavaSource(" " + methodName + ".invoke(" + targetName + ", new Object[]{null});");
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource(" " + successFlagName + " = true;");
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource(" if(!" + successFlagName + "){");
|
||||
ctxt.generateJavaSource(" throw new JspException(\"Invalid property in <set>:\"+" + propertyName + ");");
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource(" }");
|
||||
|
||||
//catch the el exception and throw it as a JspException
|
||||
ctxt.generateJavaSource(" catch (IllegalAccessException ex) {");
|
||||
ctxt.generateJavaSource(" throw new JspException(ex);");
|
||||
ctxt.generateJavaSource(" } catch (java.beans.IntrospectionException ex) {");
|
||||
ctxt.generateJavaSource(" throw new JspException(ex);");
|
||||
ctxt.generateJavaSource(" } catch (java.lang.reflect.InvocationTargetException ex) {");
|
||||
ctxt.generateJavaSource(" throw new JspException(ex);");
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource("}else{");
|
||||
ctxt.generateJavaSource(" throw new JspException();");
|
||||
ctxt.generateJavaSource("}");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-101
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* 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.tagplugins.jstl.core;
|
||||
|
||||
import org.apache.jasper.compiler.tagplugin.TagPlugin;
|
||||
import org.apache.jasper.compiler.tagplugin.TagPluginContext;
|
||||
import org.apache.jasper.tagplugins.jstl.Util;
|
||||
|
||||
public class Url implements TagPlugin {
|
||||
|
||||
public void doTag(TagPluginContext ctxt) {
|
||||
|
||||
//flags
|
||||
boolean hasVar, hasContext, hasScope;
|
||||
|
||||
//init flags
|
||||
hasVar = ctxt.isAttributeSpecified("var");
|
||||
hasContext = ctxt.isAttributeSpecified("context");
|
||||
hasScope = ctxt.isAttributeSpecified("scope");
|
||||
|
||||
//define name of the temp variables
|
||||
String valueName = ctxt.getTemporaryVariableName();
|
||||
String contextName = ctxt.getTemporaryVariableName();
|
||||
String baseUrlName = ctxt.getTemporaryVariableName();
|
||||
String resultName = ctxt.getTemporaryVariableName();
|
||||
String responseName = ctxt.getTemporaryVariableName();
|
||||
|
||||
//get the scope
|
||||
String strScope = "page";
|
||||
if(hasScope){
|
||||
strScope = ctxt.getConstantAttribute("scope");
|
||||
}
|
||||
int iScope = Util.getScope(strScope);
|
||||
|
||||
//get the value
|
||||
ctxt.generateJavaSource("String " + valueName + " = ");
|
||||
ctxt.generateAttribute("value");
|
||||
ctxt.generateJavaSource(";");
|
||||
|
||||
//get the context
|
||||
ctxt.generateJavaSource("String " + contextName + " = null;");
|
||||
if(hasContext){
|
||||
ctxt.generateJavaSource(contextName + " = ");
|
||||
ctxt.generateAttribute("context");
|
||||
ctxt.generateJavaSource(";");
|
||||
}
|
||||
|
||||
//get the raw url
|
||||
ctxt.generateJavaSource("String " + baseUrlName + " = " +
|
||||
"org.apache.jasper.tagplugins.jstl.Util.resolveUrl(" + valueName + ", " + contextName + ", pageContext);");
|
||||
ctxt.generateJavaSource("pageContext.setAttribute" +
|
||||
"(\"url_without_param\", " + baseUrlName + ");");
|
||||
|
||||
//add params
|
||||
ctxt.generateBody();
|
||||
|
||||
ctxt.generateJavaSource("String " + resultName + " = " +
|
||||
"(String)pageContext.getAttribute(\"url_without_param\");");
|
||||
ctxt.generateJavaSource("pageContext.removeAttribute(\"url_without_param\");");
|
||||
|
||||
//if the url is relative, encode it
|
||||
ctxt.generateJavaSource("if(!org.apache.jasper.tagplugins.jstl.Util.isAbsoluteUrl(" + resultName + ")){");
|
||||
ctxt.generateJavaSource(" HttpServletResponse " + responseName + " = " +
|
||||
"((HttpServletResponse) pageContext.getResponse());");
|
||||
ctxt.generateJavaSource(" " + resultName + " = "
|
||||
+ responseName + ".encodeURL(" + resultName + ");");
|
||||
ctxt.generateJavaSource("}");
|
||||
|
||||
//if "var" is specified, the url string store in the attribute var defines
|
||||
if(hasVar){
|
||||
String strVar = ctxt.getConstantAttribute("var");
|
||||
ctxt.generateJavaSource("pageContext.setAttribute" +
|
||||
"(\"" + strVar + "\", " + resultName + ", " + iScope + ");");
|
||||
|
||||
//if var is not specified, just print out the url string
|
||||
}else{
|
||||
ctxt.generateJavaSource("try{");
|
||||
ctxt.generateJavaSource(" pageContext.getOut().print(" + resultName + ");");
|
||||
ctxt.generateJavaSource("}catch(java.io.IOException ex){");
|
||||
ctxt.generateJavaSource(" throw new JspTagException(ex.toString(), ex);");
|
||||
ctxt.generateJavaSource("}");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* 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.tagplugins.jstl.core;
|
||||
|
||||
import org.apache.jasper.compiler.tagplugin.*;
|
||||
|
||||
public final class When implements TagPlugin {
|
||||
|
||||
public void doTag(TagPluginContext ctxt) {
|
||||
// Get the parent context to determine if this is the first <c:when>
|
||||
TagPluginContext parentContext = ctxt.getParentContext();
|
||||
if (parentContext == null) {
|
||||
ctxt.dontUseTagPlugin();
|
||||
return;
|
||||
}
|
||||
|
||||
if ("true".equals(parentContext.getPluginAttribute("hasBeenHere"))) {
|
||||
ctxt.generateJavaSource("} else if(");
|
||||
// See comment below for the reason we generate the extra "}" here.
|
||||
}
|
||||
else {
|
||||
ctxt.generateJavaSource("if(");
|
||||
parentContext.setPluginAttribute("hasBeenHere", "true");
|
||||
}
|
||||
ctxt.generateAttribute("test");
|
||||
ctxt.generateJavaSource("){");
|
||||
ctxt.generateBody();
|
||||
|
||||
// We don't generate the closing "}" for the "if" here because there
|
||||
// may be whitespaces in between <c:when>'s. Instead we delay
|
||||
// generating it until the next <c:when> or <c:otherwise> or
|
||||
// <c:choose>
|
||||
}
|
||||
}
|
||||
-63
@@ -1,63 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<tag-plugins>
|
||||
<tag-plugin>
|
||||
<tag-class>org.apache.taglibs.standard.tag.rt.core.IfTag</tag-class>
|
||||
<plugin-class>org.apache.jasper.tagplugins.jstl.core.If</plugin-class>
|
||||
</tag-plugin>
|
||||
<tag-plugin>
|
||||
<tag-class>org.apache.taglibs.standard.tag.common.core.ChooseTag</tag-class>
|
||||
<plugin-class>org.apache.jasper.tagplugins.jstl.core.Choose</plugin-class>
|
||||
</tag-plugin>
|
||||
<tag-plugin>
|
||||
<tag-class>org.apache.taglibs.standard.tag.rt.core.WhenTag</tag-class>
|
||||
<plugin-class>org.apache.jasper.tagplugins.jstl.core.When</plugin-class>
|
||||
</tag-plugin>
|
||||
<tag-plugin>
|
||||
<tag-class>org.apache.taglibs.standard.tag.common.core.OtherwiseTag</tag-class>
|
||||
<plugin-class>org.apache.jasper.tagplugins.jstl.core.Otherwise</plugin-class>
|
||||
</tag-plugin>
|
||||
<tag-plugin>
|
||||
<tag-class>org.apache.taglibs.standard.tag.rt.core.ForEachTag</tag-class>
|
||||
<plugin-class>org.apache.jasper.tagplugins.jstl.core.ForEach</plugin-class>
|
||||
</tag-plugin>
|
||||
<tag-plugin>
|
||||
<tag-class>org.apache.taglibs.standard.tag.rt.core.OutTag</tag-class>
|
||||
<plugin-class>org.apache.jasper.tagplugins.jstl.core.Out</plugin-class>
|
||||
</tag-plugin>
|
||||
<tag-plugin>
|
||||
<tag-class>org.apache.taglibs.standard.tag.rt.core.SetTag</tag-class>
|
||||
<plugin-class>org.apache.jasper.tagplugins.jstl.core.Set</plugin-class>
|
||||
</tag-plugin>
|
||||
<tag-plugin>
|
||||
<tag-class>org.apache.taglibs.standard.tag.common.core.RemoveTag</tag-class>
|
||||
<plugin-class>org.apache.jasper.tagplugins.jstl.core.Remove</plugin-class>
|
||||
</tag-plugin>
|
||||
<tag-plugin>
|
||||
<tag-class>org.apache.taglibs.standard.tag.common.core.CatchTag</tag-class>
|
||||
<plugin-class>org.apache.jasper.tagplugins.jstl.core.Catch</plugin-class>
|
||||
</tag-plugin>
|
||||
<tag-plugin>
|
||||
<tag-class>org.apache.taglibs.standard.tag.rt.core.ForTokensTag</tag-class>
|
||||
<plugin-class>org.apache.jasper.tagplugins.jstl.core.ForTokens</plugin-class>
|
||||
</tag-plugin>
|
||||
<tag-plugin>
|
||||
<tag-class>org.apache.taglibs.standard.tag.rt.core.ImportTag</tag-class>
|
||||
<plugin-class>org.apache.jasper.tagplugins.jstl.core.Import</plugin-class>
|
||||
</tag-plugin>
|
||||
</tag-plugins>
|
||||
@@ -1,176 +0,0 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
|
||||
/**
|
||||
* Adapter class that wraps an <code>Enumeration</code> around a Java2
|
||||
* collection classes object <code>Iterator</code> so that existing APIs
|
||||
* returning Enumerations can easily run on top of the new collections.
|
||||
* Constructors are provided to easliy create such wrappers.
|
||||
*
|
||||
* @author Craig R. McClanahan
|
||||
* @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (Tue, 24 Oct 2006) $
|
||||
*/
|
||||
|
||||
public final class Enumerator implements Enumeration {
|
||||
|
||||
|
||||
// ----------------------------------------------------------- Constructors
|
||||
|
||||
|
||||
/**
|
||||
* Return an Enumeration over the values of the specified Collection.
|
||||
*
|
||||
* @param collection Collection whose values should be enumerated
|
||||
*/
|
||||
public Enumerator(Collection collection) {
|
||||
|
||||
this(collection.iterator());
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return an Enumeration over the values of the specified Collection.
|
||||
*
|
||||
* @param collection Collection whose values should be enumerated
|
||||
* @param clone true to clone iterator
|
||||
*/
|
||||
public Enumerator(Collection collection, boolean clone) {
|
||||
|
||||
this(collection.iterator(), clone);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return an Enumeration over the values returned by the
|
||||
* specified Iterator.
|
||||
*
|
||||
* @param iterator Iterator to be wrapped
|
||||
*/
|
||||
public Enumerator(Iterator iterator) {
|
||||
|
||||
super();
|
||||
this.iterator = iterator;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return an Enumeration over the values returned by the
|
||||
* specified Iterator.
|
||||
*
|
||||
* @param iterator Iterator to be wrapped
|
||||
* @param clone true to clone iterator
|
||||
*/
|
||||
public Enumerator(Iterator iterator, boolean clone) {
|
||||
|
||||
super();
|
||||
if (!clone) {
|
||||
this.iterator = iterator;
|
||||
} else {
|
||||
List list = new ArrayList();
|
||||
while (iterator.hasNext()) {
|
||||
list.add(iterator.next());
|
||||
}
|
||||
this.iterator = list.iterator();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return an Enumeration over the values of the specified Map.
|
||||
*
|
||||
* @param map Map whose values should be enumerated
|
||||
*/
|
||||
public Enumerator(Map map) {
|
||||
|
||||
this(map.values().iterator());
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return an Enumeration over the values of the specified Map.
|
||||
*
|
||||
* @param map Map whose values should be enumerated
|
||||
* @param clone true to clone iterator
|
||||
*/
|
||||
public Enumerator(Map map, boolean clone) {
|
||||
|
||||
this(map.values().iterator(), clone);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------- Instance Variables
|
||||
|
||||
|
||||
/**
|
||||
* The <code>Iterator</code> over which the <code>Enumeration</code>
|
||||
* represented by this class actually operates.
|
||||
*/
|
||||
private Iterator iterator = null;
|
||||
|
||||
|
||||
// --------------------------------------------------------- Public Methods
|
||||
|
||||
|
||||
/**
|
||||
* Tests if this enumeration contains more elements.
|
||||
*
|
||||
* @return <code>true</code> if and only if this enumeration object
|
||||
* contains at least one more element to provide, <code>false</code>
|
||||
* otherwise
|
||||
*/
|
||||
public boolean hasMoreElements() {
|
||||
|
||||
return (iterator.hasNext());
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the next element of this enumeration if this enumeration
|
||||
* has at least one more element to provide.
|
||||
*
|
||||
* @return the next element of this enumeration
|
||||
*
|
||||
* @exception NoSuchElementException if no more elements exist
|
||||
*/
|
||||
public Object nextElement() throws NoSuchElementException {
|
||||
|
||||
return (iterator.next());
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user