mirror of
https://github.com/apache/struts.git
synced 2026-08-07 23:57:03 +00:00
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:
@@ -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);
|
||||
}
|
||||
}
|
||||
+61
@@ -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><jsp-file></code> element of a
|
||||
* servlet definition. If present on a request, this overrides the
|
||||
* value returned by <code>request.getServletPath()</code> to select
|
||||
* the JSP page to be executed.
|
||||
*/
|
||||
public static final String JSP_FILE = "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 {
|
||||
}
|
||||
}
|
||||
+647
@@ -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
+631
@@ -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();
|
||||
|
||||
}
|
||||
+115
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
+109
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+283
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+615
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+73
@@ -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;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+146
@@ -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;
|
||||
}
|
||||
}
|
||||
+58
@@ -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;
|
||||
}
|
||||
}
|
||||
+227
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1437
File diff suppressed because it is too large
Load Diff
@@ -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 =, >, <, ", 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;
|
||||
}
|
||||
}
|
||||
|
||||
+524
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
+712
@@ -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 "]]>")
|
||||
* 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
+580
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
+151
@@ -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));
|
||||
}
|
||||
}
|
||||
+177
@@ -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);
|
||||
}
|
||||
}
|
||||
+173
@@ -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);
|
||||
}
|
||||
}
|
||||
+344
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+116
@@ -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:";
|
||||
}
|
||||
+609
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+745
@@ -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;
|
||||
}
|
||||
+242
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+113
@@ -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();
|
||||
}
|
||||
}
|
||||
+560
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+38
@@ -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);
|
||||
}
|
||||
|
||||
+128
@@ -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);
|
||||
}
|
||||
|
||||
+429
@@ -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 <{0}> cannot have template data. Template data must be encapsulated within a <jsp:cdata> element. [JSP1.2 PFD section 5.1.9]\nTemplate data in error: {1}
|
||||
jspx.error.templateDataNotInJspCdata=Validation Error: Element <{0}> cannot have template data. Template data must be encapsulated within a <jsp:text> 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 ( <%!, <jsp:declaration, <%=, <jsp:expression, <%, <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=<jsp:output>: illegal to have multiple occurrences of \"{0}\" with different values (old: {1}, new: {2})
|
||||
jsp.error.jspoutput.doctypenamesystem=<jsp:output>: 'doctype-root-element' and 'doctype-system' attributes must appear together
|
||||
jsp.error.jspoutput.doctypepulicsystem=<jsp:output>: 'doctype-system' attribute must appear if 'doctype-public' attribute appears
|
||||
jsp.error.jspoutput.nonemptybody=<jsp:output> must not have a body
|
||||
jsp.error.jspoutput.invalidUse=<jsp:output> 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=\'<\', when appears in the body of <jsp:text>, 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=<jsp:text> 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 <jsp:root>
|
||||
jsp.error.unbalanced.endtag=The end tag \"</{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}.
|
||||
+423
@@ -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 <{0}> cannot have template data. Template data must be encapsulated within a <jsp:cdata> element. [JSP1.2 PFD section 5.1.9]\nTemplate data in error: {1}
|
||||
jspx.error.templateDataNotInJspCdata=Error de Validación: El Elemento <{0}> no puede tener datos plantilla. Los datos plantilla deben de estar encapsulados dentro de un elemento <jsp:text>. [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 (<%!, <jsp:declaration, <%=, <jsp:expression, <%, <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=<jsp:output>: ilegal tener ocurrencias múltiples de \"{0}\" con diferentes valores (viejo: {1}, nuevo: {2})
|
||||
jsp.error.jspoutput.doctypenamesystem=<jsp:output>: atributos 'doctype-root-element' y 'doctype-system' deben de aparecer juntos
|
||||
jsp.error.jspoutput.doctypepulicsystem=<jsp:output>: atributo 'doctype-system' debe de aparecer si aparece atributo 'doctype-public'
|
||||
jsp.error.jspoutput.nonemptybody=<jsp:output> no debe de tener un cuerpo
|
||||
jsp.error.jspoutput.invalidUse=<jsp:output> 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=\'<\', cuando aparece en el cuerpo de <jsp:text>, 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=<jsp:text> 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=<jsp:root> anidado
|
||||
jsp.error.unbalanced.endtag=El tgag final \"</{0}\" está desequilibrado
|
||||
jsp.error.invalid.bean=
|
||||
+320
@@ -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\
|
||||
où 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\
|
||||
où 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 <{0}> ne peut avoir de données template. Les données Template doivent être encapsulées à l''intérieur d''un élément <jsp:cdata>. [JSP1.2 PFD section 5.1.9]\nDonnée Template en erreur: {1}
|
||||
jspx.error.templateDataNotInJspCdata=Erreur de validation: l''élément <{0}> ne peut avoir de données template. Les données Template doivent être encapsulées à l''intérieur d''un élément <jsp:text>. [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=
|
||||
+422
@@ -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 <{0}> cannot have template data. Template data must be encapsulated within a <jsp:cdata> element. [JSP1.2 PFD section 5.1.9]\nTemplate data in error: {1}
|
||||
jspx.error.templateDataNotInJspCdata=\u8a3c\u660e\u30a8\u30e9\u30fc: \u8981\u7d20<{0}>\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<jsp:text>\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 ( <%!\u3001<jsp:declaration\u3001<%=\u3001<jsp:expression\u3001<%\u3001<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=<jsp:output>: \"{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=<jsp:output>: '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=<jsp:output>: '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=<jsp:output> \u30dc\u30c7\u30a3\u3092\u6301\u3063\u3066\u306f\u3044\u3051\u307e\u305b\u3093
|
||||
jsp.error.jspoutput.invalidUse=<jsp:output> \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=\'<\'\u304c<jsp:text>\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=<jsp:text> \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 <jsp:root> \u3067\u3059
|
||||
jsp.error.unbalanced.endtag=\u7d42\u4e86\u30bf\u30b0 \"</{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
|
||||
|
||||
+607
@@ -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;
|
||||
}
|
||||
+439
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+177
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+63
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
+1032
File diff suppressed because it is too large
Load Diff
+39
@@ -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();
|
||||
|
||||
}
|
||||
+586
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
+944
@@ -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("<");
|
||||
} else if (c == '>') {
|
||||
sb.append(">");
|
||||
} else if (c == '\'') {
|
||||
sb.append("'"); // '
|
||||
} else if (c == '&') {
|
||||
sb.append("&");
|
||||
} else if (c == '"') {
|
||||
sb.append("""); // "
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Proprietary method to evaluate EL expressions.
|
||||
* XXX - This method should go away once the EL interpreter moves
|
||||
* out of JSTL and into its own project. For now, this is necessary
|
||||
* because the standard machinery is too slow.
|
||||
*
|
||||
* @param expression The expression to be evaluated
|
||||
* @param expectedType The expected resulting type
|
||||
* @param pageContext The page context
|
||||
* @param functionMap Maps prefix and name to Method
|
||||
* @return The result of the evaluation
|
||||
*/
|
||||
public static Object proprietaryEvaluate(final String expression,
|
||||
final Class expectedType,
|
||||
final PageContext pageContext,
|
||||
final ProtectedFunctionMapper functionMap,
|
||||
final boolean escape)
|
||||
throws ELException {
|
||||
Object retValue;
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
+131
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+187
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+75
@@ -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) {
|
||||
}
|
||||
}
|
||||
}
|
||||
+163
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+113
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+42
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+167
@@ -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;
|
||||
}
|
||||
}
|
||||
+405
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+458
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+36
@@ -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>
|
||||
+326
@@ -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['&'] = "&".toCharArray();
|
||||
specialCharactersRepresentation['<'] = "<".toCharArray();
|
||||
specialCharactersRepresentation['>'] = ">".toCharArray();
|
||||
specialCharactersRepresentation['"'] = """.toCharArray();
|
||||
specialCharactersRepresentation['\''] = "'".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/>
|
||||
* & -> &
|
||||
* < -> <
|
||||
* > -> >
|
||||
* " -> "
|
||||
* ' -> '
|
||||
* <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 <import>: " +
|
||||
"Target servlet called getWriter(), then getOutputStream()");
|
||||
isWriterUsed = true;
|
||||
return new PrintWriter(sw);
|
||||
}
|
||||
|
||||
public ServletOutputStream getOutputStream() {
|
||||
if (isWriterUsed)
|
||||
throw new IllegalStateException("Unexpected internal error during <import>: " +
|
||||
"Target servlet called getOutputStream(), then getWriter()");
|
||||
isStreamUsed = true;
|
||||
return sos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Has no effect.
|
||||
*/
|
||||
public void setContentType(String x) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* Has no effect.
|
||||
*/
|
||||
public void setLocale(Locale x) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
public void setStatus(int status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public String getCharEncoding() {
|
||||
return this.charEncoding;
|
||||
}
|
||||
|
||||
public void setCharEncoding(String ce) {
|
||||
this.charEncoding = ce;
|
||||
}
|
||||
|
||||
public String getString() throws UnsupportedEncodingException {
|
||||
if (isWriterUsed)
|
||||
return sw.toString();
|
||||
else if (isStreamUsed) {
|
||||
if (this.charEncoding != null && !this.charEncoding.equals(""))
|
||||
return bos.toString(charEncoding);
|
||||
else
|
||||
return bos.toString("ISO-8859-1");
|
||||
} else
|
||||
return ""; // target didn't write anything
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+72
@@ -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("}");
|
||||
}
|
||||
|
||||
}
|
||||
+35
@@ -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("}");
|
||||
}
|
||||
}
|
||||
+342
@@ -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" +
|
||||
"}"
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
+119
@@ -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("}");
|
||||
}
|
||||
|
||||
}
|
||||
+51
@@ -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("}");
|
||||
}
|
||||
}
|
||||
+381
@@ -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 <import>\");");
|
||||
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 <import> from non-HTTP request not allowed\");");
|
||||
ctxt.generateJavaSource(" }");
|
||||
|
||||
//get the servlet context of the context defined in the context attribute
|
||||
ctxt.generateJavaSource(" ServletContext " + servletContextName + " = null;");
|
||||
if (hasContext) {
|
||||
ctxt.generateJavaSource(" if(null != " + contextName + "){");
|
||||
ctxt.generateJavaSource(" " + servletContextName + " = pageContext.getServletContext().getContext(" + contextName + ");");
|
||||
ctxt.generateJavaSource(" }else{");
|
||||
ctxt.generateJavaSource(" " + servletContextName + " = pageContext.getServletContext();");
|
||||
ctxt.generateJavaSource(" }");
|
||||
} else {
|
||||
ctxt.generateJavaSource(" " + servletContextName + " = pageContext.getServletContext();");
|
||||
}
|
||||
|
||||
//
|
||||
ctxt.generateJavaSource(" if(" + servletContextName + " == null){");
|
||||
if (hasContext) {
|
||||
ctxt.generateJavaSource(" throw new JspTagException(\"Unable to get RequestDispatcher for Context: \\\" \"+" + contextName + "+\" \\\" and URL: \\\" \" +" + urlName + "+ \" \\\". Verify values and/or enable cross context access.\");");
|
||||
} else {
|
||||
ctxt.generateJavaSource(" throw new JspTagException(\"Unable to get RequestDispatcher for URL: \\\" \" +" + urlName + "+ \" \\\". Verify values and/or enable cross context access.\");");
|
||||
}
|
||||
ctxt.generateJavaSource(" }");
|
||||
|
||||
//get the request dispatcher
|
||||
ctxt.generateJavaSource(" RequestDispatcher " + requestDispatcherName + " = " + servletContextName + ".getRequestDispatcher(org.apache.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 <import> from non-HTTP request not allowed\");");
|
||||
ctxt.generateJavaSource(" }");
|
||||
|
||||
//get the servlet context of the context defined in the context attribute
|
||||
ctxt.generateJavaSource(" ServletContext " + servletContextName + " = null;");
|
||||
if (hasContext) {
|
||||
ctxt.generateJavaSource(" if(null != " + contextName + "){");
|
||||
ctxt.generateJavaSource(" " + servletContextName + " = pageContext.getServletContext().getContext(" + contextName + ");");
|
||||
ctxt.generateJavaSource(" }else{");
|
||||
ctxt.generateJavaSource(" " + servletContextName + " = pageContext.getServletContext();");
|
||||
ctxt.generateJavaSource(" }");
|
||||
} else {
|
||||
ctxt.generateJavaSource(" " + servletContextName + " = pageContext.getServletContext();");
|
||||
}
|
||||
|
||||
//
|
||||
ctxt.generateJavaSource(" if(" + servletContextName + " == null){");
|
||||
if (hasContext) {
|
||||
ctxt.generateJavaSource(" throw new JspTagException(\"Unable to get RequestDispatcher for Context: \\\" \" +" + contextName + "+ \" \\\" and URL: \\\" \" +" + urlName + "+ \" \\\". Verify values and/or enable cross context access.\");");
|
||||
} else {
|
||||
ctxt.generateJavaSource(" throw new JspTagException(\"Unable to get RequestDispatcher for URL: \\\" \" +" + urlName + "+ \" \\\". Verify values and/or enable cross context access.\");");
|
||||
}
|
||||
ctxt.generateJavaSource(" }");
|
||||
|
||||
//get the request dispatcher
|
||||
ctxt.generateJavaSource(" RequestDispatcher " + requestDispatcherName + " = " + servletContextName + ".getRequestDispatcher(org.apache.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 + ");");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+33
@@ -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();
|
||||
}
|
||||
}
|
||||
+90
@@ -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("}");
|
||||
}
|
||||
}
|
||||
+77
@@ -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" +
|
||||
"(\"<param> outside <import> or <urlEncode>\");");
|
||||
return;
|
||||
}
|
||||
|
||||
//get the url string before adding this param
|
||||
ctxt.generateJavaSource("String " + urlName + " = " +
|
||||
"(String)pageContext.getAttribute(\"url_without_param\");");
|
||||
|
||||
//get the value of "name"
|
||||
ctxt.generateJavaSource("String " + nameName + " = ");
|
||||
ctxt.generateAttribute("name");
|
||||
ctxt.generateJavaSource(";");
|
||||
|
||||
//if the "name" is null then do nothing.
|
||||
//else add such string "name=value" to the url.
|
||||
//and the url should be encoded
|
||||
ctxt.generateJavaSource("if(" + nameName + " != null && !" + nameName + ".equals(\"\")){");
|
||||
ctxt.generateJavaSource(" String " + valueName + " = ");
|
||||
ctxt.generateAttribute("value");
|
||||
ctxt.generateJavaSource(";");
|
||||
ctxt.generateJavaSource(" if(" + valueName + " == null) " + valueName + " = \"\";");
|
||||
ctxt.generateJavaSource(" String " + encName + " = pageContext.getResponse().getCharacterEncoding();");
|
||||
ctxt.generateJavaSource(" " + nameName + " = java.net.URLEncoder.encode(" + nameName + ", " + encName + ");");
|
||||
ctxt.generateJavaSource(" " + valueName + " = java.net.URLEncoder.encode(" + valueName + ", " + encName + ");");
|
||||
ctxt.generateJavaSource(" int " + index + ";");
|
||||
ctxt.generateJavaSource(" " + index + " = " + urlName + ".indexOf(\'?\');");
|
||||
//if the current param is the first one, add a "?" ahead of it
|
||||
//else add a "&" ahead of it
|
||||
ctxt.generateJavaSource(" if(" + index + " == -1){");
|
||||
ctxt.generateJavaSource(" " + urlName + " = " + urlName + " + \"?\" + " + nameName + " + \"=\" + " + valueName + ";");
|
||||
ctxt.generateJavaSource(" }else{");
|
||||
ctxt.generateJavaSource(" " + urlName + " = " + urlName + " + \"&\" + " + nameName + " + \"=\" + " + valueName + ";");
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource(" pageContext.setAttribute(\"url_without_param\"," + urlName + ");");
|
||||
ctxt.generateJavaSource("}");
|
||||
}
|
||||
}
|
||||
+83
@@ -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("}");
|
||||
}
|
||||
|
||||
}
|
||||
+45
@@ -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 + "\");");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+167
@@ -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 <set> for property \"+" + propertyName + ");");
|
||||
ctxt.generateJavaSource(" }");
|
||||
|
||||
//invoke the method through the reflection
|
||||
ctxt.generateJavaSource(" if(" + resultName + " != null){");
|
||||
ctxt.generateJavaSource(" " + methodName + ".invoke(" + targetName + ", new Object[]{(" + methodName + ".getParameterTypes()[0]).cast(" + resultName + ")});");
|
||||
ctxt.generateJavaSource(" }else{");
|
||||
ctxt.generateJavaSource(" " + methodName + ".invoke(" + targetName + ", new Object[]{null});");
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource(" " + successFlagName + " = true;");
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource(" if(!" + successFlagName + "){");
|
||||
ctxt.generateJavaSource(" throw new JspException(\"Invalid property in <set>:\"+" + propertyName + ");");
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource(" }");
|
||||
|
||||
//catch the el exception and throw it as a JspException
|
||||
ctxt.generateJavaSource(" catch (IllegalAccessException ex) {");
|
||||
ctxt.generateJavaSource(" throw new JspException(ex);");
|
||||
ctxt.generateJavaSource(" } catch (java.beans.IntrospectionException ex) {");
|
||||
ctxt.generateJavaSource(" throw new JspException(ex);");
|
||||
ctxt.generateJavaSource(" } catch (java.lang.reflect.InvocationTargetException ex) {");
|
||||
ctxt.generateJavaSource(" throw new JspException(ex);");
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource(" }");
|
||||
ctxt.generateJavaSource("}else{");
|
||||
ctxt.generateJavaSource(" throw new JspException();");
|
||||
ctxt.generateJavaSource("}");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+101
@@ -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("}");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+50
@@ -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>
|
||||
}
|
||||
}
|
||||
+63
@@ -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;
|
||||
}
|
||||
}
|
||||
+222
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
+203
@@ -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
Reference in New Issue
Block a user