bring embedded jsp plugin into trunk

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@805867 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Musachy Barroso
2009-08-19 16:26:17 +00:00
parent cc423fc301
commit 730abcdfb9
129 changed files with 44236 additions and 0 deletions
+112
View File
@@ -0,0 +1,112 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.1.8-SNAPSHOT</version>
</parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-jsp-plugin</artifactId>
<packaging>jar</packaging>
<name>struts2-jsp-plugin</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>2.5.6</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>2.5.6</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>2.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>request</artifactId>
<version>1.0.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>${pom.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-el</groupId>
<artifactId>commons-el</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.1.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.4.2</version>
<configuration>
<additionalClasspathElements>
<element>${project.build.testOutputDirectory}/jsps.jar</element>
</additionalClasspathElements>
<forkMode>never</forkMode>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,34 @@
/*
* $Id$
*
* 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.struts2;
import com.opensymphony.xwork2.ActionInvocation;
import org.apache.commons.lang.xwork.StringUtils;
import org.apache.struts2.dispatcher.StrutsResultSupport;
/**
* Can render jsps from the classpath. "includes" in the jsps must not use relative paths
*/
public class EmbeddedJSPResult extends StrutsResultSupport {
protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
JSPRuntime.handle(StringUtils.removeStart(finalLocation, "/"));
}
}
@@ -0,0 +1,250 @@
/*
* $Id$
*
* 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.struts2;
import com.opensymphony.xwork2.util.URLUtil;
import com.opensymphony.xwork2.util.finder.ClassLoaderInterface;
import com.opensymphony.xwork2.util.finder.ClassLoaderInterfaceDelegate;
import com.opensymphony.xwork2.util.finder.UrlSet;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.xwork.ObjectUtils;
import org.apache.commons.lang.xwork.StringUtils;
import org.apache.struts2.compiler.MemoryClassLoader;
import org.apache.struts2.compiler.MemoryJavaFileObject;
import org.apache.struts2.jasper.JasperException;
import org.apache.struts2.jasper.JspC;
import org.apache.struts2.jasper.compiler.JspUtil;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.jsp.JspPage;
import javax.servlet.jsp.HttpJspPage;
import javax.tools.*;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
/**
* Uses jasper to extract a JSP from the classpath to a file and compile it. The classpath used for
* compilation is built by finding all the jar files using the current class loader (Thread), plus
* directories.
*/
public class JSPLoader {
private static final Logger LOG = LoggerFactory.getLogger(JSPLoader.class);
private static MemoryClassLoader classLoader = new MemoryClassLoader();
private static final String DEFAULT_PACKAGE = "org.apache.struts2.jsp";
private static final Pattern PACKAGE_PATTERN = Pattern.compile("package (.*?);");
private static final Pattern CLASS_PATTERN = Pattern.compile("public final class (.*?) ");
public Servlet load(String location) throws Exception {
location = StringUtils.substringBeforeLast(location, "?");
if (LOG.isDebugEnabled()) {
LOG.debug("Compiling JSP [#0]", location);
}
//use Jasper to compile the JSP into java code
JspC jspC = compileJSP(location);
String source = jspC.getSourceCode();
//System.out.print(source);
String className = extractClassName(source);
//use Java Compiler API to compile the java code into a class
//the tlds that were discovered are added (their jars) to the classpath
compileJava(className, source, jspC.getTldAbsolutePaths());
//load the class that was just built
Class clazz = Class.forName(className, false, classLoader);
return createServlet(clazz);
}
private String extractClassName(String source) {
Matcher matcher = PACKAGE_PATTERN.matcher(source);
matcher.find();
String packageName = matcher.group(1);
matcher = CLASS_PATTERN.matcher(source);
matcher.find();
String className = matcher.group(1);
return packageName + "." + className;
}
/**
* Creates and inits a servlet
*/
private Servlet createServlet(Class clazz) throws IllegalAccessException, InstantiationException, ServletException {
JSPServletConfig config = new JSPServletConfig(ServletActionContext.getServletContext());
Servlet servlet = (Servlet) clazz.newInstance();
servlet.init(config);
/*
there is no need to call JspPage.init explicitly because Jasper's
JSP base classe HttpJspBase.init(ServletConfig) calls:
jspInit();
_jspInit();
*/
return servlet;
}
/**
* Compiles the given source code into java bytecode
*/
private void compileJava(String className, final String source, Set<String> extraClassPath) throws IOException {
if (LOG.isTraceEnabled())
LOG.trace("Compiling [#0], source: [#1]", className, source);
JavaCompiler compiler =
ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> diagnostics =
new DiagnosticCollector<JavaFileObject>();
//the generated bytecode is fed to the class loader
JavaFileManager jfm = new
ForwardingJavaFileManager<StandardJavaFileManager>(
compiler.getStandardFileManager(diagnostics, null, null)) {
@Override
public JavaFileObject getJavaFileForOutput(Location location,
String name,
JavaFileObject.Kind kind,
FileObject sibling) throws IOException {
MemoryJavaFileObject fileObject = new MemoryJavaFileObject(name, kind);
classLoader.addMemoryJavaFileObject(name, fileObject);
return fileObject;
}
};
//read java source code from memory
String fileName = className.replace('.', '/') + ".java";
SimpleJavaFileObject sourceCodeObject = new SimpleJavaFileObject(toURI(fileName), JavaFileObject.Kind.SOURCE) {
@Override
public CharSequence getCharContent(boolean
ignoreEncodingErrors)
throws IOException, IllegalStateException,
UnsupportedOperationException {
return source;
}
};
//build classpath
//some entries will be added multiple times, hence the set
List<String> optionList = new ArrayList<String>();
Set<String> classPath = new HashSet<String>();
//find available jars
ClassLoaderInterface classLoaderInterface = getClassLoaderInterface();
UrlSet urlSet = new UrlSet(classLoaderInterface);
//find jars
List<URL> urls = urlSet.getUrls();
for (URL url : urls) {
URL normalizedUrl = URLUtil.normalizeToFileProtocol(url);
File file = FileUtils.toFile((URL) ObjectUtils.defaultIfNull(normalizedUrl, url));
if (file.exists())
classPath.add(file.getAbsolutePath());
}
//these should be in the list already, but I am feeling paranoid
//this jar
classPath.add(getJarUrl(EmbeddedJSPResult.class));
//servlet api
classPath.add(getJarUrl(Servlet.class));
//jsp api
classPath.add(getJarUrl(JspPage.class));
//add extra classpath entries (jars where tlds were found will be here)
for (Iterator<String> iterator = extraClassPath.iterator(); iterator.hasNext();) {
String entry = iterator.next();
classPath.add(entry);
}
String classPathString = StringUtils.join(classPath, ";");
if (LOG.isDebugEnabled()) {
LOG.debug("Compiling [#0] with classpath [#1]", className, classPathString);
}
optionList.addAll(Arrays.asList("-classpath", classPathString));
//compile
JavaCompiler.CompilationTask task = compiler.getTask(
null, jfm, diagnostics, optionList, null,
Arrays.asList(sourceCodeObject));
if (!task.call()) {
throw new StrutsException("Compilation failed:" + diagnostics.getDiagnostics().get(0).toString());
}
}
protected String getJarUrl(Class clazz) {
ProtectionDomain protectionDomain = clazz.getProtectionDomain();
CodeSource codeSource = protectionDomain.getCodeSource();
URL loc = codeSource.getLocation();
File file = FileUtils.toFile(loc);
return file.getAbsolutePath();
}
private JspC compileJSP(String location) throws JasperException {
JspC jspC = new JspC();
jspC.setClassLoaderInterface(getClassLoaderInterface());
jspC.setCompile(false);
jspC.setJspFiles(location);
jspC.setPackage(DEFAULT_PACKAGE);
jspC.execute();
return jspC;
}
private ClassLoaderInterface getClassLoaderInterface() {
ClassLoaderInterface classLoaderInterface = null;
ServletContext ctx = ServletActionContext.getServletContext();
if (ctx != null)
classLoaderInterface = (ClassLoaderInterface) ctx.getAttribute(ClassLoaderInterface.CLASS_LOADER_INTERFACE);
return (ClassLoaderInterface) ObjectUtils.defaultIfNull(classLoaderInterface, new ClassLoaderInterfaceDelegate(JSPLoader.class.getClassLoader()));
}
private static URI toURI(String name) {
try {
return new URI(name);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
}
@@ -0,0 +1,70 @@
/*
* $Id$
*
* 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.struts2;
import com.opensymphony.xwork2.ActionContext;
import org.apache.struts2.views.util.UrlHelper;
import javax.servlet.Servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.HttpJspPage;
import java.util.Map;
/**
* Maintains a cache of jsp locations -> servlet instances for those jsps. When a jsp is requested
* from the cache, the cache will block if the jsp was not compiled already, and wait for the compilation
*/
public abstract class JSPRuntime {
//maps from jsp path -> pagelet
protected static final ServletCache servletCache = new ServletCache();
public static void clearCache() {
servletCache.clear();
}
public static void handle(String location) throws Exception {
handle(location, false);
}
public static void handle(String location, boolean flush) throws Exception {
final HttpServletResponse response = ServletActionContext.getResponse();
final HttpServletRequest request = ServletActionContext.getRequest();
int i = location.indexOf("?");
if (i > 0) {
//extract params from the url and add them to the request
Map parameters = ActionContext.getContext().getParameters();
String query = location.substring(i + 1);
Map queryParams = UrlHelper.parseQueryString(query, true);
if (queryParams != null && !queryParams.isEmpty())
parameters.putAll(queryParams);
location = location.substring(0, i);
}
Servlet servlet = servletCache.get(location);
HttpJspPage page = (HttpJspPage) servlet;
page._jspService(request, response);
if (flush)
response.flushBuffer();
}
}
@@ -0,0 +1,55 @@
/*
* $Id$
*
* 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.struts2;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import java.util.Collections;
import java.util.Enumeration;
/**
* Used to init the servlets for the jsps
*/
public class JSPServletConfig implements ServletConfig {
private final Enumeration EMPTY_ENUMERATION = Collections.enumeration(Collections.EMPTY_LIST);
private ServletContext servletContext;
public JSPServletConfig(ServletContext servletContext) {
this.servletContext = servletContext;
}
public String getInitParameter(String name) {
return null;
}
public Enumeration getInitParameterNames() {
return EMPTY_ENUMERATION;
}
public ServletContext getServletContext() {
return servletContext;
}
public String getServletName() {
return null;
}
}
@@ -0,0 +1,76 @@
/*
* $Id$
*
* 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.struts2;
import javax.servlet.Servlet;
import java.util.concurrent.*;
/**
* Caches servlet instances by jsp location. If a requested jsp is not in the cache, "get"
* will block and wait for the jsp to be loaded
*/
public class ServletCache {
protected final ConcurrentMap<String, Future<Servlet>> cache
= new ConcurrentHashMap<String, Future<Servlet>>();
private final JSPLoader jspLoader = new JSPLoader();
public void clear() {
cache.clear();
}
public Servlet get(final String location) throws InterruptedException {
while (true) {
Future<Servlet> future = cache.get(location);
if (future == null) {
Callable<Servlet> loadJSPCallable = new Callable<Servlet>() {
public Servlet call() throws Exception {
return jspLoader.load(location);
}
};
FutureTask<Servlet> futureTask = new FutureTask<Servlet>(loadJSPCallable);
future = cache.putIfAbsent(location, futureTask);
if (future == null) {
future = futureTask;
futureTask.run();
}
}
try {
return future.get();
} catch (CancellationException e) {
cache.remove(location, future);
} catch (ExecutionException e) {
throw launderThrowable(e.getCause());
}
}
}
public static RuntimeException launderThrowable(Throwable t) {
if (t instanceof RuntimeException)
return (RuntimeException) t;
else if (t instanceof Error)
throw (Error) t;
else
throw new IllegalStateException(t);
}
}
@@ -0,0 +1,54 @@
/*
* $Id$
*
* 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.struts2.compiler;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Keeps a cache of class name -> MemoryJavaFileObject. If the requested class name is in the cache
* a new class is defined for it, otherwise findClass delegates to the parent class loader
*/
public class MemoryClassLoader extends ClassLoader {
private Map<String, MemoryJavaFileObject> cachedObjects = new ConcurrentHashMap<String, MemoryJavaFileObject>();
public MemoryClassLoader() {
//without this, the tests will not run, because the tests are loaded by a custom classloader
//so the classes referenced from the compiled code will not be found by the System Class Loader because
//the target dir is not part of the classpath used when calling the jvm to execute the tests
super(Thread.currentThread().getContextClassLoader());
}
@Override
protected Class<?> findClass(String name) throws
ClassNotFoundException {
MemoryJavaFileObject fileObject = cachedObjects.get(name);
if (fileObject != null) {
byte[] bytes = fileObject.toByteArray();
return defineClass(name, bytes, 0, bytes.length);
}
return super.findClass(name);
}
public void addMemoryJavaFileObject(String jsp, MemoryJavaFileObject memoryJavaFileObject) {
cachedObjects.put(jsp, memoryJavaFileObject);
}
}
@@ -0,0 +1,61 @@
/*
* $Id$
*
* 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.struts2.compiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
/**
* Captures the output of the java compiler in memory
*/
public class MemoryJavaFileObject extends SimpleJavaFileObject {
private ByteArrayOutputStream out;
public MemoryJavaFileObject(String name, JavaFileObject.Kind kind) {
super(toURI(name), kind);
}
public InputStream openInputStream() throws IOException,
IllegalStateException, UnsupportedOperationException {
return new ByteArrayInputStream(out.toByteArray());
}
public OutputStream openOutputStream() throws IOException,
IllegalStateException, UnsupportedOperationException {
return out = new ByteArrayOutputStream();
}
private static URI toURI(String name) {
try {
return new URI(name);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
public byte[] toByteArray() {
return out.toByteArray();
}
}
@@ -0,0 +1,217 @@
/*
* 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.struts2.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 = "org.apache.struts2.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 = "_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.*"
};
/**
* FIXME
* 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 = "org.apache.catalina.jsp_classpath";
/**
* FIXME
* Request attribute for <code>&lt;jsp-file&gt;</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 = "org.apache.catalina.jsp_file";
/**
* FIXME
* ServletContext attribute for class loader. This is tomcat specific.
* Other servlet engines can choose to have this attribute if they
* want to have this JSP engine running on them.
*/
//public static final String SERVLET_CLASS_LOADER = "org.apache.tomcat.classloader";
public static final String SERVLET_CLASS_LOADER = "org.apache.catalina.classloader";
/**
* Default size of the JSP buffer.
*/
public static final int K = 1024;
public static final int DEFAULT_BUFFER_SIZE = 8 * K;
/**
* 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 = "jsp_precompile";
/**
* The default package name for compiled jsp pages.
*/
public static final String 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 = "org.apache.jsp.tag";
/**
* Servlet context and request attributes that the JSP engine
* uses.
*/
public static final String INC_REQUEST_URI = "javax.servlet.include.request_uri";
public static final String INC_SERVLET_PATH = "javax.servlet.include.servlet_path";
public static final String TMP_DIR = "javax.servlet.context.tempdir";
public static final String FORWARD_SEEN = "javax.servlet.forward.seen";
// Must be kept in sync with org/apache/catalina/Globals.java
public static final String 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 =
"_jspx_temp";
/**
* Previous replacement char for "\$".
*
* @deprecated
*/
public static final char ESC = '\u001b';
/**
* Previous replacement char for "\$".
*
* @deprecated
*/
public static final String ESCStr = "'\\u001b'";
/**
* Replacement char for "\$". This is the first unicode character in the
* private use area.
* XXX This is a hack to avoid changing EL interpreter to recognize "\$"
*/
public static final char HACK_CHAR = '\ue000';
/**
* Replacement string for "\$". This is the first unicode character in the
* private use area.
* XXX This is a hack to avoid changing EL interpreter to recognize "\$"
*/
public static final String HACK_STR = "'\\ue000'";
}
@@ -0,0 +1,37 @@
/*
* $Id$
*
* 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.struts2.jasper;
import java.io.FileNotFoundException;
public class CustomCompiler extends org.apache.struts2.jasper.compiler.Compiler {
public boolean isOutDated() {
return true;
}
public boolean isOutDated(boolean checkClass) {
return true;
}
protected void generateClass(String[] smap) throws FileNotFoundException, JasperException, Exception {
}
}
@@ -0,0 +1,647 @@
/*
* 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.struts2.jasper;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.struts2.jasper.compiler.JspConfig;
import org.apache.struts2.jasper.compiler.Localizer;
import org.apache.struts2.jasper.compiler.TagPluginManager;
import org.apache.struts2.jasper.compiler.TldLocationsCache;
import org.apache.struts2.jasper.xmlparser.ParserUtils;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import java.io.File;
import java.util.Enumeration;
import java.util.Map;
import java.util.Properties;
/**
* 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 Logger log = LoggerFactory.getLogger(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 you want stack traces and such displayed in the client's
* browser? If this is false, such messages go to the standard
* error or a log file if the standard error is redirected.
*/
private boolean sendErrorToClient = false;
/**
* 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";
/**
* 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;
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?
*/
public boolean getSendErrorToClient() {
return sendErrorToClient;
}
/**
* 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;
}
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;
}
/**
* 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 senderr = config.getInitParameter("sendErrToClient");
if (senderr != null) {
if (senderr.equalsIgnoreCase("true")) {
this.sendErrorToClient = true;
} else if (senderr.equalsIgnoreCase("false")) {
this.sendErrorToClient = false;
} else {
if (log.isWarnEnabled()) {
log.warn(Localizer.getMessage("jsp.warning.sendErrToClient"));
}
}
}
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 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"));
}
}
}
// 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);
}
}
@@ -0,0 +1,46 @@
/*
* 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.struts2.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
@@ -0,0 +1,631 @@
/*
* 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.struts2.jasper;
import com.opensymphony.xwork2.util.finder.ClassLoaderInterface;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.struts2.jasper.compiler.Compiler;
import org.apache.struts2.jasper.compiler.*;
import org.apache.struts2.jasper.servlet.JasperLoader;
import org.apache.struts2.jasper.servlet.JspServletWrapper;
import org.apache.commons.lang.xwork.StringUtils;
import javax.servlet.ServletContext;
import javax.servlet.jsp.tagext.TagInfo;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Hashtable;
import java.util.Set;
/**
* 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.
* <p/>
* Most of the path-related stuff is here - mangling names, versions, dirs,
* loading resources and dealing with uris.
*
* @author Anil K. Vijendran
* @author Harish Prabandham
* @author Pierre Delisle
* @author Costin Manolache
* @author Kin-man Chung
*/
public class JspCompilationContext {
private Logger log = LoggerFactory.getLogger(JspCompilationContext.class);
private Hashtable tagFileJarUrls;
private boolean isPackagedTagFile;
private String className;
private String jspUri;
private boolean isErrPage;
private String basePackageName;
private String derivedPackageName;
private String servletJavaFileName;
private String javaPath;
private String classFileName;
private String contentType;
private ServletWriter writer;
private Options options;
private JspServletWrapper jsw;
private Compiler jspCompiler;
private String classPath;
private ServletContext context;
private URLClassLoader loader;
private JspRuntimeContext rctxt;
private int removed = 0;
private URLClassLoader jspLoader;
private URL baseUrl;
private Class servletClass;
private boolean isTagFile;
private boolean protoTypeMode;
private TagInfo tagInfo;
private URL tagFileJarUrl;
private String sourceCode;
private ClassLoaderInterface classLoaderInterface;
public String getSourceCode() {
return sourceCode;
}
public void setSourceCode(String sourceCode) {
this.sourceCode = sourceCode;
}
public JspCompilationContext(String jspUri,
boolean isErrPage,
Options options,
ServletContext context,
JspServletWrapper jsw,
JspRuntimeContext rctxt,
ClassLoaderInterface classLoaderInterface) {
this.jspUri = canonicalURI(jspUri);
this.isErrPage = isErrPage;
this.options = options;
this.jsw = jsw;
this.context = context;
this.rctxt = rctxt;
this.tagFileJarUrls = new Hashtable();
this.basePackageName = Constants.JSP_PACKAGE_NAME;
this.classLoaderInterface = classLoaderInterface;
}
public JspCompilationContext(String tagfile,
TagInfo tagInfo,
Options options,
ServletContext context,
JspServletWrapper jsw,
JspRuntimeContext rctxt,
URL tagFileJarUrl) {
this(tagfile, false, options, context, jsw, rctxt, null);
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 ---------- */
/**
* 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 {
jspCompiler = new CustomCompiler();
jspCompiler.init(this, jsw);
return jspCompiler;
}
private Compiler createCompiler(String className) {
Compiler compiler = null;
try {
compiler = (Compiler) Class.forName(className).newInstance();
} catch (Throwable t) {
if (log.isDebugEnabled()) {
log.debug(Localizer.getMessage("jsp.error.compiler"), t);
}
}
return compiler;
}
public Compiler getCompiler() {
return jspCompiler;
}
/** ---------- Access resources in the webapp ---------- */
/**
* 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) {
try {
return classLoaderInterface.getResourceAsStream(canonicalURI(StringUtils.removeStart(res, "/")));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public URL getResource(String res) throws MalformedURLException {
return classLoaderInterface.getResource(canonicalURI(StringUtils.removeStart(res, "/")));
}
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.
* <p/>
* The map is populated when parsing the tag-file elements of the TLDs
* of any imported taglibs.
*/
public Hashtable getTagFileJarUrls() {
return this.tagFileJarUrls;
}
/**
* 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();
}
}
private String getDerivedPackageName() {
if (derivedPackageName == null) {
int iSep = jspUri.lastIndexOf('/');
derivedPackageName = (iSep > 0) ?
JspUtil.makeJavaPackage(jspUri.substring(0, 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 =
getServletClassName() + ".java";
}
return servletJavaFileName;
}
public void setServletJavaFileName(String servletJavaFileName) {
this.servletJavaFileName = 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 = getServletClassName() + ".class";
}
return classFileName;
}
/**
* Get the content type of this JSP.
* <p/>
* 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 > 1) {
jspCompiler.removeGeneratedFiles();
if (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 (isPackagedTagFile || jspCompiler.isOutDated()) {
try {
jspLoader = null;
jspCompiler.compile();
jsw.setReload(true);
jsw.setCompilationException(null);
} catch (JasperException ex) {
// Cache compilation exception
jsw.setCompilationException(ex);
throw ex;
} catch (Exception ex) {
ex.printStackTrace();
JasperException je = new JasperException(
Localizer.getMessage("jsp.error.unable.compile"),
ex);
// Cache compilation exception
jsw.setCompilationException(je);
throw je;
}
}
}
public String getJspUri() {
return jspUri;
}
// ==================== 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;
}
// ==================== Private methods ====================
static Object outputDirLock = new Object();
private static final boolean isPathSeparator(char c) {
return (c == '/' || c == '\\');
}
public 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();
}
}
@@ -0,0 +1,189 @@
/*
* 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.struts2.jasper;
import org.apache.struts2.jasper.compiler.JspConfig;
import org.apache.struts2.jasper.compiler.TagPluginManager;
import org.apache.struts2.jasper.compiler.TldLocationsCache;
import java.io.File;
import java.util.Map;
/**
* 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?
*/
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();
/**
* 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();
/**
* 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();
}
@@ -0,0 +1,115 @@
/*
* 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.struts2.jasper.compiler;
import org.apache.struts2.jasper.JasperException;
import java.util.Hashtable;
import java.util.Vector;
/**
* Repository of {page, request, session, application}-scoped beans
*
* @author Mandar Raje
*/
class BeanRepository {
private Vector sessionBeans;
private Vector pageBeans;
private Vector appBeans;
private Vector requestBeans;
private Hashtable beanTypes;
private ClassLoader loader;
private ErrorDispatcher errDispatcher;
/*
* Constructor.
*/
public BeanRepository(ClassLoader loader, ErrorDispatcher err) {
this.loader = loader;
this.errDispatcher = err;
sessionBeans = new Vector(11);
pageBeans = new Vector(11);
appBeans = new Vector(11);
requestBeans = new Vector(11);
beanTypes = new Hashtable();
}
public void addBean(Node.UseBean n, String s, String type, String scope)
throws JasperException {
if (scope == null || scope.equals("page")) {
pageBeans.addElement(s);
} else if (scope.equals("request")) {
requestBeans.addElement(s);
} else if (scope.equals("session")) {
sessionBeans.addElement(s);
} else if (scope.equals("application")) {
appBeans.addElement(s);
} else {
errDispatcher.jspError(n, "jsp.error.usebean.badScope");
}
putBeanType(s, type);
}
public Class getBeanType(String bean) throws JasperException {
Class clazz = null;
try {
clazz = loader.loadClass((String) beanTypes.get(bean));
} catch (ClassNotFoundException ex) {
throw new JasperException(ex);
}
return clazz;
}
public boolean checkVariable(String bean) {
// XXX Not sure if this is the correct way.
// After pageContext is finalised this will change.
return (checkPageBean(bean) || checkSessionBean(bean) ||
checkRequestBean(bean) || checkApplicationBean(bean));
}
private void putBeanType(String bean, String type) {
beanTypes.put(bean, type);
}
private boolean checkPageBean(String s) {
return pageBeans.contains(s);
}
private boolean checkRequestBean(String s) {
return requestBeans.contains(s);
}
private boolean checkSessionBean(String s) {
return sessionBeans.contains(s);
}
private boolean checkApplicationBean(String s) {
return appBeans.contains(s);
}
}
@@ -0,0 +1,203 @@
/*
* 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.struts2.jasper.compiler;
import org.apache.struts2.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());
}
}
@@ -0,0 +1,498 @@
/*
* 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.struts2.jasper.compiler;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.struts2.jasper.JasperException;
import org.apache.struts2.jasper.JspCompilationContext;
import org.apache.struts2.jasper.Options;
import org.apache.struts2.jasper.servlet.JspServletWrapper;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.Iterator;
import java.util.List;
/**
* 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 {
private Logger log = LoggerFactory.getLogger(Compiler.class);
// ----------------------------------------------------------------- Static
// Some javac are not thread safe; use a lock to serialize compilation,
static Object javacLock = new Object();
// ----------------------------------------------------- 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.
*/
pageInfo.setELIgnored(JspUtil.booleanValue(
jspProperty.isELIgnored()));
pageInfo.setScriptingInvalid(JspUtil.booleanValue(
jspProperty.isScriptingInvalid()));
if (jspProperty.getIncludePrelude() != null) {
pageInfo.setIncludePrelude(jspProperty.getIncludePrelude());
}
if (jspProperty.getIncludeCoda() != null) {
pageInfo.setIncludeCoda(jspProperty.getIncludeCoda());
}
String javaFileName = ctxt.getServletJavaFileName();
ServletWriter writer = null;
try {
// Setup the ServletWriter
String javaEncoding = ctxt.getOptions().getJavaEncoding();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1024);
OutputStreamWriter osw = null;
try {
osw = new OutputStreamWriter(
byteArrayOutputStream, javaEncoding);
} catch (UnsupportedEncodingException ex) {
errDispatcher.jspError("jsp.error.needAlternateJavaEncoding",
javaEncoding);
}
writer = new ServletWriter(new PrintWriter(osw));
ctxt.setWriter(writer);
// Reset the temporary variable counter for the generator.
JspUtil.resetTemporaryVariableName();
// Parse the file
ParserController parserCtl = new ParserController(ctxt, this);
pageNodes = parserCtl.parse(ctxt.getJspFile());
if (ctxt.isPrototypeMode()) {
// generate prototype .java file for the tag file
Generator.generate(writer, this, pageNodes);
writer.close();
writer = null;
return null;
}
// Validate and process attributes
Validator.validate(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
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);
ctxt.setSourceCode(byteArrayOutputStream.toString());
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;
}
/**
* 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);
}
} finally {
if (tfp != null) {
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();
jspRealLastModified = uc.getLastModified();
uc.getInputStream().close();
} catch (Exception e) {
e.printStackTrace();
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 includeUconn = includeUrl.openConnection();
long includeLastModified = includeUconn.getLastModified();
includeUconn.getInputStream().close();
if (includeLastModified > targetLastModified) {
return true;
}
} catch (Exception e) {
e.printStackTrace();
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
}
}
}
@@ -0,0 +1,109 @@
/*
* 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.struts2.jasper.compiler;
import org.apache.struts2.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++) {
buf.append("\n");
if (details[i].getJspBeginLineNumber() >= 0) {
args = new Object[]{
new Integer(details[i].getJspBeginLineNumber()),
details[i].getJspFileName()};
buf.append("\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);
}
}
@@ -0,0 +1,207 @@
/*
* 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.struts2.jasper.compiler;
import org.apache.struts2.jasper.JasperException;
import org.xml.sax.Attributes;
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();
}
}
}
@@ -0,0 +1,283 @@
/*
* 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.struts2.jasper.compiler;
import org.apache.struts2.jasper.JasperException;
import javax.servlet.jsp.tagext.FunctionInfo;
import java.util.ArrayList;
import java.util.HashMap;
/**
* This class generates functions mappers for the EL expressions in the page.
* Instead of a global mapper, a mapper is used for each 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 gMap = new HashMap();
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 funcs = new ArrayList();
HashMap keyMap = new HashMap();
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.struts2.jasper.runtime.ProtectedFunctionMapper " + decName + ";\n");
ds.append(" " + decName + "= ");
ds.append("org.apache.struts2.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++;
}
}
}
@@ -0,0 +1,252 @@
/*
* 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.struts2.jasper.compiler;
import org.apache.struts2.jasper.JasperException;
import javax.servlet.jsp.tagext.FunctionInfo;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* This class defines internal representation for an EL Expression
* <p/>
* 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;
Root(ELNode.Nodes expr) {
this.expr = expr;
}
public void accept(Visitor v) throws JasperException {
v.visit(this);
}
public ELNode.Nodes getExpression() {
return expr;
}
}
/**
* 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 list;
public Nodes() {
list = new ArrayList();
}
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 iter = list.iterator();
while (iter.hasNext()) {
ELNode n = (ELNode) iter.next();
n.accept(v);
}
}
public Iterator iterator() {
return list.iterator();
}
public boolean isEmpty() {
return list.size() == 0;
}
/**
* @return true if the expression contains a ${...}
*/
public boolean containsEL() {
Iterator iter = list.iterator();
while (iter.hasNext()) {
ELNode n = (ELNode) 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 {
}
}
}
@@ -0,0 +1,372 @@
/*
* 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.struts2.jasper.compiler;
/**
* This class implements a parser for EL expressions.
* <p/>
* It takes strings of the form xxx${..}yyy${..}zzz etc, and turn it into
* a ELNode.Nodes.
* <p/>
* 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 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));
}
}
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 '\$'.
*
* @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 == '$') {
buf.append('$');
}
// else error!
} else if (prev == '$') {
if (ch == '{') {
prev = 0;
break;
}
buf.append('$');
buf.append(ch);
prev = 0;
} else if (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;
}
}
}
@@ -0,0 +1,615 @@
/*
* 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.struts2.jasper.compiler;
import org.apache.struts2.jasper.JasperException;
import org.apache.struts2.jasper.JspCompilationContext;
import org.xml.sax.SAXException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.util.Vector;
/**
* Class responsible for dispatching JSP parse and javac compilation errors
* to the configured error handler.
* <p/>
* This class is also responsible for localizing any error codes before they
* are passed on to the configured error handler.
* <p/>
* 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 {
Vector errVec = new Vector();
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
errVec.add(javacError);
}
String lineNumStr = line.substring(beginColon + 1, endColon);
try {
lineNum = Integer.parseInt(lineNumStr);
} catch (NumberFormatException e) {
// XXX
}
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) {
errVec.add(javacError);
}
reader.close();
JavacErrorDetail[] errDetails = null;
if (errVec.size() > 0) {
errDetails = new JavacErrorDetail[errVec.size()];
errVec.copyInto(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;
}
}
}
@@ -0,0 +1,73 @@
/*
* 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.struts2.jasper.compiler;
import org.apache.struts2.jasper.JasperException;
/**
* Interface for handling JSP parse and javac compilation errors.
* <p/>
* 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;
}
@@ -0,0 +1,146 @@
/*
* 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.struts2.jasper.compiler;
import org.apache.struts2.jasper.JasperException;
import org.apache.struts2.jasper.JspCompilationContext;
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 java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
/**
* 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";
// Maps tag names to tag file paths
private Hashtable tagFileMap;
private ParserController pc;
private Vector vec;
/**
* Constructor.
*/
public ImplicitTagLibraryInfo(JspCompilationContext ctxt,
ParserController pc,
String prefix,
String tagdir,
ErrorDispatcher err) throws JasperException {
super(prefix, null);
this.pc = pc;
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);
}
}
}
}
/**
* 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,
this);
} catch (JasperException je) {
throw new RuntimeException(je.toString());
}
tagFile = new TagFileInfo(shortName, path, tagInfo);
vec.addElement(tagFile);
this.tagFiles = new TagFileInfo[vec.size()];
vec.copyInto(this.tagFiles);
}
return tagFile;
}
}
@@ -0,0 +1,58 @@
/*
* 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.struts2.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;
}
}
@@ -0,0 +1,227 @@
/*
* 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.struts2.jasper.compiler;
import org.apache.struts2.jasper.JspCompilationContext;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
* 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()]);
}
}
@@ -0,0 +1,473 @@
/*
* 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.struts2.jasper.compiler;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.struts2.jasper.JasperException;
import org.apache.struts2.jasper.xmlparser.ParserUtils;
import org.apache.struts2.jasper.xmlparser.TreeNode;
import org.xml.sax.InputSource;
import javax.servlet.ServletContext;
import java.io.InputStream;
import java.net.URL;
import java.util.Iterator;
import java.util.Vector;
/**
* 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
*/
public class JspConfig {
private static final String WEB_XML = "/WEB-INF/web.xml";
// Logger
private Logger log = LoggerFactory.getLogger(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 = "false";
private JspProperty defaultJspProperty;
public JspConfig(ServletContext ctxt) {
this.ctxt = ctxt;
}
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
|| !"2.4".equals(webApp.findAttribute("version"))) {
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();
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());
}
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);
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);
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;
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);
}
}
String isXml = defaultIsXml;
String isELIgnored = defaultIsELIgnored;
String isScriptingInvalid = defaultIsScriptingInvalid;
String pageEncoding = null;
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();
}
return new JspProperty(isXml, isELIgnored, isScriptingInvalid,
pageEncoding, includePreludes, includeCodas);
}
/**
* 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();
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;
public JspProperty(String isXml, String elIgnored,
String scriptingInvalid, String pageEncoding,
Vector includePrelude, Vector includeCoda) {
this.isXml = isXml;
this.elIgnored = elIgnored;
this.scriptingInvalid = scriptingInvalid;
this.pageEncoding = pageEncoding;
this.includePrelude = includePrelude;
this.includeCoda = includeCoda;
}
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;
}
}
}
@@ -0,0 +1,654 @@
/*
* 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.struts2.jasper.compiler;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.struts2.jasper.JasperException;
import org.apache.struts2.jasper.JspCompilationContext;
import java.io.CharArrayWriter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Vector;
import java.util.jar.JarFile;
/**
* 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 Logger log = LoggerFactory.getLogger(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.
* @throws 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 =, &gt;, &lt;, ", 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;
}
}
@@ -0,0 +1,524 @@
/*
* 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.struts2.jasper.compiler;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.struts2.jasper.Constants;
import org.apache.struts2.jasper.JspCompilationContext;
import org.apache.struts2.jasper.Options;
import org.apache.struts2.jasper.runtime.JspFactoryImpl;
import org.apache.struts2.jasper.security.SecurityClassLoad;
import org.apache.struts2.jasper.servlet.JspServletWrapper;
import javax.servlet.ServletContext;
import javax.servlet.jsp.JspFactory;
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.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* Class for tracking JSP compile time file dependencies when the
* &060;%@include file="..."%&062; directive is used.
* <p/>
* 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.
* <p/>
* Only used if a web application context is a directory.
*
* @author Glenn L. Nielsen
* @version $Revision: 466606 $
*/
public final class JspRuntimeContext implements Runnable {
// Logger
private Logger log = LoggerFactory.getLogger(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());
JspFactory.setDefaultFactory(factory);
}
// ----------------------------------------------------------- Constructors
/**
* Create a JspRuntimeContext for a web application context.
* <p/>
* 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.struts2.jasper.servlet.JspCServletContext) {
return;
}
if (System.getSecurityManager() != null) {
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) {
if (appBase.endsWith(File.separator)) {
appBase = appBase.substring(0, appBase.length() - 1);
}
String directory =
appBase.substring(appBase.lastIndexOf(File.separator));
threadName = threadName + "[" + directory + "]";
threadStart();
}
}
// ----------------------------------------------------- Instance Variables
/**
* This web applications ServletContext
*/
private ServletContext context;
private Options options;
private URLClassLoader parentClassLoader;
private PermissionCollection permissionCollection;
private CodeSource codeSource;
private String classpath;
/**
* Maps JSP pages to their JspServletWrapper's
*/
private Map jsps = Collections.synchronizedMap(new HashMap());
/**
* The background thread.
*/
private Thread thread = null;
/**
* The background thread completion semaphore.
*/
private boolean threadDone = false;
/**
* Name to register for the background thread.
*/
private String threadName = "JspRuntimeContext";
// ------------------------------------------------------ Public Methods
/**
* Add a new JspServletWrapper.
*
* @param jspUri JSP URI
* @param jsw Servlet wrapper for JSP
*/
public void addWrapper(String jspUri, JspServletWrapper jsw) {
jsps.remove(jspUri);
jsps.put(jspUri, jsw);
}
/**
* Get an already existing JspServletWrapper.
*
* @param jspUri JSP URI
* @return JspServletWrapper for JSP
*/
public JspServletWrapper getWrapper(String jspUri) {
return (JspServletWrapper) 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() {
threadStop();
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;
}
// -------------------------------------------------------- Private Methods
/**
* Method used by background thread to check the JSP dependencies
* registered with this class for JSP's.
*/
private void checkCompile() {
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;
}
/**
* 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.struts2.jasper.runtime.HttpJspBase
permissionCollection.add(new RuntimePermission(
"accessClassInPackage.org.apache.struts2.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);
}
}
}
// -------------------------------------------------------- Thread Support
/**
* Start the background thread that will periodically check for
* changes to compile time included files in a JSP.
*
* @throws IllegalStateException if we should not be starting
* a background thread now
*/
protected void threadStart() {
// Has the background thread already been started?
if (thread != null) {
return;
}
// Start the background thread
threadDone = false;
thread = new Thread(this, threadName);
thread.setDaemon(true);
thread.start();
}
/**
* Stop the background thread that is periodically checking for
* changes to compile time included files in a JSP.
*/
protected void threadStop() {
if (thread == null) {
return;
}
threadDone = true;
thread.interrupt();
try {
thread.join();
} catch (InterruptedException e) {
;
}
thread = null;
}
/**
* Sleep for the duration specified by the <code>checkInterval</code>
* property.
*/
protected void threadSleep() {
try {
Thread.sleep(options.getCheckInterval() * 1000L);
} catch (InterruptedException e) {
;
}
}
// ------------------------------------------------------ Background Thread
/**
* The background thread that checks for changes to files
* included by a JSP and flags that a recompile is required.
*/
public void run() {
// Loop until the termination semaphore is set
while (!threadDone) {
// Wait for our check interval
threadSleep();
// Check for included files which are newer than the
// JSP which uses them.
try {
checkCompile();
} catch (Throwable t) {
log.error("Exception checking if recompile needed: ", t);
}
}
}
}
@@ -0,0 +1,160 @@
/*
* 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.struts2.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.struts2.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;
}
}
@@ -0,0 +1,282 @@
/*
* 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.struts2.jasper.compiler;
import org.apache.struts2.jasper.JspCompilationContext;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Stack;
/**
* 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
* @throws 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
@@ -0,0 +1,712 @@
/*
* 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.struts2.jasper.compiler;
import org.apache.struts2.jasper.JasperException;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.AttributesImpl;
import javax.servlet.jsp.tagext.PageData;
import java.io.ByteArrayInputStream;
import java.io.CharArrayWriter;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ListIterator;
/**
* An implementation of <tt>javax.servlet.jsp.tagext.PageData</tt> which
* builds the XML view of a given page.
* <p/>
* The XML view is built in two passes:
* <p/>
* 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.
* <p/>
* 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 "]]&gt;")
* 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");
}
}
}
@@ -0,0 +1,625 @@
/*
* 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.struts2.jasper.compiler;
import org.apache.struts2.jasper.Constants;
import org.apache.struts2.jasper.JasperException;
import javax.servlet.jsp.tagext.TagLibraryInfo;
import java.util.*;
/**
* 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;
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;
}
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);
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,580 @@
/*
* 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.struts2.jasper.compiler;
import org.apache.struts2.jasper.JasperException;
import org.apache.struts2.jasper.JspCompilationContext;
import org.apache.struts2.jasper.xmlparser.XMLEncodingDetector;
import org.xml.sax.Attributes;
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;
/**
* 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 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());
}
/**
* 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.
* <p/>
* This is invoked by the compiler
*
* @param inFileName The name of the tag file to be parsed.
*/
public Node.Nodes parseTagFileDirectives(String inFileName)
throws FileNotFoundException, JasperException, IOException {
boolean isTagFileSave = isTagFile;
boolean directiveOnlySave = directiveOnly;
isTagFile = true;
directiveOnly = true;
Node.Nodes page = doParse(inFileName, null,
(URL) ctxt.getTagFileJarUrls().get(inFileName));
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;
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
compiler.getPageInfo().addDependant(absFileName);
}
if (isXml && isEncodingSpecifiedInProlog) {
/*
* 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);
} else {
// Standard syntax
InputStreamReader inStreamReader = null;
try {
inStreamReader = JspUtil.getReader(absFileName, sourceEnc,
jarFile, ctxt, err);
JspReader jspReader = new JspReader(ctxt, absFileName,
sourceEnc, inStreamReader,
err);
parsedPage = Parser.parse(this, jspReader, parent, isTagFile,
directiveOnly, jarFileUrl,
sourceEnc, jspConfigPageEnc,
isDefaultPageEncoding);
} 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
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 (!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)) {
isXml = true;
if (revert) sourceEnc = "UTF-8";
return;
} else {
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.
*/
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('\\', '/');
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;
}
}
@@ -0,0 +1,151 @@
/*
* 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.struts2.jasper.compiler;
import org.apache.struts2.jasper.JasperException;
import javax.servlet.jsp.tagext.TagVariableInfo;
import javax.servlet.jsp.tagext.VariableInfo;
import java.util.Hashtable;
import java.util.Vector;
/**
* 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));
}
}
@@ -0,0 +1,177 @@
/*
* 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.struts2.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.
* <p/>
* 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.
* <p/>
* 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.
* <p/>
* 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);
}
}
@@ -0,0 +1,173 @@
/*
* 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.struts2.jasper.compiler;
import java.util.ArrayList;
import java.util.List;
/**
* 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);
}
}
@@ -0,0 +1,344 @@
/*
* 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.struts2.jasper.compiler;
import java.util.ArrayList;
import java.util.List;
/**
* 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();
}
}
@@ -0,0 +1,722 @@
/*
* 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.struts2.jasper.compiler;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.struts2.jasper.JasperException;
import org.apache.struts2.jasper.JspCompilationContext;
import java.io.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* 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 Logger log = LoggerFactory.getLogger(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 Logger log = LoggerFactory.getLogger(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;
}
}
}
@@ -0,0 +1,116 @@
/*
* 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.struts2.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:";
}
@@ -0,0 +1,609 @@
/*
* 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.struts2.jasper.compiler;
import org.apache.struts2.jasper.JasperException;
import org.apache.struts2.jasper.JspCompilationContext;
import org.apache.struts2.jasper.runtime.JspSourceDependent;
import org.apache.struts2.jasper.servlet.JspServletWrapper;
import javax.servlet.jsp.tagext.*;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
/**
* 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("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("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);
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";
}
TagAttributeInfo tagAttributeInfo =
new TagAttributeInfo(attrName, required, type, rtexprvalue,
fragment);
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, 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.
* <p/>
* 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.
* <p/>
* 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.
*/
public static TagInfo parseTagFileDirectives(ParserController pc,
String name,
String path,
TagLibraryInfo tagLibInfo)
throws JasperException {
ErrorDispatcher err = pc.getCompiler().getErrorDispatcher();
Node.Nodes page = null;
try {
page = pc.parseTagFileDirectives(path);
} 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 {
JspCompilationContext ctxt = compiler.getCompilationContext();
JspRuntimeContext rctxt = ctxt.getRuntimeContext();
JspServletWrapper wrapper =
(JspServletWrapper) rctxt.getWrapper(tagFilePath);
synchronized (rctxt) {
if (wrapper == null) {
wrapper = new JspServletWrapper(ctxt.getServletContext(),
ctxt.getOptions(),
tagFilePath,
tagInfo,
ctxt.getRuntimeContext(),
(URL) ctxt.getTagFileJarUrls().get(tagFilePath));
rctxt.addWrapper(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(),
(URL) ctxt.getTagFileJarUrls().get(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();
JspCompilationContext ctxt = compiler.getCompilationContext();
if (ctxt.getTagFileJarUrls().get(tagFilePath) == null) {
// Omit tag file dependency info on jar files for now.
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;
}
}
}
}
@@ -0,0 +1,745 @@
/*
* 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.struts2.jasper.compiler;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.struts2.jasper.JasperException;
import org.apache.struts2.jasper.JspCompilationContext;
import org.apache.struts2.jasper.xmlparser.ParserUtils;
import org.apache.struts2.jasper.xmlparser.TreeNode;
import javax.servlet.jsp.tagext.*;
import java.io.*;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.*;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
/**
* 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 Logger log = LoggerFactory.getLogger(TagLibraryInfoImpl.class);
private Hashtable jarEntries;
private JspCompilationContext ctxt;
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,
String prefix,
String uriIn,
String[] location,
ErrorDispatcher err) throws JasperException {
super(prefix, uriIn);
this.ctxt = ctxt;
this.parserController = pc;
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) {
}
}
}
}
/*
* @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) {
//TODO: implement for tld
//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
// check if jarFileUrl is not null before adding it, or this will
// cause a NPE.
if (jarFileUrl != null) {
ctxt.getTagFileJarUrls().put(path, jarFileUrl);
}
} else if (!path.startsWith("/WEB-INF/tags")) {
err.jspError("jsp.error.tagfile.illegalPath", path);
}
TagInfo tagInfo
= TagFileProcessor.parseTagFileDirectives(parserController, name,
path, this);
return new TagFileInfo(name, path, tagInfo);
}
TagAttributeInfo createAttribute(TreeNode elem, String jspVersion) {
String name = null;
String type = null;
boolean required = false, rtexprvalue = false, reqTime = false,
isFragment = 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 ("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) {
// 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);
}
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;
}
@@ -0,0 +1,242 @@
/*
* 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.struts2.jasper.compiler;
import org.apache.struts2.jasper.JasperException;
import org.apache.struts2.jasper.compiler.tagplugin.TagPlugin;
import org.apache.struts2.jasper.compiler.tagplugin.TagPluginContext;
import org.apache.struts2.jasper.xmlparser.ParserUtils;
import org.apache.struts2.jasper.xmlparser.TreeNode;
import javax.servlet.ServletContext;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
/**
* 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.
* <p/>
* 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 JspUtil.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;
}
}
}
@@ -0,0 +1,113 @@
/*
* 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.struts2.jasper.compiler;
import org.apache.struts2.jasper.JasperException;
import org.apache.struts2.jasper.Options;
/**
*/
public class TextOptimizer {
/**
* A visitor to concatenate contiguous template texts.
*/
static class TextCatVisitor extends Node.Visitor {
private Options options;
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();
}
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() && 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();
}
}
@@ -0,0 +1,560 @@
/*
* 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.struts2.jasper.compiler;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.commons.io.FileUtils;
import org.apache.struts2.jasper.Constants;
import org.apache.struts2.jasper.JasperException;
import org.apache.struts2.jasper.xmlparser.ParserUtils;
import org.apache.struts2.jasper.xmlparser.TreeNode;
import org.xml.sax.InputSource;
import javax.servlet.ServletContext;
import java.io.File;
import java.io.InputStream;
import java.net.*;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* A container for all tag libraries that are defined "globally"
* for the web application.
* <p/>
* 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.
* <p/>
* 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.
* <p/>
* 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 Logger log = LoggerFactory.getLogger(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 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();
noTldJars.add("ant.jar");
noTldJars.add("catalina.jar");
noTldJars.add("catalina-ant.jar");
noTldJars.add("catalina-cluster.jar");
noTldJars.add("catalina-optional.jar");
noTldJars.add("catalina-i18n-fr.jar");
noTldJars.add("catalina-i18n-ja.jar");
noTldJars.add("catalina-i18n-es.jar");
noTldJars.add("commons-dbcp.jar");
noTldJars.add("commons-modeler.jar");
noTldJars.add("commons-logging-api.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("commons-el.jar");
noTldJars.add("jakarta-regexp-1.2.jar");
noTldJars.add("jasper-compiler.jar");
noTldJars.add("jasper-runtime.jar");
noTldJars.add("jmx.jar");
noTldJars.add("jmx-tools.jar");
noTldJars.add("jsp-api.jar");
noTldJars.add("jkshm.jar");
noTldJars.add("jkconfig.jar");
noTldJars.add("naming-common.jar");
noTldJars.add("naming-resources.jar");
noTldJars.add("naming-factory.jar");
noTldJars.add("naming-java.jar");
noTldJars.add("servlet-api.jar");
noTldJars.add("servlets-default.jar");
noTldJars.add("servlets-invoker.jar");
noTldJars.add("servlets-common.jar");
noTldJars.add("servlets-webdav.jar");
noTldJars.add("tomcat-util.jar");
noTldJars.add("tomcat-http11.jar");
noTldJars.add("tomcat-jni.jar");
noTldJars.add("tomcat-jk.jar");
noTldJars.add("tomcat-jk2.jar");
noTldJars.add("tomcat-coyote.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");
}
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'.
* <p/>
* 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 a list of absolute paths of the locations in the cache
*/
public Set<String> getAbsolutePathsOfLocations() {
Set<String> paths = new HashSet<String>(mappings.size());
for (Object value : mappings.values()) {
String[] location = (String[]) value;
try {
File file = FileUtils.toFile(new URL(location[0]));
paths.add(file.getAbsolutePath());
} catch (Exception e) {
//ignore
}
}
return paths;
}
/**
* 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) {
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));
}
}
}
@@ -0,0 +1,38 @@
/*
* 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.struts2.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.
* <p/>
* 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);
}
@@ -0,0 +1,128 @@
/*
* 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.struts2.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);
}
@@ -0,0 +1,429 @@
# 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.
# $Id: LocalStrings.properties 685823 2008-08-14 09:04:26Z markt $
#
# Default localized string information
# Localized this the Default Locale as is en_US
jsp.error.compiler=No Java compiler available
jsp.error.bad.servlet.engine=Incorrect servlet engine version!
jsp.error.no.scratch.dir=The JSP engine is not configured with a scratch dir.\
\n Please add \"jsp.initparams=scratchdir=<dir-name>\" \
\n in the servlets.properties file for this context.
jsp.error.bad.scratch.dir=The scratchDir you specified: {0} is unusable.
jsp.message.scratch.dir.is=Scratch dir for the JSP engine is: {0}
jsp.message.parent_class_loader_is=Parent class loader is: {0}
jsp.message.dont.modify.servlets=IMPORTANT: Do not modify the generated servlets
jsp.error.not.impl.comments=Internal error: Comments not implemented
jsp.error.not.impl.directives=Internal error: Directives not implemented
jsp.error.not.impl.declarations=Internal error: Declarations not implemented
jsp.error.not.impl.expressions=Internal error: Expressions not implemented
jsp.error.not.impl.scriptlets=Internal error: Scriptlets not implemented
jsp.error.not.impl.usebean=Internal error: useBean not implemented
jsp.error.not.impl.getp=Internal error: getProperty not implemented
jsp.error.not.impl.setp=Internal error: setProperty not implemented
jsp.error.not.impl.plugin=Internal error: plugin not implemented
jsp.error.not.impl.forward=Internal error: forward not implemented
jsp.error.not.impl.include=Internal error: include not implemented
jsp.error.unavailable=JSP has been marked unavailable
jsp.error.usebean.missing.attribute=useBean: id attribute missing or misspelled
jsp.error.usebean.missing.type=useBean ({0}): Either class or type attribute must be \
specified:
jsp.error.usebean.duplicate=useBean: Duplicate bean name: {0}
jsp.error.usebean.prohibited.as.session=Can't use as session bean {0} since it is prohibited \
by jsp directive defined earlier:
jsp.error.usebean.not.both=useBean: Can't specify both class and beanName attribute:
jsp.error.usebean.bad.type.cast=useBean ({0}): Type ({1}) is not assignable from class ({2})
jsp.error.invalid.scope=Illegal value of \'scope\' attribute: {0} (must be one of \"page\", \"request\", \"session\", or \"application\")
jsp.error.classname=Can't determine classname from .class file
jsp.warning.bad.type=Warning: bad type in .class file
jsp.error.data.file.write=Error while writing data file
jsp.error.page.invalid.buffer=Page directive: invalid buffer size
jsp.error.page.conflict.contenttype=Page directive: illegal to have multiple occurrences of 'contentType' with different values (old: {0}, new: {1})
jsp.error.page.invalid.contenttype=Page directive: invalid value for contentType
jsp.error.page.conflict.session=Page directive: illegal to have multiple occurrences of 'session' with different values (old: {0}, new: {1})
jsp.error.page.invalid.session=Page directive: invalid value for session
jsp.error.page.conflict.buffer=Page directive: illegal to have multiple occurrences of 'buffer' with different values (old: {0}, new: {1})
jsp.error.page.invalid.buffer=Page directive: invalid value for buffer
jsp.error.page.conflict.autoflush=Page directive: illegal to have multiple occurrences of 'autoFlush' with different values (old: {0}, new: {1})
jsp.error.page.invalid.autoflush=Page directive: invalid value for autoFlush
jsp.error.page.conflict.isthreadsafe=Page directive: illegal to have multiple occurrences of 'isThreadSafe' with different values (old: {0}, new: {1})
jsp.error.page.invalid.isthreadsafe=Page directive: invalid value for isThreadSafe
jsp.error.page.conflict.info=Page directive: illegal to have multiple occurrences of 'info' with different values (old: {0}, new: {1})
jsp.error.page.invalid.info=Page directive: invalid value for info
jsp.error.page.conflict.iserrorpage=Page directive: illegal to have multiple occurrences of 'isErrorPage' with different values (old: {0}, new: {1})
jsp.error.page.invalid.iserrorpage=Page directive: invalid value for isErrorPage
jsp.error.page.conflict.errorpage=Page directive: illegal to have multiple occurrences of 'errorPage' with different values (old: {0}, new: {1})
jsp.error.page.conflict.language=Page directive: illegal to have multiple occurrences of 'language' with different values (old: {0}, new: {1})
jsp.error.tag.conflict.language=Tag directive: illegal to have multiple occurrences of 'language' with different values (old: {0}, new: {1})
jsp.error.page.language.nonjava=Page directive: invalid language attribute
jsp.error.tag.language.nonjava=Tag directive: invalid language attribute
jsp.error.page.defafteruse.language=Page directive: can't define language after a scriptlet
jsp.error.page.nomapping.language=Page directive: No mapping for language:
jsp.error.page.conflict.extends=Page directive: illegal to have multiple occurrences of 'extends' with different values (old: {0}, new: {1})
jsp.error.page.conflict.iselignored=Page directive: illegal to have multiple occurrences of 'isELIgnored' with different values (old: {0}, new: {1})
jsp.error.tag.conflict.iselignored=Tag directive: illegal to have multiple occurrences of 'isELIgnored' with different values (old: {0}, new: {1})
jsp.error.page.invalid.iselignored=Page directive: invalid value for isELIgnored
jsp.error.tag.invalid.iselignored=Tag directive: invalid value for isELIgnored
jsp.error.page.multi.pageencoding=Page directive must not have multiple occurrences of pageencoding
jsp.error.tag.conflict.attr=Tag directive: illegal to have multiple occurrences of the attribute \"{0}\" with different values (old: {1}, new: {2})
jsp.error.tag.multi.pageencoding=Tag directive must not have multiple occurrences of pageencoding
jsp.error.page.bad_b_and_a_combo=Page directive: Illegal combination of buffer=\"none\" && autoFlush=\"false\"
jsp.error.not.impl.taglib=Internal error: Tag extensions not implemented
jsp.error.include.missing.file=Missing file argument to include
jsp.error.include.bad.file=Bad file argument to include
jsp.error.include.exception=Unable to include {0}
jsp.error.stream.closed=Stream closed
jsp.error.invalid.forward=Invalid forward tag
jsp.error.unknownException=Unhandled error! You might want to consider having an error page \
to report such errors more gracefully
jsp.error.invalid.directive=Invalid directive
jsp.error.directive.istagfile={0} directive cannot be used in a tag file
jsp.error.directive.isnottagfile={0} directive can only be used in a tag file
jsp.error.tagfile.tld.name=The \"name\" attribute of the tag directive has a value {0} while the \"name\" tag of the \"tag-file\" element in the TLD is {1}
jsp.error.action.istagfile={0} action cannot be used in a tag file
jsp.error.action.isnottagfile={0} action can be used in tag files only
jsp.error.unterminated=Unterminated {0} tag
jsp.error.usebean.notinsamefile=useBean tag must begin and end in the same physical file
jsp.error.loadclass.taghandler=Unable to load tag handler class \"{0}\" for tag \"{1}\"
jsp.error.unable.compile=Unable to compile class for JSP
jsp.error.unable.load=Unable to load class for JSP
jsp.error.unable.rename=Unable to rename class file {0} to {1}
jsp.error.mandatory.attribute={0}: Mandatory attribute {1} missing
jsp.engine.info=Jasper JSP 2.0 Engine
jsp.error.invalid.expression="{0}" contains invalid expression(s): {1}
jsp.error.invalid.attribute={0} has invalid attribute: {1}
jsp.error.usebean.class.notfound=Class: {0} not found
jsp.error.file.cannot.read=Cannot read file: {0}
jsp.error.file.already.registered=Recursive include of file {0}
jsp.error.file.not.registered=file {0} not seen in include
jsp.error.quotes.unterminated=Unterminated quotes
jsp.error.attr.quoted=Attribute value should be quoted
jsp.error.attr.novalue=Attribute {0} has no value
jsp.error.tag.attr.unterminated=Unterminated tag attribute list
jsp.error.param.noname=No name in PARAM tag
jsp.error.param.novalue=No value in PARAM tag
jsp.error.beans.nullbean=Attempted a bean operation on a null object.
jsp.error.beans.nobeaninfo=No BeanInfo for the bean of type ''{0}'' could be found, the class likely does not exist.
jsp.error.beans.introspection=An exception occurred while introspecting the read method of property ''{0}'' in a bean of type ''{1}'':\n{2}
jsp.error.beans.nomethod=Cannot find a method to read property ''{0}'' in a bean of type ''{1}''
jsp.error.beans.nomethod.setproperty=Can''t find a method to write property ''{0}'' of type ''{1}'' in a bean of type ''{2}''
jsp.error.beans.noproperty=Cannot find any information on property ''{0}'' in a bean of type ''{1}''
jsp.error.beans.property.conversion=Unable to convert string \"{0}\" to class \"{1}\" for attribute \"{2}\": {3}
jsp.error.beans.propertyeditor.notregistered=Property Editor not registered with the PropertyEditorManager
jsp.error.beans.setproperty.noindexset=Cannot set indexed property
jsp.error.include.tag=Invalid jsp:include tag
jsp.error.include.noflush=jsp:include needs to have \"flush=true\"
jsp.error.include.badflush=jsp:include page=\"...\" flush=\"true\" is the only valid combination in JSP 1.0
jsp.error.attempt_to_clear_flushed_buffer=Error: Attempt to clear a buffer that's already been flushed
jsp.error.overflow=Error: JSP Buffer overflow
jsp.error.paramexpected=Expecting \"jsp:param\" standard action with \"name\" and \"value\" attributes
jsp.error.param.invalidUse=The jsp:param action must not be used outside the jsp:include, jsp:forward, or jsp:params elements
jsp.error.params.invalidUse=jsp:params must be a direct child of jsp:plugin
jsp.error.fallback.invalidUse=jsp:fallback must be a direct child of jsp:plugin
jsp.error.namedAttribute.invalidUse=jsp:attribute must be the subelement of a standard or custom action
jsp.error.jspbody.invalidUse=jsp:body must be the subelement of a standard or custom action
jsp.error.closeindividualparam=param tag needs to be closed with \"/>\"
jsp.error.closeparams=param tag needs to be closed with /params
jsp.error.params.emptyBody=jsp:params must contain at least one nested jsp:param
jsp.error.params.illegalChild=jsp:params must not have any nested elements other than jsp:param
jsp.error.plugin.notype=type not declared in jsp:plugin
jsp.error.plugin.badtype=Illegal value for 'type' attribute in jsp:plugin: must be 'bean' or 'applet'
jsp.error.plugin.nocode=code not declared in jsp:plugin
jsp.error.ise_on_clear=Illegal to clear() when buffer size == 0
jsp.error.setproperty.beanNotFound=setProperty: Bean {0} not found
jsp.error.getproperty.beanNotFound=getProperty: Bean {0} not found
jsp.error.setproperty.ClassNotFound=setProperty: Class {0} not found
# typo ?
#jsp.error.setproperty.invalidSayntax=setProperty: can't have non-null value when property=*
jsp.error.setproperty.invalidSyntax=setProperty: can't have non-null value when property=*
jsp.error.setproperty.beanInfoNotFound=setproperty: beanInfo for bean {0} not found
jsp.error.setproperty.paramOrValue=setProperty: either param or value can be present
jsp.error.setproperty.arrayVal=setProperty: can't set array property {0} through a string constant value
jsp.warning.keepgen=Warning: Invalid value for the initParam keepgenerated. Will use the default value of \"false\"
jsp.warning.xpoweredBy=Warning: Invalid value for the initParam xpoweredBy. Will use the default value of \"false\"
jsp.warning.enablePooling=Warning: Invalid value for the initParam enablePooling. Will use the default value of \"true\"
jsp.warning.invalidTagPoolSize=Warning: Invalid value for the init parameter named tagPoolSize. Will use default size of {0}
jsp.warning.mappedFile=Warning: Invalid value for the initParam mappedFile. Will use the default value of \"false\"
jsp.warning.sendErrToClient=Warning: Invalid value for the initParam sendErrToClient. Will use the default value of \"false\"
jsp.warning.classDebugInfo=Warning: Invalid value for the initParam classdebuginfo. Will use the default value of \"false\"
jsp.warning.checkInterval=Warning: Invalid value for the initParam checkInterval. Will use the default value of \"300\" seconds
jsp.warning.modificationTestInterval=Warning: Invalid value for the initParam modificationTestInterval. Will use the default value of \"4\" seconds
jsp.warning.development=Warning: Invalid value for the initParam development. Will use the default value of \"true\"
jsp.warning.fork=Warning: Invalid value for the initParam fork. Will use the default value of \"true\"
jsp.warning.reloading=Warning: Invalid value for the initParam reloading. Will use the default value of \"true\"
jsp.warning.dumpSmap=Warning: Invalid value for the initParam dumpSmap. Will use the default value of \"false\"
jsp.warning.genchararray=Warning: Invalid value for the initParam genStrAsCharArray. Will use the default value of \"false\"
jsp.warning.suppressSmap=Warning: Invalid value for the initParam suppressSmap. Will use the default value of \"false\"
jsp.error.badtaglib=Unable to open taglibrary {0} : {1}
jsp.error.badGetReader=Cannot create a reader when the stream is not buffered
jsp.warning.unknown.element.in.taglib=Unknown element ({0}) in taglib
jsp.warning.unknown.element.in.tag=Unknown element ({0}) in tag
jsp.warning.unknown.element.in.tagfile=Unknown element ({0}) in tag-file
jsp.warning.unknown.element.in.attribute=Unknown element ({0}) in attribute
jsp.warning.unknown.element.in.variable=Unknown element ({0}) in variable
jsp.warning.unknown.element.in.validator=Unknown element ({0}) in validator
jsp.warning.unknown.element.in.initParam=Unknown element ({0}) in validator's init-param
jsp.warning.unknown.element.in.function=Unknown element ({0}) in function
jsp.error.more.than.one.taglib=More than one taglib in the TLD: {0}
jsp.error.teiclass.instantiation=Failed to load or instantiate TagExtraInfo class: {0}
jsp.error.non_null_tei_and_var_subelems=Tag {0} has one or more variable subelements and a TagExtraInfo class that returns one or more VariableInfo
jsp.error.parse.error.in.TLD=Parse Error in the tag library descriptor: {0}
jsp.error.unable.to.open.TLD=Unable to open the tag library descriptor: {0}
jsp.buffer.size.zero=Buffer size <= 0
jsp.error.file.not.found=File \"{0}\" not found
jsp.message.copyinguri=Copying {0} into {1}
jsp.message.htmlcomment=\nStripping Comment: \t{0}
jsp.message.handling_directive=\nHandling Directive: {0}\t{1}
jsp.message.handling_plugin=\nPlugin: {0}
jsp.message.package_name_is=Package name is: {0}
jsp.message.class_name_is=Class name is: {0}
jsp.message.java_file_name_is=Java file name is: {0}
jsp.message.class_file_name_is=Class file name is: {0}
jsp.message.accepted=Accepted {0} at {1}
jsp.message.adding_jar=Adding jar {0} to my classpath
jsp.message.compiling_with=Compiling with: {0}
jsp.message.template_text=template text
jsp.error.missing_attribute=According to the TLD or the tag file, attribute {0} is mandatory for tag {1}
jsp.error.bad_attribute=Attribute {0} invalid for tag {1} according to TLD
jsp.error.tld.unable_to_read=Unable to read TLD \"{1}\" from JAR file \"{0}\": {2}
jsp.error.tld.unable_to_get_jar=Unable to get JAR resource \"{0}\" containing TLD: {1}
jsp.error.tld.missing_jar=Missing JAR resource \"{0}\" containing TLD
jsp.error.webxml_not_found=Could not locate web.xml
jsp.cmd_line.usage=Usage: jsptoservlet [-dd <path/to/outputDirectory>] [-keepgenerated] \
<.jsp files>
jsp.message.cp_is=Classpath {0} is: {1}
jsp.error.unable.to_load_taghandler_class=Unable to load tag handler class {0} because of {1}
jsp.error.unable.to_find_method=Unable to find setter method for attribute: {0}
jsp.error.unable.to_convert_string=Unable to convert a String to {0} for attribute {1}
jsp.error.unable.to_introspect=Unable to introspect on tag handler class: {0} because of {1}
jsp.error.bad_tag=No tag \"{0}\" defined in tag library imported with prefix \"{1}\"
jsp.error.xml.bad_tag=No tag \"{0}\" defined in tag library associated with uri \"{1}\"
jsp.error.bad_string_Character=Cannot extract a Character from a zero length array
jsp.error.bad_string_char=Cannot extract a char from a zero length array
jsp.warning.compiler.class.cantcreate=Can't create an instance of specified compiler plugin class {0} due to {1}. Will default to Sun Java Compiler.
jsp.warning.compiler.class.notfound=Specified compiler plugin class {0} not found. Will default to Sun Java Compiler.
jsp.warning.compiler.path.notfound=Specified compiler path {0} not found. Will default to system PATH.
jsp.error.jspc.uriroot_not_dir=The -uriroot option must specify a pre-existing directory
jsp.error.jspc.missingTarget=Missing target: Must specify -webapp or -uriroot, or one or more JSP pages
jsp.error.jspc.no_uriroot=The uriroot is not specified and cannot be located with the specified JSP file(s)
jspc.implicit.uriRoot=uriRoot implicitly set to "{0}"
jspc.usage=Usage: jspc <options> [--] <jsp files>\n\
where jsp files is\n\
\ -webapp <dir> A directory containing a web-app, whose JSP pages\n\
\ will be processed recursively\n\
or any number of\n\
\ <file> A file to be parsed as a JSP page\n\
where options include:\n\
\ -help Print this help message\n\
\ -v Verbose mode\n\
\ -d <dir> Output Directory (default -Djava.io.tmpdir)\n\
\ -l Outputs the name of the JSP page upon failure\n\
\ -s Outputs the name of the JSP page upon success\n\
\ -p <name> Name of target package (default org.apache.jsp)\n\
\ -c <name> Name of target class name (only applies to first JSP page)\n\
\ -mapped Generates separate write() calls for each HTML line in the JSP\n\
\ -die[#] Generates an error return code (#) on fatal errors (default 1)\n\
\ -uribase <dir> The uri directory compilations should be relative to\n\
\ (default "/")\n\
\ -uriroot <dir> Same as -webapp\n\
\ -compile Compiles generated servlets\n\
\ -webinc <file> Creates a partial servlet mappings in the file\n\
\ -webxml <file> Creates a complete web.xml in the file\n\
\ -ieplugin <clsid> Java Plugin classid for Internet Explorer\n\
\ -classpath <path> Overrides java.class.path system property\n\
\ -xpoweredBy Add X-Powered-By response header\n\
\ -trimSpaces Trim spaces in template text between actions, directives\n\
\ -javaEncoding <enc> Set the encoding charset for Java classes (default UTF-8)\n\
\ -source <version> Set the -source argument to the compiler (default 1.4)\n\
\ -target <version> Set the -target argument to the compiler (default 1.4)\n\
jspc.webxml.header=<?xml version="1.0" encoding="ISO-8859-1"?>\n\
\n\
<!DOCTYPE web-app\n\
\ PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"\n\
\ "http://java.sun.com/dtd/web-app_2_3.dtd">\n\
<!--\n\
Automatically created by Apache Jakarta Tomcat JspC.\n\
-->\n\
<web-app>\n\
\n
jspc.webxml.footer=\n\
</web-app>\n\
\n
jspc.webinc.header=\n\
<!--\n\
Automatically created by Apache Jakarta Tomcat JspC.\n\
Place this fragment in the web.xml before all icon, display-name,\n\
description, distributable, and context-param elements.\n\
-->\n
jspc.webinc.footer=\n\
<!--\n\
All session-config, mime-mapping, welcome-file-list, error-page, taglib,\n\
resource-ref, security-constraint, login-config, security-role,\n\
env-entry, and ejb-ref elements should follow this fragment.\n\
-->\n
jspc.webinc.insertEnd=<!-- JSPC servlet mappings end -->
jspc.webinc.insertStart=<!-- JSPC servlet mappings start -->
jspc.error.jasperException=error-the file ''{0}'' generated the following parse exception: {1}
jspc.error.generalException=ERROR-the file ''{0}'' generated the following general exception:
jspc.error.fileDoesNotExist=The file argument ''{0}'' does not exist
jspc.error.emptyWebApp=-webapp requires a trailing file argument
jsp.error.library.invalid=JSP page is invalid according to library {0}: {1}
jsp.error.tlvclass.instantiation=Failed to load or instantiate TagLibraryValidator class: {0}
jsp.error.tlv.invalid.page=Validation error messages from TagLibraryValidator for {0} in {1}
jsp.error.tei.invalid.attributes=Validation error messages from TagExtraInfo for {0}
jsp.parser.sax.propertynotsupported=SAX property not supported: {0}
jsp.parser.sax.propertynotrecognized=SAX property not recognized: {0}
jsp.parser.sax.featurenotsupported=SAX feature not supported: {0}
jsp.parser.sax.featurenotrecognized=SAX feature not recognized: {0}
jsp.error.no.more.content=End of content reached while more parsing required: tag nesting error?
jsp.error.parse.xml=XML parsing error on file {0}
jsp.error.parse.xml.line=XML parsing error on file {0}: (line {1}, col {2})
jsp.error.parse.xml.scripting.invalid.body=Body of {0} element must not contain any XML elements
jsp.error.internal.tldinit=Unable to initialize TldLocationsCache: {0}
jsp.error.internal.filenotfound=Internal Error: File {0} not found
jsp.error.internal.evaluator_not_found=Internal error: unable to load expression evaluator
jsp.error.parse.xml.invalidPublicId=Invalid PUBLIC ID: {0}
jsp.error.include.flush.invalid.value=Invalid value for the flush attribute: {0}
jsp.error.unsupported.encoding=Unsupported encoding: {0}
tld.error.variableNotAllowed=It is an error for a tag that has one or more variable subelements to have a TagExtraInfo class that returns a non-null object.
jsp.error.tldInWebDotXmlNotFound=Could not locate TLD {1} for URI {0} specified in web.xml
jsp.error.taglibDirective.absUriCannotBeResolved=The absolute uri: {0} cannot be resolved in either web.xml or the jar files deployed with this application
jsp.error.taglibDirective.missing.location=Neither \'uri\' nor \'tagdir\' attribute specified
jsp.error.taglibDirective.both_uri_and_tagdir=Both \'uri\' and \'tagdir\' attributes specified
jsp.error.invalid.tagdir=Tag file directory {0} does not start with \"/WEB-INF/tags\"
jsp.error.unterminated.user.tag=Unterminated user-defined tag: ending tag {0} not found or incorrectly nested
#jspx.error.templateDataNotInJspCdata=Validation Error: Element &lt;{0}&gt; cannot have template data. Template data must be encapsulated within a &lt;jsp:cdata&gt; element. [JSP1.2 PFD section 5.1.9]\nTemplate data in error: {1}
jspx.error.templateDataNotInJspCdata=Validation Error: Element &lt;{0}&gt; cannot have template data. Template data must be encapsulated within a &lt;jsp:text&gt; element. [JSP1.2 PFD section 5.1.9]\nTemplate data in error: {1}
#Error while processing taglib jar file {0}: {1}
jsp.error.taglib.reserved.prefix=The taglib prefix {0} is reserved
jsp.error.invalid.javaEncoding=Invalid java encodings. Tried {0} and then {1}. Both failed.
jsp.error.needAlternateJavaEncoding=Default java encoding {0} is invalid on your java platform. An alternate can be specified via the 'javaEncoding' parameter of JspServlet.
#Error when compiling, used for jsp line number error messages
jsp.error.single.line.number=An error occurred at line: {0} in the jsp file: {1}
jsp.error.multiple.line.number=\n\nAn error occurred between lines: {0} and {1} in the jsp file: {2}\n\n
jsp.error.java.line.number=An error occurred at line: {0} in the generated java file
jsp.error.corresponding.servlet=Generated servlet error:\n
jsp.error.empty.body.not.allowed=Empty body not allowed for {0}
jsp.error.jspbody.required=Must use jsp:body to specify tag body for {0} if jsp:attribute is used.
jsp.error.jspbody.emptybody.only=The {0} tag can only have jsp:attribute in its body.
jsp.error.no.scriptlets=Scripting elements ( &lt;%!, &lt;jsp:declaration, &lt;%=, &lt;jsp:expression, &lt;%, &lt;jsp:scriptlet ) are disallowed here.
jsp.error.internal.unexpected_node_type=Internal Error: Unexpected node type encountered
jsp.error.tld.fn.invalid.signature=Invalid syntax for function signature in TLD. Tag Library: {0}, Function: {1}
jsp.error.tld.fn.duplicate.name=Duplicate function name {0} in tag library {1}
jsp.error.tld.fn.invalid.signature.commaexpected=Invalid syntax for function signature in TLD. Comma ',' expected. Tag Library: {0}, Function: {1}.
jsp.error.tld.fn.invalid.signature.parenexpected=Invalid syntax for function signature in TLD. Parenthesis '(' expected. Tag Library: {0}, Function: {1}.
jsp.error.tld.mandatory.element.missing=Mandatory TLD element missing or empty: {0}
jsp.error.dynamic.attributes.not.implemented=The {0} tag declares that it accepts dynamic attributes but does not implement the required interface
jsp.error.nomatching.fragment=Cannot find an attribute directive (with name={0} and fragment=true) prior to the fragment directive.
jsp.error.attribute.noequal=equal symbol expected
jsp.error.attribute.noquote=quote symbol expected
jsp.error.attribute.unterminated=attribute for {0} is not properly terminated
jsp.error.attribute.noescape=Attribute value {0} is quoted with {1} which must be escaped when used within the value
jsp.error.missing.tagInfo=TagInfo object for {0} is missing from TLD
jsp.error.fragmentwithtype=Cannot specify both 'fragment' and 'type' attributes. If 'fragment' is present, 'type' is fixed as 'javax.servlet.jsp.tagext.JspFragment'
jsp.error.fragmentwithrtexprvalue=Cannot specify both 'fragment' and 'rtexprvalue' attributes. If 'fragment' is present, 'rtexprvalue' is fixed as 'true'
jsp.error.fragmentWithDeclareOrScope=Both 'fragment' and 'declare' or 'scope' attributes specified in variable directive
jsp.error.var_and_varReader=Only one of \'var\' or \'varReader\' may be specified
jsp.error.missing_var_or_varReader=Missing \'var\' or \'varReader\' attribute
jsp.warning.bad.urlpattern.propertygroup=Bad value {0} in the url-pattern subelement in web.xml
jsp.error.unknown_attribute_type=Unknown attribute type ({1}) for attribute {0}.
jsp.error.jspelement.missing.name=Mandatory XML-style \'name\' attribute missing
jsp.error.xmlns.redefinition.notimplemented=Internal error: Attempt to redefine xmlns:{0}. Redefinition of namespaces is not implemented.
jsp.error.could.not.add.taglibraries=Could not add one or more tag libraries.
jsp.error.duplicate.name.jspattribute=The attribute {0} specified in the standard or custom action also appears as the value of the name attribute in the enclosed jsp:attribute
jsp.error.not.in.template={0} not allowed in a template text body.
jsp.error.badStandardAction=Invalid standard action
jsp.error.xml.badStandardAction=Invalid standard action: {0}
jsp.error.tagdirective.badbodycontent=Invalid body-content ({0}) in tag directive
jsp.error.simpletag.badbodycontent=The TLD for the class {0} specifies an invalid body-content (JSP) for a SimpleTag.
jsp.error.config_pagedir_encoding_mismatch=Page-encoding specified in jsp-property-group ({0}) is different from that specified in page directive ({1})
jsp.error.prolog_pagedir_encoding_mismatch=Page-encoding specified in XML prolog ({0}) is different from that specified in page directive ({1})
jsp.error.prolog_config_encoding_mismatch=Page-encoding specified in XML prolog ({0}) is different from that specified in jsp-property-group ({1})
jsp.error.attribute.custom.non_rt_with_expr=According to TLD or attribute directive in tag file, attribute {0} does not accept any expressions
jsp.error.attribute.standard.non_rt_with_expr=The {0} attribute of the {1} standard action does not accept any expressions
jsp.error.scripting.variable.missing_name=Unable to determine scripting variable name from attribute {0}
jasper.error.emptybodycontent.nonempty=According to TLD, tag {0} must be empty, but is not
jsp.error.tagfile.nameNotUnique=The value of {0} and the value of {1} in line {2} are the same.
jsp.error.tagfile.nameFrom.noAttribute=Cannot find an attribute directive with a name attribute with a value \"{0}\", the value of this name-from-attribute attribute.
jsp.error.tagfile.nameFrom.badAttribute=The attribute directive (declared in line {1} and whose name attribute is \"{0}\", the value of this name-from-attribute attribute) must be of type java.lang.String, is \"required\" and not a \"rtexprvalue\".
jsp.error.page.noSession=Cannot access session scope in page that does not participate in any session
jsp.error.usebean.noSession=Illegal for useBean to use session scope when JSP page declares (via page directive) that it does not participate in sessions
jsp.error.xml.encodingByteOrderUnsupported = Given byte order for encoding \"{0}\" is not supported.
jsp.error.xml.encodingDeclInvalid = Invalid encoding name \"{0}\".
jsp.error.xml.encodingDeclRequired = The encoding declaration is required in the text declaration.
jsp.error.xml.morePseudoAttributes = more pseudo attributes is expected.
jsp.error.xml.noMorePseudoAttributes = no more pseudo attributes is allowed.
jsp.error.xml.versionInfoRequired = The version is required in the XML declaration.
jsp.error.xml.xmlDeclUnterminated = The XML declaration must end with \"?>\".
jsp.error.xml.reservedPITarget = The processing instruction target matching \"[xX][mM][lL]\" is not allowed.
jsp.error.xml.spaceRequiredInPI = White space is required between the processing instruction target and data.
jsp.error.xml.invalidCharInContent = An invalid XML character (Unicode: 0x{0}) was found in the element content of the document.
jsp.error.xml.spaceRequiredBeforeStandalone = White space is required before the encoding pseudo attribute in the XML declaration.
jsp.error.xml.sdDeclInvalid = The standalone document declaration value must be \"yes\" or \"no\", not \"{0}\".
jsp.error.xml.invalidCharInPI = An invalid XML character (Unicode: 0x{0}) was found in the processing instruction.
jsp.error.xml.versionNotSupported = XML version \"{0}\" is not supported, only XML 1.0 is supported.
jsp.error.xml.pseudoAttrNameExpected = a pseudo attribute name is expected.
jsp.error.xml.expectedByte = Expected byte {0} of {1}-byte UTF-8 sequence.
jsp.error.xml.invalidByte = Invalid byte {0} of {1}-byte UTF-8 sequence.
jsp.error.xml.operationNotSupported = Operation \"{0}\" not supported by {1} reader.
jsp.error.xml.invalidHighSurrogate = High surrogate bits in UTF-8 sequence must not exceed 0x10 but found 0x{0}.
jsp.error.xml.invalidASCII = Byte \"{0}\" not 7-bit ASCII.
jsp.error.xml.spaceRequiredBeforeEncodingInXMLDecl = White space is required before the encoding pseudo attribute in the XML declaration.
jsp.error.xml.spaceRequiredBeforeEncodingInTextDecl = White space is required before the encoding pseudo attribute in the text declaration.
jsp.error.xml.spaceRequiredBeforeVersionInTextDecl = White space is required before the version pseudo attribute in the text declaration.
jsp.error.xml.spaceRequiredBeforeVersionInXMLDecl = White space is required before the version pseudo attribute in the XML declaration.
jsp.error.xml.eqRequiredInXMLDecl = The '' = '' character must follow \"{0}\" in the XML declaration.
jsp.error.xml.eqRequiredInTextDecl = The '' = '' character must follow \"{0}\" in the text declaration.
jsp.error.xml.quoteRequiredInTextDecl = The value following \"{0}\" in the text declaration must be a quoted string.
jsp.error.xml.quoteRequiredInXMLDecl = The value following \"{0}\" in the XML declaration must be a quoted string.
jsp.error.xml.invalidCharInTextDecl = An invalid XML character (Unicode: 0x{0}) was found in the text declaration.
jsp.error.xml.invalidCharInXMLDecl = An invalid XML character (Unicode: 0x{0}) was found in the XML declaration.
jsp.error.xml.closeQuoteMissingInTextDecl = closing quote in the value following \"{0}\" in the text declaration is missing.
jsp.error.xml.closeQuoteMissingInXMLDecl = closing quote in the value following \"{0}\" in the XML declaration is missing.
jsp.error.xml.invalidHighSurrogate = High surrogate bits in UTF-8 sequence must not exceed 0x10 but found 0x{0}.
jsp.error.multiple.jsp = Cannot have multiple specifications of
jsp.error.jspoutput.conflict=&lt;jsp:output&gt;: illegal to have multiple occurrences of \"{0}\" with different values (old: {1}, new: {2})
jsp.error.jspoutput.doctypenamesystem=&lt;jsp:output&gt;: 'doctype-root-element' and 'doctype-system' attributes must appear together
jsp.error.jspoutput.doctypepulicsystem=&lt;jsp:output&gt;: 'doctype-system' attribute must appear if 'doctype-public' attribute appears
jsp.error.jspoutput.nonemptybody=&lt;jsp:output&gt; must not have a body
jsp.error.jspoutput.invalidUse=&lt;jsp:output&gt; must not be used in standard syntax
jsp.error.attributes.not.allowed = {0} must not have any attributes
jsp.error.tagfile.badSuffix=Missing \".tag\" suffix in tag file path {0}
jsp.error.tagfile.illegalPath=Illegal tag file path: {0}, must start with \"/WEB-INF/tags\" or \"/META-INF/tags\"
jsp.error.plugin.wrongRootElement=Name of root element in {0} different from {1}
jsp.error.attribute.invalidPrefix=The attribute prefix {0} does not correspond to any imported tag library
jsp.error.nested.jspattribute=A jsp:attribute standard action cannot be nested within another jsp:attribute standard action
jsp.error.nested.jspbody=A jsp:body standard action cannot be nested within another jsp:body or jsp:attribute standard action
jsp.error.variable.either.name=Either name-given or name-from-attribute attribute must be specified in a variable directive
jsp.error.variable.both.name=Cannot specify both name-given or name-from-attribute attributes in a variable directive
jsp.error.variable.alias=Both or none of the name-from-attribute and alias attributes must be specified in a variable directive
jsp.error.attribute.null_name=Null attribute name
jsp.error.jsptext.badcontent=\'&lt;\', when appears in the body of &lt;jsp:text&gt;, must be encapsulated within a CDATA
jsp.error.jsproot.version.invalid=Invalid version number: \"{0}\", must be \"1.2\" or \"2.0\"
jsp.error.noFunctionPrefix=The function {0} must be used with a prefix when a default namespace is not specified
jsp.error.noFunction=The function {0} cannot be located with the specified prefix
jsp.error.noFunctionMethod=Method \"{0}\" for function \"{1}\" not found in class \"{2}\"
jsp.error.function.classnotfound=The class {0} specified in TLD for the function {1} cannot be found: {2}
jsp.error.signature.classnotfound=The class {0} specified in the method signature in TLD for the function {1} cannot be found. {2}
jsp.error.text.has_subelement=&lt;jsp:text&gt; must not have any subelements
jsp.error.data.file.read=Error reading file \"{0}\"
jsp.error.prefix.refined=Attempt to redefine the prefix {0} to {1}, when it was already defined as {2} in the current scope.
jsp.error.nested_jsproot=Nested &lt;jsp:root&gt;
jsp.error.unbalanced.endtag=The end tag \"&lt;/{0}\" is unbalanced
jsp.error.invalid.bean=The value for the useBean class attribute {0} is invalid.
jsp.error.prefix.use_before_dcl=The prefix {0} specified in this tag directive has been previously used by an action in file {1} line {2}.
@@ -0,0 +1,423 @@
# 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.
# $Id: LocalStrings_es.properties 565193 2007-08-12 22:53:10Z markt $
#
# Default localized string information
# Localized para Locale es_ES
jsp.error.bad.servlet.engine=¡Versión incorrecta del motor servlet!
jsp.error.no.scratch.dir=El motor JSP no tiene configurado un directorio de trabajo.\
\n Añada \"jsp.initparams=scratchdir=<dir-name>\" \
\n en el fichero servlets.properties para este contexto.
jsp.error.bad.scratch.dir=El directorio de trabajo especificado: {0} no es utilizable.
jsp.message.scratch.dir.is=El directorio de trabajo para el motor JSP es: {0}
jsp.message.parent_class_loader_is=El cargador de clases es: {0}
jsp.message.dont.modify.servlets=IMPORTANTE: No modifique los servlets generados
jsp.error.not.impl.comments=Error Interno: Comments no implementado
jsp.error.not.impl.directives=Error Interno: Directives no implementado
jsp.error.not.impl.declarations=Error Interno: Declarations no implementado
jsp.error.not.impl.expressions=Error Interno: Expressions no implementado
jsp.error.not.impl.scriptlets=Error Interno: Scriptlets no implementado
jsp.error.not.impl.useBean=Error Interno: useBean no implementado
jsp.error.not.impl.getp=Error Interno: getProperty no implementado
jsp.error.not.impl.setp=Error Interno: setProperty no implementado
jsp.error.not.impl.plugin=Error Interno: plugin no implementado
jsp.error.not.impl.forward=Error Interno: forward no implementado
jsp.error.not.impl.include=Error Interno: include no implementado
jsp.error.unavailable=JSP ha sido marcado como no disponible
jsp.error.usebean.missing.attribute=useBean: falta atributo id o está mal digitado
jsp.error.usebean.missing.type=useBean ({0}): Se debe de especificar atributo class o type:
jsp.error.usebean.duplicate=useBean: Nombre de bean duplicado: {0}
jsp.error.usebean.prohibited.as.session=No puedo usar como bean de sesión {0} ya que está prohibido \
por directiva jsp definida previamente:
jsp.error.usebean.not.both=useBean: No puede especificar ambos atributos class y beanName:
jsp.error.usebean.bad.type.cast=useBean ({0}): Tipo ({1}) no es asignable desde clase ({2})
jsp.error.invalid.scope=Valor ilegal de atributo \'scope\': {0} (debe de ser uno de \"page\", \"request\", \"session\", o \"application\")
jsp.error.classname=No pude determinar el nombre de clase desde el fichero .class
jsp.warning.bad.type=Aviso: tipo incorrecto en archivo .class
jsp.error.data.file.write=Error mientras escribía el archivo de datos
jsp.error.page.invalid.buffer=Directiva Page: medida de buffer inválida
jsp.error.page.conflict.contenttype=Directiva Page: es ilegal tener múltiples ocurrencias de 'contentType' con valores distintos (viejo: {0}, nuevo: {1})
jsp.error.page.invalid.contenttype=Directiva Page: valor incorrecto para contentType
jsp.error.page.conflict.session=Directiva Page: es ilegal tener múltiples ocurrencias de 'session' con valores distintos (viejo: {0}, nuevo: {1})
jsp.error.page.invalid.session=Directiva Page: valor incorrecto para session
jsp.error.page.conflict.buffer=Directiva Page: es ilegal tener múltiples ocurrencias de 'buffer'con valores distintos (viejo: {0}, nuevo: {1})
jsp.error.page.invalid.buffer=Directiva Page: valor incorrecto para buffer
jsp.error.page.conflict.autoflush=Directiva Page: es ilegal tener múltiples ocurrencias de 'autoFlush' con valores distintos (viejo: {0}, nuevo: {1})
jsp.error.page.invalid.autoflush==Directiva Page: valor incorrecto para autoFlush
jsp.error.page.conflict.isthreadsafe=Directiva Page: es ilegal tener múltiples ocurrencias de 'isThreadSafe' con valores distintos (viejo: {0}, nuevo: {1})
jsp.error.page.invalid.isthreadsafe==Directiva Page: valor incorrecto para isThreadSafe
jsp.error.page.conflict.info=Directiva Page: es ilegal tener múltiples ocurrencias de 'info' con valores distintos (viejo: {0}, nuevo: {1})
jsp.error.page.invalid.info==Directiva Page: valor incorrecto para info
jsp.error.page.conflict.iserrorpage=Directiva Page: es ilegal tener múltiples ocurrencias de 'isErrorPage' con valores distintos (viejo: {0}, nuevo: {1})
jsp.error.page.invalid.iserrorpage==Directiva Page: valor incorrecto para isErrorPage
jsp.error.page.conflict.errorpage=Directiva Page: es ilegal tener múltiples ocurrencias de 'errorPage' con valores distintos (viejo: {0}, nuevo: {1})
jsp.error.page.conflict.language=Directiva Page: es ilegal tener múltiples ocurrencias de 'language' con valores distintos (viejo: {0}, nuevo: {1})
jsp.error.tag.conflict.language=Directiva Tag: es ilegal tener múltiples ocurrencias de 'language' con valores distintos (viejo: {0}, nuevo: {1})
jsp.error.page.language.nonjava=Directiva Page: atributo language incorrecto
jsp.error.tag.language.nonjava=Directiva Tag: atributo language incorrecto
jsp.error.page.defafterusar.language=Directiva Page: No puede definir language tras un scriptlet
jsp.error.page.nomapping.language=Directiva Page: No hay mapeado para language:
jsp.error.page.conflict.extends=Directiva Page: es ilegal tener múltiples ocurrencias de 'extends' con valores distintos (viejo: {0}, nuevo: {1})
jsp.error.page.conflict.iselignored=Directiva Page: es ilegal tener múltiples ocurrencias de 'isELIgnored' con valores distintos (viejo: {0}, nuevo: {1})
jsp.error.tag.conflict.iselignored=Directiva Tag: es ilegal tener múltiples ocurrencias de 'isELIgnored' con valores distintos (viejo: {0}, nuevo: {1})
jsp.error.page.invalid.iselignored=Directiva Page: valor inválido para isELIgnored
jsp.error.tag.invalid.iselignored=Directiva Tag: valor incorrecto para isELIgnored
jsp.error.page.multi.pageencoding=La directiva Page no debe de tener múltiples ocurrencias de pageencoding
jsp.error.tag.conflict.attr=Directiva Tag: es ilegal tener múltiples ocurrencias del atributo \"{0}\" con valores distintos (viejo: {1}, nuevo: {2})
jsp.error.tag.multi.pageencoding=La directiva Tag no debe de tener múltiples ocurrencias de pageencoding
jsp.error.page.bad_b_and_a_combo=Directiva Page: Combinación ilegal de buffer=\"none\" y autoFlush=\"false\"
jsp.error.not.impl.taglib=Error Interno: Tag extensions no implementado
jsp.error.include.missing.file=No tiene argumento de nombre de fichero
jsp.error.include.bad.file=Argumento de nombre de fichero no válido
jsp.error.include.exception=No se puede incluir {0}
jsp.error.stream.closed=Stream cerrado
jsp.error.invalid.forward=Tag forward no válido
jsp.error.unknownException=¡Error no caturado!. Deberías de considerar el poner una página de error para avisar de los errores más elegantemente
jsp.error.invalid.directive=Directiva no válida
jsp.error.directive.istagfile=La Directiva {0} no puede usarse en archivo de tag
jsp.error.directive.isnottagfile=La Directiva {0} sólo se puede usar en un archivo de tag
jsp.error.tagfile.tld.name=El atributo \"name\" de la directiva tag tiene un valor {0} mientras que el tag \"name\" del elemento \"tag-file\" en el TLD es {1}
jsp.error.action.istagfile=La acción {0} no se puede usar en un archivo tag
jsp.error.action.isnottagfile=La acción {0} sólo se puede usar en archivos tag
jsp.error.unterminated=Tag {0} no terminado
jsp.error.usebean.notinsamefile=El Tag useBean debe de empezar y terminar en el mismo archivo físico
jsp.error.loadclass.taghandler=No se puede cargar la clase {0}
jsp.error.unable.compile=No se puede compilar la clase para JSP
jsp.error.unable.load=No se puede cargar la clase para JSP
jsp.error.unable.rename=No se puede renombrar el archivo de clase {0} a {1}
jsp.error.mandatory.atributo={0}: atributo obligatorio {1} perdido
jsp.engine.info=Motor Jasper JSP 2.0
jsp.error.invalid.expression="{0}" contiene expresiones incorrectas: {1}
jsp.error.invalid.attribute={0}: Atributo incorrecto, {1}
jsp.error.usebean.class.notfound=Clase: {0} no hallada
jsp.error.file.cannot.read=No se puede leer el archivo: {0}
jsp.error.file.already.registered=El archivo {0} ya se ha visto, ¿podría ser un include recursivo?
jsp.error.file.not.registered=Archivo {0} not visto en include
jsp.error.quotes.unterminated=Comillas no terminadas
jsp.error.attr.quoted=El valor del atributo debería ir entre comillas
jsp.error.attr.novalue=Atributo {0} no tiene valor
jsp.error.tag.attr.unterminated=Lista de atributos del tag no terminada
jsp.error.param.noname=No hay nombre en el tag PARAM
jsp.error.param.novalue=No hay valor en el tag PARAM
jsp.error.beans.nullbean=Se ha intentado una operación de bean en un objeto nulo
jsp.error.beans.nobeaninfo=No se puede encontrar BeanInfo para el bean ''{0}'' seguramente la clase no existe
jsp.error.beans.introspection=Una excepción ha tenido lugar mientras se leía el método de lectura de la propiedad ''{0}'' en un bean del tipo ''{1}'':\n{2}
jsp.error.beans.nomethod=No puedo encontrar un método para leer la propiedad ''{0}'' en un bean del tipo ''{1}''
jsp.error.beans.nomethod.setproperty=No puedo encontrar un método para escribir la propiedad ''{0}'' en un bean del tipo ''{2}''
jsp.error.beans.noproperty=No puedo encontrar información de la propiedad ''{0}'' en un bean del tipo ''{1}''
jsp.error.beans.setproperty.noindexset=No puedo poner la propiedad indexada
jsp.error.include.tag=Tag jsp:include no válido
jsp.error.include.noflush=jsp:include necesita tener \"flush=true\"
jsp.error.include.badflush=jsp:include page=\"...\" flush=\"true\" es la única combinación válida en JSP 1.0
jsp.error.attempt_to_clear_flushed_buffer=Error: Se ha intentado limpiar un buffer que ya había sido escrito
jsp.error.overflow=Error:Buffer de JSP desbordado
jsp.error.paramexpected=El tag \"param\" era esperado con los atributos \"name\" y \"value\" después del tag \"params\".
jsp.error.param.invalidUse=La acción jsp:param no debe de ser usada fuera de los elementos jsp:include, jsp:forward o jsp:params
jsp.error.params.invalidUse=jsp:params debe de ser un hijo directo de jsp:plugin
jsp.error.fallback.invalidUse=jsp:fallback debe de ser un hijo directo de jsp:plugin
jsp.error.namedAttribute.invalidUse=jsp:attribute debe de ser el subelemento de una acción estándar o de cliente
jsp.error.jspbody.invalidUse=jsp:body debe de ser el subelemento de una acción estándar o de cliente
jsp.error.closeindividualparam=El tag param necesita ser cerrado con \"/>\"
jsp.error.closeparams=El tag param necesita ser cerrado con /params
jsp.error.params.emptyBody=jsp:params debe de contener al menos un jsp:param anidado
jsp.error.params.illegalChild=jsp:params no debe de contener elementos anidados que no sean jsp:param
jsp.error.plugin.notype=Tipo no declarado en jsp:plugin
jsp.error.plugin.badtype=Valor ilegal para atributo 'type' en jsp:plugin: debe de ser 'bean' o 'applet'
jsp.error.plugin.nocode=Código no declarado en jsp:plugin
jsp.error.ise_on_clear=Es ilegal usar clear() cuando el tamaño del buffer es cero
jsp.error.setproperty.beanNotFound=setProperty: Bean {0} no encontrado
jsp.error.getproperty.beanNotFound=getProperty: Bean {0} no encontrado
jsp.error.setproperty.ClassNotFound=setProperty: clase {0} no encontrada
# typo ?
#jsp.error.setproperty.invalidSayntax=setProperty: can't have non-null value when property=*
jsp.error.setproperty.invalidSyantax=setProperty: No puede haber un valor no nulo cuando se ha especificado property=*
jsp.error.setproperty.beanInfoNotFound=setproperty: beanInfo para bean {0} no encontrado
jsp.error.setproperty.paramOrValue=setProperty: O param o value pueden estar presentes
jsp.error.setproperty.arrayVal=setProperty: No puede escribir en la propiedad de array {0} a través de una valor de cadena literal
jsp.warning.keepgen=Aviso: valor incorrecto para el initParam keepgen. Se usará el valor por defecto de \"false\"
jsp.warning.xpoweredBy=Aviso: valor incorrecto para el initParam xpoweredBy. Se usará el valor por defecto de \"false\"
jsp.warning.enablePooling=Aviso: valor incorrecto para el initParam enablePooling. Se usará el valor por defecto de \"true\"
jsp.warning.invalidTagPoolSize=Aviso: valor incorrecto para el parámetro init llamado tagPoolSize. Se usará la medida por defecto de {0}
jsp.warning.mappedFile=Aviso: valor incorrecto para el initParam mappedFile. Se usará el valor por defecto de \"false\"
jsp.warning.sendErrToClient=Aviso: valor incorrecto para el initParam sendErrToClient. Se usará el valor por defecto de \"false\"
jsp.warning.classDebugInfo=Aviso: valor incorrecto para el initParam classdebuginfo. Se usará el valor por defecto de \"false\"
jsp.warning.checkInterval=Aviso: valor incorrecto para el initParam checkInterval. Se usará el valor por defecto de \"300\" segundos
jsp.warning.development=Aviso: valor incorrecto para el initParam development. Se usará el valor por defecto de \"true\"
jsp.warning.fork=Aviso: valor incorrecto para el initParam fork. Se usará el valor por defecto de \"true\"
jsp.warning.reloading=Aviso: valor incorrecto para el initParam reloading. Se usará el valor por defecto de \"true\"
jsp.warning.dumpSmap=Aviso: valor incorrecto para el initParam dumpSmap. Se usará el valor por defecto de \"false\"
jsp.warning.genchararray=Aviso: valor incorrecto para el initParam genStrAsCharArray. Se usará el valor por defecto de \"false\"
jsp.warning.suppressSmap=Aviso: valor incorrecto para el initParam suppressSmap. Se usará el valor por defecto de \"false\"
jsp.error.badtaglib=No se puede abrir la biblioteca de tags {0}: {1}
jsp.error.badGetReader=No se puede crear un reader cuando el stream no tiene buffer
jsp.warning.unknown.element.in.taglib=Elemento desconocido ({0}) en taglib
jsp.warning.unknown.element.in.tag=Elemento desconocido ({0}) en tag
jsp.warning.unknown.element.in.tagfile=Elemento desconocido ({0}) en tag-file
jsp.warning.unknown.element.in.attribute=Elemento desconocido ({0}) en attribute
jsp.warning.unknown.element.in.variable=Elemento desconocido ({0}) en variable
jsp.warning.unknown.element.in.validator=Elemento desconocido ({0}) en validator
jsp.warning.unknown.element.in.initParam=Elemento desconocido ({0}) en init-param de validator
jsp.warning.unknown.element.in.function=Elemento desconocido ({0}) en function
jsp.error.more.than.one.taglib=Más de una biblioteca de tags en el TLD: {0}
jsp.error.teiclass.instantiation=No se puede cargar la clase TagExtraInfo llamada: {0}
jsp.error.non_null_tei_and_var_subelems=Tag {0} tiene uno o más subelementos variable y una clase TagExtraInfo que devuelve una o más VariableInfo
jsp.error.parse.error.in.TLD=Error de análisis en el descriptor de biblioteca de tags: {0}
jsp.error.unable.to.open.TLD=No se puede abrir el descriptor de biblioteca de tags: {0}
jsp.buffer.size.zero=Tamaño de buffer <= 0
jsp.error.file.not.found=Archivo JSP \"{0}\" no encontrado
jsp.message.copyinguri=Copiando {0} en {1}
jsp.message.htmlcomment=\nQuitando comentario: \t{0}
jsp.message.handling_directive=\nResolviendo directiva: {0}\t{1}
jsp.message.handling_plugin=\nPlugin: {0}
jsp.message.package_name_is=El Nombre del Package es: {0}
jsp.message.class_name_is=El Nombre de la clase es: {0}
jsp.message.java_file_name_is=El Nombre del Archivo Java es: {0}
jsp.message.class_file_name_is=El Nombre del Archivo de clase es: {0}
jsp.message.accepted=Aceptó {0} en {1}
jsp.message.adding_jar=Añadiendo jar {0} a mi classpath
jsp.message.compiling_with=Compilado con: {0}
jsp.message.template_text=texto plantilla
jsp.error.missing_attribute=De acuerdo con el TLD el atributo {0} es obligatorio para el tag {1}
jsp.error.bad_attribute=El atributo {0} no es válido según el TLD especificado
jsp.error.tld.unable_to_read=Imposible de leer TLD \"{1}\" desde archivo JAR \"{0}\": {2}
jsp.error.tld.unable_to_get_jar=Imposible obtener recurso JAR \"{0}\" conteniendo TLD: {1}
jsp.error.tld.missing_jar=Falta recurso JAR \"{0}\" conteniendo TLD
jsp.error.webxml_not_found=No puedo localizar web.xml
jsp.cmd_line.usage=Uso: jsptoservlet [-dd <ruta/a/DirectorioSalida>] [-keepgenerated] <Archivos .jsp>
jsp.message.cp_is=Classpath {0} es: {1}
jsp.error.unable.to_load_taghandler_class=No se puede cargar clase manejadora {0} del tag a causa de {1}
jsp.error.unable.to_find_method=No se puede encontrar el método de escritura para el atributo: {0}
jsp.error.unable.to_convert_string=No pude convertir un String a {0} para atributo {1}
jsp.error.unable.to_introspect=No se puede hacer introspección en manejador de tag clase: {0} a causa de {1}
jsp.error.bad_tag=No existe el tag {0} en la biblioteca importada con prefijo {1}
jsp.error.xml.bad_tag=No se ha definido el tag \"{0}\" en la biblioteca tag asociada con uri \"{1}\"
jsp.error.bad_string_Character=No puede extraer un Character desde un array de tamaño cero
jsp.error.bad_string_char=No puede extraer un char desde un array de tamaño cero
jsp.warning.compiler.class.cantcreate=No puedo crear una instancia de la clase especificada {0} de plugin del compilador debido a {1}. Se usará el compilador Java de Sun.
jsp.warning.compiler.class.notfound=No puedo encontrar una instancia de la clase {0} de plugin de compilador. Se usará el compilador del Java de Sun.
jsp.warning.compiler.path.notfound=Trayectoria del compilador especificado {0} no encontrada. Se usará el PATH del sistema.
jsp.error.jspc.uriroot_not_dir=La opción -uriroot debe de especificar un directorio ya existente
jsp.error.jspc.missingTarget=Falta target: Debe de especificar -webapp o -uriroot o una o más páginas JSP
jsp.error.jspc.no_uriroot=No se ha especificado uriroot y no puede ser localizado en los archivos JSP especificados
jspc.implicit.uriRoot=uriRoot implicitamente puesto a "{0}"
jspc.usage=Uso: jspc <opciones> [--] <Archivos JSP>\n\
donde <Archivos JSP> son:\n\
\ -webapp <dir> Un directorio conteniendo una web-app. Todas las\n\
\ páginas jsp serán compiladas recursivamente\n\
o cualquier número de\n\
\ <Archivo> Un Archivo para ser interpretado como una página jsp\n\
y donde <opciones> incluyen:\n\
\ -help Muestra este mensaje de ayuda\n\
\ -v Modo detallado\n\
\ -d <dir> Directorio de salida\n\
\ -l Muestra el nombre de la página JSP al ocurrir un fallo\n\
\ -s Muestra el nombre de la página JSP al tener éxito\n\
\ -p <name> Nombre del package objetivo\n\
\ (por defecto org.apache.jsp)\n\
\ -c <name> Nombre de la clase objetivo\n\
\ (sólo se aplica a la primera página JSP)\n\
\ -mapped Genera llamadas separadas a write() para cada línea de\n\
\ HTML en el JSP\n\
\ -die[#] Genera un código de retorno de error (#) en errores\n\
\ fatales. (por defecto 1).\n\
\ -uribase <dir> El directorio uri de donde deben de partir las\n\
\ compilaciones. (por defecto "/")\n\
\ -uriroot <dir> Igual que -webapp\n\
\ -compile Compila los servlets generados\n\
\ -webinc <file> Crea unos mapeos parciales de servlet en el archivo\n\
\ -webxml <file> Crea un web.xml completo en el archivo.\n\
\ -ieplugin <clsid> Java Plugin classid para Internet Explorer\n\
\ -classpath <path> Pasa por alto la propiedad de sistema java.class.path\n\
\ -xpoweredBy Añade cabecera de respuesta X-Powered-By\n\
\ -trimSpaces Trim spaces in template text between actions, directives\n\
\ -javaEncoding <enc> Set the encoding charset for Java classes (default UTF-8)\n\
\ -source <version> Set the -source argument to the compiler (default 1.4)\n\
\ -target <version> Set the -target argument to the compiler (default 1.4)\n\
jspc.webxml.header=<?xml version="1.0" encoding="ISO-8859-1"?>\n\
\n\
<!DOCTYPE web-app\n\
\ PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"\n\
\ "http://java.sun.com/dtd/web-app_2_3.dtd">\n\
<!--\n\
Creado automaticamente mediante Apache Jakarta Tomcat JspC.\n\
-->\n\
<web-app>\n\
\n
jspc.webxml.footer=\n\
</web-app>\n\
\n
jspc.webinc.header=\n\
<!--\n\
Creado automaticamente mediante Apache Jakarta Tomcat JspC.\n\
Coloque este fragmento en el fichero web.xml antes de \n\
todos los elementos: icon, display-name, description, \n\
distributable y context-param .\n\
-->\n
jspc.webinc.footer=\n\
<!--\n\
Los Elementos: session-config, mime-mapping, welcome-file-list, error-page, taglib,\n\
resource-ref, security-constraint, login-config, security-role,\n\
env-entry y ejb-ref deberán de ir después de este fragmento .\n\
-->\n
jspc.webinc.insertEnd=<!-- Fin de mapeos de servlet JSPC -->
jspc.webinc.insertStart=<!-- Inicio de mapeos de servlet JSPC -->
jspc.error.jasperException=error-el archivo ''{0}'' ha generado la excepción de sintáxis siguiente: {1}
jspc.error.generalException=ERROR-el archivo ''{0}'' ha generado la excepción general siguiente:
jspc.error.fileDoesNotExist=El archivo ''{0}'' utilizado como argumento no existe.
jspc.error.emptyWebApp=-webapp necesita un argumento de archivo
jsp.error.library.invalid=La página JSP es incorrecta de acuerdo a la biblioteca {0}: {1}
jsp.error.tlvclass.instantiation=No pude cargar o instanciar clase TagLibraryValidator: {0}
jsp.error.tlv.invalid.page=Mensajes de error de validación desde TagLibraryValidator para {0} in {1}
jsp.error.tei.invalid.attributes=Mensajes de error de validación desde TagExtraInfo para {0}
jsp.parser.sax.propertynotsupported=Propiedad SAX no soportada: {0}
jsp.parser.sax.propertynotrecognized=Propiedad SAX no reconocida: {0}
jsp.parser.sax.featurenotsupported=Característica SAX no soportada: {0}
jsp.parser.sax.featurenotrecognized=Característica SAX no reconocida: {0}
jsp.error.no.more.content=Alcanzado fin de contenido mietras se requería más análisis: ¿error de anidamiento de tag?
jsp.error.parse.xml=Error de análisis XML en archivo {0}
jsp.error.parse.xml.line=Error de análisis XML en archivo {0}: (línea {1}, col {2})
jsp.error.parse.xml.scripting.invalid.body=El cuerpo de elemento {0} no debe de contener elementos XML
jsp.error.internal.tldinit=No pude inicializar TldLocationsCache: {0}
jsp.error.internal.filenotfound=Error Interno: Archivo {0} no hallado
jsp.error.internal.evaluator_not_found=Error interno: no pude cargar evaluador de expresiones
jsp.error.parse.xml.invalidPublicId=PUBLIC ID incorrecta: {0}
jsp.error.include.flush.invalid.value=Valor incorrecto para atributo flush: {0}
jsp.error.unsupported.encoding=Codificación no soportada: {0}
tld.error.variableNotAllowed=Es un error para un tag, que tiene uno o más subelementos variables, el tener una clase TagExtraInfo que devuelve un objeto no nulo.
jsp.error.tldInWebDotXmlNotFound=No pude localizar TLD {1} para URI {0} especificado en web.xml
jsp.error.taglibDirective.absUriCannotBeResolved=La uri absoluta: {0} no puede resolverse o en web.xml o el los archivos jar desplegados con esta aplicación
jsp.error.taglibDirective.missing.location=No se ha especificado ni el atributo \'uri\' ni el \'tagdir\'
jsp.error.taglibDirective.both_uri_and_tagdir=Se han especificado ambos atributos \'uri\' y \'tagdir\'
jsp.error.invalid.tagdir=El directorio de archivo Tag {0} no comienza con \"/WEB-INF/tags\"
jsp.error.unterminated.user.tag=Tag definido por usuario no terminado: tag final {0} no hallado o anidado incorrectamente
#jspx.error.templateDataNotInJspCdata=Validation Error: Element &lt;{0}&gt; cannot have template data. Template data must be encapsulated within a &lt;jsp:cdata&gt; element. [JSP1.2 PFD section 5.1.9]\nTemplate data in error: {1}
jspx.error.templateDataNotInJspCdata=Error de Validación: El Elemento &lt;{0}&gt; no puede tener datos plantilla. Los datos plantilla deben de estar encapsulados dentro de un elemento &lt;jsp:text&gt;. [JSP1.2 PFD sección 5.1.9]\nDatos de Plantilla en error: {1}
#Error while processing taglib jar file {0}: {1}
jsp.error.taglib.reserved.prefix=El prefijo taglib {0} está reservado
jsp.error.invalid.javaEncoding=Codificaciones java incorrectas. Intenté {0} y luego {1}. Ambas fallaron.
jsp.error.needAlternateJavaEncoding=La codificación java por defecto {0} es incorrecta en tu plataforma java. Se puede especificar una alternativa vía parámetro 'javaEncoding' de JspServlet.
#Error when compiling, used for jsp line number error messages
jsp.error.single.line.number=Ha tenido lugar un error en la línea: {0} en el archivo jsp: {1}
jsp.error.multiple.line.number=\n\nHa tenido lugar un error entre las líneas: {0} y {1} en el archivo jsp: {2}\n\n
jsp.error.corresponding.servlet=Error de servlet generado:\n
jsp.error.empty.body.not.allowed=Cuerpo vacío no permitido para {0}
jsp.error.jspbody.required=Se debe de usar jsp:body para especificar cuerpo tag para {0} si se usa jsp:attribute.
jsp.error.jspbody.emptybody.only=El tag {0} sólo puede tener jsp:attribute en su cuerpo.
jsp.error.no.scriptlets=Los elementos de Scripting (&lt;%!, &lt;jsp:declaration, &lt;%=, &lt;jsp:expression, &lt;%, &lt;jsp:scriptlet ) no están permitidos aquí.
jsp.error.internal.unexpected_node_type=Error Interno: Encontrado tipo de nodo inesperado
jsp.error.tld.fn.invalid.signature=Sintáxis incorrecta para firma de función en TLD. Biblioteca de Tag: {0}, Función: {1}
jsp.error.tld.fn.duplicate.name=Nombre duplicado de función {0} en biblioteca de tag {1}
jsp.error.tld.fn.invalid.signature.commaexpected=Sintáxis incorrecta para firma de función en TLD. Se esperaba Coma ','. Biblioteca de Tag: {0}, Función: {1}.
jsp.error.tld.fn.invalid.signature.parenexpected=Sintáxis incorrecta para firma de función en TLD. Se esperaba Paréntesis '('. Biblioteca de Tag: {0}, Función: {1}.
jsp.error.tld.mandatory.element.missing=Falta o está vacío elemento TLD obligatorio: {0}
jsp.error.dynamic.attributes.not.implemented=El tag {0} declara que acepta atributos dinámicos pero no implementa la interfaz requerida
jsp.error.nomatching.fragment=No puedo hallar una directiva de atributo (con name={0} y fragment=true) antes de la directiva de fragment.
jsp.error.attribute.noequal=se esperaba símbolo igual
jsp.error.attribute.noquote=se esperaba símbolo comillas
jsp.error.attribute.unterminated=el atributo para {0} no está terminado correctamente
jsp.error.missing.tagInfo=El objeto TagInfo para {0} falta del TLD
jsp.error.fragmentwithtype=No puede especificar ambos atributos 'fragment' y 'type'. Si está presente 'fragment', 'type' se pone como 'javax.servlet.jsp.tagext.JspFragment'
jsp.error.fragmentwithrtexprvalue=No puede especificar ambos atributos 'fragment' y 'rtexprvalue'. Si está presente 'fragment', 'rtexprvalue' se pone como 'true'
jsp.error.fragmentWithDeclareOrScope=Ambos atributos 'fragment' y 'declare' o 'scope' se han especificado en la directiva variable
jsp.error.var_and_varReader=Sólo se puede especificar uno de \'var\' o \'varReader\'
jsp.error.missing_var_or_varReader=Falta atributo \'var\' o \'varReader\'
jsp.warning.bad.urlpattern.propertygroup=Valor malo {0} en el subelemento url-pattern en web.xml
jsp.error.unknown_attribute_type=Tipo de atributo desconocido ({1}) para atributo {0}.
jsp.error.jspelement.missing.name=Falta atributo obligatorio XML-style \'name\'
jsp.error.xmlns.redefinition.notimplemented=Error interno: Intento de redefinir xmlns:{0}. La redefinición de espacios de nombre no está implementada.
jsp.error.could.not.add.taglibraries=No pude añadir una o más bibliotecas.
jsp.error.duplicate.name.jspattribute=El atributo {0} especificado en la acción standard o custom también aparece como el valor del atributo name en jsp:attribute
jsp.error.not.in.template={0} no permitido en una plantilla cuerpo de texto.
jsp.error.badStandardAction=Acción estándar incorrecta
jsp.error.xml.badStandardAction=Acción estándar incorrecta: {0}
jsp.error.tagdirective.badbodycontent=body-content incorrecto ({0}) en directiva tag
jsp.error.simpletag.badbodycontent=El TLD para la clase {0} especifica un body-content es incorrecto (JSP) para un SimpleTag.
jsp.error.config_pagedir_encoding_mismatch=El Page-encoding especificado en jsp-property-group ({0}) es diferente del especificado en la diectiva page ({1})
jsp.error.prolog_pagedir_encoding_mismatch=El Page-encoding especificado en XML prolog ({0}) difiere del especificado en la directiva page ({1})
jsp.error.prolog_config_encoding_mismatch=El Page-encoding especificado en XML prolog ({0}) difiere del especificado en jsp-property-group ({1})
jsp.error.attribute.custom.non_rt_with_expr=Según el TLD o la directiva attribute del archivo tag, el atributo {0} no acepta expresiones
jsp.error.attribute.standard.non_rt_with_expr=El atributo {0} de la acción estándar {1} no acepta expresiones
jsp.error.scripting.variable.missing_name=Imposible determinar nombre de variable de scripting desde atributo {0}
jasper.error.emptybodycontent.nonempty=Según el TLD, el tag {0} debe de estar vacío, pero no lo está
jsp.error.tagfile.nameNotUnique=El valor de {0} y el valor de {1} en la línea {2} son el mismo.
jsp.error.tagfile.nameFrom.noAttribute=No puedo hallar una directiva attribute con un atributo name con un valor \"{0}\", el valor de este atributo name-from-attribute.
jsp.error.tagfile.nameFrom.badAttribute=La directiva attribute (declarada en la línea {1} y cuyo atributo name es \"{0}\", el valor de este atributo name-from-attribute attribute) debe de ser del tipo java.lang.String, es \"required\" y no un \"rtexprvalue\".
jsp.error.page.noSession=No puedo acceder al ámbito de sesión en una página que no participa en una sesión
jsp.error.useBean.noSession=Es ilegal para useBean usar un ámbito de sesión cuando la página JSP declara (vía directiva page) que no participa en sesiones
jsp.error.xml.encodingByteOrderUnsupported=El orden de byte dado para encoding \"{0}\" no está soportado
jsp.error.xml.encodingDeclInvalid=Nombre de codificación \"{0}\" incorrecto.
jsp.error.xml.encodingDeclRequired=Se necesita la declaración encoding en la declaración de texto
jsp.error.xml.morePseudoAttributes=se esperan más pseudo-atributos
jsp.error.xml.noMorePseudoAttributes=no se permiten más pseudo-atributos.
jsp.error.xml.versionInfoRequired=Se requiere la versión en la declaración XML.
jsp.error.xml.xmlDeclUnterminated=La declaración XML debe de terminar con \"?>\".
jsp.error.xml.reservedPITarget=La instrucción de procesamiento que coincide con \"[xX][mM][lL]\" no está permitida.
jsp.error.xml.spaceRequiredInPI=Se necesita un espacio en blanco entre la instrucción de procesamiento y los datos.
jsp.error.xml.invalidCharInContent=Un carácter XML incorrecto (Unicode: 0x{0}) se halló en el contenido del elemento del documento.
jsp.error.xml.spaceRequiredBeforeStandalone=Se necesita un espacio en blanco antes del pseudo-atributo encoding en la declaración XML.
jsp.error.xml.sdDeclInvalid=El valor de declaración de documento standalone debe de ser \"yes\" o \"no\", no \"{0}\".
jsp.error.xml.invalidCharInPI=Se halló un carácter XML incorrecto (Unicode: 0x{0}) en la instrucción de procesamiento
jsp.error.xml.versionNotSupported=No se soporta la versión XML \"{0}\", sólo se soporta XML 1.0
jsp.error.xml.pseudoAttrNameExpected=se esperaba un pseudo-atributo name.
jsp.error.xml.expectedByte=Se esperaba byte {0} de {1}-byte de secuencia UTF-8.
jsp.error.xml.invalidByte=Incorrecto byte {0} de {1}-byte de secuencia UTF-8.
jsp.error.xml.operationNotSupported=La operación \"{0}\" no está soportada por lector {1}.
jsp.error.xml.invalidHighSurrogate=Surrogación Alta de bits en secuencia UTF-8 no debe de exceder 0x10, pero se halló 0x{0}.
jsp.error.xml.invalidASCII=El Byte \"{0}\" no es ASCII de 7-bit.
jsp.error.xml.spaceRequiredBeforeEncodingInXMLDecl=Se necesita espacio en blanco antes del pseudo-atributo encoding en la declaración XML.
jsp.error.xml.spaceRequiredBeforeEncodingInTextDecl=Se necesita espacio en blanco antes del pseudo-atributo encoding en la declaración text.
jsp.error.xml.spaceRequiredBeforeVersionInTextDecl=Se necesita espacio en blanco antes del pseudo-atributo version en la declaración text.
jsp.error.xml.spaceRequiredBeforeVersionInXMLDecl=Se necesita espacio en blanco antes del pseudo-atributo version en la declaración XML.
jsp.error.xml.eqRequiredInXMLDecl=El carácter '' = '' debe de serguir a \"{0}\" en la declaración XML.
jsp.error.xml.eqRequiredInTextDecl=El carácter '' = '' debe de serguir a \"{0}\" en la declaración text.
jsp.error.xml.quoteRequiredInTextDecl=El valor que sigue a \"{0}\" en la declaración text debe de ser una cadena entre comillas.
jsp.error.xml.quoteRequiredInXMLDecl=El valor que sigue a \"{0}\" en la declaración XML debe de ser un cadena entre comillas.
jsp.error.xml.invalidCharInTextDecl=Un carácter XML incorrecto (Unicode: 0x{0}) se halló en la declaración text
jsp.error.xml.invalidCharInXMLDecl=Un carácter XML incorrecto (Unicode: 0x{0}) se halló en la declaración XML
jsp.error.xml.closeQuoteMissingInTextDecl=Faltan las comillas de cierre en el valor que sigue a \"{0}\" en la declaración text.
jsp.error.xml.closeQuoteMissingInXMLDecl=Faltan las comillas de cierre en el valor que sigue a \"{0}\" en la declaración XML.
jsp.error.multiple.jsp=No puedo tener múltiples especificaciones de
jsp.error.jspoutput.conflict=&lt;jsp:output&gt;: ilegal tener ocurrencias múltiples de \"{0}\" con diferentes valores (viejo: {1}, nuevo: {2})
jsp.error.jspoutput.doctypenamesystem=&lt;jsp:output&gt;: atributos 'doctype-root-element' y 'doctype-system' deben de aparecer juntos
jsp.error.jspoutput.doctypepulicsystem=&lt;jsp:output&gt;: atributo 'doctype-system' debe de aparecer si aparece atributo 'doctype-public'
jsp.error.jspoutput.nonemptybody=&lt;jsp:output&gt; no debe de tener un cuerpo
jsp.error.jspoutput.invalidUse=&lt;jsp:output&gt; no se debe de usar en sintáxis estándar
jsp.error.attributes.not.allowed = {0} no debe de tener atributos
jsp.error.tagfile.badSuffix=Falta sufijo \".tag\" en trayectoria de archivo de tag {0}
jsp.error.tagfile.illegalPath=Trayectoria de archivo de tag: {0}, debe de comenzar con \"/WEB-INF/tags\" o \"/META-INF/tags\"
jsp.error.plugin.wrongRootElement=El nombre del elemento raíz en {0} difiere de {1}
jsp.error.attribute.invalidPrefix=El prefijo de atributo {0} no se correponde con ninguna biblioteca importada
jsp.error.nested.jspattribute=Una acción estándar jsp:attribute no puede estar anidada dentro de otra acción estándar jsp:attribute
jsp.error.nested.jspbody=Una acción estándar jsp:body no puede estar anidada dentro de otra acción estándar jsp:body o jsp:attribute
jsp.error.variable.either.name=O el atributo name-given o name-from-attribute deben de ser especificados en una directiva variable
jsp.error.variable.both.name=No se puede especificar ambos atributos name-given o name-from-attribute en una directiva variable
jsp.error.variable.alias=Ambos atributos o ninguno de name-from-attribute y alias pueden ser especificados en una directiva variable
jsp.error.attribute.null_name=Nombre de atributo nulo
jsp.error.jsptext.badcontent=\'&lt;\', cuando aparece en el cuerpo de &lt;jsp:text&gt;, debe de estar encapsulado dentro de un CDATA
jsp.error.jsproot.version.invalid=Número incorrecto de versión: \"{0}\", debe de ser \"1.2\" o \"2.0\"
jsp.error.noFunctionPrefix=La función {0} debe de usarse con un prefijo cuando no se especifica un espacio de nombres por defecto
jsp.error.noFunction=La función {0} no puede ser localizada mediante el prefijo especificado
jsp.error.noFunctionMethod=El método \"{0}\" para la función \"{1}\" no se pudo hallar en la clase \"{2}\"
jsp.error.function.classnotfound=La clase {0} especificada en el TLD para la función {1} no se puede hallar: {2}
jsp.error.signature.classnotfound=La clase {0} especificada en la firma del método en el TLD para la función {1} no se puede hallar. {2}
jsp.error.text.has_subelement=&lt;jsp:text&gt; no debe de tener subelementos
jsp.error.data.file.read=Error leyendo archivo \"{0}\"
jsp.error.prefix.refined=Intento de redefinir el prefijo {0} por {1}, cuando ya estaba definido como {2} en el ámbito en curso.
jsp.error.nested_jsproot=&lt;jsp:root&gt; anidado
jsp.error.unbalanced.endtag=El tgag final \"&lt;/{0}\" está desequilibrado
jsp.error.invalid.bean=
@@ -0,0 +1,320 @@
# 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.
# $Id: LocalStrings_fr.properties 565193 2007-08-12 22:53:10Z markt $
#
# Default localized string information
# Localized this the Default Locale as is fr_FR
jsp.error.bad.servlet.engine=Version de moteur de servlet incorrecte!
jsp.error.no.scratch.dir=Le moteur de JSP engine n''est pas configuré avec un répertoire de travail.\
\n Merci d''ajouter \"jsp.initparams=scratchdir=<dir-name>\" \
\n dans le fichier "servlets.properties" de ce contexte.
jsp.error.bad.scratch.dir=Le paramêtre "scratchDir" que vous avez spécifié: {0} est inutilisable.
jsp.message.scratch.dir.is=Le répertoire de travail (scratch dir) pour le moteur de JSP est: {0}
jsp.message.parent_class_loader_is=Le chargeur de classe parent (class loader) est: {0}
jsp.message.dont.modify.servlets=IMPORTANT: Ne pas modifier les servlets générées
jsp.error.not.impl.comments=Erreur interne: Commentaires non implémentés
jsp.error.not.impl.directives=Erreur interne: Directives non implémentées
jsp.error.not.impl.declarations=Erreur interne: Declarations non implémentées
jsp.error.not.impl.expressions=Erreur interne: Expressions non implémentées
jsp.error.not.impl.scriptlets=Erreur interne: Scriptlets non implémentés
jsp.error.not.impl.usebean=Erreur interne: useBean non implémenté
jsp.error.not.impl.getp=Erreur interne: getProperty non implémenté
jsp.error.not.impl.setp=Erreur interne: setProperty non implémenté
jsp.error.not.impl.plugin=Erreur interne: plugin non implémenté
jsp.error.not.impl.forward=Erreur interne: forward non implémenté
jsp.error.not.impl.include=Erreur interne: include non implémenté
jsp.error.unavailable=La JSP a été marquée comme non disponible
jsp.error.usebean.missing.attribute=useBean: l''identificateur d''attribut (id attribute) est manquant ou mal orthographié
jsp.error.usebean.missing.type=useBean ({0}): La classe ou le type d''attribut doit être\
spécifié:
jsp.error.usebean.duplicate=useBean: Nom de bean dupliqué: {0}
jsp.error.usebean.prohibited.as.session=Impossible d''utiliser comme bean de session {0} car c''est interdit\
par la directive jsp définie précédemment:
jsp.error.usebean.not.both=useBean: Impossible de spécifier à la fois la classe et l''attribut beanName:
jsp.error.usebean.bad.type.cast=useBean ({0}): Le type ({1}) n''est pas assignable depuis la classe ({2})
jsp.error.classname=Impossible de déterminer le nom de classe d''après le fichier .class
jsp.warning.bad.type=Attention: mauvais type dans le fichier .class
jsp.error.data.file.write=Erreur lors de l''écriture du fichier de données
#Directive de Page: valeur incorrecte pour pageEncoding
jsp.error.page.invalid.contenttype=Directive de Page: valeur incorrecte pour contentType
jsp.error.page.invalid.session=Directive de Page: valeur incorrecte pour session
jsp.error.page.invalid.buffer=Directive de Page: valeur incorrecte pour "buffer"
jsp.error.page.invalid.autoflush=Directive de Page: valeur incorrecte pour autoFlush
jsp.error.page.invalid.isthreadsafe=Directive de Page: valeur incorrecte pour isThreadSafe
jsp.error.page.invalid.info=Directive de Page: valeur incorrecte pour info
jsp.error.page.invalid.iserrorpage=Directive de Page: valeur incorrecte pour isErrorPage
jsp.error.page.defafteruse.language=Directive de Page: on ne peut définir language après un scriptlet
jsp.error.page.nomapping.language=Directive de Page: Pas de correspondance pour language:
jsp.error.page.bad_b_and_a_combo=Directive de Page: combinaison illégale de buffer=\"none\" && autoFlush=\"false\"
jsp.error.not.impl.taglib=Internal error: Tag extensions non implémentés
jsp.error.include.missing.file=l''argument fichier (file) pour l''inclusion (include) est absent
jsp.error.include.bad.file=Mauvais argument fichier (file) pour l''inclusion (include)
jsp.error.include.exception=Impossible d''inclure (include) {0}
jsp.error.stream.closed=Flux fermé
jsp.error.invalid.forward=Tag forward incorrect
jsp.error.unknownException=Erreur non traitée! Vous devriez penser à utiliser une page d''erreur \
pour rapporter ce type d''erreur plus élégamment
jsp.error.invalid.directive=Directive incorrecte
jsp.error.directive.istagfile=La directive {0} ne peut être utilisée dans un fichier tag
jsp.error.directive.isnottagfile=La directive {0} ne peut être utilisée que dans un fichier tag
jsp.error.tagfile.tld.name=L''attribut \"name\" de la directive tag contient la valeur {0} alors que le tag \"name\" de l''élément \"tag-file\" dans le TLD est {1}
jsp.error.action.istagfile=L''action {0} ne peut être utilisée dans un fichier tag
jsp.error.action.isnottagfile=L''action {0} ne peut être utilisée que dans un fichier tag
jsp.error.unterminated=Tag {0} non terminé
jsp.error.usebean.notinsamefile=le tag useBean doit commencé et finir dans le même fichier physique
jsp.error.loadclass.taghandler=Impossible de charger la classe {0}
jsp.error.unable.compile=Impossible de compiler la classe pour la JSP
jsp.error.unable.load=Impossible de charger la classe pour la JSP
jsp.error.unable.rename=Impossible de renommer le fichier classe de {0} vers {1}
jsp.error.mandatory.attribute={0}: L''attribut obligatoire {1} est manquant
jsp.engine.info=Moteur Jasper JSP 2.0
jsp.error.invalid.expression="{0}" contient d''incorrecte(s) expression(s): {1}
jsp.error.invalid.attribute={0}: Attribut incorrect: {1}
jsp.error.usebean.class.notfound=Classe: {0} non trouvée
jsp.error.file.cannot.read=Impossible de lire le fichier: {0}
jsp.error.file.already.registered=Inclusion récursive du fichier {0}
jsp.error.file.not.registered=Le fichier {0} n''apparaît pas dans l''inclusion (include)
jsp.error.quotes.unterminated=guillemets non terminés
jsp.error.attr.quoted=La valeur de l''attribute doit être entre guillemets
jsp.error.attr.novalue=L''attribute {0} n''a pas de valeur
jsp.error.tag.attr.unterminated=Liste de tag d''attribut non terminée
jsp.error.param.noname=Pas de nom dans le tag PARAM
jsp.error.param.novalue=Pas de valeur dans le tag PARAM
jsp.error.beans.nullbean=Tentative d''opération bean sur un objet nul.
jsp.error.beans.nobeaninfo=Pas d''information bean (BeanInfo) pour le bean de type ''{0}'' n''a pu être trouvée, la classe n''existe probablement pas.
jsp.error.beans.introspection=Une exception s''est produite lors de l''introspection de la méthode read de la propriété ''{0}'' dans le bean de type ''{1}'':\n{2}
jsp.error.beans.nomethod=Impossible de trouver une méthode pour lire la propriété ''{0}'' dans le bean de type ''{1}''
jsp.error.beans.nomethod.setproperty=Impossible de trouver une méthode pour mettre à jour la propriété ''{0}'' de type ''{1}''dans le bean de type ''{2}''
jsp.error.beans.noproperty==Impossible de trouver de l''information sur la propriété ''{0}'' dans le bean de type ''{1}''
jsp.error.beans.setproperty.noindexset=Impossible de renseigner la propriété indéxée
jsp.error.include.tag=Tag jsp:include incorrect
jsp.error.include.noflush=jsp:include doit avoir \"flush=true\"
jsp.error.include.badflush=jsp:include page=\"...\" flush=\"true\" est la seule combinaison valide dans JSP 1.0
jsp.error.attempt_to_clear_flushed_buffer=Erreur: Tentative d''effacement d''un tampon qui a déjà été vidangé (flush)
jsp.error.overflow=Erreur: Dépassement de capacité du tampon JSP
jsp.error.paramexpected=Le tag \"param\" est attendu avec les attributs \"name\" et \"value\" après le tag \"params\".
jsp.error.closeindividualparam=Le tag param doit être fermé avec \"/>\"
jsp.error.closeparams=Le tag param tag doit être fermé avec /params
jsp.error.plugin.notype=type non déclaré dans jsp:plugin
jsp.error.plugin.nocode=code non déclaré dans jsp:plugin
jsp.error.ise_on_clear=Il est interdit d''utiliser clear() quand la taille de tampon== 0
jsp.error.setproperty.beanNotFound=setProperty: le Bean {0} est introuvable
jsp.error.getproperty.beanNotFound=getProperty: le Bean {0} est introuvable
jsp.error.setproperty.ClassNotFound=setProperty: la Classe {0} est introuvable
jsp.error.setproperty.invalidSyntax=setProperty: On ne peut avoir de valeur non nulle quand property=*
jsp.error.setproperty.beanInfoNotFound=setproperty: beanInfo pour le bean {0} est introuvable
jsp.error.setproperty.paramOrValue=setProperty: param ou value doit être présent
jsp.error.setproperty.arrayVal=setProperty: on ne peut renseigner les array property {0} au travers d''une valeur chaîne constante (string constant value)
jsp.warning.keepgen=Attention: Valeur incorrecte pour le initParam keepgenerated. Utilisation de la valeur par défaut \"false\"
jsp.warning.enablePooling=Attention: Valeur incorrecte pour le initParam enablePooling. Utilisation de la valeur par défaut \"true\"
jsp.warning.mappedFile=Attention: Valeur incorrecte pour le initParam mappedFile. Utilisation de la valeur par défaut \"false\"
jsp.warning.sendErrToClient=Attention: Valeur incorrecte pour le initParam sendErrToClient. Utilisation de la valeur par défaut \"false\"
jsp.warning.classDebugInfo=Attention: Valeur incorrecte pour le initParam classdebuginfo. Utilisation de la valeur par défaut \"false\"
jsp.warning.checkInterval=Attention: Valeur incorrecte pour le initParam checkInterval. Utilisation de la valeur par défaut \"300\" secondes
jsp.warning.development=Attention: Valeur incorrecte pour le initParam development. Utilisation de la valeur par défaut \"true\"
jsp.warning.reloading=Attention: Valeur incorrecte pour le initParam reloading. Utilisation de la valeur par défaut \"true\"
jsp.warning.reloading=
jsp.error.badtaglib=Impossible d''ouvrir le taglibrary {0} : {1}
jsp.error.badGetReader=Impossible de créer un lecteur (reader) quand le flux n''utilse pas des tampons (not buffered)
jsp.warning.unknown.element.in.TLD=Attention: Elément inconnu {0} dans le TLD
jsp.warning.unknown.element.in.tag=Attention: Elément inconnu {0} dans le tag
jsp.warning.unknown.element.in.tagfile=Attention: El?ment inconnu {0} dans le tag-file
jsp.warning.unknown.element.in.attribute=Attention: Elément inconnu {0} dans l''attribute
jsp.error.more.than.one.taglib=plus d''un taglib dans le TLD: {0}
jsp.error.teiclass.instantiation=Impossible de charger ou d''instancier la classe TagExtraInfo: {0}
jsp.error.non_null_tei_and_var_subelems=Le tag {0} possède une ou plusieurs variables subelements et une classe TagExtraInfo qui retourne une ou plusieurs VariableInfo
jsp.error.parse.error.in.TLD=Erreur d''évaluation (parse) dans le descripteur de librairie de tag (TLD): {0}
jsp.error.unable.to.open.TLD=Impossible d''ouvrir le descripteur de librairie de tag (TLD): {0}
jsp.buffer.size.zero=Taille du tampon <= 0
jsp.error.file.not.found=Le fichier \"{0}\" n''a pas été trouvé
jsp.message.copyinguri=Copie de {0} dans {1}
jsp.message.htmlcomment=\nEffacement des commentaires: \t{0}
jsp.message.handling_directive=\nDirective de gestion (handling): {0}\t{1}
jsp.message.handling_plugin=\nPlugin: {0}
jsp.message.package_name_is=Le nom de package est: {0}
jsp.message.class_name_is=Le nom de classe est: {0}
jsp.message.java_file_name_is=Le nom de fichier Java est: {0}
jsp.message.class_file_name_is=Le nom de fichier Class est: {0}
jsp.message.accepted=Accepté {0} à {1}
jsp.message.adding_jar=Ajout du jar {0} à mon classpath
jsp.message.compiling_with=Compilation avec: {0}
jsp.message.template_text=texte template
jsp.error.missing_attribute=D''après le TLD l''attribut {0} est obligatoire pour le tag {1}
jsp.error.bad_attribute=L''attribut {0} est incorrect pour le tag {1} d''après la TLD indiquée
jsp.error.webxml_not_found=Impossible de localiser le fichier web.xml
jsp.cmd_line.usage=Usage: jsptoservlet [-dd <path/to/outputDirectory>] [-keepgenerated] \
<.jsp files>
jsp.message.cp_is=Le Classpath {0} est: {1}
jsp.error.unable.to_load_taghandler_class=Impossible de charger la classe gestionnaire de tag {0} car {1}
jsp.error.unable.to_find_method=Impossible de trouver une méthode de mise à jour pour l''attribut: {0}
jsp.error.unable.to_convert_string=Impossible de convertir une chaîne vers {0} pour l''attribut {1}
jsp.error.unable.to_introspect=Impossible d''introspecter la classe gestionnaire de tag : {0} car {1}
jsp.error.bad_tag=Aucun tag {0} dans la librairie de tag importée avec le préfixe {1}
jsp.error.bad_string_Character=Impossible d''extraire un caractère depuis un tableau vide
jsp.error.bad_string_char=Impossible d''extraire un caractère depuis un tableau vide
jsp.warning.compiler.class.cantcreate=Impossible de créer une instance de classe plugin pour le compilateur indiqué {0} due to {1}. Utilisation par défaut du Compilateur Java Sun.
jsp.warning.compiler.class.notfound=La classe plugin de compilateur {0} est introuvable. Utilisation par défaut du Compilateur Java Sun.
jsp.warning.compiler.path.notfound=le chemin de compilateur indiqué {0} est introuvable. Utilisation par défaut du chemin système (system PATH).
jsp.error.jspc.uriroot_not_dir=L''option -uriroot doit indiqué un répertoire déjà existant
jspc.implicit.uriRoot=uriRoot réglé implicitement à "{0}"
jspc.usage=Usage: jspc <options> [--] <fichiers jsp>\n\
les fichiers jsp sont n''importe quel nombre de:\n\
\ <file> Un fichier à évaluer (parser) comme page jsp\n\
\ -webapp <dir> Un répertoire contenant une application web, toutes les pages jsp\n\
\ seront récursivement évaluées\n\
les options comprennet:\n\
\ -q Mode silencieux (identique à -v0)\n\
\ -v[#] Mode bavard (Le nombre optionnel indique le niveau, 2 par défaut)\n\
\ -d <dir> Dossier de sortie\n\
\ -dd <dir> Dossier de sortie literal. (Les dossiers de paquets ne seront pas construits)\n\
\ -l Sortie du nom la page JSP en cas d''échec\n\
\ -s Sortie du nom la page JSP en cas de succès\n\
\ -p <name> Nom du paquet cible\n\
\ -c <name> Nom d'un nom de classe cible\n\
\ (s''applique seulement à la première page JSP)\n\
\ -mapped Génère des appels à write() séparés pour chaque ligne HTML dans la JSP\n\
\ -die[#] Génère un code d''erreur de retour (#) en cas d''erreurs fatales.\n\
\ Si le nombre est absent ou non numérique, le défaut est 1.\n\
\ -uribase <dir> Le répertoire uri de compilations relatif\n\
\ (Par défaut "/")\n\
\ -uriroot <dir> The répertoire racine contre lequel les fichiers seront résolus\n\
\ , (Par défaut le répertoire depuis lequel jspc est appelé)\n\
\ -webinc <file> Création d''association partielle de servlet pour l''option -webapp.\n\
\ -webxml <file> Création d''un fichier web.xml complet pour l''option -webapp.\n\
\ -ieplugin <clsid> Le classid du Plugin Java Plugin pour Internet Explorer\n\
\ -sax2 <driverclassname> Le nom de classe du Driver SAX 2.0 à utiliser\n\
\ -trimSpaces Trim spaces in template text between actions, directives\n\
\ -javaEncoding <enc> Set the encoding charset for Java classes (default UTF-8)\n\
\ -source <version> Set the -source argument to the compiler (default 1.4)\n\
\ -target <version> Set the -target argument to the compiler (default 1.4)\n\
jspc.webxml.header=<?xml version="1.0" encoding="ISO-8859-1"?>\n\
\n\
<!DOCTYPE web-app\n\
\ PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"\n\
\ "http://java.sun.com/dtd/web-app_2_3.dtd">\n\
<!--\n\
Créer automatiquement par le JspC Apache Jakarta Tomcat.\n\
-->\n\
<web-app>\n\
\n
jspc.webxml.footer=\n\
</web-app>\n\
\n
jspc.webinc.header=\n\
<!--\n\
Créer automatiquement par le JspC Apache Jakarta Tomcat.\n\
Placez ce fragment dans le fichier web.xml avant all icon, display-name,\n\
description, distributable, and context-param elements.\n\
-->\n
jspc.webinc.footer=\n\
<!--\n\
All session-config, mime-mapping, welcome-file-list, error-page, taglib,\n\
resource-ref, security-constraint, login-config, security-role,\n\
env-entry, and ejb-ref elements should follow this fragment.\n\
-->\n
jspc.error.jasperException=erreur-le fichier ''{0}'' a généré l''exception d''évaluation suivante: {1}
jspc.error.generalException=ERREUR-le fichier ''{0}'' a généré l''exception générale suivante:
jspc.error.fileDoesNotExist=L''argument fichier ''{0}'' n''existe pas
jspc.error.emptyWebApp=-webapp nécessite à sa suite un argument fichier
jsp.error.library.invalid=La page JSP page est incorrecte d''après la librairie {0}: {1}
jsp.error.tlvclass.instantiation=Impossible de charger ou d''instancier la classe TagLibraryValidator: {0}
jsp.error.tlv.invalid.page=Message d''erreurs de validation provenant du TagLibraryValidator pour {0} en {1}
jsp.error.tei.invalid.attributes=Message d''erreurs de validation provenant du TagExtraInfo pour {0}
jsp.parser.sax.propertynotsupported=Propriété SAX non supportée: {0}
jsp.parser.sax.propertynotrecognized=Propriété SAX non reconnue: {0}
jsp.parser.sax.featurenotsupported=Fonctionnalité SAX non supportée: {0}
jsp.parser.sax.featurenotrecognized=Fonctionnalité SAX non reconnue: {0}
jsp.error.no.more.content=Fin de contenu alors que l''évalution n''était pas terminée: erreur de tags imbriqués?
jsp.error.parse.xml=Erreur d''évaluation XML sur le fichier {0}
jsp.error.parse.xml.line=Erreur d''évaluation XML sur le fichier {0}: (ligne {1}, col {2})
jsp.error.parse.xml.scripting.invalid.body=Le corps de l''élément {0} ne doit contenir aucun éléments XML
jsp.error.internal.tldinit=Exception lors de l'initialisation de TldLocationsCache: {0}
jsp.error.internal.filenotfound=Erreur interne: Fichier {0} introuvable
jsp.error.internal.evaluator_not_found=Erreur interne: Impossible de charger l''évaluateur d''expression
jsp.error.parse.xml.invalidPublicId=PUBLIC ID invalide: {0}
jsp.error.include.flush.invalid.value=Valeur incorrecte pour l''attribut flush: {0}
jsp.error.unsupported.encoding=Encodage non supporté: {0}
jsp.warning.unknown.element.in.variable=Attention: Element inconnu {0} dans la variable
tld.error.variableNotAllowed=Ceci est une erreur pour le tag qui possède une ou plusieurs variables subelements pour avoir une classe TagExtraInfo qui retourne un objet non-nul.
jsp.error.tldInWebDotXmlNotFound=Ne peut trouver le TLD {1} pour l''URI {0} indiquée dans le fichier web.xml
jsp.error.taglibDirective.absUriCannotBeResolved=L''uri absolue: {0} ne peut être résolu dans le fichier web.xml ou dans les fichiers jar déployés avec cette application
jsp.error.taglibDirective.missing.location=Ni l''uri' ni l''attribut 'tagdir' n''ont été indiqués dans la directive taglib
jsp.error.invalid.tagdir=Le répertoire du fichier Tag {0} ne commence pas par \"/WEB-INF/tags\"
jsp.error.unterminated.user.tag=Tag user-defined non terminé: Le tag de fermeture {0} est introuvable found ou incorrectement imbriqué
#jspx.error.templateDataNotInJspCdata=Erreur de validation: l''élément &lt;{0}&gt; ne peut avoir de données template. Les données Template doivent être encapsulées à l''intérieur d''un élément &lt;jsp:cdata&gt;. [JSP1.2 PFD section 5.1.9]\nDonnée Template en erreur: {1}
jspx.error.templateDataNotInJspCdata=Erreur de validation: l''élément &lt;{0}&gt; ne peut avoir de données template. Les données Template doivent être encapsulées à l''intérieur d''un élément &lt;jsp:text&gt;. [JSP1.2 PFD section 5.1.9]\nDonnée Template en erreur: {1}
#Erreur lors du traitement du fichier jar de la taglib {0}: {1}
jsp.error.taglib.reserved.prefix=Le préfixe taglib {0} est réservé
jsp.error.invalid.javaEncoding=Encodage java incorrect. Essai de {0} puis de {1}. Les deux ont échoué.
jsp.error.needAlternateJavaEncoding=L''encodage java par défaut {0} est incorrect sur votre environnement java. Une alternative peut être indiquée via le paramêtre 'javaEncoding' de la JspServlet.
#Erreur lors de la compilation, utilisé pour la ligne jsp des messages d''erreur
jsp.error.single.line.number=Une erreur s''est produite à la ligne: {0} dans le fichier jsp: {1}
jsp.error.multiple.line.number=\n\nUne erreur s''est produite entre les lignes: {0} et {1} dans le fichier jsp: {2}\n\n
jsp.error.corresponding.servlet=Erreur de servlet générée:\n
jsp.error.empty.body.not.allowed=Un corps vide n'est pas autorisé pour {0}
jsp.error.jspbody.required=Doit utiliser jsp:body pour indiqué le corps de tag body de {0} si jsp:attribute est utilisé.
jsp.error.jspbody.emptybody.only=Le tag {0} ne peut avoir que jsp:attribute dans son corps.
jsp.error.no.scriptlets=Les éléments de Scripting ( <%!, <jsp:declaration, <%=, <jsp:expression, <%, <jsp:scriptlet ) ne sont pas autorisés ici.
jsp.error.internal.unexpected_node_type=Erreur Interne: Type de node inattendu rencontré
jsp.error.tld.fn.invalid.signature=Synthaxe invalide pour la signature de fonction dans la TLD. Librairie de Tag : {0}, Fonction: {1}
jsp.error.tld.fn.invalid.signature.classnotfound=Synthaxe invalide pour la signature de fonction dans la TLD. Classe introuvable: ${0}. Librairie de Tag: {1}, Fonction: {2}.
jsp.error.tld.fn.invalid.signature.commaexpected=Synthaxe invalide pour la signature de fonction dans la TLD. Virgule ',' attendue. Librairie de Tag: {0}, Fonction: {1}.
jsp.error.tld.fn.invalid.signature.parenexpected=Synthaxe invalide pour la signature de fonction dans la TLD. Parenthèse '(' attendue. Librairie de Tag: {0}, Fonction: {1}.
jsp.error.dynamic.attributes.not.implemented=Le tag {0} indique qu''il accepte des attributs dynamics mais n''implémente pas l''interface requise
jsp.error.nomatching.fragment=Ne peut trouver une directive attribut (avec pour nom={0} et fragment=true) avant la directive fragment.
jsp.error.attribute.noequal=Symbole égal (equal) attendu
jsp.error.attribute.noquote=Symbole guillemet (quote) attendu
jsp.error.attribute.unterminated=L''attribut pour {0} n''est pas correctement terminé
jsp.error.missing.tagInfo=L''objet TagInfo de {0} est absent de la TLD
jsp.error.fragmentwithtype=On ne peut indiquer à la fois les attributs 'fragment' et 'type'. Si 'fragment' est présent, 'type' est fixé comme 'javax.servlet.jsp.tagext.JspFragment'
jsp.error.fragmentwithrtexprvalue=On ne peut indiquer à la fois les attributs 'fragment' et 'rtexprvalue'. Si 'fragment' est présent, 'rtexprvalue' est fixé à 'true'
jsp.error.fragmentWithDeclareOrScope=Les attributs 'fragment' et 'declare' ou 'scope' sont indiqués dans la directive variable
jsp.error.var_and_varReader=A la fois 'var' et 'varReader' sont indiqués
jsp.warning.bad.urlpattern.propertygroup=Mauvaise valeur {0} dans le sous-élément (subelement) url-pattern du fichier web.xml
jsp.error.unknown_attribute_type=Type d''attribut inconnu ({1}) pour l''attribut {0}.
jsp.error.jspelement.missing.name=L''attribut obligatoire 'name' est absent de jsp:element
jsp.error.xmlns.redefinition.notimplemented=Erreur Interne: Tentative de redéfinition de xmlns:{0}. La redéfinition des domaines de noms (namespaces) n''est pas implémentée.
jsp.error.could.not.add.taglibraries=Impossible d''ajouter une ou plusieurs librairies de tag.
jsp.error.duplicate.name.jspattribute=L''attribut {0} indiqué dans l''action standard ou spécifique (custom) apparait aussi comme valeur de l''attribut de nom dans le jsp:attribute inclus
jsp.error.not.in.template={0} n''est pas autorisé dans le corps de texte de template.
jsp.error.badStandardAction=L''action n''est pas reconnue comme une action standard.
jsp.error.tagdirective.badbodycontent=Contenu de corps (body-content) ({0}) invalide dans la directive tag
jsp.error.config_pagedir_encoding_mismatch=L''encode de page (Page-encoding) indiqué dans le jsp-property-group ({0}) est différent de celui indiqué dans la directive de page ({1})
jsp.error.prolog_pagedir_encoding_mismatch=
jsp.error.prolog_config_encoding_mismatch=
jsp.error.attribute.custom.non_rt_with_expr=D''après la TLD, l''attribut {0} n''accepte aucune expression
jsp.error.scripting.variable.missing_name=Incapable de déterminer le nom de variable scripting d''après l''attribut {0}
jasper.error.emptybodycontent.nonempty=D''après la TLD, le tag {0} doit être vide, mais ne l''est pas
jsp.error.tagfile.nameNotUnique=
jsp.error.tagfile.nameFrom.noAttribute=
jsp.error.tagfile.nameFrom.badAttribute=
jsp.error.useBean.noSession=Il est illégal pour useBean d''utiliser une portée de session (session scope) quand la page JSP indique (via la directive de page) qu''elle ne participe pas aux sessions
jsp.error.attributes.not.allowed = {0} ne doit avoir aucun attribut
jsp.error.nested.jspattribute=
jsp.error.nested.jspbody=
jsp.error.variable.either.name=
jsp.error.variable.both.name=
jsp.error.variable.alias=
jsp.error.jsptext.badcontent=
jsp.error.prefix.refined=
jsp.error.jspoutput.conflict=
jsp.error.jspoutput.doctypenamesystem=
jsp.error.jspoutput.doctypepulicsystem=
jsp.error.jspoutput.nonemptybody=
jsp.error.jspoutput.invalidUse=
jsp.error.invalid.bean=
@@ -0,0 +1,422 @@
# 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.
# $Id: LocalStrings_ja.properties 565193 2007-08-12 22:53:10Z markt $
#
# Default localized string information
# Localized this the Default Locale as is ja_JP
jsp.error.bad.servlet.engine=\u30b5\u30fc\u30d6\u30ec\u30c3\u30c8\u30a8\u30f3\u30b8\u30f3\u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093
jsp.error.no.scratch.dir=JSP\u30a8\u30f3\u30b8\u30f3\u306b\u30c7\u30d5\u30a9\u30eb\u30c8\u306escratchDir\u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002\
\n \u3053\u306e\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\u306eservlets.properties\u30d5\u30a1\u30a4\u30eb\u306b\u3001\
\n \"jsp.initparams=scratchdir=<dir-name>\" \u3092\u8ffd\u52a0\u3057\u3066\u304f\u3060\u3055\u3044\u3002
jsp.error.bad.scratch.dir=\u3042\u306a\u305f\u304c\u6307\u5b9a\u3057\u305fscratchDir: {0} \u306f\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093
jsp.message.scratch.dir.is=JSP\u30a8\u30f3\u30b8\u30f3\u306eScratchdir: {0}
jsp.message.parent_class_loader_is=\u89aa\u30af\u30e9\u30b9\u30ed\u30fc\u30c0: {0}
jsp.message.dont.modify.servlets=\u91cd\u8981: \u751f\u6210\u3055\u308c\u305f\u30b5\u30fc\u30d6\u30ec\u30c3\u30c8\u3092\u5909\u66f4\u3057\u3066\u306f\u3044\u3051\u307e\u305b\u3093
jsp.error.not.impl.comments=\u5185\u90e8\u30a8\u30e9\u30fc: Comments\u306f\u5b9f\u88c5\u3055\u308c\u3066\u3044\u307e\u305b\u3093
jsp.error.not.impl.directives=\u5185\u90e8\u30a8\u30e9\u30fc: Directives\u306f\u5b9f\u88c5\u3055\u308c\u3066\u3044\u307e\u305b\u3093
jsp.error.not.impl.declarations=\u5185\u90e8\u30a8\u30e9\u30fc: Declarations\u306f\u5b9f\u88c5\u3055\u308c\u3066\u3044\u307e\u305b\u3093
jsp.error.not.impl.expressions=\u5185\u90e8\u30a8\u30e9\u30fc: Expressions\u306f\u5b9f\u88c5\u3055\u308c\u3066\u3044\u307e\u305b\u3093
jsp.error.not.impl.scriptlets=\u5185\u90e8\u30a8\u30e9\u30fc: Scriptlets\u306f\u5b9f\u88c5\u3055\u308c\u3066\u3044\u307e\u305b\u3093
jsp.error.not.impl.usebean=\u5185\u90e8\u30a8\u30e9\u30fc: useBean\u306f\u5b9f\u88c5\u3055\u308c\u3066\u3044\u307e\u305b\u3093
jsp.error.not.impl.getp=\u5185\u90e8\u30a8\u30e9\u30fc: getProperty\u306f\u5b9f\u88c5\u3055\u308c\u3066\u3044\u307e\u305b\u3093
jsp.error.not.impl.setp=\u5185\u90e8\u30a8\u30e9\u30fc: setProperty\u306f\u5b9f\u88c5\u3055\u308c\u3066\u3044\u307e\u305b\u3093
jsp.error.not.impl.plugin=\u5185\u90e8\u30a8\u30e9\u30fc: plugin\u306f\u5b9f\u88c5\u3055\u308c\u3066\u3044\u307e\u305b\u3093
jsp.error.not.impl.forward=\u5185\u90e8\u30a8\u30e9\u30fc: forward\u306f\u5b9f\u88c5\u3055\u308c\u3066\u3044\u307e\u305b\u3093
jsp.error.not.impl.include=\u5185\u90e8\u30a8\u30e9\u30fc: include\u306f\u5b9f\u88c5\u3055\u308c\u3066\u3044\u307e\u305b\u3093
jsp.error.unavailable=JSP\u306f\u5229\u7528\u4e0d\u53ef\u3068\u30de\u30fc\u30af\u3055\u308c\u3066\u3044\u307e\u3059
jsp.error.usebean.missing.attribute=useBean: id\u5c5e\u6027\u304c\u5b58\u5728\u3057\u306a\u3044\u304b\u3001\u30b9\u30da\u30eb\u30df\u30b9\u3067\u3059
jsp.error.usebean.missing.type=useBean ({0}): class\u5c5e\u6027\u304btype\u5c5e\u6027\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044:
jsp.error.usebean.duplicate=useBean: beanName\u5c5e\u6027\u304c\u91cd\u8907\u3057\u3066\u3044\u307e\u3059: {0}
jsp.error.usebean.prohibited.as.session=\u4ee5\u524d\u306b\u5b9a\u7fa9\u3057\u305fJSP\u6307\u793a\u5b50\u306b\u3088\u3063\u3066\u7981\u6b62\u3055\u308c\u3066\u3044\u308b\u305f\u3081\u306b\u3001session bean {0} \u3068\u3057\u3066\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093:
jsp.error.usebean.not.both=useBean: class\u5c5e\u6027\u3068beanName\u5c5e\u6027\u306e\u4e21\u65b9\u3092\u540c\u6642\u306b\u6307\u5b9a\u3067\u304d\u307e\u305b\u3093:
jsp.error.usebean.bad.type.cast=useBean ({0}): type ({1}) \u306fclass ({2}) \u304b\u3089\u5272\u308a\u5f53\u3066\u3089\u308c\u307e\u305b\u3093
jsp.error.invalid.scope='scope'\u5c5e\u6027\u306e\u5024\u304c\u7121\u52b9\u3067\u3059: {0} (\"page\"\u3001\"request\"\u3001\"session\"\u53c8\u306f\"application\"\u306e\u3069\u308c\u304b\u3067\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093)
jsp.error.classname=.class\u30d5\u30a1\u30a4\u30eb\u304b\u3089\u30af\u30e9\u30b9\u540d\u3092\u6c7a\u5b9a\u3067\u304d\u307e\u305b\u3093
jsp.warning.bad.type=\u8b66\u544a: .class\u30d5\u30a1\u30a4\u30eb\u4e2d\u306e\u578b\u304c\u9055\u3044\u307e\u3059
jsp.error.data.file.write=\u30c7\u30fc\u30bf\u30d5\u30a1\u30a4\u30eb\u3092\u66f8\u304d\u8fbc\u307f\u4e2d\u306e\u30a8\u30e9\u30fc\u3067\u3059
jsp.error.page.invalid.buffer=page\u6307\u793a\u5b50: \u7121\u52b9\u306a\u30d0\u30c3\u30d5\u30a1\u30b5\u30a4\u30ba\u3067\u3059
jsp.error.page.conflict.contenttype=page\u6307\u793a\u5b50: 'contentType'\u3092\u7570\u306a\u308b\u5024\u3067\u8907\u6570\u56de\u6307\u5b9a\u3059\u308b\u306e\u306f\u7121\u52b9\u3067\u3059 (\u65e7: {0}, \u65b0: {1})
jsp.error.page.invalid.contenttype=page\u6307\u793a\u5b50: contentType\u5c5e\u6027\u306e\u5024\u304c\u7121\u52b9\u3067\u3059
jsp.error.page.conflict.session=page\u6307\u793a\u5b50: 'session'\u3092\u7570\u306a\u308b\u5024\u3067\u8907\u6570\u56de\u6307\u5b9a\u3059\u308b\u306e\u306f\u7121\u52b9\u3067\u3059 (\u65e7: {0}, \u65b0: {1})
jsp.error.page.invalid.session=page\u6307\u793a\u5b50: session\u5c5e\u6027\u306e\u5024\u304c\u7121\u52b9\u3067\u3059
jsp.error.page.conflict.buffer=page\u6307\u793a\u5b50: 'buffer'\u3092\u7570\u306a\u308b\u5024\u3067\u8907\u6570\u56de\u6307\u5b9a\u3059\u308b\u306e\u306f\u7121\u52b9\u3067\u3059 (\u65e7: {0}, \u65b0: {1})
jsp.error.page.invalid.buffer=page\u6307\u793a\u5b50: buffer\u5c5e\u6027\u306e\u5024\u304c\u7121\u52b9\u3067\u3059
jsp.error.page.conflict.autoflush=page\u6307\u793a\u5b50: 'autoFlush'\u3092\u7570\u306a\u308b\u5024\u3067\u8907\u6570\u56de\u6307\u5b9a\u3059\u308b\u306e\u306f\u7121\u52b9\u3067\u3059 (\u65e7: {0}, \u65b0: {1})
jsp.error.page.invalid.autoflush=page\u6307\u793a\u5b50: autoFlush\u5c5e\u6027\u306e\u5024\u304c\u7121\u52b9\u3067\u3059
jsp.error.page.conflict.isthreadsafe=page\u6307\u793a\u5b50: 'isThreadSafe'\u3092\u7570\u306a\u308b\u5024\u3067\u8907\u6570\u56de\u6307\u5b9a\u3059\u308b\u306e\u306f\u7121\u52b9\u3067\u3059 (\u65e7: {0}, \u65b0: {1})
jsp.error.page.invalid.isthreadsafe=page\u6307\u793a\u5b50: isThreadSafe\u306e\u5024\u304c\u7121\u52b9\u3067\u3059
jsp.error.page.conflict.info=page\u6307\u793a\u5b50: 'info'\u3092\u7570\u306a\u308b\u5024\u3067\u8907\u6570\u56de\u6307\u5b9a\u3059\u308b\u306e\u306f\u7121\u52b9\u3067\u3059 (\u65e7: {0}, \u65b0: {1})
jsp.error.page.invalid.info=page\u6307\u793a\u5b50: info\u5c5e\u6027\u306e\u5024\u304c\u7121\u52b9\u3067\u3059
jsp.error.page.conflict.iserrorpage=page\u6307\u793a\u5b50: 'isErrorPage'\u3092\u7570\u306a\u308b\u5024\u3067\u8907\u6570\u56de\u6307\u5b9a\u3059\u308b\u306e\u306f\u7121\u52b9\u3067\u3059 (\u65e7: {0}, \u65b0: {1})
jsp.error.page.invalid.iserrorpage=page\u6307\u793a\u5b50: isErrorPage\u5c5e\u6027\u306e\u5024\u304c\u7121\u52b9\u3067\u3059
jsp.error.page.conflict.errorpage=page\u6307\u793a\u5b50: 'errorPage'\u3092\u7570\u306a\u308b\u5024\u3067\u8907\u6570\u56de\u6307\u5b9a\u3059\u308b\u306e\u306f\u7121\u52b9\u3067\u3059 (\u65e7: {0}, \u65b0: {1})
jsp.error.page.conflict.language=page\u6307\u793a\u5b50: 'language'\u3092\u7570\u306a\u308b\u5024\u3067\u8907\u6570\u56de\u6307\u5b9a\u3059\u308b\u306e\u306f\u7121\u52b9\u3067\u3059 (\u65e7: {0}, \u65b0: {1})
jsp.error.tag.conflict.language=tag\u6307\u793a\u5b50: 'language'\u3092\u7570\u306a\u308b\u5024\u3067\u8907\u6570\u56de\u6307\u5b9a\u3059\u308b\u306e\u306f\u7121\u52b9\u3067\u3059 (\u65e7: {0}, \u65b0: {1})
jsp.error.page.language.nonjava=page\u6307\u793a\u5b50: \u7121\u52b9\u306alanguage\u5c5e\u6027\u3067\u3059
jsp.error.tag.language.nonjava=tag\u6307\u793a\u5b50: \u7121\u52b9\u306alanguage\u5c5e\u6027\u3067\u3059
jsp.error.page.defafteruse.language=page\u6307\u793a\u5b50: scriptlet\u306e\u5f8c\u3067language\u5c5e\u6027\u3092\u6307\u5b9a\u3067\u304d\u307e\u305b\u3093
jsp.error.page.nomapping.language=page\u6307\u793a\u5b50 language\u5c5e\u6027\u306e\u30de\u30c3\u30d4\u30f3\u30b0\u304c\u5b58\u5728\u3057\u307e\u305b\u3093:
jsp.error.page.conflict.extends=page\u6307\u793a\u5b50: 'extends'\u3092\u7570\u306a\u308b\u5024\u3067\u8907\u6570\u56de\u6307\u5b9a\u3059\u308b\u306e\u306f\u7121\u52b9\u3067\u3059 (\u65e7: {0}, \u65b0: {1})
jsp.error.page.conflict.iselignored=page\u6307\u793a\u5b50: 'isELIgnored'\u3092\u7570\u306a\u308b\u5024\u3067\u8907\u6570\u56de\u6307\u5b9a\u3059\u308b\u306e\u306f\u7121\u52b9\u3067\u3059 (\u65e7: {0}, \u65b0: {1})
jsp.error.tag.conflict.iselignored=tag\u6307\u793a\u5b50: 'isELIgnored'\u3092\u7570\u306a\u308b\u5024\u3067\u8907\u6570\u56de\u6307\u5b9a\u3059\u308b\u306e\u306f\u7121\u52b9\u3067\u3059 (\u65e7: {0}, \u65b0: {1})
jsp.error.page.invalid.iselignored=page\u6307\u793a\u5b50: isELIgnored\u306b\u7121\u52b9\u306a\u5024\u304c\u6307\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059
jsp.error.tag.invalid.iselignored=tag\u6307\u793a\u5b50: isELIgnored\u306b\u7121\u52b9\u306a\u5024\u304c\u6307\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059
jsp.error.page.multi.pageencoding=page\u6307\u793a\u5b50\u306f\u8907\u6570\u306epageencoding\u3092\u6301\u3064\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093
jsp.error.tag.conflict.attr=Tag\u6307\u793a\u5b50: \u5c5e\u6027\"{0}\"\u3092\u7570\u306a\u308b\u5024\u3067\u8907\u6570\u56de\u6307\u5b9a\u3059\u308b\u306e\u306f\u4e0d\u6b63\u3067\u3059 (\u65e7: {1}, \u65b0: {2})
jsp.error.tag.multi.pageencoding=tag\u6307\u793a\u5b50\u306f\u8907\u6570\u306epageencoding\u3092\u6301\u3064\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093
jsp.error.page.bad_b_and_a_combo=page\u6307\u793a\u5b50: buffer=\"none\"\u3068autoFlush=\"false\"\u3092\u540c\u6642\u306b\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093
jsp.error.not.impl.taglib=\u5185\u90e8\u30a8\u30e9\u30fc: \u30bf\u30b0\u62e1\u5f35\u5b50\u306f\u5b9f\u88c5\u3055\u308c\u3066\u3044\u307e\u305b\u3093
jsp.error.include.missing.file=\u53d6\u308a\u8fbc\u3080\u30d5\u30a1\u30a4\u30eb\u5f15\u6570\u304c\u3042\u308a\u307e\u305b\u3093
jsp.error.include.bad.file=include\u5c5e\u6027\u306e\u30d5\u30a1\u30a4\u30eb\u5f15\u6570\u304c\u9593\u9055\u3063\u3066\u3044\u307e\u3059
jsp.error.include.exception={0} \u3092\u53d6\u308a\u8fbc\u3081\u307e\u305b\u3093
jsp.error.stream.closed=\u30b9\u30c8\u30ea\u30fc\u30e0\u304c\u30af\u30ed\u30fc\u30ba\u3055\u308c\u3066\u3044\u307e\u3059
jsp.error.invalid.forward=\u7121\u52b9\u306aforward\u30bf\u30b0\u3067\u3059
jsp.error.unknownException=\u51e6\u7406\u4e0d\u53ef\u80fd\u306a\u30a8\u30e9\u30fc\u3067\u3059! \u3053\u306e\u3088\u3046\u306a\u30a8\u30e9\u30fc\u3092\u3088\u308a\u8a73\u7d30\u306b\u5831\u544a\u3059\u308b\u30a8\u30e9\u30fc\u30da\u30fc\u30b8\u3092\u6301\u3063\u305f\u65b9\u304c\u3088\u3044\u304b\u3082\u3057\u308c\u307e\u305b\u3093
jsp.error.invalid.directive=\u7121\u52b9\u306a\u6307\u793a\u5b50\u3067\u3059
jsp.error.directive.istagfile={0} \u6307\u793a\u5b50\u306f\u30bf\u30b0\u30d5\u30a1\u30a4\u30eb\u4e2d\u3067\u306f\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093
jsp.error.directive.isnottagfile={0} \u6307\u793a\u5b50\u306f\u30bf\u30b0\u30d5\u30a1\u30a4\u30eb\u4e2d\u3067\u3057\u304b\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093
jsp.error.tagfile.tld.name=TLD\u4e2d\u306e\u30bf\u30b0\u6307\u793a\u5b50\u306e\"tag-file\"\u8981\u7d20\u306e\"name\"\u30bf\u30b0\u306f {1} \u3067\u3059\u304c\uff0c\"name\"\u5c5e\u6027\u306f\u5024 {0} \u3092\u6301\u3063\u3066\u3044\u307e\u3059
jsp.error.action.istagfile={0} \u30a2\u30af\u30b7\u30e7\u30f3\u306f\u30bf\u30b0\u30d5\u30a1\u30a4\u30eb\u4e2d\u3067\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093
jsp.error.action.isnottagfile={0} \u30a2\u30af\u30b7\u30e7\u30f3\u306f\u30bf\u30b0\u30d5\u30a1\u30a4\u30eb\u4e2d\u3067\u306e\u307f\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093
jsp.error.unterminated={0} \u30bf\u30b0\u304c\u7d42\u4e86\u3057\u3066\u3044\u307e\u305b\u3093
jsp.error.usebean.notinsamefile=useBean\u30bf\u30b0\u306f\u3001\u540c\u4e00\u30d5\u30a1\u30a4\u30eb\u4e2d\u3067\u958b\u59cb\u3057\u3001\u7d42\u4e86\u3057\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.loadclass.taghandler=\u30bf\u30b0 \"{1}\" \u306b\u30bf\u30b0\u30cf\u30f3\u30c9\u30e9\u30af\u30e9\u30b9 \"{0}\" \u3092\u30ed\u30fc\u30c9\u3067\u304d\u307e\u305b\u3093
jsp.error.unable.compile=JSP\u306e\u30af\u30e9\u30b9\u3092\u30b3\u30f3\u30d1\u30a4\u30eb\u3067\u304d\u307e\u305b\u3093
jsp.error.unable.load=JSP\u306e\u30af\u30e9\u30b9\u3092\u30ed\u30fc\u30c9\u3067\u304d\u307e\u305b\u3093
jsp.error.unable.rename=\u30af\u30e9\u30b9\u30d5\u30a1\u30a4\u30eb {0} \u3092 {1} \u306b\u30d5\u30a1\u30a4\u30eb\u540d\u3092\u5909\u66f4\u3067\u304d\u307e\u305b\u3093
jsp.error.mandatory.attribute={0}: \u5fc5\u9808\u5c5e\u6027 {1} \u304c\u3042\u308a\u307e\u305b\u3093
jsp.engine.info=Jasper JSP 2.0\u30a8\u30f3\u30b8\u30f3
jsp.error.invalid.expression="{0}" \u306f\u7121\u52b9\u306a\u5f0f\u3092\u542b\u3093\u3067\u3044\u307e\u3059: {1}
jsp.error.invalid.attribute={0}\u306f\u7121\u52b9\u306a\u5c5e\u6027\u3092\u6301\u3063\u3066\u3044\u307e\u3059: {1}
jsp.error.usebean.class.notfound=\u30af\u30e9\u30b9: {0} \u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093
jsp.error.file.cannot.read=\u30d5\u30a1\u30a4\u30eb\u304c\u8aad\u3081\u307e\u305b\u3093: {0}
jsp.error.file.already.registered=\u30d5\u30a1\u30a4\u30eb {0} \u306e\u518d\u5e30\u7684\u306a\u53d6\u308a\u8fbc\u307f\u3067\u3059
jsp.error.file.not.registered=include\u5c5e\u6027\u4e2d\u306e\u30d5\u30a1\u30a4\u30eb {0} \u304c\u5b58\u5728\u3057\u307e\u305b\u3093
jsp.error.quotes.unterminated=\u5f15\u7528\u7b26\u304c\u7d42\u4e86\u3057\u3066\u3044\u307e\u305b\u3093
jsp.error.attr.quoted=\u5c5e\u6027\u5024\u306f\u5f15\u7528\u7b26\u3067\u56f2\u308f\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.attr.novalue=\u5c5e\u6027 {0} \u306b\u306f\u5024\u304c\u6307\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093
jsp.error.tag.attr.unterminated=\u30bf\u30b0\u306e\u5c5e\u6027\u30ea\u30b9\u30c8\u304c\u7d42\u4e86\u3057\u3066\u3044\u307e\u305b\u3093
jsp.error.param.noname=PARAM\u30bf\u30b0\u306bname\u5c5e\u6027\u304c\u3042\u308a\u307e\u305b\u3093
jsp.error.param.novalue=PARAM\u30bf\u30b0\u306bvalue\u5c5e\u6027\u304c\u3042\u308a\u307e\u305b\u3093
jsp.error.beans.nullbean=null\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306bBean\u64cd\u4f5c\u3092\u304a\u3053\u306a\u304a\u3046\u3068\u3057\u307e\u3057\u305f
jsp.error.beans.nobeaninfo=\u30bf\u30a4\u30d7 ''{0}'' \u306eBean\u306bBeanInfo\u304c\u306a\u3044\u306e\u3092\u691c\u51fa\u3057\u307e\u3057\u305f, \u30af\u30e9\u30b9\u304c\u5b58\u5728\u3057\u306a\u3044\u304b\u3082\u3057\u308c\u307e\u305b\u3093
jsp.error.beans.introspection=\u30bf\u30a4\u30d7 ''{1}'' \u306eBean\u4e2d\u306e\u5c5e\u6027 ''{0}'' \u306eread\u30e1\u30bd\u30c3\u30c9\u3092\u5185\u7701\u4e2d\u306b\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f:\n{2}
jsp.error.beans.nomethod=\u30bf\u30a4\u30d7 ''{1}'' \u306eBean\u4e2d\u306e\u5c5e\u6027 ''{0}'' \u3092\u8aad\u307f\u8fbc\u3080\u30e1\u30bd\u30c3\u30c9\u3092\u767a\u898b\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f
jsp.error.beans.nomethod.setproperty=\u30bf\u30a4\u30d7''{2}''\u306eBean\u306e\u30bf\u30a4\u30d7 ''{1}'' \u306e\u5c5e\u6027 ''{0}'' \u3092\u66f8\u304d\u8fbc\u3080\u30e1\u30bd\u30c3\u30c9\u3092\u767a\u898b\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f
jsp.error.beans.noproperty=\u30bf\u30a4\u30d7 ''{1}'' \u306ebean\u4e2d\u306e\u5c5e\u6027 ''{0}'' \u306e\u60c5\u5831\u3092\u767a\u898b\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f
jsp.error.beans.setproperty.noindexset=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u4ed8\u304d\u306e\u5c5e\u6027\u3092\u6307\u5b9a\u3067\u304d\u307e\u305b\u3093
jsp.error.include.tag=\u7121\u52b9\u306ajsp:include\u30bf\u30b0\u3067\u3059
jsp.error.include.noflush=jsp:include\u30bf\u30b0\u306b \"flush=true\" \u3092\u5b9a\u7fa9\u3057\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.include.badflush=jsp:include page=\"...\" flush=\"true\" \u306f\u3001JSP 1.0\u3067\u306e\u307f\u6709\u52b9\u306a\u7d44\u307f\u5408\u308f\u305b\u3067\u3059
jsp.error.attempt_to_clear_flushed_buffer=\u30a8\u30e9\u30fc: \u65e2\u306b\u30d5\u30e9\u30c3\u30b7\u30e5\u3055\u308c\u3066\u3044\u308b\u30d0\u30c3\u30d5\u30a1\u3092\u30af\u30ea\u30a2\u3057\u3088\u3046\u3068\u3057\u307e\u3057\u305f
jsp.error.overflow=\u30a8\u30e9\u30fc: JSP\u30d0\u30c3\u30d5\u30a1\u304c\u30aa\u30fc\u30d0\u30fc\u30d5\u30ed\u30fc\u3057\u307e\u3057\u305f
jsp.error.paramexpected=\"name\"\u5c5e\u6027 \u3068 \"value\" \u5c5e\u6027\u3092\u6301\u3064 \"jsp:param\" \u6a19\u6e96\u30a2\u30af\u30b7\u30e7\u30f3\u304c\u5fc5\u8981\u3067\u3059
jsp.error.param.invalidUse=jsp:include\u3001jsp:forward\u3001\u53c8\u306fjsp:params\u8981\u7d20\u306e\u5916\u3067jsp:param\u30a2\u30af\u30b7\u30e7\u30f3\u3092\u4f7f\u7528\u3057\u3066\u306f\u3044\u3051\u307e\u305b\u3093
jsp.error.params.invalidUse=jsp:params\u306fjsp:plugin\u306e\u76f4\u63a5\u306e\u5b50\u4f9b\u3067\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.fallback.invalidUse=jsp:fallback\u306fjsp:plugin\u306e\u76f4\u63a5\u306e\u5b50\u4f9b\u3067\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.namedAttribute.invalidUse=jsp:attribute\u306f\u6a19\u6e96\u53c8\u306f\u30ab\u30b9\u30bf\u30e0\u30a2\u30af\u30b7\u30e7\u30f3\u306e\u526f\u8981\u7d20\u3067\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.jspbody.invalidUse=jsp:body\u306f\u6a19\u6e96\u53c8\u306f\u30ab\u30b9\u30bf\u30e0\u30a2\u30af\u30b7\u30e7\u30f3\u306e\u526f\u8981\u7d20\u3067\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.closeindividualparam=param\u30bf\u30b0\u306f \"/>\" \u3067\u9589\u3058\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.closeparams=param\u30bf\u30b0\u306f/params\u3067\u9589\u3058\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.params.emptyBody=jsp:params\u306f\u5c11\u306a\u304f\u3068\u3082\u4e00\u3064\u306e\u30cd\u30b9\u30c8\u3057\u305fjsp:param\u3092\u542b\u307e\u306d\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.params.illegalChild=jsp:params\u306fjsp:param\u4ee5\u5916\u306e\u30cd\u30b9\u30c8\u3057\u305f\u8981\u7d20\u3092\u542b\u3093\u3067\u306f\u3044\u3051\u307e\u305b\u3093
jsp.error.plugin.notype=jsp:plugin\u3067type\u5c5e\u6027\u304c\u5ba3\u8a00\u3055\u308c\u3066\u3044\u307e\u305b\u3093
jsp.error.plugin.badtype=jsp:plugin\u306e 'type'\u5c5e\u6027\u306e\u5024\u304c\u7121\u52b9\u3067\u3059: 'bean'\u53c8\u306f'applet'\u3067\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.plugin.nocode=jsp:plugin\u3067code\u5c5e\u6027\u304c\u5ba3\u8a00\u3055\u308c\u3066\u3044\u307e\u305b\u3093
jsp.error.ise_on_clear=\u30d0\u30c3\u30d5\u30a1\u30b5\u30a4\u30ba\u304c0\u306e\u6642\u306bclear()\u3092\u5b9f\u884c\u3057\u3066\u3082\u7121\u52b9\u3067\u3059
jsp.error.setproperty.beanNotFound=setProperty: Bean {0} \u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093
jsp.error.getproperty.beanNotFound=getProperty: Bean {0} \u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093
jsp.error.setproperty.ClassNotFound=setProperty: \u30af\u30e9\u30b9 {0} \u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093
# typo ?
#jsp.error.setproperty.invalidSayntax=setProperty: property=*\u306e\u5834\u5408\u306fnull\u3067\u306a\u3044\u5024\u3092\u6307\u5b9a\u3067\u304d\u307e\u305b\u3093
jsp.error.setproperty.invalidSyntax=setProperty: property=*\u306e\u5834\u5408\u306fnull\u3067\u306a\u3044\u5024\u3092\u6307\u5b9a\u3067\u304d\u307e\u305b\u3093
jsp.error.setproperty.beanInfoNotFound=setproperty: Bean {0} \u306ebeanInfo\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093
jsp.error.setproperty.paramOrValue=setProperty: param\u5c5e\u6027\u304bvalue\u5c5e\u6027\u306e\u3069\u3061\u3089\u304b\u4e00\u3064\u3060\u3051\u3092\u6307\u5b9a\u3067\u304d\u307e\u3059
jsp.error.setproperty.arrayVal=setProperty: \u5c5e\u6027\u914d\u5217 {0} \u3092\u6587\u5b57\u5217\u5b9a\u6570\u5024\u3067\u6307\u5b9a\u3067\u304d\u307e\u305b\u3093
jsp.warning.keepgen=\u8b66\u544a: initParam keepgenerated\u306e\u5024\u304c\u7121\u52b9\u3067\u3059\u3002 \u30c7\u30d5\u30a9\u30eb\u30c8\u5024 \"false\" \u3092\u4f7f\u7528\u3057\u307e\u3059
jsp.warning.xpoweredBy=\u8b66\u544a: Invalid value for the initParam xpoweredBy\u306e\u5024\u304c\u7121\u52b9\u3067\u3059\u3002\u30c7\u30d5\u30a9\u30eb\u30c8\u5024 \"false\" \u3092\u4f7f\u7528\u3057\u307e\u3059
jsp.warning.enablePooling=\u8b66\u544a: initParam enablePooling\u304c\u7121\u52b9\u306a\u5024\u3067\u3059\u3002\"true\"\u306e\u30c7\u30d5\u30a9\u30eb\u30c8\u5024\u3092\u4f7f\u7528\u3057\u307e\u3059
jsp.warning.invalidTagPoolSize=\u8b66\u544a: tagPoolSize\u306e\u521d\u671f\u30d1\u30e9\u30e1\u30fc\u30bf\u304c\u7121\u52b9\u306a\u5024\u3067\u3059\u3002{0}\u306e\u30c7\u30d5\u30a9\u30eb\u30c8\u30b5\u30a4\u30ba\u3092\u4f7f\u7528\u3057\u307e\u3059
jsp.warning.mappedFile=\u8b66\u544a: initParam mappedFile\u306e\u5024\u304c\u7121\u52b9\u3067\u3059\u3002\u30c7\u30d5\u30a9\u30eb\u30c8\u5024 \"false\" \u3092\u4f7f\u7528\u3057\u307e\u3059
jsp.warning.sendErrToClient=\u8b66\u544a: initParam sendErrToClient\u306e\u5024\u304c\u7121\u52b9\u3067\u3059\u3002\u30c7\u30d5\u30a9\u30eb\u30c8\u5024 \"false\" \u3092\u4f7f\u7528\u3057\u307e\u3059
jsp.warning.classDebugInfo=\u8b66\u544a: initParam classDebugInfo\u306e\u5024\u304c\u7121\u52b9\u3067\u3059\u3002\u30c7\u30d5\u30a9\u30eb\u30c8\u5024 \"false\"\u3092\u4f7f\u7528\u3057\u307e\u3059
jsp.warning.checkInterval=\u8b66\u544a: initParam checkInterval\u306e\u5024\u304c\u7121\u52b9\u3067\u3059\u3002\"300\"\u79d2\u306e\u30c7\u30d5\u30a9\u30eb\u30c8\u5024\u3092\u4f7f\u7528\u3057\u307e\u3059
jsp.warning.development=\u8b66\u544a: initParam development\u306e\u5024\u304c\u7121\u52b9\u3067\u3059\u3002\"true\"\u306e\u30c7\u30d5\u30a9\u30eb\u30c8\u5024\u3092\u4f7f\u7528\u3057\u307e\u3059
jsp.warning.fork=\u8b66\u544a: initParam fork\u306e\u5024\u304c\u7121\u52b9\u3067\u3059\u3002\"true\"\u306e\u30c7\u30d5\u30a9\u30eb\u30c8\u5024\u3092\u4f7f\u7528\u3057\u307e\u3059
jsp.warning.reloading=\u8b66\u544a: initParam reloading\u306e\u5024\u304c\u7121\u52b9\u3067\u3059\u3002\"true\"\u306e\u30c7\u30d5\u30a9\u30eb\u30c8\u5024\u3092\u4f7f\u7528\u3057\u307e\u3059
jsp.warning.dumpSmap=\u8b66\u544a: initParam dumpSmap\u306e\u5024\u304c\u7121\u52b9\u3067\u3059\u3002\"false\"\u306e\u30c7\u30d5\u30a9\u30eb\u30c8\u5024\u3092\u4f7f\u7528\u3057\u307e\u3059
jsp.warning.genchararray=\u8b66\u544a: initParam genStrAsCharArray\u306e\u5024\u304c\u7121\u52b9\u3067\u3059\u3002\"false\"\u306e\u30c7\u30d5\u30a9\u30eb\u30c8\u5024\u3092\u4f7f\u7528\u3057\u307e\u3059
jsp.warning.suppressSmap=\u8b66\u544a: initParam suppressSmap\u306e\u5024\u304c\u7121\u52b9\u3067\u3059\u3002\u30c7\u30d5\u30a9\u30eb\u30c8\u5024 \"false\" \u3092\u4f7f\u7528\u3057\u307e\u3059
jsp.error.badtaglib=\u30bf\u30b0\u30e9\u30a4\u30d6\u30e9\u30ea {0} \u3092\u30aa\u30fc\u30d7\u30f3\u3067\u304d\u307e\u305b\u3093: {1}
jsp.error.badGetReader=\u30b9\u30c8\u30ea\u30fc\u30e0\u304c\u30d0\u30c3\u30d5\u30a1\u30ea\u30f3\u30b0\u3055\u308c\u3066\u3044\u306a\u3044\u5834\u5408\u306b\u306f\u3001Reader\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093
jsp.warning.unknown.element.in.taglib=taglib\u4e2d\u306b\u672a\u77e5\u306e\u8981\u7d20 ({0}) \u304c\u3042\u308a\u307e\u3059
jsp.warning.unknown.element.in.tag=tag\u4e2d\u306b\u672a\u77e5\u306e\u8981\u7d20 ({0}) \u304c\u3042\u308a\u307e\u3059
jsp.warning.unknown.element.in.tagfile=tag-file\u4e2d\u306b\u672a\u77e5\u306e\u8981\u7d20 ({0}) \u304c\u3042\u308a\u307e\u3059
jsp.warning.unknown.element.in.attribute=attribute\u4e2d\u306b\u672a\u77e5\u306e\u8981\u7d20 ({0}) \u304c\u3042\u308a\u307e\u3059
jsp.warning.unknown.element.in.variable=variable\u4e2d\u306b\u672a\u77e5\u306e\u8981\u7d20 ({0}) \u304c\u3042\u308a\u307e\u3059
jsp.warning.unknown.element.in.validator=validator\u4e2d\u306b\u672a\u77e5\u306e\u8981\u7d20 ({0}) \u304c\u3042\u308a\u307e\u3059
jsp.warning.unknown.element.in.initParam=validator\u306einit-param\u4e2d\u306b\u672a\u77e5\u306e\u8981\u7d20 ({0}) \u304c\u3042\u308a\u307e\u3059
jsp.warning.unknown.element.in.function=function\u4e2d\u306b\u672a\u77e5\u306e\u8981\u7d20 ({0}) \u304c\u3042\u308a\u307e\u3059
jsp.error.more.than.one.taglib=TLD\u306e\u4e2d\u306b\u8907\u6570\u306etaglib\u304c\u5b58\u5728\u3057\u307e\u3059: {0}
jsp.error.teiclass.instantiation=TagExtraInfo class\u306e\u30ed\u30fc\u30c9\u53c8\u306f\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u5316\u306b\u5931\u6557\u3057\u307e\u3057\u305f: {0}
jsp.error.non_null_tei_and_var_subelems=\u30bf\u30b0 {0} \u306f\u4e00\u3064\u4ee5\u4e0a\u306evariable\u526f\u8981\u7d20\u3068\u4e00\u3064\u4ee5\u4e0a\u306eVariableInfo\u3092\u8fd4\u3059TagExtraInfo\u30af\u30e9\u30b9\u3092\u6301\u3063\u3066\u3044\u307e\u3059
jsp.error.parse.error.in.TLD=\u30bf\u30b0\u30e9\u30a4\u30d6\u30e9\u30ea\u8a18\u8ff0\u5b50 {0} \u4e2d\u306e\u89e3\u6790\u30a8\u30e9\u30fc\u3067\u3059
jsp.error.unable.to.open.TLD=\u30bf\u30b0\u30e9\u30a4\u30d6\u30e9\u30ea\u8a18\u8ff0\u5b50 {0} \u3092\u30aa\u30fc\u30d7\u30f3\u3067\u304d\u307e\u305b\u3093
jsp.buffer.size.zero=\u30d0\u30c3\u30d5\u30a1\u30b5\u30a4\u30ba\u304c0\u4ee5\u4e0b\u3067\u3059
jsp.error.file.not.found=JSP \u30d5\u30a1\u30a4\u30eb \"{0}\" \u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093
jsp.message.copyinguri={0} \u3092 {1} \u306b\u30b3\u30d4\u30fc\u3057\u307e\u3059
jsp.message.htmlcomment=\n\u524a\u9664\u3059\u308b\u30b3\u30e1\u30f3\u30c8: \t{0}
jsp.message.handling_directive=\n\u51e6\u7406\u3059\u308b\u6307\u793a\u5b50: {0}\t{1}
jsp.message.handling_plugin=\nPlugin: {0}
jsp.message.package_name_is=\u30d1\u30c3\u30b1\u30fc\u30b8\u540d: {0}
jsp.message.class_name_is=\u30af\u30e9\u30b9\u540d: {0}
jsp.message.java_file_name_is=Java\u30d5\u30a1\u30a4\u30eb\u540d: {0}
jsp.message.class_file_name_is=\u30af\u30e9\u30b9\u30d5\u30a1\u30a4\u30eb\u540d: {0}
jsp.message.accepted={1} \u3067 {0} \u3092\u53d7\u3051\u5165\u308c\u307e\u3059
jsp.message.adding_jar=jar {0} \u3092\u30af\u30e9\u30b9\u30d1\u30b9\u306b\u8ffd\u52a0\u3057\u307e\u3059
jsp.message.compiling_with={0} \u3092\u30b3\u30f3\u30d1\u30a4\u30eb\u4e2d\u3067\u3059
jsp.message.template_text=\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u30c6\u30ad\u30b9\u30c8
jsp.error.missing_attribute=TLD\u53c8\u306f\u30bf\u30b0\u30d5\u30a1\u30a4\u30eb\u306b\u3088\u308b\u3068\u3001\u5c5e\u6027 {0} \u306f\u30bf\u30b0 {1} \u306b\u306f\u5fc5\u9808\u3067\u3059
jsp.error.bad_attribute=TLD\u306b\u3088\u308b\u3068\u3001\u30bf\u30b0 {1} \u306e\u5c5e\u6027 {0} \u306f\u7121\u52b9\u3067\u3059
jsp.error.tld.unable_to_read=JAR\u30d5\u30a1\u30a4\u30eb \"{0}\" \u304b\u3089TLD \"{1}\" \u3092\u8aad\u307f\u8fbc\u3081\u307e\u305b\u3093: {2}
jsp.error.tld.unable_to_get_jar=TLD\u3092\u542b\u3080JAR\u30ea\u30bd\u30fc\u30b9 \"{0}\" \u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093 : {1}
jsp.error.tld.missing_jar=TLD\u3092\u542b\u3080JAR\u30ea\u30bd\u30fc\u30b9 \"{0}\" \u304c\u3042\u308a\u307e\u305b\u3093
jsp.error.webxml_not_found=web.xml\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093
jsp.cmd_line.usage=\u4f7f\u7528\u6cd5: [-dd <\u51fa\u529b\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u30d1\u30b9>] [-keepgenerated] \
<.jsp\u30d5\u30a1\u30a4\u30eb\u7fa4>
jsp.message.cp_is=\u30af\u30e9\u30b9\u30d1\u30b9 {0} \u306f {1} \u3067\u3059
jsp.error.unable.to_load_taghandler_class=\u30bf\u30b0\u30cf\u30f3\u30c9\u30e9\u30af\u30e9\u30b9 {0} \u3092 {1} \u306e\u305f\u3081\u306b\u30ed\u30fc\u30c9\u3067\u304d\u307e\u305b\u3093
jsp.error.unable.to_find_method=\u5c5e\u6027 {0} \u306esetter\u30e1\u30bd\u30c3\u30c9\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093
jsp.error.unable.to_convert_string=\u5c5e\u6027 {1}\u306e\u6587\u5b57\u5217\u3092 {0}\u306b\u5909\u63db\u3067\u304d\u307e\u305b\u3093
jsp.error.unable.to_introspect=\u30bf\u30b0\u30cf\u30f3\u30c9\u30e9\u30af\u30e9\u30b9 {0} \u3092 {1} \u306e\u305f\u3081\u306b\u5185\u7701\u3067\u304d\u307e\u305b\u3093
jsp.error.bad_tag=\u30d7\u30ec\u30d5\u30a3\u30c3\u30af\u30b9 {1}\u3067\u30a4\u30f3\u30dd\u30fc\u30c8\u3055\u308c\u305f\u30bf\u30b0\u30e9\u30a4\u30d6\u30e9\u30ea\u306b\u306f\u3001\u30bf\u30b0 {0} \u306f\u5b58\u5728\u3057\u307e\u305b\u3093
jsp.error.xml.bad_tag=URI \"{1}\" \u306b\u95a2\u9023\u3065\u3051\u3089\u308c\u305f\u30bf\u30b0\u30e9\u30a4\u30d6\u30e9\u30ea\u306e\u4e2d\u306b\u306f\u30bf\u30b0 \"{0}\" \u306f\u5b9a\u7fa9\u3055\u308c\u3066\u3044\u307e\u305b\u3093
jsp.error.bad_string_Character=\u9577\u30550\u306e\u914d\u5217\u304b\u3089\u306f\u6587\u5b57\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093
jsp.error.bad_string_char=\u9577\u30550\u306e\u914d\u5217\u304b\u3089\u306f\u6587\u5b57\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093
jsp.warning.compiler.class.cantcreate=\u6307\u5b9a\u3055\u308c\u305f\u30b3\u30f3\u30d1\u30a4\u30e9\u30d7\u30e9\u30b0\u30a4\u30f3\u30af\u30e9\u30b9 {0} \u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u3092 {1} \u306e\u305f\u3081\u306b\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3002\u30c7\u30d5\u30a9\u30eb\u30c8\u3092Sun\u306eJava\u30b3\u30f3\u30d1\u30a4\u30e9\u306b\u3057\u307e\u3059\u3002
jsp.warning.compiler.class.notfound=\u6307\u5b9a\u3055\u308c\u305f\u30b3\u30f3\u30d1\u30a4\u30e9\u30d7\u30e9\u30b0\u30a4\u30f3\u30af\u30e9\u30b9 {0} \u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002not found. \u30c7\u30d5\u30a9\u30eb\u30c8\u3092Sun\u306eJava\u30b3\u30f3\u30d1\u30a4\u30e9\u306b\u3057\u307e\u3059\u3002
jsp.warning.compiler.path.notfound=\u6307\u5b9a\u3055\u308c\u305f\u30b3\u30f3\u30d1\u30a4\u30e9\u30d1\u30b9 {0} \u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002\u30b7\u30b9\u30c6\u30e0\u306ePATH\u3092\u30c7\u30d5\u30a9\u30eb\u30c8\u306b\u3057\u307e\u3059\u3002
jsp.error.jspc.uriroot_not_dir=-uriroot \u30aa\u30d7\u30b7\u30e7\u30f3\u306f\u3001\u65e2\u306b\u5b58\u5728\u3059\u308b\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u6307\u5b9a\u3057\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.jspc.missingTarget=\u30bf\u30fc\u30b2\u30c3\u30c8\u304c\u3042\u308a\u307e\u305b\u3093: -webapp\u53c8\u306f-uriroot\uff0c\u53c8\u306f\u4e00\u3064\u4ee5\u4e0a\u306eJSP\u30da\u30fc\u30b8\u3092\u6307\u5b9a\u3057\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.jspc.no_uriroot=uriroot\u304c\u6307\u5b9a\u3055\u308c\u3066\u3044\u306a\u3044\u306e\u3067\u3001\u6307\u5b9a\u3055\u308c\u305fJSP\u30d5\u30a1\u30a4\u30eb(\u7fa4)\u3092\u914d\u7f6e\u3067\u304d\u307e\u305b\u3093
jspc.implicit.uriRoot=uriRoot\u306f\u30c7\u30d5\u30a9\u30eb\u30c8"{0}"\u306b\u8a2d\u5b9a\u3055\u308c\u307e\u3059
jspc.usage=\u4f7f\u7528\u6cd5: jspc <options> [--] <jsp files>\n\
JSP\u30d5\u30a1\u30a4\u30eb\u306e\u5834\u6240\u306f\u6b21\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3067\u6307\u5b9a\u3059\u308b\u304b\u3001\n\
\ -webapp <dir> web-app\u3092\u542b\u3080\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3002\u3059\u3079\u3066\u306eJSP\u30d5\u30a1\u30a4\u30eb\u306f\n\
\ \u518d\u5e30\u7684\u306b\u89e3\u6790\u3055\u308c\u308b\n\
\u53c8\u306f\u6b21\u306e\u4efb\u610f\u306e\u6570\u306e\u30d5\u30a1\u30a4\u30eb\u3067\u6307\u5b9a\u3057\u307e\u3059\u3002\n\
\ <file> JSP\u3068\u3057\u3066\u89e3\u6790\u3055\u308c\u308b\u30d5\u30a1\u30a4\u30eb\n\
\u30aa\u30d7\u30b7\u30e7\u30f3\u306f\u4ee5\u4e0b\u306e\u901a\u308a\u3067\u3059\n\
\ -help \u3053\u306e\u30d8\u30eb\u30d7\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u8868\u793a\n\
\ -v Verbose\u30e2\u30fc\u30c9\n\
\ -d <dir> \u51fa\u529b\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\n\
\ -l \u5931\u6557\u3057\u305fJSP\u30da\u30fc\u30b8\u306e\u540d\u524d\u306e\u51fa\u529b\n\
\ -s \u6210\u529f\u3057\u305fJSP\u30da\u30fc\u30b8\u306e\u540d\u524d\u306e\u51fa\u529b\n\
\ -p <name> \u30bf\u30fc\u30b2\u30c3\u30c8\u30d1\u30c3\u30b1\u30fc\u30b8\u306e\u540d\u524d (\u30c7\u30d5\u30a9\u30eb\u30c8\u306forg.apache.jsp)\n\
\ -c <name> \u30bf\u30fc\u30b2\u30c3\u30c8\u30af\u30e9\u30b9\u306e\u540d\u524d (\u6700\u521d\u306eJSP\u30da\u30fc\u30b8\u3060\u3051\u306b\u9069\u7528\u3055\u308c\u308b)\n\
\ -mapped JSP\u306e\u5404HTML\u884c\u3054\u3068\u306bwrite()\u30b3\u30fc\u30eb\u3092\u751f\u6210\n\
\ -die[#] \u81f4\u547d\u7684\u30a8\u30e9\u30fc\u306b\u30a8\u30e9\u30fc\u30ea\u30bf\u30fc\u30f3\u30b3\u30fc\u30c9(#)\u3092\u751f\u6210 (\u30c7\u30d5\u30a9\u30eb\u30c8\u306f1)\n\
\ -uribase <dir> \u30b3\u30f3\u30d1\u30a4\u30eb\u304c\u76f8\u5bfe\u7684\u306b\u304a\u3053\u306a\u308f\u308c\u308buri\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\n\
\ (\u30c7\u30d5\u30a9\u30eb\u30c8\u306f"/")\n\
\ -uriroot <dir> -webapp\u3068\u540c\u3058\n\
\ -compile \u751f\u6210\u3057\u305f\u30b5\u30fc\u30d6\u30ec\u30c3\u30c8\u306e\u30b3\u30f3\u30d1\u30a4\u30eb\n\
\ -webinc <file> \u30d5\u30a1\u30a4\u30eb\u306b\u90e8\u5206\u7684\u306a\u30b5\u30fc\u30d6\u30ec\u30c3\u30c8\u30de\u30c3\u30d4\u30f3\u30b0\u3092\u4f5c\u6210\n\
\ -webxml <file> \u30d5\u30a1\u30a4\u30eb\u306b\u5b8c\u5168\u306aweb.xml\u3092\u4f5c\u6210\n\
\ -ieplugin <clsid> Internet Explorer\u306eJava Plugin\u306eclassid\n\
\ -classpath <path> java.class.path\u30b7\u30b9\u30c6\u30e0\u30d7\u30ed\u30d1\u30c6\u30a3\u306e\u4e0a\u66f8\u304d\n\
\ -xpoweredBy X-Powered-By\u30ec\u30b9\u30dd\u30f3\u30b9\u30d8\u30c3\u30c0\u306e\u8ffd\u52a0\n\
\ -trimSpaces \u30a2\u30af\u30b7\u30e7\u30f3\u3084\u6307\u793a\u5b50\u306e\u9593\u306e\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u30c6\u30ad\u30b9\u30c8\u4e2d\u306e\u30b9\u30da\u30fc\u30b9\u3092\u524a\u9664\n\
\ -trimSpaces Trim spaces in template text between actions, directives\n\
\ -javaEncoding <enc> Set the encoding charset for Java classes (default UTF-8)\n\
\ -source <version> Set the -source argument to the compiler (default 1.4)\n\
\ -target <version> Set the -target argument to the compiler (default 1.4)\n\
jspc.webxml.header=<?xml version="1.0" encoding="ISO-8859-1"?>\n\
\n\
<!DOCTYPE web-app\n\
\ PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"\n\
\ "http://java.sun.com/dtd/web-app_2_3.dtd">\n\
<!--\n\
Automatically created by Apache Jakarta Tomcat JspC.\n\
-->\n\
<web-app>\n\
\n
jspc.webxml.footer=\n\
</web-app>\n\
\n
jspc.webinc.header=\n\
<!--\n\
Automatically created by Apache Jakarta Tomcat JspC.\n\
Place this fragment in the web.xml before all icon, display-name,\n\
description, distributable, and context-param elements.\n\
-->\n
jspc.webinc.footer=\n\
<!--\n\
All session-config, mime-mapping, welcome-file-list, error-page, taglib,\n\
resource-ref, security-constraint, login-config, security-role,\n\
env-entry, and ejb-ref elements should follow this fragment.\n\
-->\n
jspc.webinc.insertEnd=<!-- JSPC servlet mappings end -->
jspc.webinc.insertStart=<!-- JSPC servlet mappings start -->
jspc.error.jasperException=\u30a8\u30e9\u30fc: \u30d5\u30a1\u30a4\u30eb ''{0}'' \u306f\u6b21\u306e\u4f8b\u5916\u3092\u767a\u751f\u3057\u307e\u3057\u305f: {1}
jspc.error.generalException=\u30a8\u30e9\u30fc: \u30d5\u30a1\u30a4\u30eb ''{0}'' \u306f\u6b21\u306e\u4f8b\u5916\u3092\u767a\u751f\u3057\u307e\u3057\u305f:
jspc.error.fileDoesNotExist=\u30d5\u30a1\u30a4\u30eb\u5f15\u6570 ''{0}'' \u306f\u5b58\u5728\u3057\u307e\u305b\u3093\u3002
jspc.error.emptyWebApp=-webapp\u30aa\u30d7\u30b7\u30e7\u30f3\u306b\u306f\u3001\u30d5\u30a1\u30a4\u30eb\u5f15\u6570\u304c\u5fc5\u8981\u3067\u3059
jsp.error.library.invalid=\u30e9\u30a4\u30d6\u30e9\u30ea{0}\u306b\u5f93\u3046\u3068JSP\u30da\u30fc\u30b8\u306f\u7121\u52b9\u3067\u3059: {1}
jsp.error.tlvclass.instantiation=TagLibraryValidator\u30af\u30e9\u30b9\u306e\u30ed\u30fc\u30c9\u53c8\u306f\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u5316\u306b\u5931\u6557\u3057\u307e\u3057\u305f: {0}
jsp.error.tlv.invalid.page={0} \u306b\u5bfe\u3059\u308bTagLibraryValidator\u306e\u691c\u8a3c\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u3067\u3059 ({1})
jsp.error.tei.invalid.attributes={0} \u306b\u5bfe\u3059\u308bTagExtraInfo\u304b\u3089\u306e\u691c\u8a3c\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u3067\u3059
jsp.parser.sax.propertynotsupported=SAX\u30d7\u30ed\u30d1\u30c6\u30a3\u304c\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u307e\u305b\u3093: {0}
jsp.parser.sax.propertynotrecognized=SAX\u30d7\u30ed\u30d1\u30c6\u30a3\u304c\u8a8d\u8b58\u3055\u308c\u307e\u305b\u3093: {0}
jsp.parser.sax.featurenotsupported=SAX\u30d5\u30a3\u30fc\u30c1\u30e3\u304c\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u307e\u305b\u3093: {0}
jsp.parser.sax.featurenotrecognized=SAX\u30d5\u30a3\u30fc\u30c1\u30e3\u304c\u8a8d\u8b58\u3055\u308c\u307e\u305b\u3093: {0}
jsp.error.no.more.content=\u5fc5\u8981\u306a\u89e3\u6790\u4e2d\u306b\u5185\u5bb9\u306e\u6700\u5f8c\u307e\u3067\u9054\u3057\u307e\u3057\u305f: \u30bf\u30b0\u306e\u30cd\u30b9\u30c8\u306e\u30a8\u30e9\u30fc\u304b\u3082\u3057\u308c\u307e\u305b\u3093
jsp.error.parse.xml=\u30d5\u30a1\u30a4\u30eb{0}\u306eXML\u89e3\u6790\u30a8\u30e9\u30fc
jsp.error.parse.xml.line=\u30d5\u30a1\u30a4\u30eb{0}\u306eXML\u89e3\u6790\u30a8\u30e9\u30fc: (\u884c {1}, \u5217 {2})
jsp.error.parse.xml.scripting.invalid.body={0} \u8981\u7d20\u306e\u30dc\u30c7\u30a3\u306fXML\u8981\u7d20\u3092\u542b\u3093\u3067\u306f\u3044\u3051\u307e\u305b\u3093
jsp.error.internal.tldinit=TldLocationsCache\u3092\u521d\u671f\u5316\u4e2d\u306e\u4f8b\u5916\u3067\u3059: {0}
jsp.error.internal.filenotfound=\u5185\u90e8\u30a8\u30e9\u30fc: \u30d5\u30a1\u30a4\u30eb {0} \u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093
jsp.error.internal.evaluator_not_found=\u5185\u90e8\u30a8\u30e9\u30fc: \u5f0f\u691c\u8a3c\u5668\u3092\u30ed\u30fc\u30c9\u3067\u304d\u307e\u305b\u3093
jsp.error.parse.xml.invalidPublicId=\u7121\u52b9\u306aPUBLIC ID: {0}
jsp.error.include.flush.invalid.value=flush\u5c5e\u6027\u306b\u7121\u52b9\u306a\u5024\u304c\u6307\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059: {0}
jsp.error.unsupported.encoding=\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u306a\u3044\u30a8\u30f3\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0\u3067\u3059: {0}
tld.error.variableNotAllowed=null\u3067\u306a\u3044\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u8fd4\u3059TagExtraInfo\u3092\u6301\u3064\u4e00\u3064\u4ee5\u4e0a\u306e\u5909\u6570\u526f\u8981\u7d20\u3092\u6301\u3064\u30bf\u30b0\u306f\u30a8\u30e9\u30fc\u3067\u3059\u3002
jsp.error.tldInWebDotXmlNotFound=web.xml\u3067\u6307\u5b9a\u3055\u308c\u305fURI {0} \u306bTLD\u3092\u914d\u7f6e\u3067\u304d\u307e\u305b\u3093
jsp.error.taglibDirective.absUriCannotBeResolved=\u7d76\u5bfeURI: {0} \u306fweb.xml\u3068\u3053\u306e\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u914d\u5099\u3057\u305fJAR\u30d5\u30a1\u30a4\u30eb\u306e\u3069\u3061\u3089\u304b\u3067\u3082\u89e3\u6c7a\u3067\u304d\u307e\u305b\u3093
jsp.error.taglibDirective.missing.location=taglib\u6307\u793a\u5b50\u306e\u4e2d\u306b'uri'\u5c5e\u6027\u3068'tagdir'\u5c5e\u6027\u306e\u3069\u3061\u3089\u3082\u6307\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093
jsp.error.taglibDirective.both_uri_and_tagdir=\'uri\'\u5c5e\u6027 \u3068 \'tagdir\'\u5c5e\u6027\u306e\u4e21\u65b9\u304c\u6307\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059
jsp.error.invalid.tagdir=\u30bf\u30b0\u30d5\u30a1\u30a4\u30eb\u30c7\u30a3\u30ec\u30af\u30c8\u30ea {0} \u304c\"/WEB-INF/tags\"\u3067\u59cb\u307e\u308a\u307e\u305b\u3093
jsp.error.unterminated.user.tag=\u672a\u7d42\u4e86\u306e\u30e6\u30fc\u30b6\u5b9a\u7fa9\u30bf\u30b0: \u7d42\u4e86\u30bf\u30b0 {0} \u304c\u898b\u3064\u304b\u3089\u306a\u3044\u304b\u3001\u30cd\u30b9\u30c8\u304c\u9593\u9055\u3063\u3066\u3044\u307e\u3059
#jspx.error.templateDataNotInJspCdata=Validation Error: Element &lt;{0}&gt; cannot have template data. Template data must be encapsulated within a &lt;jsp:cdata&gt; element. [JSP1.2 PFD section 5.1.9]\nTemplate data in error: {1}
jspx.error.templateDataNotInJspCdata=\u8a3c\u660e\u30a8\u30e9\u30fc: \u8981\u7d20&lt;{0}&gt;\u306f\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u30c7\u30fc\u30bf\u3092\u6301\u3064\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u30c7\u30fc\u30bf\u306f\u3001&lt;jsp:text&gt;\u8981\u7d20\u306e\u4e2d\u3067\u96a0\u853d\u3055\u308c\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093\u3002[JSP1.2 PFD 5.1.9]\n\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u30c7\u30fc\u30bf\u306e\u30a8\u30e9\u30fc\u3067\u3059: {1}
#Error while processing taglib jar file {0}: {1}
jsp.error.taglib.reserved.prefix=taglib\u30d7\u30ea\u30d5\u30a3\u30af\u30b9 {0} \u306f\u4e88\u7d04\u3055\u308c\u3066\u3044\u307e\u3059
jsp.error.invalid.javaEncoding=\u7121\u52b9\u306aJava\u30a8\u30f3\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0\u3067\u3059\u3002{0}\u3092\u8a66\u3057\u3066\u3001\u305d\u308c\u304b\u3089{1}\u3092\u8a66\u3057\u307e\u3057\u305f\u304c\u3001\u4e21\u65b9\u304c\u5931\u6557\u3057\u307e\u3057\u305f
jsp.error.needAlternateJavaEncoding=\u30c7\u30d5\u30a9\u30eb\u30c8\u306eJava\u30a8\u30f3\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0 {0} \u306f\u3042\u306a\u305f\u306e\u30d7\u30e9\u30c3\u30c8\u30d5\u30a9\u30fc\u30e0\u3067\u306f\u7121\u52b9\u3067\u3059\u3002JspServlet\u306e 'javaEncoding' \u30d1\u30e9\u30e1\u30bf\u3067\u3001\u5225\u306e\u5024\u3092\u6307\u5b9a\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002
#Error when compiling, used for jsp line number error messages
jsp.error.single.line.number=JSP\u30d5\u30a1\u30a4\u30eb: {1} \u306e\u4e2d\u306e{0}\u884c\u76ee\u3067\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f
jsp.error.multiple.line.number=\n\nJPS\u30d5\u30a1\u30a4\u30eb: {2}\u306e\u4e2d\u306e{0}\u884c\u76ee\u3068{1}\u884c\u76ee\u306e\u9593\u3067\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\n\n
jsp.error.corresponding.servlet=\u751f\u6210\u3055\u308c\u305f\u30b5\u30fc\u30d6\u30ec\u30c3\u30c8\u306e\u30a8\u30e9\u30fc\u3067\u3059:\n
jsp.error.empty.body.not.allowed={0} \u306b\u5bfe\u3057\u3066\u7a7a\u306e\u30dc\u30c7\u30a3\u306f\u8a31\u3055\u308c\u307e\u305b\u3093
jsp.error.jspbody.required=jsp:attribute\u304c\u4f7f\u7528\u3055\u308c\u305f\u5834\u5408\u306b\u306f\u3001{0}\u306b\u30bf\u30b0\u30dc\u30c7\u30a3\u3092\u6307\u5b9a\u3059\u308b\u305f\u3081\u306bjsp:body\u3092\u4f7f\u7528\u3057\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.jspbody.emptybody.only={0} \u30bf\u30b0\u306f\u3001\u305d\u306e\u30dc\u30c7\u30a3\u4e2d\u306bjsp:attribute\u3060\u3051\u3092\u6301\u3064\u3053\u3068\u304c\u3067\u304d\u307e\u3059
jsp.error.no.scriptlets=\u30b9\u30af\u30ea\u30d7\u30c6\u30a3\u30f3\u30b0\u8981\u7d20 ( &lt;%!\u3001&lt;jsp:declaration\u3001&lt;%=\u3001&lt;jsp:expression\u3001&lt;%\u3001&lt;jsp:scriptlet ) \u306f\u3053\u3053\u3067\u306f\u8a31\u3055\u308c\u307e\u305b\u3093
jsp.error.internal.unexpected_node_type=\u5185\u90e8\u30a8\u30e9\u30fc: \u672a\u77e5\u306e\u30ce\u30fc\u30c9\u30bf\u30a4\u30d7\u304c\u8868\u308c\u307e\u3057\u305f
jsp.error.tld.fn.invalid.signature=TLD\u306e\u4e2d\u306e\u95a2\u6570\u30b7\u30b0\u30cd\u30c1\u30e3\u306b\u5bfe\u3059\u308b\u7121\u52b9\u306a\u69cb\u6587\u3067\u3059\u3002\u30bf\u30b0\u30e9\u30a4\u30d6\u30e9\u30ea: {0}\u3001\u95a2\u6570: {1}
jsp.error.tld.fn.duplicate.name=\u30bf\u30b0\u30e9\u30a4\u30d6\u30e9\u30ea {1} \u306e\u4e2d\u306e\u95a2\u6570\u540d {0} \u304c\u91cd\u8907\u3057\u3066\u3044\u307e\u3059
jsp.error.tld.fn.invalid.signature.commaexpected=TLD\u306e\u4e2d\u306e\u95a2\u6570\u30b7\u30b0\u30cd\u30c1\u30e3\u306b\u5bfe\u3059\u308b\u7121\u52b9\u306a\u69cb\u6587\u3067\u3059\u3002\u30b3\u30f3\u30de ',' \u304c\u3042\u308a\u307e\u305b\u3093\u3002\u30bf\u30b0\u30e9\u30a4\u30d6\u30e9\u30ea: {0}\u3001\u95a2\u6570: {1}\u3002
jsp.error.tld.fn.invalid.signature.parenexpected=TLD\u306e\u4e2d\u306e\u95a2\u6570\u30b7\u30b0\u30cd\u30c1\u30e3\u306b\u5bfe\u3059\u308b\u7121\u52b9\u306a\u69cb\u6587\u3067\u3059\u3002\u62ec\u5f27 '(' \u304c\u3042\u308a\u307e\u305b\u3093\u3002\u30bf\u30b0\u30e9\u30a4\u30d6\u30e9\u30ea: {0}\u3001\u95a2\u6570: {1}\u3002
jsp.error.tld.mandatory.element.missing=\u5fc5\u9808TLD\u8981\u7d20\u304c\u306a\u3044\u3001\u53c8\u306f\u7a7a\u3067\u3059: {0}
jsp.error.dynamic.attributes.not.implemented={0} \u30bf\u30b0\u306f\u305d\u308c\u304cdynamic\u5c5e\u6027\u3092\u53d7\u3051\u4ed8\u3051\u308b\u3068\u5ba3\u8a00\u3057\u3066\u3044\u307e\u3059\u304c\u3001\u305d\u308c\u306b\u5fc5\u8981\u306a\u30a4\u30f3\u30bf\u30d5\u30a7\u30fc\u30b9\u3092\u5b9f\u88c5\u3057\u3066\u3044\u307e\u305b\u3093
jsp.error.nomatching.fragment=attribute\u6307\u793a\u5b50 (name={0}\u304a\u3088\u3073fragment=true\u3092\u6301\u3064) \u304cfragment\u6307\u793a\u5b50\u3088\u308a\u524d\u306b\u898b\u3064\u304b\u308a\u307e\u305b\u3093
jsp.error.attribute.noequal=\u7b49\u53f7\u8a18\u53f7\u304c\u5fc5\u8981\u3067\u3059
jsp.error.attribute.noquote=\u5f15\u7528\u7b26\u304c\u5fc5\u8981\u3067\u3059
jsp.error.attribute.unterminated={0} \u306e\u5c5e\u6027\u304c\u6b63\u3057\u304f\u7d42\u4e86\u3057\u3066\u3044\u307e\u305b\u3093
jsp.error.missing.tagInfo={0} \u306b\u5bfe\u3059\u308bTagInfo\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u304cTLD\u304b\u3089\u5931\u308f\u308c\u307e\u3057\u305f
jsp.error.fragmentwithtype='fragment'\u5c5e\u6027\u3068'type'\u5c5e\u6027\u3092\u4e21\u65b9\u6307\u5b9a\u3067\u304d\u307e\u305b\u3093\u3002'fragment'\u304c\u5b58\u5728\u3059\u308b\u5834\u5408\u306b\u306f'type'\u306f'javax.servlet.jsp.tagext.JspFragment'\u306b\u56fa\u5b9a\u3055\u308c\u307e\u3059
jsp.error.fragmentwithrtexprvalue='fragment'\u5c5e\u6027\u3068'rtexprvalue'\u5c5e\u6027\u3092\u4e21\u65b9\u6307\u5b9a\u3067\u304d\u307e\u305b\u3093\u3002'fragment'\u304c\u5b58\u5728\u3059\u308b\u5834\u5408\u306b\u306f'rtexprvalue'\u306f'true'\u306b\u56fa\u5b9a\u3055\u308c\u307e\u3059
jsp.error.fragmentWithDeclareOrScope='fragment'\u5c5e\u6027\u3068'declare'\u5c5e\u6027\u306e\u4e21\u65b9\u53c8\u306f'scope'\u5c5e\u6027\u304cvariable\u6307\u793a\u5b50\u4e2d\u3067\u6307\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059
jsp.error.var_and_varReader=\'var\'\u53c8\u306f\'varReader\'\u306e\u3069\u3061\u3089\u304b\u4e00\u3064\u3092\u6307\u5b9a\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059
jsp.error.missing_var_or_varReader=\'var\'\u53c8\u306f\'varReader\'\u5c5e\u6027\u304c\u3042\u308a\u307e\u305b\u3093
jsp.warning.bad.urlpattern.propertygroup=web.xml\u4e2d\u306eurl-pattern\u526f\u8981\u7d20\u4e2d\u306b\u8aa4\u3063\u305f\u5024 {0} \u304c\u3042\u308a\u307e\u3059
jsp.error.unknown_attribute_type=\u5c5e\u6027 {0} \u306b\u5bfe\u3059\u308b\u672a\u77e5\u306e\u5c5e\u6027\u30bf\u30a4\u30d7\u3067\u3059
jsp.error.jspelement.missing.name=\u5fc5\u9808\u306eXML\u30b9\u30bf\u30a4\u30eb\u306e'name'\u5c5e\u6027\u304cjsp:element\u4e2d\u306b\u3042\u308a\u307e\u305b\u3093
jsp.error.xmlns.redefinition.notimplemented=\u5185\u90e8\u30a8\u30e9\u30fc: xmlns:{0}\u3092\u518d\u5b9a\u7fa9\u3057\u3088\u3046\u3068\u3057\u307e\u3057\u305f\u3002\u540d\u524d\u7a7a\u9593\u306e\u518d\u5b9a\u7fa9\u306f\u5b9f\u88c5\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002
jsp.error.could.not.add.taglibraries=1\u3064\u4ee5\u4e0a\u306e\u30bf\u30b0\u30e9\u30a4\u30d6\u30e9\u30ea\u3092\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093
jsp.error.duplicate.name.jspattribute=\u6a19\u6e96\u53c8\u306f\u30ab\u30b9\u30bf\u30e0\u30a2\u30af\u30b7\u30e7\u30f3\u4e2d\u3067\u6307\u5b9a\u3055\u308c\u3066\u3044\u308b\u5c5e\u6027 {0} \u306f\u305d\u308c\u306b\u56f2\u307e\u308c\u305fjsp:attribute\u4e2d\u306ename\u5c5e\u6027\u306e\u5024\u3068\u3057\u3066\u3082\u8868\u308c\u307e\u3059
jsp.error.not.in.template=\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u30c6\u30ad\u30b9\u30c8\u30dc\u30c7\u30a3\u4e2d\u3067\u306f {0} \u306f\u8a31\u3055\u308c\u307e\u305b\u3093
jsp.error.badStandardAction=\u7121\u52b9\u306a\u6a19\u6e96\u30a2\u30af\u30b7\u30e7\u30f3\u3067\u3059
jsp.error.xml.badStandardAction=\u7121\u52b9\u306a\u6a19\u6e96\u30a2\u30af\u30b7\u30e7\u30f3\u3067\u3059: {0}
jsp.error.tagdirective.badbodycontent=tag\u6307\u793a\u5b50\u4e2d\u306e\u7121\u52b9\u306abody-content ({0})\u3067\u3059
jsp.error.simpletag.badbodycontent=\u30af\u30e9\u30b9 {0} \u306eTLD\u306fSimpleTag\u306b\u7121\u52b9\u306abody-content (JSP)\u3092\u6307\u5b9a\u3057\u3066\u3044\u307e\u3059
jsp.error.config_pagedir_encoding_mismatch=jsp-property-group\u4e2d\u306b\u6307\u5b9a\u3055\u308c\u3066\u3044\u308bPage-encoding ({0}) \u304cpage\u6307\u793a\u5b50\u4e2d\u306e\u6307\u5b9a ({1}) \u3068\u9055\u3044\u307e\u3059
jsp.error.prolog_pagedir_encoding_mismatch=XML\u5c0e\u5165\u90e8\u3067\u6307\u5b9a\u3055\u308c\u305fpage-encoding ({0}) \u304cpage\u6307\u793a\u5b50\u4e2d\u306e\u6307\u5b9a ({1}) \u3068\u9055\u3044\u307e\u3059
jsp.error.prolog_config_encoding_mismatch=XML\u5c0e\u5165\u90e8\u3067\u6307\u5b9a\u3055\u308c\u305fpage-encoding ({0}) \u304cjsp-property-group\u4e2d\u306e\u6307\u5b9a\u3068\u9055\u3044\u307e\u3059 ({1})
jsp.error.attribute.custom.non_rt_with_expr=TLD\u53c8\u306f\u30bf\u30b0\u30d5\u30a1\u30a4\u30eb\u4e2d\u306eattribute\u6307\u793a\u5b50\u306b\u5f93\u3063\u3066\u5c5e\u6027{0}\u306f\u3069\u3093\u306a\u5f0f\u3082\u53d7\u3051\u4ed8\u3051\u307e\u305b\u3093
jsp.error.attribute.standard.non_rt_with_expr={1} \u6a19\u6e96\u30a2\u30af\u30b7\u30e7\u30f3\u306e {0} \u5c5e\u6027\u306f\u3069\u3093\u306a\u5f0f\u3082\u53d7\u3051\u4ed8\u3051\u307e\u305b\u3093
jsp.error.scripting.variable.missing_name=\u5c5e\u6027 {0} \u304b\u3089\u30b9\u30af\u30ea\u30d7\u30c8\u5909\u6570\u540d\u3092\u6c7a\u5b9a\u3067\u304d\u307e\u305b\u3093
jasper.error.emptybodycontent.nonempty=TLD\u306b\u5f93\u3063\u3066\u30bf\u30b0 {0} \u306f\u7a7a\u3067\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093\u304c\u3001\u305d\u3046\u3067\u306f\u3042\u308a\u307e\u305b\u3093
jsp.error.tagfile.nameNotUnique={2}\u884c\u76ee\u306e {0} \u306e\u5024\u3068 {1} \u306e\u5024\u306f\u540c\u3058\u3067\u3059
jsp.error.tagfile.nameFrom.noAttribute=\u3053\u306ename-from-attribute\u5c5e\u6027\u306e\u5024\u3067\u3042\u308b\u5024 \"{0}\" \u306ename\u5c5e\u6027\u3092\u6301\u3064attribute\u6307\u793a\u5b50\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093
jsp.error.tagfile.nameFrom.badAttribute=attribute\u6307\u793a\u5b50 ({1}\u884c\u76ee\u3067\u5ba3\u8a00\u3055\u308c\u3001\u305d\u306ename\u5c5e\u6027\u304c\"{0}\"\u3001\u3053\u306ename-from-attribute\u5c5e\u6027\u306e\u5024) \u306fjava.lang.String\u578b\u306e\"required\" \u3067 \"rtexprvalue\".\u3067\u3042\u3063\u3066\u306f\u3044\u3051\u307e\u305b\u3093
jsp.error.page.noSession=\u30bb\u30c3\u30b7\u30e7\u30f3\u306b\u52a0\u308f\u3063\u3066\u3044\u306a\u3044\u30da\u30fc\u30b8\u306e\u4e2d\u3067\u306f\u30bb\u30c3\u30b7\u30e7\u30f3\u30b9\u30b3\u30fc\u30d7\u306b\u30a2\u30af\u30bb\u30b9\u3067\u304d\u307e\u305b\u3093
jsp.error.useBean.noSession=JSP\u30da\u30fc\u30b8\u304c(page\u6307\u793a\u5b50\u306b\u3088\u308a)\u30bb\u30c3\u30b7\u30e7\u30f3\u4e2d\u3067\u5354\u8abf\u3057\u306a\u3044\u3053\u3068\u3092\u5ba3\u8a00\u3057\u3066\u3044\u308b\u6642\u3001\u30bb\u30c3\u30b7\u30e7\u30f3\u30b9\u30b3\u30fc\u30d7\u3092\u4f7f\u7528\u3059\u308b\u305f\u3081\u306euseBean\u304c\u4e0d\u6b63\u3067\u3059
jsp.error.xml.encodingByteOrderUnsupported = \u30a8\u30f3\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0 \"{0}\" \u306b\u6307\u5b9a\u3055\u308c\u305f\u30d0\u30a4\u30c8\u30aa\u30fc\u30c0\u306f\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u307e\u305b\u3093
jsp.error.xml.encodingDeclInvalid = \u7121\u52b9\u306a\u30a8\u30f3\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0\u540d \"{0}\" \u3067\u3059
jsp.error.xml.encodingDeclRequired = \u30c6\u30ad\u30b9\u30c8\u5ba3\u8a00\u4e2d\u306b\u30a8\u30f3\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0\u5ba3\u8a00\u304c\u5fc5\u8981\u3067\u3059
jsp.error.xml.morePseudoAttributes = \u3088\u308a\u591a\u304f\u306e\u7591\u4f3c\u5c5e\u6027\u304c\u5fc5\u8981\u3067\u3059
jsp.error.xml.noMorePseudoAttributes = \u3053\u308c\u4ee5\u4e0a\u306e\u7591\u4f3c\u5c5e\u6027\u306f\u8a31\u3055\u308c\u307e\u305b\u3093
jsp.error.xml.versionInfoRequired = XML\u5ba3\u8a00\u306e\u4e2d\u306b\u30d0\u30fc\u30b8\u30e7\u30f3\u304c\u5fc5\u8981\u3067\u3059
jsp.error.xml.xmlDeclUnterminated = XML\u5ba3\u8a00\u306f\"?>\"\u3067\u7d42\u3089\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.xml.reservedPITarget = \"[xX][mM][lL]\"\u306b\u4e00\u81f4\u3059\u308b\u51e6\u7406\u547d\u4ee4\u30bf\u30fc\u30b2\u30c3\u30c8\u306f\u8a31\u3055\u308c\u3066\u3044\u307e\u305b\u3093
jsp.error.xml.spaceRequiredInPI = \u7a7a\u767d\u304c\u51e6\u7406\u547d\u4ee4\u30bf\u30fc\u30b2\u30c3\u30c8\u3068\u30c7\u30fc\u30bf\u306e\u9593\u306b\u5fc5\u8981\u3067\u3059
jsp.error.xml.invalidCharInContent = \u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u306e\u7121\u52b9\u306aXML\u6587\u5b57 (Unicode: 0x{0}) \u304c\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u306e\u8981\u7d20\u5185\u5bb9\u306e\u4e2d\u306b\u898b\u3064\u304b\u308a\u307e\u3057\u305f
jsp.error.xml.spaceRequiredBeforeStandalone = XML\u5ba3\u8a00\u306eencoding\u7591\u4f3c\u5c5e\u6027\u306e\u524d\u306b\u7a7a\u767d\u304c\u5fc5\u8981\u3067\u3059
jsp.error.xml.sdDeclInvalid = \u30b9\u30bf\u30f3\u30c9\u30a2\u30ed\u30f3\u6587\u66f8\u5ba3\u8a00\u5024\u306f\"yes\"\u53c8\u306f\"no\"\u306e\u3069\u3061\u3089\u304b\u3067\u3042\u308a\u3001\"{0}\"\u3067\u306f\u3044\u3051\u307e\u305b\u3093
jsp.error.xml.invalidCharInPI = \u7121\u52b9\u306aXML\u6587\u5b57 (Unicode: 0x{0}) \u304c\u547d\u4ee4\u51e6\u7406\u4e2d\u306b\u898b\u3064\u304b\u308a\u307e\u3057\u305f
jsp.error.xml.versionNotSupported = XML\u30d0\u30fc\u30b8\u30e7\u30f3 \"{0}\" \u306f\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3001XML 1.0\u3060\u3051\u3092\u30b5\u30dd\u30fc\u30c8\u3057\u3066\u3044\u307e\u3059
jsp.error.xml.pseudoAttrNameExpected = \u7591\u4f3c\u5c5e\u6027\u540d\u304c\u5fc5\u8981\u3067\u3059
jsp.error.xml.expectedByte ={1}\u30d0\u30a4\u30c8UTF-8\u30b7\u30fc\u30b1\u30f3\u30b9\u306e\u30d0\u30a4\u30c8 {0} \u304c\u5fc5\u8981\u3067\u3059
jsp.error.xml.invalidByte = {1}\u30d0\u30a4\u30c8UTF-8\u30b7\u30fc\u30b1\u30f3\u30b9\u306e\u7121\u52b9\u306a\u30d0\u30a4\u30c8 {0} \u3067\u3059
jsp.error.xml.operationNotSupported = {1} reader\u306f\u64cd\u4f5c \"{0}\" \u3092\u30b5\u30dd\u30fc\u30c8\u3057\u3066\u3044\u307e\u305b\u3093
jsp.error.xml.invalidHighSurrogate = UTF-8\u30b7\u30fc\u30b1\u30f3\u30b9\u306e\u30cf\u30a4\u30b5\u30ed\u30b2\u30fc\u30c8\u30d3\u30c3\u30c8\u306f0x10\u3092\u8d8a\u3048\u3066\u306f\u3044\u3051\u307e\u305b\u3093\u304c\u30010x{0}\u304c\u898b\u3064\u304b\u308a\u307e\u3057\u305f
jsp.error.xml.invalidASCII = \u30d0\u30a4\u30c8 \"{0}\" \u306f7\u30d3\u30c3\u30c8ASCII\u3067\u306f\u3042\u308a\u307e\u305b\u3093
jsp.error.xml.spaceRequiredBeforeEncodingInXMLDecl = XML\u5ba3\u8a00\u306eencoding\u7591\u4f3c\u5c5e\u6027\u306e\u524d\u306b\u7a7a\u767d\u304c\u5fc5\u8981\u3067\u3059
jsp.error.xml.spaceRequiredBeforeEncodingInTextDecl = \u30c6\u30ad\u30b9\u30c8\u5ba3\u8a00\u306eencoding\u7591\u4f3c\u5c5e\u6027\u306e\u524d\u306b\u7a7a\u767d\u304c\u5fc5\u8981\u3067\u3059
jsp.error.xml.spaceRequiredBeforeVersionInTextDecl = \u30c6\u30ad\u30b9\u30c8\u5ba3\u8a00\u306eversion\u7591\u4f3c\u5c5e\u6027\u306e\u524d\u306b\u7a7a\u767d\u304c\u5fc5\u8981\u3067\u3059
jsp.error.xml.spaceRequiredBeforeVersionInXMLDecl = XML\u5ba3\u8a00\u306eversion\u7591\u4f3c\u5c5e\u6027\u306e\u524d\u306b\u7a7a\u767d\u304c\u5fc5\u8981\u3067\u3059
jsp.error.xml.eqRequiredInXMLDecl = XML\u5ba3\u8a00\u4e2d\u3067\"{0}\"\u306e\u6b21\u306b'' = '' \u6587\u5b57\u304c\u7d9a\u304b\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.xml.eqRequiredInTextDecl = \u30c6\u30ad\u30b9\u30c8\u5ba3\u8a00\u4e2d\u3067\"{0}\"\u306e\u6b21\u306b'' = ''\u6587\u5b57\u304c\u7d9a\u304b\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.xml.quoteRequiredInTextDecl = \u30c6\u30ad\u30b9\u30c8\u5ba3\u8a00\u4e2d\u306e\"{0}\"\u306b\u7d9a\u304f\u5024\u306f\u30af\u30aa\u30fc\u30c8\u3067\u56f2\u307e\u308c\u305f\u6587\u5b57\u5217\u3067\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.xml.quoteRequiredInXMLDecl = XML\u5ba3\u8a00\u4e2d\u306e\"{0}\"\u306b\u7d9a\u304f\u5024\u306f\u30af\u30aa\u30fc\u30c8\u3067\u56f2\u307e\u308c\u305f\u6587\u5b57\u5217\u3067\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.xml.invalidCharInTextDecl = \u30c6\u30ad\u30b9\u30c8\u5ba3\u8a00\u306e\u4e2d\u306b\u7121\u52b9\u306aXML\u6587\u5b57 (Unicode: 0x{0}) \u304c\u898b\u3064\u304b\u308a\u307e\u3057\u305f
jsp.error.xml.invalidCharInXMLDecl = XML\u5ba3\u8a00\u306e\u4e2d\u306b\u7121\u52b9\u306aXML\u6587\u5b57 (Unicode: 0x{0}) \u304c\u898b\u3064\u304b\u308a\u307e\u3057\u305f
jsp.error.xml.closeQuoteMissingInTextDecl = \u30c6\u30ad\u30b9\u30c8\u5ba3\u8a00\u4e2d\u306e\"{0}\"\u306b\u7d9a\u304f\u5024\u306e\u4e2d\u306e\u6700\u5f8c\u306e\u30af\u30aa\u30fc\u30c8\u304c\u3042\u308a\u307e\u305b\u3093
jsp.error.xml.closeQuoteMissingInXMLDecl = XML\u5ba3\u8a00\u4e2d\u306e\"{0}\"\u306b\u7d9a\u304f\u5024\u306e\u4e2d\u306e\u6700\u5f8c\u306e\u30af\u30aa\u30fc\u30c8\u304c\u3042\u308a\u307e\u305b\u3093
jsp.error.xml.invalidHighSurrogate = UTF-8\u30b7\u30fc\u30b1\u30f3\u30b9\u306e\u30cf\u30a4\u30b5\u30ed\u30b2\u30fc\u30c8\u30d3\u30c3\u30c8\u306f0x10\u3092\u8d8a\u3048\u3066\u306f\u3044\u3051\u307e\u305b\u3093\u304c\u30010x{0}\u304c\u898b\u3064\u304b\u308a\u307e\u3057\u305f
jsp.error.multiple.jsp = \u8907\u6570\u306e\u4ed5\u69d8\u3092\u6e80\u305f\u3059\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093
jsp.error.jspoutput.conflict=&lt;jsp:output&gt;: \"{0}\"\u306b\u7570\u306a\u308b\u5024\u3092\u8907\u6570\u56de\u6307\u5b9a\u3059\u308b\u306e\u306f\u7121\u52b9\u3067\u3059 (\u65e7: {1}, \u65b0: {2})
jsp.error.jspoutput.doctypenamesystem=&lt;jsp:output&gt;: 'doctype-root-element' \u53ca\u3073 'doctype-system' \u5c5e\u6027\u306f\u540c\u6642\u306b\u6307\u5b9a\u3057\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.jspoutput.doctypepulicsystem=&lt;jsp:output&gt;: 'doctype-public'\u5c5e\u6027\u3092\u6307\u5b9a\u3059\u308b\u5834\u5408\u306f\u3001'doctype-system' \u5c5e\u6027\u3082\u6307\u5b9a\u3057\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.jspoutput.nonemptybody=&lt;jsp:output&gt; \u30dc\u30c7\u30a3\u3092\u6301\u3063\u3066\u306f\u3044\u3051\u307e\u305b\u3093
jsp.error.jspoutput.invalidUse=&lt;jsp:output&gt; \u6a19\u6e96\u69cb\u6587\u306e\u4e2d\u3067\u4f7f\u7528\u3057\u3066\u306f\u3044\u3051\u307e\u305b\u3093
jsp.error.attributes.not.allowed = {0} \u306f\u5c5e\u6027\u3092\u6301\u3064\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093
jsp.error.tagfile.badSuffix=\u30bf\u30b0\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9 {0} \u306e\u4e2d\u306b\".tag\" \u62e1\u5f35\u5b50\u304c\u3042\u308a\u307e\u305b\u3093
jsp.error.tagfile.illegalPath=\u4e0d\u6b63\u306a\u30bf\u30b0\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9\u3067\u3059: {0}\u3001\u3053\u308c\u306f\"/WEB-INF/tags\"\u53c8\u306f\"/META-INF/tags\"\u3067\u59cb\u307e\u3089\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.plugin.wrongRootElement={0} \u306e\u4e2d\u306e\u30eb\u30fc\u30c8\u8981\u7d20\u306e\u540d\u524d\u306f {1} \u3067\u306f\u3042\u308a\u307e\u305b\u3093
jsp.error.attribute.invalidPrefix=\u5c5e\u6027\u306e\u30d7\u30ec\u30d5\u30a3\u30c3\u30af\u30b9 {0} \u306f\u3069\u306e\u53d6\u308a\u8fbc\u307e\u308c\u305f\u30bf\u30b0\u30e9\u30a4\u30d6\u30e9\u30ea\u306b\u3082\u5bfe\u5fdc\u3057\u307e\u305b\u3093
jsp.error.nested.jspattribute=jsp:attribute\u6a19\u6e96\u30a2\u30af\u30b7\u30e7\u30f3\u306f\u5225\u306ejsp:attribute\u6a19\u6e96\u30a2\u30af\u30b7\u30e7\u30f3\u306e\u7bc4\u56f2\u5185\u3067\u30cd\u30b9\u30c8\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093
jsp.error.nested.jspbody=jsp:body\u6a19\u6e96\u30a2\u30af\u30b7\u30e7\u30f3\u306f\u5225\u306ejsp:body\u53c8\u306fjsp:attribute\u6a19\u6e96\u30a2\u30af\u30b7\u30e7\u30f3\u306e\u7bc4\u56f2\u5185\u3067\u30cd\u30b9\u30c8\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093
jsp.error.variable.either.name=name-given\u53c8\u306fname-from-attribute\u5c5e\u6027\u306e\u3069\u3061\u3089\u304b\u3092variable\u6307\u793a\u5b50\u306e\u4e2d\u3067\u6307\u5b9a\u3055\u308c\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.variable.both.name=variable\u6307\u793a\u5b50\u4e2d\u3067name-given\u3068name-from-attribute\u5c5e\u6027\u306e\u4e21\u65b9\u3092\u6307\u5b9a\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093
jsp.error.variable.alias=name-from-attribute\u304a\u3088\u3073alias\u5c5e\u6027\u306e\u4e21\u65b9\u3092variable\u6307\u793a\u5b50\u4e2d\u306b\u6307\u5b9a\u3059\u308b\u3001\u53c8\u306f\u3069\u3061\u3089\u3082\u6307\u5b9a\u3057\u306a\u3044\u3053\u3068\u304c\u3067\u304d\u307e\u3059
jsp.error.attribute.null_name=\u7a7a\u306e\u5c5e\u6027\u540d\u3067\u3059
jsp.error.jsptext.badcontent=\'&lt;\'\u304c&lt;jsp:text&gt;\u306e\u30dc\u30c7\u30a3\u306e\u4e2d\u306b\u73fe\u308c\u308b\u6642\u306f\u3001CDATA\u306e\u4e2d\u306b\u96a0\u853d\u3057\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.jsproot.version.invalid=\u7121\u52b9\u306a\u30d0\u30fc\u30b8\u30e7\u30f3\u756a\u53f7\u3067\u3059: \"{0}\"\u3001\"1.2\" \u53c8\u306f \"2.0\"\u3000\u3067\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.noFunctionPrefix=\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u540d\u524d\u7a7a\u9593\u304c\u6307\u5b9a\u3055\u308c\u3066\u3044\u306a\u3044\u6642\u306b\u306f\u3001\u95a2\u6570 {0} \u306f\u30d7\u30ea\u30d5\u30a3\u30af\u30b9\u4ed8\u304d\u3067\u4f7f\u7528\u3057\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093
jsp.error.noFunction=\u95a2\u6570 {0} \u3092\u6307\u5b9a\u3055\u308c\u305f\u30d7\u30ea\u30d5\u30a3\u30af\u30b9\u3067\u914d\u7f6e\u3067\u304d\u307e\u305b\u3093
jsp.error.noFunctionMethod=\u95a2\u6570 \"{1}\" \u306e\u30e1\u30bd\u30c3\u30c9 \"{0}\" \u304c \"{2}\" \u4e2d\u3067\u898b\u3064\u304b\u308a\u307e\u305b\u3093
jsp.error.function.classnotfound=TLD\u306e\u4e2d\u3067\u95a2\u6570 {1} \u306b\u6307\u5b9a\u3055\u308c\u3066\u3044\u308b\u30af\u30e9\u30b9 {0} \u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093: {2}
jsp.error.signature.classnotfound=TLD\u306e\u4e2d\u306e\u30e1\u30bd\u30c3\u30c9\u30b7\u30b0\u30cd\u30c1\u30e3\u3067\u95a2\u6570 {1} \u306b\u6307\u5b9a\u3055\u308c\u3066\u3044\u308b\u30af\u30e9\u30b9 {0} \u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002 {2}
jsp.error.text.has_subelement=&lt;jsp:text&gt; \u306f\u526f\u8981\u7d20\u3092\u6301\u3063\u3066\u306f\u3044\u3051\u307e\u305b\u3093
jsp.error.data.file.read=\u30d5\u30a1\u30a4\u30eb \"{0}\" \u3092\u8aad\u307f\u8fbc\u307f\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f
jsp.error.prefix.refined=\u30d7\u30ea\u30d5\u30a3\u30c3\u30af\u30b9 {0} \u304c\u73fe\u5728\u306e\u30b9\u30b3\u30fc\u30d7\u4e2d\u3067\u65e2\u306b {2} \u3068\u5b9a\u7fa9\u3055\u308c\u3066\u3044\u308b\u306e\u3067 {1} \u306b\u518d\u5b9a\u7fa9\u3057\u307e\u3057\u305f
jsp.error.nested_jsproot=\u5165\u308c\u5b50\u306b\u306a\u3063\u305f &lt;jsp:root&gt; \u3067\u3059
jsp.error.unbalanced.endtag=\u7d42\u4e86\u30bf\u30b0 \"&lt;/{0}\" \u306e\u5bfe\u5fdc\u304c\u53d6\u308c\u3066\u3044\u307e\u305b\u3093
jsp.error.invalid.bean=useBean\u306e\u30af\u30e9\u30b9\u5c5e\u6027 {0} \u306e\u5024\u304c\u7121\u52b9\u3067\u3059
jsp.error.prefix.use_before_dcl=\u3053\u306e\u30bf\u30b0\u6307\u793a\u5b50\u3067\u6307\u5b9a\u3055\u308c\u3066\u3044\u308b\u30d7\u30ea\u30d5\u30a3\u30c3\u30af\u30b9 {0} \u306f\u3001\u3059\u3067\u306b\u30d5\u30a1\u30a4\u30eb {1} \u306e {2} \u884c\u76ee\u306e\u30a2\u30af\u30b7\u30e7\u30f3\u3067\u4f7f\u7528\u3055\u308c\u3066\u3044\u307e\u3059
@@ -0,0 +1,607 @@
/*
* 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.struts2.jasper.runtime;
import org.apache.struts2.jasper.Constants;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyContent;
import java.io.CharArrayReader;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
/**
* Write text to a character-output stream, buffering characters so as
* to provide for the efficient writing of single characters, arrays,
* and strings.
* <p/>
* 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.struts2.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;
// See comment in setWriter()
private int bufferSizeSave;
/**
* 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/>
* <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;
}
}
/**
* @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) {
// 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. The implementation of
// JspWriter.getBufferSize() returns the value of JspWriter's
// 'bufferSize' field, which is inherited by this class.
// Therefore, we simply save the current 'bufferSize' (so we can
// later restore it should this BodyContentImpl ever be reused by
// a call to PageContext.pushBody()) before setting it to 0.
if (bufferSize != 0) {
bufferSizeSave = bufferSize;
bufferSize = 0;
}
} else {
bufferSize = bufferSizeSave;
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;
}
}
@@ -0,0 +1,113 @@
/*
* 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.struts2.jasper.runtime;
import org.apache.struts2.jasper.compiler.Localizer;
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 java.io.IOException;
/**
* This is the super class of all JSP-generated servlets.
*
* @author Anil K. Vijendran
*/
public abstract class HttpJspBase
extends HttpServlet
implements HttpJspPage
{
static {
if (JspFactory.getDefaultFactory() == null) {
JspFactoryImpl factory = new JspFactoryImpl();
if (System.getSecurityManager() != null) {
String basePackage = "org.apache.struts2.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) {
org.apache.commons.logging.LogFactory.getLog(HttpJspBase.class)
.error("Jasper JspRuntimeContext preload of class failed: " +
ex.getMessage(), ex);
}
}
JspFactory.setDefaultFactory(factory);
}
}
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;
}
@@ -0,0 +1,439 @@
/*
* 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.struts2.jasper.runtime;
import org.apache.commons.el.VariableResolverImpl;
import org.apache.struts2.jasper.compiler.Localizer;
import javax.servlet.*;
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 java.io.IOException;
import java.io.Writer;
import java.util.*;
/**
* Implementation of a JSP Context Wrapper.
* <p/>
* 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
*/
public class JspContextWrapper
extends PageContext implements VariableResolver {
// Invoking JSP context
private PageContext invokingJspCtxt;
private transient Hashtable 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 Hashtable originalNestedVars;
/**
* The variable resolver, for evaluating EL expressions.
*/
private VariableResolverImpl variableResolver
= new VariableResolverImpl(this);
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 Hashtable(16);
this.aliases = aliases;
if (nestedVars != null) {
this.originalNestedVars = new Hashtable(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 getAttributeNamesInScope(int scope) {
if (scope == PAGE_SCOPE) {
return pageAttributes.keys();
}
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 {
include(relativeUrlPath, false); // XXX
}
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 {
return variableResolver.resolveVariable(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;
}
}
@@ -0,0 +1,177 @@
/*
* 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.struts2.jasper.runtime;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.struts2.jasper.util.SimplePool;
import javax.servlet.Servlet;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.jsp.JspEngineInfo;
import javax.servlet.jsp.JspFactory;
import javax.servlet.jsp.PageContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
/**
* Implementation of JspFactory.
*
* @author Anil K. Vijendran
*/
public class JspFactoryImpl extends JspFactory {
// Logger
private Logger log = LoggerFactory.getLogger(JspFactoryImpl.class);
private static final String SPEC_VERSION = "2.0";
private static final boolean USE_POOL =
Boolean.valueOf(System.getProperty("org.apache.struts2.jasper.runtime.JspFactoryImpl.USE_POOL", "true")).booleanValue();
private SimplePool pool = new SimplePool(100);
public PageContext getPageContext(Servlet servlet,
ServletRequest request,
ServletResponse response,
String errorPageURL,
boolean needsSession,
int bufferSize,
boolean autoflush) {
if (System.getSecurityManager() != null) {
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 (System.getSecurityManager() != null) {
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) {
pc = (PageContext) pool.get();
if (pc == null) {
pc = new PageContextImpl(this);
}
} else {
pc = new PageContextImpl(this);
}
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)) {
pool.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;
}
}
}
@@ -0,0 +1,63 @@
/*
* 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.struts2.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;
}
}
@@ -0,0 +1,39 @@
/*
* 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.struts2.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();
}
@@ -0,0 +1,586 @@
/*
* 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.struts2.jasper.runtime;
import org.apache.struts2.jasper.Constants;
import org.apache.struts2.jasper.compiler.Localizer;
import org.apache.struts2.jasper.security.SecurityUtil;
import javax.servlet.ServletResponse;
import javax.servlet.jsp.JspWriter;
import java.io.IOException;
import java.io.Writer;
import java.security.AccessController;
import java.security.PrivilegedAction;
/**
* Write text to a character-output stream, buffering characters so as
* to provide for the efficient writing of single characters, arrays,
* and strings.
* <p/>
* Provide support for discarding for the output that has been
* buffered.
* <p/>
* 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
* @throws 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/>
* <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.
*
* @throws 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>).
* <p/>
* 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();
}
}
@@ -0,0 +1,944 @@
/*
* 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.struts2.jasper.runtime;
import org.apache.commons.el.ExpressionEvaluatorImpl;
import org.apache.commons.el.VariableResolverImpl;
import org.apache.struts2.jasper.Constants;
import org.apache.struts2.jasper.compiler.Localizer;
import org.apache.struts2.jasper.security.SecurityUtil;
import javax.servlet.*;
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 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.Hashtable;
/**
* 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
*/
public class PageContextImpl extends PageContext implements VariableResolver {
// The expression evaluator, for evaluating EL expressions.
private static ExpressionEvaluatorImpl elExprEval
= new ExpressionEvaluatorImpl(false);
// The variable resolver, for evaluating EL expressions.
private VariableResolverImpl variableResolver;
private BodyContentImpl[] outs;
private int depth;
// per-servlet state
private Servlet servlet;
private ServletConfig config;
private ServletContext context;
private String errorPageURL;
// page-scope attributes
private transient Hashtable attributes;
// per-request state
private transient ServletRequest request;
private transient ServletResponse response;
private transient HttpSession session;
private boolean isIncluded;
// initial output stream
private transient JspWriter out;
private transient JspWriterImpl baseOut;
/*
* Constructor.
*/
PageContextImpl(JspFactory factory) {
this.variableResolver = new VariableResolverImpl(this);
this.outs = new BodyContentImpl[0];
this.attributes = new Hashtable(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;
// 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) {
context.log(
"PageContextImpl.release(): Internal error flushing buffer");
}
servlet = null;
config = null;
context = 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 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 attributes.keys();
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 this;
}
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);
request.setAttribute(Constants.FORWARD_SEEN, "true");
}
}
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 elExprEval;
}
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);
}
}
/**
* VariableResolver interface
*/
public Object resolveVariable(String pName) throws ELException {
return variableResolver.resolveVariable(pName);
}
/**
* XML-escape the given string.
*
* @param s The string to escape
* @return The escape string
*/
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("&lt;");
} else if (c == '>') {
sb.append("&gt;");
} else if (c == '\'') {
sb.append("&#039;"); // &apos;
} else if (c == '&') {
sb.append("&amp;");
} else if (c == '"') {
sb.append("&#034;"); // &quot;
} 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;
if (SecurityUtil.isPackageProtectionEnabled()) {
try {
retValue = AccessController.doPrivileged(
new PrivilegedExceptionAction() {
public Object run() throws Exception {
return elExprEval.evaluate(expression,
expectedType,
pageContext.getVariableResolver(),
functionMap);
}
});
} catch (PrivilegedActionException ex) {
Exception realEx = ex.getException();
if (realEx instanceof ELException) {
throw (ELException) realEx;
} else {
throw new ELException(realEx);
}
}
} else {
retValue = elExprEval.evaluate(expression,
expectedType,
pageContext.getVariableResolver(),
functionMap);
}
if (escape) {
retValue = XmlEscape(retValue.toString());
}
return retValue;
}
}
@@ -0,0 +1,131 @@
/*
* 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.struts2.jasper.runtime;
import org.apache.struts2.jasper.Constants;
import javax.servlet.ServletConfig;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.Tag;
import java.util.Enumeration;
import java.util.Vector;
/**
* 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();
}
}
}
}
}
}
@@ -0,0 +1,187 @@
/*
* 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.struts2.jasper.runtime;
import org.apache.struts2.jasper.security.SecurityUtil;
import javax.servlet.jsp.el.FunctionMapper;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.HashMap;
/**
* 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 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;
}
}
@@ -0,0 +1,75 @@
/*
* 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.struts2.jasper.runtime;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import javax.servlet.jsp.JspWriter;
import java.io.IOException;
import java.io.PrintWriter;
/**
* ServletResponseWrapper used by the JSP 'include' action.
* <p/>
* 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) {
}
}
}
@@ -0,0 +1,163 @@
/*
* 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.struts2.jasper.runtime;
import org.apache.struts2.jasper.Constants;
import javax.servlet.ServletConfig;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.Tag;
/**
* 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";
// index of next available tag handler
private int current;
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;
}
/**
* 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 {
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) {
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();
}
/**
* 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();
}
}
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;
}
}
@@ -0,0 +1,113 @@
/*
* 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.struts2.jasper.security;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
/**
* 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 Logger log = LoggerFactory.getLogger(SecurityClassLoad.class);
public static void securityClassLoad(ClassLoader loader) {
if (System.getSecurityManager() == null) {
return;
}
String basePackage = "org.apache.struts2.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);
}
}
}
@@ -0,0 +1,42 @@
/*
* 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.struts2.jasper.security;
/**
* 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 && System.getSecurityManager() != null) {
return true;
}
return false;
}
}
@@ -0,0 +1,167 @@
/*
* 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.struts2.jasper.servlet;
import org.apache.struts2.jasper.Constants;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.CodeSource;
import java.security.PermissionCollection;
/**
* 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 ClassLoader parent;
private SecurityManager securityManager;
public JasperLoader(URL[] urls, ClassLoader parent,
PermissionCollection permissionCollection,
CodeSource codeSource) {
super(urls, parent);
this.permissionCollection = permissionCollection;
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
* @throws 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
* @throws 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.struts2.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.
* <p/>
* 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;
}
}
@@ -0,0 +1,405 @@
/*
* 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.struts2.jasper.servlet;
import com.opensymphony.xwork2.util.finder.ClassLoaderInterface;
import com.opensymphony.xwork2.ActionContext;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import java.io.File;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import org.apache.struts2.ServletActionContext;
/**
* 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;
private ClassLoaderInterface classLoaderInterface;
private static final String WEB_XML = "/WEB-INF/web.xml";
// ----------------------------------------------------------- Constructors
/**
* Create a new instance of this ServletContext implementation.
*
* @param aLogWriter PrintWriter which is used for <code>log()</code> calls
*/
public JspCServletContext(PrintWriter aLogWriter, ClassLoaderInterface classLoaderInterface) {
myAttributes = new Hashtable();
myLogWriter = aLogWriter;
this.classLoaderInterface = classLoaderInterface;
}
// --------------------------------------------------------- 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 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) {
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
* @throws MalformedURLException if the resource path is
* not properly formed
*/
public URL getResource(String path) throws MalformedURLException {
if (WEB_XML.equals(path)) {
if (ActionContext.getContext() != null) {
ServletContext context = ServletActionContext.getServletContext();
return context.getResource(path);
}
return null;
}
return classLoaderInterface.getResource(path);
}
/**
* 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 classLoaderInterface.getResourceAsStream(path);
} 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);
}
}
@@ -0,0 +1,330 @@
/*
* 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.struts2.jasper.servlet;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.struts2.jasper.Constants;
import org.apache.struts2.jasper.EmbeddedServletOptions;
import org.apache.struts2.jasper.Options;
import org.apache.struts2.jasper.compiler.JspRuntimeContext;
import org.apache.struts2.jasper.compiler.Localizer;
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 java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.Enumeration;
/**
* The JSP engine (a.k.a Jasper).
* <p/>
* 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 {
// Logger
private Logger log = LoggerFactory.getLogger(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/>
* <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/>
* <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
* @throws 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();
}
// -------------------------------------------------------- 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
throw new ServletException(Localizer.getMessage(
"jsp.error.file.not.found", jspUri));
} 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);
}
}
@@ -0,0 +1,458 @@
/*
* 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.struts2.jasper.servlet;
import org.apache.struts2.jasper.JasperException;
import org.apache.struts2.jasper.JspCompilationContext;
import org.apache.struts2.jasper.Options;
import org.apache.struts2.jasper.compiler.ErrorDispatcher;
import org.apache.struts2.jasper.compiler.JavacErrorDetail;
import org.apache.struts2.jasper.compiler.JspRuntimeContext;
import org.apache.struts2.jasper.compiler.Localizer;
import org.apache.struts2.jasper.runtime.JspSourceDependent;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.tagext.TagInfo;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
/**
* The JSP engine (a.k.a Jasper).
* <p/>
* 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 {
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.
*/
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, null);
}
/*
* 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();
} catch (IllegalAccessException ex1) {
throw new JasperException(ex1);
} catch (InstantiationException ex) {
throw new JasperException(ex);
}
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;
}
/*
* (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();
}
}
/**
* @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,
this.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);
}
return new JasperException("Exception in JSP: " +
detail.getJspFileName() + ":" + jspLineNumber + "\n\n" +
detail.getJspExtract() + "\n\nStacktrace:", 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);
}
}
}
}
@@ -0,0 +1,36 @@
<?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.struts2.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>
@@ -0,0 +1,326 @@
/*
* 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.struts2.jasper.tagplugins.jstl;
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;
import java.io.*;
import java.util.Locale;
/**
* 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['&'] = "&amp;".toCharArray();
specialCharactersRepresentation['<'] = "&lt;".toCharArray();
specialCharactersRepresentation['>'] = "&gt;".toCharArray();
specialCharactersRepresentation['"'] = "&#034;".toCharArray();
specialCharactersRepresentation['\''] = "&#039;".toCharArray();
}
/**
* Converts the given string description of a scope to the corresponding
* PageContext constant.
* <p/>
* 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
* <p/>
* 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).
* <p/>
* 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(";jsessionid=")) != -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):
* <p/>
* & -> &amp;
* < -> &lt;
* > -> &gt;
* " -> &#034;
* ' -> &#039;
* <p/>
* See also OutSupport.writeEscapedXml().
* <p/>
* 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 &lt;import&gt: " +
"Target servlet called getWriter(), then getOutputStream()");
isWriterUsed = true;
return new PrintWriter(sw);
}
public ServletOutputStream getOutputStream() {
if (isWriterUsed)
throw new IllegalStateException("Unexpected internal error during &lt;import&gt: " +
"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
}
}
}
@@ -0,0 +1,72 @@
/*
* 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.struts2.jasper.tagplugins.jstl.core;
import org.apache.struts2.jasper.compiler.tagplugin.TagPlugin;
import org.apache.struts2.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("}");
}
}
@@ -0,0 +1,35 @@
/*
* 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.struts2.jasper.tagplugins.jstl.core;
import org.apache.struts2.jasper.compiler.tagplugin.TagPlugin;
import org.apache.struts2.jasper.compiler.tagplugin.TagPluginContext;
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("}");
}
}
@@ -0,0 +1,342 @@
/*
* 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.struts2.jasper.tagplugins.jstl.core;
import org.apache.struts2.jasper.compiler.tagplugin.TagPlugin;
import org.apache.struts2.jasper.compiler.tagplugin.TagPluginContext;
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" +
"}"
);
}
}
@@ -0,0 +1,119 @@
/*
* 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.struts2.jasper.tagplugins.jstl.core;
import org.apache.struts2.jasper.compiler.tagplugin.TagPlugin;
import org.apache.struts2.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("}");
}
}
@@ -0,0 +1,51 @@
/*
* 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.struts2.jasper.tagplugins.jstl.core;
import org.apache.struts2.jasper.compiler.tagplugin.TagPlugin;
import org.apache.struts2.jasper.compiler.tagplugin.TagPluginContext;
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("}");
}
}
@@ -0,0 +1,381 @@
/*
* 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.struts2.jasper.tagplugins.jstl.core;
import org.apache.struts2.jasper.compiler.tagplugin.TagPlugin;
import org.apache.struts2.jasper.compiler.tagplugin.TagPluginContext;
import org.apache.struts2.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 &lt;import&gt;\");");
ctxt.generateJavaSource("}");
//initialize the is_absolute_url
ctxt.generateJavaSource(iauName + " = " +
"org.apache.struts2.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.struts2.jasper.tagplugins.jstl.Util.getContentTypeAttribute(" + contentTypeName + ", \"charset\");");
ctxt.generateJavaSource(" if(" + charSetName + " == null) "
+ charSetName + " = org.apache.struts2.jasper.tagplugins.jstl.Util.DEFAULT_ENCODING;");
ctxt.generateJavaSource(" }else{");
ctxt.generateJavaSource(" " + charSetName + " = org.apache.struts2.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.struts2.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 &lt;import&gt; 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.struts2.jasper.tagplugins.jstl.Util.stripSession(" + urlName + "));");
ctxt.generateJavaSource(" if(" + requestDispatcherName + " == null) throw new JspTagException(org.apache.struts2.jasper.tagplugins.jstl.Util.stripSession(" + urlName + "));");
//initialize a ImportResponseWrapper to include the resource
ctxt.generateJavaSource(" org.apache.struts2.jasper.tagplugins.jstl.Util.ImportResponseWrapper " + irwName + " = new org.apache.struts2.jasper.tagplugins.jstl.Util.ImportResponseWrapper((HttpServletResponse) pageContext.getResponse());");
ctxt.generateJavaSource(" if(" + charSetName + " == null){");
ctxt.generateJavaSource(" " + charSetName + " = org.apache.struts2.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.struts2.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.struts2.jasper.tagplugins.jstl.Util.getContentTypeAttribute(" + contentTypeName + ", \"charset\");");
ctxt.generateJavaSource(" if(" + charSetName + " == null) "
+ charSetName + " = org.apache.struts2.jasper.tagplugins.jstl.Util.DEFAULT_ENCODING;");
ctxt.generateJavaSource(" }else{");
ctxt.generateJavaSource(" " + charSetName + " = org.apache.struts2.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.struts2.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 &lt;import&gt; 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.struts2.jasper.tagplugins.jstl.Util.stripSession(" + urlName + "));");
ctxt.generateJavaSource(" if(" + requestDispatcherName + " == null) throw new JspTagException(org.apache.struts2.jasper.tagplugins.jstl.Util.stripSession(" + urlName + "));");
//initialize a ImportResponseWrapper to include the resource
ctxt.generateJavaSource(" org.apache.struts2.jasper.tagplugins.jstl.Util.ImportResponseWrapper " + irwName + " = new org.apache.struts2.jasper.tagplugins.jstl.Util.ImportResponseWrapper((HttpServletResponse) pageContext.getResponse());");
ctxt.generateJavaSource(" if(" + charSetName + " == null){");
ctxt.generateJavaSource(" " + charSetName + " = org.apache.struts2.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.struts2.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 + ");");
}
}
}
}
@@ -0,0 +1,33 @@
/*
* 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.struts2.jasper.tagplugins.jstl.core;
import org.apache.struts2.jasper.compiler.tagplugin.TagPlugin;
import org.apache.struts2.jasper.compiler.tagplugin.TagPluginContext;
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();
}
}
@@ -0,0 +1,90 @@
/*
* 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.struts2.jasper.tagplugins.jstl.core;
import org.apache.struts2.jasper.compiler.tagplugin.TagPlugin;
import org.apache.struts2.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.struts2.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.struts2.jasper.tagplugins.jstl.Util.escapeXml(" + strDefName + ");");
ctxt.generateJavaSource(" }");
ctxt.generateJavaSource(" out.write(" + strDefName + ");");
ctxt.generateJavaSource(" }else{");
ctxt.generateBody();
ctxt.generateJavaSource(" }");
ctxt.generateJavaSource("}");
}
}
@@ -0,0 +1,77 @@
/*
* 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.struts2.jasper.tagplugins.jstl.core;
import org.apache.struts2.jasper.compiler.tagplugin.TagPlugin;
import org.apache.struts2.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" +
"(\"&lt;param&gt; outside &lt;import&gt; or &lt;urlEncode&gt;\");");
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("}");
}
}
@@ -0,0 +1,83 @@
/*
* 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.struts2.jasper.tagplugins.jstl.core;
import org.apache.struts2.jasper.compiler.tagplugin.TagPlugin;
import org.apache.struts2.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.struts2.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.struts2.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("}");
}
}
@@ -0,0 +1,45 @@
/*
* 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.struts2.jasper.tagplugins.jstl.core;
import org.apache.struts2.jasper.compiler.tagplugin.TagPlugin;
import org.apache.struts2.jasper.compiler.tagplugin.TagPluginContext;
import org.apache.struts2.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 + "\");");
}
}
}
@@ -0,0 +1,167 @@
/*
* 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.struts2.jasper.tagplugins.jstl.core;
import org.apache.struts2.jasper.compiler.tagplugin.TagPlugin;
import org.apache.struts2.jasper.compiler.tagplugin.TagPluginContext;
import org.apache.struts2.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 &lt;set&gt; 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 &lt;set&gt;:\"+" + 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("}");
}
}
}
@@ -0,0 +1,101 @@
/*
* 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.struts2.jasper.tagplugins.jstl.core;
import org.apache.struts2.jasper.compiler.tagplugin.TagPlugin;
import org.apache.struts2.jasper.compiler.tagplugin.TagPluginContext;
import org.apache.struts2.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.struts2.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.struts2.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("}");
}
}
}
@@ -0,0 +1,50 @@
/*
* 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.struts2.jasper.tagplugins.jstl.core;
import org.apache.struts2.jasper.compiler.tagplugin.TagPlugin;
import org.apache.struts2.jasper.compiler.tagplugin.TagPluginContext;
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>
}
}
@@ -0,0 +1,63 @@
<?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.struts2.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.struts2.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.struts2.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.struts2.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.struts2.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.struts2.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.struts2.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.struts2.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.struts2.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.struts2.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.struts2.jasper.tagplugins.jstl.core.Import</plugin-class>
</tag-plugin>
</tag-plugins>
@@ -0,0 +1,133 @@
/*
* 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.struts2.jasper.util;
import java.text.DateFormat;
import java.text.FieldPosition;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Fast date formatter that caches recently formatted date information
* and uses it to avoid too-frequent calls to the underlying
* formatter. Note: breaks fieldPosition param of format(Date,
* StringBuffer, FieldPosition). If you care about the field
* position, call the underlying DateFormat directly.
*
* @author Stan Bailes
* @author Alex Chaffee
*/
public class FastDateFormat extends DateFormat {
private DateFormat df;
private long lastSec = -1;
private StringBuffer sb = new StringBuffer();
private FieldPosition fp = new FieldPosition(DateFormat.MILLISECOND_FIELD);
public FastDateFormat(DateFormat df) {
this.df = df;
}
public Date parse(String text, ParsePosition pos) {
return df.parse(text, pos);
}
/**
* Note: breaks functionality of fieldPosition param. Also:
* there's a bug in SimpleDateFormat with "S" and "SS", use "SSS"
* instead if you want a msec field.
*/
public StringBuffer format(Date date, StringBuffer toAppendTo,
FieldPosition fieldPosition) {
long dt = date.getTime();
long ds = dt / 1000;
if (ds != lastSec) {
sb.setLength(0);
df.format(date, sb, fp);
lastSec = ds;
} else {
// munge current msec into existing string
int ms = (int) (dt % 1000);
int pos = fp.getEndIndex();
int begin = fp.getBeginIndex();
if (pos > 0) {
if (pos > begin)
sb.setCharAt(--pos, Character.forDigit(ms % 10, 10));
ms /= 10;
if (pos > begin)
sb.setCharAt(--pos, Character.forDigit(ms % 10, 10));
ms /= 10;
if (pos > begin)
sb.setCharAt(--pos, Character.forDigit(ms % 10, 10));
}
}
toAppendTo.append(sb.toString());
return toAppendTo;
}
public static void main(String[] args) {
String format = "yyyy-MM-dd HH:mm:ss.SSS";
if (args.length > 0)
format = args[0];
SimpleDateFormat sdf = new SimpleDateFormat(format);
FastDateFormat fdf = new FastDateFormat(sdf);
Date d = new Date();
d.setTime(1);
System.out.println(fdf.format(d) + "\t" + sdf.format(d));
d.setTime(20);
System.out.println(fdf.format(d) + "\t" + sdf.format(d));
d.setTime(500);
System.out.println(fdf.format(d) + "\t" + sdf.format(d));
d.setTime(543);
System.out.println(fdf.format(d) + "\t" + sdf.format(d));
d.setTime(999);
System.out.println(fdf.format(d) + "\t" + sdf.format(d));
d.setTime(1050);
System.out.println(fdf.format(d) + "\t" + sdf.format(d));
d.setTime(2543);
System.out.println(fdf.format(d) + "\t" + sdf.format(d));
d.setTime(12345);
System.out.println(fdf.format(d) + "\t" + sdf.format(d));
d.setTime(12340);
System.out.println(fdf.format(d) + "\t" + sdf.format(d));
final int reps = 100000;
{
long start = System.currentTimeMillis();
for (int i = 0; i < reps; i++) {
d.setTime(System.currentTimeMillis());
fdf.format(d);
}
long elap = System.currentTimeMillis() - start;
System.out.println("fast: " + elap + " elapsed");
System.out.println(fdf.format(d));
}
{
long start = System.currentTimeMillis();
for (int i = 0; i < reps; i++) {
d.setTime(System.currentTimeMillis());
sdf.format(d);
}
long elap = System.currentTimeMillis() - start;
System.out.println("slow: " + elap + " elapsed");
System.out.println(sdf.format(d));
}
}
}
@@ -0,0 +1,89 @@
/*
* 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.struts2.jasper.util;
import java.util.Vector;
/**
* A simple FIFO queue class which causes the calling thread to wait
* if the queue is empty and notifies threads that are waiting when it
* is not empty.
*
* @author Anil V (akv@eng.sun.com)
*/
public class Queue {
private Vector vector = new Vector();
/**
* Put the object into the queue.
*
* @param object the object to be appended to the
* queue.
*/
public synchronized void put(Object object) {
vector.addElement(object);
notify();
}
/**
* Pull the first object out of the queue. Wait if the queue is
* empty.
*/
public synchronized Object pull() {
while (isEmpty())
try {
wait();
} catch (InterruptedException ex) {
}
return get();
}
/**
* Get the first object out of the queue. Return null if the queue
* is empty.
*/
public synchronized Object get() {
Object object = peek();
if (object != null)
vector.removeElementAt(0);
return object;
}
/**
* Peek to see if something is available.
*/
public Object peek() {
if (isEmpty())
return null;
return vector.elementAt(0);
}
/**
* Is the queue empty?
*/
public boolean isEmpty() {
return vector.isEmpty();
}
/**
* How many elements are there in this queue?
*/
public int size() {
return vector.size();
}
}
@@ -0,0 +1,86 @@
/*
* 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.struts2.jasper.util;
/**
* Simple object pool. Based on ThreadPool and few other classes
* <p/>
* The pool will ignore overflow and return null if empty.
*
* @author Gal Shachor
* @author Costin
*/
public final class SimplePool {
private static final int DEFAULT_SIZE = 16;
/*
* Where the threads are held.
*/
private Object pool[];
private int max;
private int current = -1;
private Object lock;
public SimplePool() {
this.max = DEFAULT_SIZE;
this.pool = new Object[max];
this.lock = new Object();
}
public SimplePool(int max) {
this.max = max;
this.pool = new Object[max];
this.lock = new Object();
}
/**
* Adds the given object to the pool, and does nothing if the pool is full
*/
public void put(Object o) {
synchronized (lock) {
if (current < (max - 1)) {
current += 1;
pool[current] = o;
}
}
}
/**
* Get an object from the pool, null if the pool is empty.
*/
public Object get() {
Object item = null;
synchronized (lock) {
if (current >= 0) {
item = pool[current];
current -= 1;
}
}
return item;
}
/**
* Return the size of the pool
*/
public int getMax() {
return max;
}
}
@@ -0,0 +1,222 @@
/*
* 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.struts2.jasper.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
/**
* This helper class may be used to do sophisticated redirection of
* System.out and System.err.
*
* @author Remy Maucherat
*/
public 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);
}
}
@@ -0,0 +1,203 @@
/*
* 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.struts2.jasper.xmlparser;
import org.apache.struts2.jasper.compiler.Localizer;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
/**
* A simple ASCII byte reader. This is an optimized reader for reading
* byte streams that only contain 7-bit ASCII characters.
*
* @author Andy Clark, IBM
* @version $Id: ASCIIReader.java 466606 2006-10-21 23:07:12Z markt $
*/
public class ASCIIReader
extends Reader {
//
// Constants
//
/**
* Default byte buffer size (2048).
*/
public static final int DEFAULT_BUFFER_SIZE = 2048;
//
// Data
//
/**
* Input stream.
*/
protected InputStream fInputStream;
/**
* Byte buffer.
*/
protected byte[] fBuffer;
//
// Constructors
//
/**
* Constructs an ASCII reader from the specified input stream
* and buffer size.
*
* @param inputStream The input stream.
* @param size The initial buffer size.
*/
public ASCIIReader(InputStream inputStream, int size) {
fInputStream = inputStream;
fBuffer = new byte[size];
}
//
// Reader methods
//
/**
* Read a single character. This method will block until a character is
* available, an I/O error occurs, or the end of the stream is reached.
* <p/>
* <p> Subclasses that intend to support efficient single-character input
* should override this method.
*
* @return The character read, as an integer in the range 0 to 127
* (<tt>0x00-0x7f</tt>), or -1 if the end of the stream has
* been reached
* @throws IOException If an I/O error occurs
*/
public int read() throws IOException {
int b0 = fInputStream.read();
if (b0 > 0x80) {
throw new IOException(Localizer.getMessage("jsp.error.xml.invalidASCII",
Integer.toString(b0)));
}
return b0;
} // read():int
/**
* Read characters into a portion of an array. This method will block
* until some input is available, an I/O error occurs, or the end of the
* stream is reached.
*
* @param ch Destination buffer
* @param offset Offset at which to start storing characters
* @param length Maximum number of characters to read
* @return The number of characters read, or -1 if the end of the
* stream has been reached
* @throws IOException If an I/O error occurs
*/
public int read(char ch[], int offset, int length) throws IOException {
if (length > fBuffer.length) {
length = fBuffer.length;
}
int count = fInputStream.read(fBuffer, 0, length);
for (int i = 0; i < count; i++) {
int b0 = fBuffer[i];
if (b0 > 0x80) {
throw new IOException(Localizer.getMessage("jsp.error.xml.invalidASCII",
Integer.toString(b0)));
}
ch[offset + i] = (char) b0;
}
return count;
} // read(char[],int,int)
/**
* Skip characters. This method will block until some characters are
* available, an I/O error occurs, or the end of the stream is reached.
*
* @param n The number of characters to skip
* @return The number of characters actually skipped
* @throws IOException If an I/O error occurs
*/
public long skip(long n) throws IOException {
return fInputStream.skip(n);
} // skip(long):long
/**
* Tell whether this stream is ready to be read.
*
* @return True if the next read() is guaranteed not to block for input,
* false otherwise. Note that returning false does not guarantee that the
* next read will block.
* @throws IOException If an I/O error occurs
*/
public boolean ready() throws IOException {
return false;
} // ready()
/**
* Tell whether this stream supports the mark() operation.
*/
public boolean markSupported() {
return fInputStream.markSupported();
} // markSupported()
/**
* Mark the present position in the stream. Subsequent calls to reset()
* will attempt to reposition the stream to this point. Not all
* character-input streams support the mark() operation.
*
* @param readAheadLimit Limit on the number of characters that may be
* read while still preserving the mark. After
* reading this many characters, attempting to
* reset the stream may fail.
* @throws IOException If the stream does not support mark(),
* or if some other I/O error occurs
*/
public void mark(int readAheadLimit) throws IOException {
fInputStream.mark(readAheadLimit);
} // mark(int)
/**
* Reset the stream. If the stream has been marked, then attempt to
* reposition it at the mark. If the stream has not been marked, then
* attempt to reset it in some way appropriate to the particular stream,
* for example by repositioning it to its starting point. Not all
* character-input streams support the reset() operation, and some support
* reset() without supporting mark().
*
* @throws IOException If the stream has not been marked,
* or if the mark has been invalidated,
* or if the stream does not support reset(),
* or if some other I/O error occurs
*/
public void reset() throws IOException {
fInputStream.reset();
} // reset()
/**
* Close the stream. Once a stream has been closed, further read(),
* ready(), mark(), or reset() invocations will throw an IOException.
* Closing a previously-closed stream, however, has no effect.
*
* @throws IOException If an I/O error occurs
*/
public void close() throws IOException {
fInputStream.close();
} // close()
} // class ASCIIReader

Some files were not shown because too many files have changed in this diff Show More