This commit is contained in:
2024-11-30 19:03:49 +08:00
commit 1e6763c160
3806 changed files with 737676 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,60 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jasper.runtime;
import java.lang.reflect.InvocationTargetException;
/**
* Utilities for handling Throwables and Exceptions.
*/
public class ExceptionUtils {
/**
* Checks whether the supplied Throwable is one that needs to be
* rethrown and swallows all others.
* @param t the Throwable to check
*/
public static void handleThrowable(Throwable t) {
if (t instanceof ThreadDeath) {
throw (ThreadDeath) t;
}
if (t instanceof StackOverflowError) {
// Swallow silently - it should be recoverable
return;
}
if (t instanceof VirtualMachineError) {
throw (VirtualMachineError) t;
}
// All other instances of Throwable will be silently swallowed
}
/**
* Checks whether the supplied Throwable is an instance of
* <code>InvocationTargetException</code> and returns the throwable that is
* wrapped by it, if there is any.
*
* @param t the Throwable to check
* @return <code>t</code> or <code>t.getCause()</code>
*/
public static Throwable unwrapInvocationTargetException(Throwable t) {
if (t instanceof InvocationTargetException && t.getCause() != null) {
return t.getCause();
}
return t;
}
}

View File

@@ -0,0 +1,91 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jasper.runtime;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.HttpJspPage;
import org.apache.jasper.compiler.Localizer;
/**
* This is the super class of all JSP-generated servlets.
*
* @author Anil K. Vijendran
*/
public abstract class HttpJspBase extends HttpServlet implements HttpJspPage {
private static final long serialVersionUID = 1L;
protected HttpJspBase() {
}
@Override
public final void init(ServletConfig config)
throws ServletException
{
super.init(config);
jspInit();
_jspInit();
}
@Override
public String getServletInfo() {
return Localizer.getMessage("jsp.engine.info");
}
@Override
public final void destroy() {
jspDestroy();
_jspDestroy();
}
/**
* Entry point into service.
*/
@Override
public final void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
_jspService(request, response);
}
@Override
public void jspInit() {
}
public void _jspInit() {
}
@Override
public void jspDestroy() {
}
protected void _jspDestroy() {
}
@Override
public abstract void _jspService(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException;
}

View File

@@ -0,0 +1,37 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jasper.runtime;
import javax.servlet.ServletConfig;
import org.apache.tomcat.InstanceManager;
public class InstanceManagerFactory {
private InstanceManagerFactory() {
}
public static InstanceManager getInstanceManager(ServletConfig config) {
InstanceManager instanceManager =
(InstanceManager) config.getServletContext().getAttribute(InstanceManager.class.getName());
if (instanceManager == null) {
throw new IllegalStateException("No org.apache.tomcat.InstanceManager set in ServletContext");
}
return instanceManager;
}
}

View File

@@ -0,0 +1,144 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jasper.runtime;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.List;
import javax.el.CompositeELResolver;
import javax.el.ELContext;
import javax.el.ELContextEvent;
import javax.el.ELContextListener;
import javax.el.ELResolver;
import javax.el.ExpressionFactory;
import javax.servlet.ServletContext;
import javax.servlet.jsp.JspApplicationContext;
import javax.servlet.jsp.JspContext;
import org.apache.jasper.Constants;
import org.apache.jasper.el.ELContextImpl;
import org.apache.jasper.el.JasperELResolver;
/**
* Implementation of JspApplicationContext
*
* @author Jacob Hookom
*/
public class JspApplicationContextImpl implements JspApplicationContext {
private static final String KEY = JspApplicationContextImpl.class.getName();
private final ExpressionFactory expressionFactory =
ExpressionFactory.newInstance();
private final List<ELContextListener> contextListeners = new ArrayList<>();
private final List<ELResolver> resolvers = new ArrayList<>();
private boolean instantiated = false;
private ELResolver resolver;
public JspApplicationContextImpl() {
}
@Override
public void addELContextListener(ELContextListener listener) {
if (listener == null) {
throw new IllegalArgumentException("ELContextListener was null");
}
this.contextListeners.add(listener);
}
public static JspApplicationContextImpl getInstance(ServletContext context) {
if (context == null) {
throw new IllegalArgumentException("ServletContext was null");
}
JspApplicationContextImpl impl = (JspApplicationContextImpl) context
.getAttribute(KEY);
if (impl == null) {
impl = new JspApplicationContextImpl();
context.setAttribute(KEY, impl);
}
return impl;
}
public ELContextImpl createELContext(JspContext context) {
if (context == null) {
throw new IllegalArgumentException("JspContext was null");
}
// create ELContext for JspContext
final ELResolver r = this.createELResolver();
ELContextImpl ctx;
if (Constants.IS_SECURITY_ENABLED) {
ctx = AccessController.doPrivileged(
new PrivilegedAction<ELContextImpl>() {
@Override
public ELContextImpl run() {
return new ELContextImpl(r);
}
});
} else {
ctx = new ELContextImpl(r);
}
ctx.putContext(JspContext.class, context);
// alert all ELContextListeners
fireListeners(ctx);
return ctx;
}
protected void fireListeners(ELContext elContext) {
ELContextEvent event = new ELContextEvent(elContext);
for (int i = 0; i < this.contextListeners.size(); i++) {
this.contextListeners.get(i).contextCreated(event);
}
}
private ELResolver createELResolver() {
this.instantiated = true;
if (this.resolver == null) {
CompositeELResolver r = new JasperELResolver(this.resolvers,
expressionFactory.getStreamELResolver());
this.resolver = r;
}
return this.resolver;
}
@Override
public void addELResolver(ELResolver resolver) throws IllegalStateException {
if (resolver == null) {
throw new IllegalArgumentException("ELResolver was null");
}
if (this.instantiated) {
throw new IllegalStateException(
"cannot call addELResolver after the first request has been made");
}
this.resolvers.add(resolver);
}
@Override
public ExpressionFactory getExpressionFactory() {
return expressionFactory;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,220 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jasper.runtime;
import java.io.IOException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.jsp.JspApplicationContext;
import javax.servlet.jsp.JspEngineInfo;
import javax.servlet.jsp.JspFactory;
import javax.servlet.jsp.PageContext;
import org.apache.jasper.Constants;
/**
* Implementation of JspFactory.
*
* @author Anil K. Vijendran
*/
public class JspFactoryImpl extends JspFactory {
private static final String SPEC_VERSION = "2.3";
private static final boolean USE_POOL =
Boolean.parseBoolean(System.getProperty("org.apache.jasper.runtime.JspFactoryImpl.USE_POOL", "true"));
private static final int POOL_SIZE =
Integer.parseInt(System.getProperty("org.apache.jasper.runtime.JspFactoryImpl.POOL_SIZE", "8"));
private final ThreadLocal<PageContextPool> localPool = new ThreadLocal<>();
@Override
public PageContext getPageContext(Servlet servlet, ServletRequest request,
ServletResponse response, String errorPageURL, boolean needsSession,
int bufferSize, boolean autoflush) {
if( Constants.IS_SECURITY_ENABLED ) {
PrivilegedGetPageContext dp = new PrivilegedGetPageContext(
this, servlet, request, response, errorPageURL,
needsSession, bufferSize, autoflush);
return AccessController.doPrivileged(dp);
} else {
return internalGetPageContext(servlet, request, response,
errorPageURL, needsSession,
bufferSize, autoflush);
}
}
@Override
public void releasePageContext(PageContext pc) {
if( pc == null )
return;
if( Constants.IS_SECURITY_ENABLED ) {
PrivilegedReleasePageContext dp = new PrivilegedReleasePageContext(
this,pc);
AccessController.doPrivileged(dp);
} else {
internalReleasePageContext(pc);
}
}
@Override
public JspEngineInfo getEngineInfo() {
return new JspEngineInfo() {
@Override
public String getSpecificationVersion() {
return SPEC_VERSION;
}
};
}
private PageContext internalGetPageContext(Servlet servlet, ServletRequest request,
ServletResponse response, String errorPageURL, boolean needsSession,
int bufferSize, boolean autoflush) {
PageContext pc;
if (USE_POOL) {
PageContextPool pool = localPool.get();
if (pool == null) {
pool = new PageContextPool();
localPool.set(pool);
}
pc = pool.get();
if (pc == null) {
pc = new PageContextImpl();
}
} else {
pc = new PageContextImpl();
}
try {
pc.initialize(servlet, request, response, errorPageURL,
needsSession, bufferSize, autoflush);
} catch (IOException ioe) {
// Implementation never throws IOE but can't change the signature
// since it is part of the JSP API
}
return pc;
}
private void internalReleasePageContext(PageContext pc) {
pc.release();
if (USE_POOL && (pc instanceof PageContextImpl)) {
localPool.get().put(pc);
}
}
private static class PrivilegedGetPageContext
implements PrivilegedAction<PageContext> {
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;
}
@Override
public PageContext run() {
return factory.internalGetPageContext(servlet, request, response,
errorPageURL, needsSession, bufferSize, autoflush);
}
}
private static class PrivilegedReleasePageContext
implements PrivilegedAction<Void> {
private JspFactoryImpl factory;
private PageContext pageContext;
PrivilegedReleasePageContext(JspFactoryImpl factory,
PageContext pageContext) {
this.factory = factory;
this.pageContext = pageContext;
}
@Override
public Void run() {
factory.internalReleasePageContext(pageContext);
return null;
}
}
private static final class PageContextPool {
private final PageContext[] pool;
private int current = -1;
public PageContextPool() {
this.pool = new PageContext[POOL_SIZE];
}
public void put(PageContext o) {
if (current < (POOL_SIZE - 1)) {
current++;
pool[current] = o;
}
}
public PageContext get() {
PageContext item = null;
if (current >= 0) {
item = pool[current];
current--;
}
return item;
}
}
@Override
public JspApplicationContext getJspApplicationContext(
final ServletContext context) {
if (Constants.IS_SECURITY_ENABLED) {
return AccessController.doPrivileged(
new PrivilegedAction<JspApplicationContext>() {
@Override
public JspApplicationContext run() {
return JspApplicationContextImpl.getInstance(context);
}
});
} else {
return JspApplicationContextImpl.getInstance(context);
}
}
}

View File

@@ -0,0 +1,65 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jasper.runtime;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.JspTag;
/**
* Helper class from which all Jsp Fragment helper classes extend.
* This class allows for the emulation of numerous fragments within
* a single class, which in turn reduces the load on the class loader
* since there are potentially many JspFragments in a single page.
* <p>
* The class also provides various utility methods for JspFragment
* implementations.
*
* @author Mark Roth
*/
public abstract class JspFragmentHelper extends JspFragment {
protected final int discriminator;
protected final JspContext jspContext;
protected final PageContext _jspx_page_context;
protected final JspTag parentTag;
public JspFragmentHelper( int discriminator, JspContext jspContext,
JspTag parentTag )
{
this.discriminator = discriminator;
this.jspContext = jspContext;
if(jspContext instanceof PageContext) {
_jspx_page_context = (PageContext)jspContext;
} else {
_jspx_page_context = null;
}
this.parentTag = parentTag;
}
@Override
public JspContext getJspContext() {
return this.jspContext;
}
public JspTag getParentTag() {
return this.parentTag;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,40 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jasper.runtime;
import java.util.Map;
/**
* 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 map of file names and last modified time where the current page
* has a source dependency on the file.
* @return the map of dependent resources
*/
public Map<String,Long> getDependants();
}

View File

@@ -0,0 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jasper.runtime;
import java.util.Set;
/**
* The EL engine needs access to the imports used in the JSP page to configure
* the ELContext. The imports are available at compile time but the ELContext
* is created lazily per page. This interface exposes the imports at runtime so
* that they may be added to the ELContext when it is created.
*/
public interface JspSourceImports {
Set<String> getPackageImports();
Set<String> getClassImports();
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,153 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jasper.runtime;
import java.lang.reflect.Method;
import java.util.HashMap;
import javax.servlet.jsp.el.FunctionMapper;
/**
* 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
*/
@SuppressWarnings("deprecation") // Have to support old JSP EL API
public final class ProtectedFunctionMapper extends javax.el.FunctionMapper
implements FunctionMapper {
/**
* Maps "prefix:name" to java.lang.Method objects.
*/
private HashMap<String,Method> 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.
*
* @return A new protected function mapper.
*/
public static ProtectedFunctionMapper getInstance() {
ProtectedFunctionMapper funcMapper = new ProtectedFunctionMapper();
funcMapper.fnmap = new 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) {
// Skip if null values were passed in. They indicate a function
// added via a lambda or ImportHandler; nether of which need to be
// placed in the Map.
if (fnQName == null) {
return;
}
java.lang.reflect.Method method;
try {
method = c.getMethod(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.
* @return the mapped function
*/
public static ProtectedFunctionMapper getMapForFunction(String fnQName,
final Class<?> c, final String methodName, final Class<?>[] args) {
java.lang.reflect.Method method = null;
ProtectedFunctionMapper funcMapper = new ProtectedFunctionMapper();
// Skip if null values were passed in. They indicate a function
// added via a lambda or ImportHandler; nether of which need to be
// placed in the Map.
if (fnQName != null) {
try {
method = c.getMethod(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.
*/
@Override
public Method resolveFunction(String prefix, String localName) {
if (this.fnmap != null) {
return this.fnmap.get(prefix + ":" + localName);
}
return theMethod;
}
}

View File

@@ -0,0 +1,79 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jasper.runtime;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import javax.servlet.jsp.JspWriter;
/**
* ServletResponseWrapper used by the JSP 'include' action.
*
* This wrapper response object is passed to RequestDispatcher.include(), so
* that the output of the included resource is appended to that of the
* including page.
*
* @author Pierre Delisle
*/
public class ServletResponseWrapperInclude extends HttpServletResponseWrapper {
/**
* PrintWriter which appends to the JspWriter of the including page.
*/
private final PrintWriter printWriter;
private final 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.
*/
@Override
public PrintWriter getWriter() throws IOException {
return printWriter;
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
throw new IllegalStateException();
}
/**
* Clears the output buffer of the JspWriter associated with the including
* page.
*/
@Override
public void resetBuffer() {
try {
jspWriter.clearBuffer();
} catch (IOException ioe) {
}
}
}

View File

@@ -0,0 +1,172 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jasper.runtime;
import javax.servlet.ServletConfig;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.Tag;
import org.apache.jasper.Constants;
import org.apache.tomcat.InstanceManager;
/**
* Pool of tag handlers that can be reused.
*
* @author Jan Luehe
*/
public class TagHandlerPool {
private Tag[] handlers;
public static final String OPTION_TAGPOOL = "tagpoolClassName";
public static final String OPTION_MAXSIZE = "tagpoolMaxSize";
// index of next available tag handler
private int current;
protected InstanceManager instanceManager = null;
public static TagHandlerPool getTagHandlerPool(ServletConfig config) {
TagHandlerPool result = null;
String tpClassName = getOption(config, OPTION_TAGPOOL, null);
if (tpClassName != null) {
try {
Class<?> c = Class.forName(tpClassName);
result = (TagHandlerPool) c.getConstructor().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;
instanceManager = InstanceManagerFactory.getInstanceManager(config);
}
/**
* 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 .
}
/**
* 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<? extends Tag> handlerClass) throws JspException {
Tag handler;
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 {
if (Constants.USE_INSTANCE_MANAGER_FOR_TAGS) {
return (Tag) instanceManager.newInstance(
handlerClass.getName(), handlerClass.getClassLoader());
} else {
Tag instance = handlerClass.getConstructor().newInstance();
instanceManager.newInstance(instance);
return instance;
}
} catch (Exception e) {
Throwable t = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(t);
throw new JspException(e.getMessage(), t);
}
}
/**
* 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
JspRuntimeLibrary.releaseTag(handler, instanceManager);
}
/**
* 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--) {
JspRuntimeLibrary.releaseTag(handlers[i], instanceManager);
}
}
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;
}
}