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

View File

@@ -0,0 +1,64 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.util.Arrays;
import java.util.Objects;
import org.apache.catalina.AccessLog;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
/**
* A helper class that wraps several AccessLog instances.
*/
public class AccessLogAdapter implements AccessLog {
private AccessLog[] logs;
public AccessLogAdapter(AccessLog log) {
Objects.requireNonNull(log);
logs = new AccessLog[] { log };
}
public void add(AccessLog log) {
Objects.requireNonNull(log);
AccessLog newArray[] = Arrays.copyOf(logs, logs.length + 1);
newArray[newArray.length - 1] = log;
logs = newArray;
}
@Override
public void log(Request request, Response response, long time) {
for (AccessLog log: logs) {
log.log(request, response, time);
}
}
@Override
public void setRequestAttributesEnabled(boolean requestAttributesEnabled) {
// NOOP
}
@Override
public boolean getRequestAttributesEnabled() {
// NOOP. Could return logs[0].getRequestAttributesEnabled(), but I do
// not see a use case for that.
return false;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,978 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.Filter;
import javax.servlet.FilterRegistration;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.ServletRegistration.Dynamic;
import javax.servlet.SessionCookieConfig;
import javax.servlet.SessionTrackingMode;
import javax.servlet.descriptor.JspConfigDescriptor;
import org.apache.catalina.Globals;
import org.apache.catalina.security.SecurityUtil;
import org.apache.tomcat.util.ExceptionUtils;
/**
* Facade object which masks the internal <code>ApplicationContext</code>
* object from the web application.
*
* @author Remy Maucherat
*/
public class ApplicationContextFacade implements ServletContext {
// ---------------------------------------------------------- Attributes
/**
* Cache Class object used for reflection.
*/
private final Map<String,Class<?>[]> classCache;
/**
* Cache method object.
*/
private final Map<String,Method> objectCache;
// ----------------------------------------------------------- Constructors
/**
* Construct a new instance of this class, associated with the specified
* Context instance.
*
* @param context The associated Context instance
*/
public ApplicationContextFacade(ApplicationContext context) {
super();
this.context = context;
classCache = new HashMap<>();
objectCache = new ConcurrentHashMap<>();
initClassCache();
}
private void initClassCache(){
Class<?>[] clazz = new Class[]{String.class};
classCache.put("getContext", clazz);
classCache.put("getMimeType", clazz);
classCache.put("getResourcePaths", clazz);
classCache.put("getResource", clazz);
classCache.put("getResourceAsStream", clazz);
classCache.put("getRequestDispatcher", clazz);
classCache.put("getNamedDispatcher", clazz);
classCache.put("getServlet", clazz);
classCache.put("setInitParameter", new Class[]{String.class, String.class});
classCache.put("createServlet", new Class[]{Class.class});
classCache.put("addServlet", new Class[]{String.class, String.class});
classCache.put("createFilter", new Class[]{Class.class});
classCache.put("addFilter", new Class[]{String.class, String.class});
classCache.put("createListener", new Class[]{Class.class});
classCache.put("addListener", clazz);
classCache.put("getFilterRegistration", clazz);
classCache.put("getServletRegistration", clazz);
classCache.put("getInitParameter", clazz);
classCache.put("setAttribute", new Class[]{String.class, Object.class});
classCache.put("removeAttribute", clazz);
classCache.put("getRealPath", clazz);
classCache.put("getAttribute", clazz);
classCache.put("log", clazz);
classCache.put("setSessionTrackingModes", new Class[]{Set.class} );
}
// ----------------------------------------------------- Instance Variables
/**
* Wrapped application context.
*/
private final ApplicationContext context;
// ------------------------------------------------- ServletContext Methods
@Override
public ServletContext getContext(String uripath) {
ServletContext theContext = null;
if (SecurityUtil.isPackageProtectionEnabled()) {
theContext = (ServletContext)
doPrivileged("getContext", new Object[]{uripath});
} else {
theContext = context.getContext(uripath);
}
if ((theContext != null) &&
(theContext instanceof ApplicationContext)){
theContext = ((ApplicationContext)theContext).getFacade();
}
return theContext;
}
@Override
public int getMajorVersion() {
return context.getMajorVersion();
}
@Override
public int getMinorVersion() {
return context.getMinorVersion();
}
@Override
public String getMimeType(String file) {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (String)doPrivileged("getMimeType", new Object[]{file});
} else {
return context.getMimeType(file);
}
}
@Override
@SuppressWarnings("unchecked") // doPrivileged() returns the correct type
public Set<String> getResourcePaths(String path) {
if (SecurityUtil.isPackageProtectionEnabled()){
return (Set<String>)doPrivileged("getResourcePaths",
new Object[]{path});
} else {
return context.getResourcePaths(path);
}
}
@Override
public URL getResource(String path)
throws MalformedURLException {
if (Globals.IS_SECURITY_ENABLED) {
try {
return (URL) invokeMethod(context, "getResource",
new Object[]{path});
} catch(Throwable t) {
ExceptionUtils.handleThrowable(t);
if (t instanceof MalformedURLException){
throw (MalformedURLException)t;
}
return null;
}
} else {
return context.getResource(path);
}
}
@Override
public InputStream getResourceAsStream(String path) {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (InputStream) doPrivileged("getResourceAsStream",
new Object[]{path});
} else {
return context.getResourceAsStream(path);
}
}
@Override
public RequestDispatcher getRequestDispatcher(final String path) {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (RequestDispatcher) doPrivileged("getRequestDispatcher",
new Object[]{path});
} else {
return context.getRequestDispatcher(path);
}
}
@Override
public RequestDispatcher getNamedDispatcher(String name) {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (RequestDispatcher) doPrivileged("getNamedDispatcher",
new Object[]{name});
} else {
return context.getNamedDispatcher(name);
}
}
/**
* @deprecated As of Java Servlet API 2.1, with no direct replacement.
*/
@Override
@Deprecated
public Servlet getServlet(String name)
throws ServletException {
if (SecurityUtil.isPackageProtectionEnabled()) {
try {
return (Servlet) invokeMethod(context, "getServlet",
new Object[]{name});
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
if (t instanceof ServletException) {
throw (ServletException) t;
}
return null;
}
} else {
return context.getServlet(name);
}
}
/**
* @deprecated As of Java Servlet API 2.1, with no direct replacement.
*/
@Override
@SuppressWarnings("unchecked") // doPrivileged() returns the correct type
@Deprecated
public Enumeration<Servlet> getServlets() {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (Enumeration<Servlet>) doPrivileged("getServlets", null);
} else {
return context.getServlets();
}
}
/**
* @deprecated As of Java Servlet API 2.1, with no direct replacement.
*/
@Override
@SuppressWarnings("unchecked") // doPrivileged() returns the correct type
@Deprecated
public Enumeration<String> getServletNames() {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (Enumeration<String>) doPrivileged("getServletNames", null);
} else {
return context.getServletNames();
}
}
@Override
public void log(String msg) {
if (SecurityUtil.isPackageProtectionEnabled()) {
doPrivileged("log", new Object[]{msg} );
} else {
context.log(msg);
}
}
/**
* @deprecated As of Java Servlet API 2.1, use
* <code>log(String, Throwable)</code> instead
*/
@Override
@Deprecated
public void log(Exception exception, String msg) {
if (SecurityUtil.isPackageProtectionEnabled()) {
doPrivileged("log", new Class[]{Exception.class, String.class},
new Object[]{exception,msg});
} else {
context.log(exception, msg);
}
}
@Override
public void log(String message, Throwable throwable) {
if (SecurityUtil.isPackageProtectionEnabled()) {
doPrivileged("log", new Class[]{String.class, Throwable.class},
new Object[]{message, throwable});
} else {
context.log(message, throwable);
}
}
@Override
public String getRealPath(String path) {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (String) doPrivileged("getRealPath", new Object[]{path});
} else {
return context.getRealPath(path);
}
}
@Override
public String getServerInfo() {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (String) doPrivileged("getServerInfo", null);
} else {
return context.getServerInfo();
}
}
@Override
public String getInitParameter(String name) {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (String) doPrivileged("getInitParameter",
new Object[]{name});
} else {
return context.getInitParameter(name);
}
}
@Override
@SuppressWarnings("unchecked") // doPrivileged() returns the correct type
public Enumeration<String> getInitParameterNames() {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (Enumeration<String>) doPrivileged(
"getInitParameterNames", null);
} else {
return context.getInitParameterNames();
}
}
@Override
public Object getAttribute(String name) {
if (SecurityUtil.isPackageProtectionEnabled()) {
return doPrivileged("getAttribute", new Object[]{name});
} else {
return context.getAttribute(name);
}
}
@Override
@SuppressWarnings("unchecked") // doPrivileged() returns the correct type
public Enumeration<String> getAttributeNames() {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (Enumeration<String>) doPrivileged(
"getAttributeNames", null);
} else {
return context.getAttributeNames();
}
}
@Override
public void setAttribute(String name, Object object) {
if (SecurityUtil.isPackageProtectionEnabled()) {
doPrivileged("setAttribute", new Object[]{name,object});
} else {
context.setAttribute(name, object);
}
}
@Override
public void removeAttribute(String name) {
if (SecurityUtil.isPackageProtectionEnabled()) {
doPrivileged("removeAttribute", new Object[]{name});
} else {
context.removeAttribute(name);
}
}
@Override
public String getServletContextName() {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (String) doPrivileged("getServletContextName", null);
} else {
return context.getServletContextName();
}
}
@Override
public String getContextPath() {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (String) doPrivileged("getContextPath", null);
} else {
return context.getContextPath();
}
}
@Override
public FilterRegistration.Dynamic addFilter(String filterName,
String className) {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (FilterRegistration.Dynamic) doPrivileged(
"addFilter", new Object[]{filterName, className});
} else {
return context.addFilter(filterName, className);
}
}
@Override
public FilterRegistration.Dynamic addFilter(String filterName,
Filter filter) {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (FilterRegistration.Dynamic) doPrivileged("addFilter",
new Class[]{String.class, Filter.class},
new Object[]{filterName, filter});
} else {
return context.addFilter(filterName, filter);
}
}
@Override
public FilterRegistration.Dynamic addFilter(String filterName,
Class<? extends Filter> filterClass) {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (FilterRegistration.Dynamic) doPrivileged("addFilter",
new Class[]{String.class, Class.class},
new Object[]{filterName, filterClass});
} else {
return context.addFilter(filterName, filterClass);
}
}
@Override
@SuppressWarnings("unchecked") // doPrivileged() returns the correct type
public <T extends Filter> T createFilter(Class<T> c)
throws ServletException {
if (SecurityUtil.isPackageProtectionEnabled()) {
try {
return (T) invokeMethod(context, "createFilter",
new Object[]{c});
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
if (t instanceof ServletException) {
throw (ServletException) t;
}
return null;
}
} else {
return context.createFilter(c);
}
}
@Override
public FilterRegistration getFilterRegistration(String filterName) {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (FilterRegistration) doPrivileged(
"getFilterRegistration", new Object[]{filterName});
} else {
return context.getFilterRegistration(filterName);
}
}
@Override
public ServletRegistration.Dynamic addServlet(String servletName,
String className) {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (ServletRegistration.Dynamic) doPrivileged(
"addServlet", new Object[]{servletName, className});
} else {
return context.addServlet(servletName, className);
}
}
@Override
public ServletRegistration.Dynamic addServlet(String servletName,
Servlet servlet) {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (ServletRegistration.Dynamic) doPrivileged("addServlet",
new Class[]{String.class, Servlet.class},
new Object[]{servletName, servlet});
} else {
return context.addServlet(servletName, servlet);
}
}
@Override
public ServletRegistration.Dynamic addServlet(String servletName,
Class<? extends Servlet> servletClass) {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (ServletRegistration.Dynamic) doPrivileged("addServlet",
new Class[]{String.class, Class.class},
new Object[]{servletName, servletClass});
} else {
return context.addServlet(servletName, servletClass);
}
}
public Dynamic addJspFile(String jspName, String jspFile) {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (ServletRegistration.Dynamic) doPrivileged("addJspFile",
new Object[]{jspName, jspFile});
} else {
return context.addJspFile(jspName, jspFile);
}
}
@Override
@SuppressWarnings("unchecked") // doPrivileged() returns the correct type
public <T extends Servlet> T createServlet(Class<T> c)
throws ServletException {
if (SecurityUtil.isPackageProtectionEnabled()) {
try {
return (T) invokeMethod(context, "createServlet",
new Object[]{c});
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
if (t instanceof ServletException) {
throw (ServletException) t;
}
return null;
}
} else {
return context.createServlet(c);
}
}
@Override
public ServletRegistration getServletRegistration(String servletName) {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (ServletRegistration) doPrivileged(
"getServletRegistration", new Object[]{servletName});
} else {
return context.getServletRegistration(servletName);
}
}
@Override
@SuppressWarnings("unchecked") // doPrivileged() returns the correct type
public Set<SessionTrackingMode> getDefaultSessionTrackingModes() {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (Set<SessionTrackingMode>)
doPrivileged("getDefaultSessionTrackingModes", null);
} else {
return context.getDefaultSessionTrackingModes();
}
}
@Override
@SuppressWarnings("unchecked") // doPrivileged() returns the correct type
public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (Set<SessionTrackingMode>)
doPrivileged("getEffectiveSessionTrackingModes", null);
} else {
return context.getEffectiveSessionTrackingModes();
}
}
@Override
public SessionCookieConfig getSessionCookieConfig() {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (SessionCookieConfig)
doPrivileged("getSessionCookieConfig", null);
} else {
return context.getSessionCookieConfig();
}
}
@Override
public void setSessionTrackingModes(
Set<SessionTrackingMode> sessionTrackingModes) {
if (SecurityUtil.isPackageProtectionEnabled()) {
doPrivileged("setSessionTrackingModes",
new Object[]{sessionTrackingModes});
} else {
context.setSessionTrackingModes(sessionTrackingModes);
}
}
@Override
public boolean setInitParameter(String name, String value) {
if (SecurityUtil.isPackageProtectionEnabled()) {
return ((Boolean) doPrivileged("setInitParameter",
new Object[]{name, value})).booleanValue();
} else {
return context.setInitParameter(name, value);
}
}
@Override
public void addListener(Class<? extends EventListener> listenerClass) {
if (SecurityUtil.isPackageProtectionEnabled()) {
doPrivileged("addListener",
new Class[]{Class.class},
new Object[]{listenerClass});
} else {
context.addListener(listenerClass);
}
}
@Override
public void addListener(String className) {
if (SecurityUtil.isPackageProtectionEnabled()) {
doPrivileged("addListener",
new Object[]{className});
} else {
context.addListener(className);
}
}
@Override
public <T extends EventListener> void addListener(T t) {
if (SecurityUtil.isPackageProtectionEnabled()) {
doPrivileged("addListener",
new Class[]{EventListener.class},
new Object[]{t});
} else {
context.addListener(t);
}
}
@Override
@SuppressWarnings("unchecked") // doPrivileged() returns the correct type
public <T extends EventListener> T createListener(Class<T> c)
throws ServletException {
if (SecurityUtil.isPackageProtectionEnabled()) {
try {
return (T) invokeMethod(context, "createListener",
new Object[]{c});
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
if (t instanceof ServletException) {
throw (ServletException) t;
}
return null;
}
} else {
return context.createListener(c);
}
}
@Override
public void declareRoles(String... roleNames) {
if (SecurityUtil.isPackageProtectionEnabled()) {
doPrivileged("declareRoles", new Object[]{roleNames});
} else {
context.declareRoles(roleNames);
}
}
@Override
public ClassLoader getClassLoader() {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (ClassLoader) doPrivileged("getClassLoader", null);
} else {
return context.getClassLoader();
}
}
@Override
public int getEffectiveMajorVersion() {
if (SecurityUtil.isPackageProtectionEnabled()) {
return ((Integer) doPrivileged("getEffectiveMajorVersion",
null)).intValue();
} else {
return context.getEffectiveMajorVersion();
}
}
@Override
public int getEffectiveMinorVersion() {
if (SecurityUtil.isPackageProtectionEnabled()) {
return ((Integer) doPrivileged("getEffectiveMinorVersion",
null)).intValue();
} else {
return context.getEffectiveMinorVersion();
}
}
@Override
@SuppressWarnings("unchecked") // doPrivileged() returns the correct type
public Map<String, ? extends FilterRegistration> getFilterRegistrations() {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (Map<String, ? extends FilterRegistration>) doPrivileged(
"getFilterRegistrations", null);
} else {
return context.getFilterRegistrations();
}
}
@Override
public JspConfigDescriptor getJspConfigDescriptor() {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (JspConfigDescriptor) doPrivileged("getJspConfigDescriptor",
null);
} else {
return context.getJspConfigDescriptor();
}
}
@Override
@SuppressWarnings("unchecked") // doPrivileged() returns the correct type
public Map<String, ? extends ServletRegistration> getServletRegistrations() {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (Map<String, ? extends ServletRegistration>) doPrivileged(
"getServletRegistrations", null);
} else {
return context.getServletRegistrations();
}
}
@Override
public String getVirtualServerName() {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (String) doPrivileged("getVirtualServerName", null);
} else {
return context.getVirtualServerName();
}
}
public int getSessionTimeout() {
if (SecurityUtil.isPackageProtectionEnabled()) {
return ((Integer) doPrivileged("getSessionTimeout", null)).intValue();
} else {
return context.getSessionTimeout();
}
}
public void setSessionTimeout(int sessionTimeout) {
if (SecurityUtil.isPackageProtectionEnabled()) {
doPrivileged("setSessionTimeout", new Object[] { Integer.valueOf(sessionTimeout) });
} else {
context.setSessionTimeout(sessionTimeout);
}
}
public String getRequestCharacterEncoding() {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (String) doPrivileged("getRequestCharacterEncoding", null);
} else {
return context.getRequestCharacterEncoding();
}
}
public void setRequestCharacterEncoding(String encoding) {
if (SecurityUtil.isPackageProtectionEnabled()) {
doPrivileged("setRequestCharacterEncoding", new Object[] { encoding });
} else {
context.setRequestCharacterEncoding(encoding);
}
}
public String getResponseCharacterEncoding() {
if (SecurityUtil.isPackageProtectionEnabled()) {
return (String) doPrivileged("getResponseCharacterEncoding", null);
} else {
return context.getResponseCharacterEncoding();
}
}
public void setResponseCharacterEncoding(String encoding) {
if (SecurityUtil.isPackageProtectionEnabled()) {
doPrivileged("setResponseCharacterEncoding", new Object[] { encoding });
} else {
context.setResponseCharacterEncoding(encoding);
}
}
/**
* Use reflection to invoke the requested method. Cache the method object
* to speed up the process
* @param methodName The method to call.
* @param params The arguments passed to the called method.
*/
private Object doPrivileged(final String methodName, final Object[] params) {
try{
return invokeMethod(context, methodName, params);
}catch(Throwable t){
ExceptionUtils.handleThrowable(t);
throw new RuntimeException(t.getMessage(), t);
}
}
/**
* Use reflection to invoke the requested method. Cache the method object
* to speed up the process
* @param appContext The ApplicationContext object on which the method
* will be invoked
* @param methodName The method to call.
* @param params The arguments passed to the called method.
*/
private Object invokeMethod(ApplicationContext appContext,
final String methodName,
Object[] params)
throws Throwable{
try{
Method method = objectCache.get(methodName);
if (method == null){
method = appContext.getClass()
.getMethod(methodName, classCache.get(methodName));
objectCache.put(methodName, method);
}
return executeMethod(method,appContext,params);
} catch (Exception ex){
handleException(ex);
return null;
} finally {
params = null;
}
}
/**
* Use reflection to invoke the requested method. Cache the method object
* to speed up the process
* @param methodName The method to invoke.
* @param clazz The class where the method is.
* @param params The arguments passed to the called method.
*/
private Object doPrivileged(final String methodName,
final Class<?>[] clazz,
Object[] params) {
try{
Method method = context.getClass().getMethod(methodName, clazz);
return executeMethod(method,context,params);
} catch (Exception ex){
try {
handleException(ex);
} catch (Throwable t){
ExceptionUtils.handleThrowable(t);
throw new RuntimeException(t.getMessage());
}
return null;
} finally {
params = null;
}
}
/**
* Executes the method of the specified <code>ApplicationContext</code>
* @param method The method object to be invoked.
* @param context The ApplicationContext object on which the method
* will be invoked
* @param params The arguments passed to the called method.
*/
private Object executeMethod(final Method method,
final ApplicationContext context,
final Object[] params)
throws PrivilegedActionException,
IllegalAccessException,
InvocationTargetException {
if (SecurityUtil.isPackageProtectionEnabled()){
return AccessController.doPrivileged(
new PrivilegedExecuteMethod(method, context, params));
} else {
return method.invoke(context, params);
}
}
/**
*
* Throw the real exception.
* @param ex The current exception
*/
private void handleException(Exception ex)
throws Throwable {
Throwable realException;
if (ex instanceof PrivilegedActionException) {
ex = ((PrivilegedActionException) ex).getException();
}
if (ex instanceof InvocationTargetException) {
realException = ex.getCause();
if (realException == null) {
realException = ex;
}
} else {
realException = ex;
}
throw realException;
}
private static class PrivilegedExecuteMethod implements PrivilegedExceptionAction<Object> {
private final Method method;
private final ApplicationContext context;
private final Object[] params;
public PrivilegedExecuteMethod(Method method, ApplicationContext context, Object[] params) {
this.method = method;
this.context = context;
this.params = params;
}
@Override
public Object run() throws Exception {
return method.invoke(context, params);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,348 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.io.IOException;
import java.security.Principal;
import java.security.PrivilegedActionException;
import java.util.Set;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.Globals;
import org.apache.catalina.security.SecurityUtil;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.res.StringManager;
/**
* Implementation of <code>javax.servlet.FilterChain</code> used to manage
* the execution of a set of filters for a particular request. When the
* set of defined filters has all been executed, the next call to
* <code>doFilter()</code> will execute the servlet's <code>service()</code>
* method itself.
*
* @author Craig R. McClanahan
*/
public final class ApplicationFilterChain implements FilterChain {
// Used to enforce requirements of SRV.8.2 / SRV.14.2.5.1
private static final ThreadLocal<ServletRequest> lastServicedRequest;
private static final ThreadLocal<ServletResponse> lastServicedResponse;
static {
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest = new ThreadLocal<>();
lastServicedResponse = new ThreadLocal<>();
} else {
lastServicedRequest = null;
lastServicedResponse = null;
}
}
// -------------------------------------------------------------- Constants
public static final int INCREMENT = 10;
// ----------------------------------------------------- Instance Variables
/**
* Filters.
*/
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
/**
* The int which is used to maintain the current position
* in the filter chain.
*/
private int pos = 0;
/**
* The int which gives the current number of filters in the chain.
*/
private int n = 0;
/**
* The servlet instance to be executed by this chain.
*/
private Servlet servlet = null;
/**
* Does the associated servlet instance support async processing?
*/
private boolean servletSupportsAsync = false;
/**
* The string manager for our package.
*/
private static final StringManager sm =
StringManager.getManager(Constants.Package);
/**
* Static class array used when the SecurityManager is turned on and
* <code>doFilter</code> is invoked.
*/
private static final Class<?>[] classType = new Class[]{
ServletRequest.class, ServletResponse.class, FilterChain.class};
/**
* Static class array used when the SecurityManager is turned on and
* <code>service</code> is invoked.
*/
private static final Class<?>[] classTypeUsedInService = new Class[]{
ServletRequest.class, ServletResponse.class};
// ---------------------------------------------------- FilterChain Methods
/**
* Invoke the next filter in this chain, passing the specified request
* and response. If there are no more filters in this chain, invoke
* the <code>service()</code> method of the servlet itself.
*
* @param request The servlet request we are processing
* @param response The servlet response we are creating
*
* @exception IOException if an input/output error occurs
* @exception ServletException if a servlet exception occurs
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
if( Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
try {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedExceptionAction<Void>() {
@Override
public Void run()
throws ServletException, IOException {
internalDoFilter(req,res);
return null;
}
}
);
} catch( PrivilegedActionException pe) {
Exception e = pe.getException();
if (e instanceof ServletException)
throw (ServletException) e;
else if (e instanceof IOException)
throw (IOException) e;
else if (e instanceof RuntimeException)
throw (RuntimeException) e;
else
throw new ServletException(e.getMessage(), e);
}
} else {
internalDoFilter(request,response);
}
}
private void internalDoFilter(ServletRequest request,
ServletResponse response)
throws IOException, ServletException {
// Call the next filter if there is one
if (pos < n) {
ApplicationFilterConfig filterConfig = filters[pos++];
try {
Filter filter = filterConfig.getFilter();
if (request.isAsyncSupported() && "false".equalsIgnoreCase(
filterConfig.getFilterDef().getAsyncSupported())) {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);
}
if( Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
Principal principal =
((HttpServletRequest) req).getUserPrincipal();
Object[] args = new Object[]{req, res, this};
SecurityUtil.doAsPrivilege ("doFilter", filter, classType, args, principal);
} else {
filter.doFilter(request, response, this);
}
} catch (IOException | ServletException | RuntimeException e) {
throw e;
} catch (Throwable e) {
e = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("filterChain.filter"), e);
}
return;
}
// We fell off the end of the chain -- call the servlet instance
try {
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest.set(request);
lastServicedResponse.set(response);
}
if (request.isAsyncSupported() && !servletSupportsAsync) {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,
Boolean.FALSE);
}
// Use potentially wrapped request from this point
if ((request instanceof HttpServletRequest) &&
(response instanceof HttpServletResponse) &&
Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
Principal principal =
((HttpServletRequest) req).getUserPrincipal();
Object[] args = new Object[]{req, res};
SecurityUtil.doAsPrivilege("service",
servlet,
classTypeUsedInService,
args,
principal);
} else {
servlet.service(request, response);
}
} catch (IOException | ServletException | RuntimeException e) {
throw e;
} catch (Throwable e) {
e = ExceptionUtils.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("filterChain.servlet"), e);
} finally {
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest.set(null);
lastServicedResponse.set(null);
}
}
}
/**
* The last request passed to a servlet for servicing from the current
* thread.
*
* @return The last request to be serviced.
*/
public static ServletRequest getLastServicedRequest() {
return lastServicedRequest.get();
}
/**
* The last response passed to a servlet for servicing from the current
* thread.
*
* @return The last response to be serviced.
*/
public static ServletResponse getLastServicedResponse() {
return lastServicedResponse.get();
}
// -------------------------------------------------------- Package Methods
/**
* Add a filter to the set of filters that will be executed in this chain.
*
* @param filterConfig The FilterConfig for the servlet to be executed
*/
void addFilter(ApplicationFilterConfig filterConfig) {
// Prevent the same filter being added multiple times
for(ApplicationFilterConfig filter:filters)
if(filter==filterConfig)
return;
if (n == filters.length) {
ApplicationFilterConfig[] newFilters =
new ApplicationFilterConfig[n + INCREMENT];
System.arraycopy(filters, 0, newFilters, 0, n);
filters = newFilters;
}
filters[n++] = filterConfig;
}
/**
* Release references to the filters and wrapper executed by this chain.
*/
void release() {
for (int i = 0; i < n; i++) {
filters[i] = null;
}
n = 0;
pos = 0;
servlet = null;
servletSupportsAsync = false;
}
/**
* Prepare for reuse of the filters and wrapper executed by this chain.
*/
void reuse() {
pos = 0;
}
/**
* Set the servlet that will be executed at the end of this chain.
*
* @param servlet The Wrapper for the servlet to be executed
*/
void setServlet(Servlet servlet) {
this.servlet = servlet;
}
void setServletSupportsAsync(boolean servletSupportsAsync) {
this.servletSupportsAsync = servletSupportsAsync;
}
/**
* Identifies the Filters, if any, in this FilterChain that do not support
* async.
*
* @param result The Set to which the fully qualified class names of each
* Filter in this FilterChain that does not support async will
* be added
*/
public void findNonAsyncFilters(Set<String> result) {
for (int i = 0; i < n ; i++) {
ApplicationFilterConfig filter = filters[i];
if ("false".equalsIgnoreCase(filter.getFilterDef().getAsyncSupported())) {
result.add(filter.getFilterClass());
}
}
}
}

View File

@@ -0,0 +1,409 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.management.ObjectName;
import javax.naming.NamingException;
import javax.servlet.Filter;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.apache.catalina.Context;
import org.apache.catalina.Globals;
import org.apache.catalina.security.SecurityUtil;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.InstanceManager;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.descriptor.web.FilterDef;
import org.apache.tomcat.util.log.SystemLogHandler;
import org.apache.tomcat.util.modeler.Registry;
import org.apache.tomcat.util.modeler.Util;
import org.apache.tomcat.util.res.StringManager;
/**
* Implementation of a <code>javax.servlet.FilterConfig</code> useful in
* managing the filter instances instantiated when a web application
* is first started.
*
* @author Craig R. McClanahan
*/
public final class ApplicationFilterConfig implements FilterConfig, Serializable {
private static final long serialVersionUID = 1L;
static final StringManager sm =
StringManager.getManager(Constants.Package);
private transient Log log = LogFactory.getLog(ApplicationFilterConfig.class); // must not be static
/**
* Empty String collection to serve as the basis for empty enumerations.
*/
private static final List<String> emptyString = Collections.emptyList();
// ----------------------------------------------------------- Constructors
/**
* Construct a new ApplicationFilterConfig for the specified filter
* definition.
*
* @param context The context with which we are associated
* @param filterDef Filter definition for which a FilterConfig is to be
* constructed
*
* @exception ClassCastException if the specified class does not implement
* the <code>javax.servlet.Filter</code> interface
* @exception ClassNotFoundException if the filter class cannot be found
* @exception IllegalAccessException if the filter class cannot be
* publicly instantiated
* @exception InstantiationException if an exception occurs while
* instantiating the filter object
* @exception ServletException if thrown by the filter's init() method
* @throws NamingException
* @throws InvocationTargetException
* @throws SecurityException
* @throws NoSuchMethodException
* @throws IllegalArgumentException
*/
ApplicationFilterConfig(Context context, FilterDef filterDef)
throws ClassCastException, ClassNotFoundException, IllegalAccessException,
InstantiationException, ServletException, InvocationTargetException, NamingException,
IllegalArgumentException, NoSuchMethodException, SecurityException {
super();
this.context = context;
this.filterDef = filterDef;
// Allocate a new filter instance if necessary
if (filterDef.getFilter() == null) {
getFilter();
} else {
this.filter = filterDef.getFilter();
getInstanceManager().newInstance(filter);
initFilter();
}
}
// ----------------------------------------------------- Instance Variables
/**
* The Context with which we are associated.
*/
private final transient Context context;
/**
* The application Filter we are configured for.
*/
private transient Filter filter = null;
/**
* The <code>FilterDef</code> that defines our associated Filter.
*/
private final FilterDef filterDef;
/**
* the InstanceManager used to create and destroy filter instances.
*/
private transient InstanceManager instanceManager;
/**
* JMX registration name
*/
private ObjectName oname;
// --------------------------------------------------- FilterConfig Methods
/**
* Return the name of the filter we are configuring.
*/
@Override
public String getFilterName() {
return filterDef.getFilterName();
}
/**
* @return The class of the filter we are configuring.
*/
public String getFilterClass() {
return filterDef.getFilterClass();
}
/**
* Return a <code>String</code> containing the value of the named
* initialization parameter, or <code>null</code> if the parameter
* does not exist.
*
* @param name Name of the requested initialization parameter
*/
@Override
public String getInitParameter(String name) {
Map<String,String> map = filterDef.getParameterMap();
if (map == null) {
return null;
}
return map.get(name);
}
/**
* Return an <code>Enumeration</code> of the names of the initialization
* parameters for this Filter.
*/
@Override
public Enumeration<String> getInitParameterNames() {
Map<String,String> map = filterDef.getParameterMap();
if (map == null) {
return Collections.enumeration(emptyString);
}
return Collections.enumeration(map.keySet());
}
/**
* Return the ServletContext of our associated web application.
*/
@Override
public ServletContext getServletContext() {
return this.context.getServletContext();
}
/**
* Return a String representation of this object.
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder("ApplicationFilterConfig[");
sb.append("name=");
sb.append(filterDef.getFilterName());
sb.append(", filterClass=");
sb.append(filterDef.getFilterClass());
sb.append("]");
return sb.toString();
}
// --------------------------------------------------------- Public Methods
public Map<String, String> getFilterInitParameterMap() {
return Collections.unmodifiableMap(filterDef.getParameterMap());
}
// -------------------------------------------------------- Package Methods
/**
* Return the application Filter we are configured for.
*
* @exception ClassCastException if the specified class does not implement
* the <code>javax.servlet.Filter</code> interface
* @exception ClassNotFoundException if the filter class cannot be found
* @exception IllegalAccessException if the filter class cannot be
* publicly instantiated
* @exception InstantiationException if an exception occurs while
* instantiating the filter object
* @exception ServletException if thrown by the filter's init() method
* @throws NamingException
* @throws InvocationTargetException
* @throws SecurityException
* @throws NoSuchMethodException
* @throws IllegalArgumentException
*/
Filter getFilter() throws ClassCastException, ClassNotFoundException, IllegalAccessException,
InstantiationException, ServletException, InvocationTargetException, NamingException,
IllegalArgumentException, NoSuchMethodException, SecurityException {
// Return the existing filter instance, if any
if (this.filter != null)
return this.filter;
// Identify the class loader we will be using
String filterClass = filterDef.getFilterClass();
this.filter = (Filter) getInstanceManager().newInstance(filterClass);
initFilter();
return this.filter;
}
private void initFilter() throws ServletException {
if (context instanceof StandardContext &&
context.getSwallowOutput()) {
try {
SystemLogHandler.startCapture();
filter.init(this);
} finally {
String capturedlog = SystemLogHandler.stopCapture();
if (capturedlog != null && capturedlog.length() > 0) {
getServletContext().log(capturedlog);
}
}
} else {
filter.init(this);
}
// Expose filter via JMX
registerJMX();
}
/**
* Return the filter definition we are configured for.
*/
FilterDef getFilterDef() {
return this.filterDef;
}
/**
* Release the Filter instance associated with this FilterConfig,
* if there is one.
*/
void release() {
unregisterJMX();
if (this.filter != null) {
try {
if (Globals.IS_SECURITY_ENABLED) {
try {
SecurityUtil.doAsPrivilege("destroy", filter);
} finally {
SecurityUtil.remove(filter);
}
} else {
filter.destroy();
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
context.getLogger().error(sm.getString(
"applicationFilterConfig.release",
filterDef.getFilterName(),
filterDef.getFilterClass()), t);
}
if (!context.getIgnoreAnnotations()) {
try {
((StandardContext) context).getInstanceManager().destroyInstance(this.filter);
} catch (Exception e) {
Throwable t = ExceptionUtils
.unwrapInvocationTargetException(e);
ExceptionUtils.handleThrowable(t);
context.getLogger().error(
sm.getString("applicationFilterConfig.preDestroy",
filterDef.getFilterName(), filterDef.getFilterClass()), t);
}
}
}
this.filter = null;
}
// -------------------------------------------------------- Private Methods
private InstanceManager getInstanceManager() {
if (instanceManager == null) {
if (context instanceof StandardContext) {
instanceManager = ((StandardContext)context).getInstanceManager();
} else {
instanceManager = new DefaultInstanceManager(null,
new HashMap<String, Map<String, String>>(),
context,
getClass().getClassLoader());
}
}
return instanceManager;
}
private void registerJMX() {
String parentName = context.getName();
if (!parentName.startsWith("/")) {
parentName = "/" + parentName;
}
String hostName = context.getParent().getName();
hostName = (hostName == null) ? "DEFAULT" : hostName;
// domain == engine name
String domain = context.getParent().getParent().getName();
String webMod = "//" + hostName + parentName;
String onameStr = null;
String filterName = filterDef.getFilterName();
if (Util.objectNameValueNeedsQuote(filterName)) {
filterName = ObjectName.quote(filterName);
}
if (context instanceof StandardContext) {
StandardContext standardContext = (StandardContext) context;
onameStr = domain + ":j2eeType=Filter,WebModule=" + webMod +
",name=" + filterName + ",J2EEApplication=" +
standardContext.getJ2EEApplication() + ",J2EEServer=" +
standardContext.getJ2EEServer();
} else {
onameStr = domain + ":j2eeType=Filter,name=" + filterName +
",WebModule=" + webMod;
}
try {
oname = new ObjectName(onameStr);
Registry.getRegistry(null, null).registerComponent(this, oname, null);
} catch (Exception ex) {
log.warn(sm.getString("applicationFilterConfig.jmxRegisterFail",
getFilterClass(), getFilterName()), ex);
}
}
private void unregisterJMX() {
// unregister this component
if (oname != null) {
try {
Registry.getRegistry(null, null).unregisterComponent(oname);
if (log.isDebugEnabled())
log.debug(sm.getString("applicationFilterConfig.jmxUnregister",
getFilterClass(), getFilterName()));
} catch(Exception ex) {
log.warn(sm.getString("applicationFilterConfig.jmxUnregisterFail",
getFilterClass(), getFilterName()), ex);
}
}
}
}

View File

@@ -0,0 +1,290 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import javax.servlet.DispatcherType;
import javax.servlet.Servlet;
import javax.servlet.ServletRequest;
import org.apache.catalina.Globals;
import org.apache.catalina.Wrapper;
import org.apache.catalina.connector.Request;
import org.apache.tomcat.util.descriptor.web.FilterMap;
/**
* Factory for the creation and caching of Filters and creation
* of Filter Chains.
*
* @author Greg Murray
* @author Remy Maucherat
*/
public final class ApplicationFilterFactory {
private ApplicationFilterFactory() {
// Prevent instance creation. This is a utility class.
}
/**
* Construct a FilterChain implementation that will wrap the execution of
* the specified servlet instance.
*
* @param request The servlet request we are processing
* @param wrapper The wrapper managing the servlet instance
* @param servlet The servlet instance to be wrapped
*
* @return The configured FilterChain instance or null if none is to be
* executed.
*/
public static ApplicationFilterChain createFilterChain(ServletRequest request,
Wrapper wrapper, Servlet servlet) {
// If there is no servlet to execute, return null
if (servlet == null)
return null;
// Create and initialize a filter chain object
ApplicationFilterChain filterChain = null;
if (request instanceof Request) {
Request req = (Request) request;
if (Globals.IS_SECURITY_ENABLED) {
// Security: Do not recycle
filterChain = new ApplicationFilterChain();
} else {
filterChain = (ApplicationFilterChain) req.getFilterChain();
if (filterChain == null) {
filterChain = new ApplicationFilterChain();
req.setFilterChain(filterChain);
}
}
} else {
// Request dispatcher in use
filterChain = new ApplicationFilterChain();
}
filterChain.setServlet(servlet);
filterChain.setServletSupportsAsync(wrapper.isAsyncSupported());
// Acquire the filter mappings for this Context
StandardContext context = (StandardContext) wrapper.getParent();
FilterMap filterMaps[] = context.findFilterMaps();
// If there are no filter mappings, we are done
if ((filterMaps == null) || (filterMaps.length == 0))
return filterChain;
// Acquire the information we will need to match filter mappings
DispatcherType dispatcher =
(DispatcherType) request.getAttribute(Globals.DISPATCHER_TYPE_ATTR);
String requestPath = null;
Object attribute = request.getAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR);
if (attribute != null){
requestPath = attribute.toString();
}
String servletName = wrapper.getName();
// Add the relevant path-mapped filters to this filter chain
for (int i = 0; i < filterMaps.length; i++) {
if (!matchDispatcher(filterMaps[i] ,dispatcher)) {
continue;
}
if (!matchFiltersURL(filterMaps[i], requestPath))
continue;
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
context.findFilterConfig(filterMaps[i].getFilterName());
if (filterConfig == null) {
// FIXME - log configuration problem
continue;
}
filterChain.addFilter(filterConfig);
}
// Add filters that match on servlet name second
for (int i = 0; i < filterMaps.length; i++) {
if (!matchDispatcher(filterMaps[i] ,dispatcher)) {
continue;
}
if (!matchFiltersServlet(filterMaps[i], servletName))
continue;
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
context.findFilterConfig(filterMaps[i].getFilterName());
if (filterConfig == null) {
// FIXME - log configuration problem
continue;
}
filterChain.addFilter(filterConfig);
}
// Return the completed filter chain
return filterChain;
}
// -------------------------------------------------------- Private Methods
/**
* Return <code>true</code> if the context-relative request path
* matches the requirements of the specified filter mapping;
* otherwise, return <code>false</code>.
*
* @param filterMap Filter mapping being checked
* @param requestPath Context-relative request path of this request
*/
private static boolean matchFiltersURL(FilterMap filterMap, String requestPath) {
// Check the specific "*" special URL pattern, which also matches
// named dispatches
if (filterMap.getMatchAllUrlPatterns())
return true;
if (requestPath == null)
return false;
// Match on context relative request path
String[] testPaths = filterMap.getURLPatterns();
for (int i = 0; i < testPaths.length; i++) {
if (matchFiltersURL(testPaths[i], requestPath)) {
return true;
}
}
// No match
return false;
}
/**
* Return <code>true</code> if the context-relative request path
* matches the requirements of the specified filter mapping;
* otherwise, return <code>false</code>.
*
* @param testPath URL mapping being checked
* @param requestPath Context-relative request path of this request
*/
private static boolean matchFiltersURL(String testPath, String requestPath) {
if (testPath == null)
return false;
// Case 1 - Exact Match
if (testPath.equals(requestPath))
return true;
// Case 2 - Path Match ("/.../*")
if (testPath.equals("/*"))
return true;
if (testPath.endsWith("/*")) {
if (testPath.regionMatches(0, requestPath, 0,
testPath.length() - 2)) {
if (requestPath.length() == (testPath.length() - 2)) {
return true;
} else if ('/' == requestPath.charAt(testPath.length() - 2)) {
return true;
}
}
return false;
}
// Case 3 - Extension Match
if (testPath.startsWith("*.")) {
int slash = requestPath.lastIndexOf('/');
int period = requestPath.lastIndexOf('.');
if ((slash >= 0) && (period > slash)
&& (period != requestPath.length() - 1)
&& ((requestPath.length() - period)
== (testPath.length() - 1))) {
return (testPath.regionMatches(2, requestPath, period + 1,
testPath.length() - 2));
}
}
// Case 4 - "Default" Match
return false; // NOTE - Not relevant for selecting filters
}
/**
* Return <code>true</code> if the specified servlet name matches
* the requirements of the specified filter mapping; otherwise
* return <code>false</code>.
*
* @param filterMap Filter mapping being checked
* @param servletName Servlet name being checked
*/
private static boolean matchFiltersServlet(FilterMap filterMap,
String servletName) {
if (servletName == null) {
return false;
}
// Check the specific "*" special servlet name
else if (filterMap.getMatchAllServletNames()) {
return true;
} else {
String[] servletNames = filterMap.getServletNames();
for (int i = 0; i < servletNames.length; i++) {
if (servletName.equals(servletNames[i])) {
return true;
}
}
return false;
}
}
/**
* Convenience method which returns true if the dispatcher type
* matches the dispatcher types specified in the FilterMap
*/
private static boolean matchDispatcher(FilterMap filterMap, DispatcherType type) {
switch (type) {
case FORWARD :
if ((filterMap.getDispatcherMapping() & FilterMap.FORWARD) != 0) {
return true;
}
break;
case INCLUDE :
if ((filterMap.getDispatcherMapping() & FilterMap.INCLUDE) != 0) {
return true;
}
break;
case REQUEST :
if ((filterMap.getDispatcherMapping() & FilterMap.REQUEST) != 0) {
return true;
}
break;
case ERROR :
if ((filterMap.getDispatcherMapping() & FilterMap.ERROR) != 0) {
return true;
}
break;
case ASYNC :
if ((filterMap.getDispatcherMapping() & FilterMap.ASYNC) != 0) {
return true;
}
break;
}
return false;
}
}

View File

@@ -0,0 +1,215 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.servlet.DispatcherType;
import javax.servlet.FilterRegistration;
import org.apache.catalina.Context;
import org.apache.catalina.util.ParameterMap;
import org.apache.tomcat.util.descriptor.web.FilterDef;
import org.apache.tomcat.util.descriptor.web.FilterMap;
import org.apache.tomcat.util.res.StringManager;
public class ApplicationFilterRegistration
implements FilterRegistration.Dynamic {
/**
* The string manager for this package.
*/
private static final StringManager sm =
StringManager.getManager(Constants.Package);
private final FilterDef filterDef;
private final Context context;
public ApplicationFilterRegistration(FilterDef filterDef,
Context context) {
this.filterDef = filterDef;
this.context = context;
}
@Override
public void addMappingForServletNames(
EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter,
String... servletNames) {
FilterMap filterMap = new FilterMap();
filterMap.setFilterName(filterDef.getFilterName());
if (dispatcherTypes != null) {
for (DispatcherType dispatcherType : dispatcherTypes) {
filterMap.setDispatcher(dispatcherType.name());
}
}
if (servletNames != null) {
for (String servletName : servletNames) {
filterMap.addServletName(servletName);
}
if (isMatchAfter) {
context.addFilterMap(filterMap);
} else {
context.addFilterMapBefore(filterMap);
}
}
// else error?
}
@Override
public void addMappingForUrlPatterns(
EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter,
String... urlPatterns) {
FilterMap filterMap = new FilterMap();
filterMap.setFilterName(filterDef.getFilterName());
if (dispatcherTypes != null) {
for (DispatcherType dispatcherType : dispatcherTypes) {
filterMap.setDispatcher(dispatcherType.name());
}
}
if (urlPatterns != null) {
// % decoded (if necessary) using UTF-8
for (String urlPattern : urlPatterns) {
filterMap.addURLPattern(urlPattern);
}
if (isMatchAfter) {
context.addFilterMap(filterMap);
} else {
context.addFilterMapBefore(filterMap);
}
}
// else error?
}
@Override
public Collection<String> getServletNameMappings() {
Collection<String> result = new HashSet<>();
FilterMap[] filterMaps = context.findFilterMaps();
for (FilterMap filterMap : filterMaps) {
if (filterMap.getFilterName().equals(filterDef.getFilterName())) {
for (String servletName : filterMap.getServletNames()) {
result.add(servletName);
}
}
}
return result;
}
@Override
public Collection<String> getUrlPatternMappings() {
Collection<String> result = new HashSet<>();
FilterMap[] filterMaps = context.findFilterMaps();
for (FilterMap filterMap : filterMaps) {
if (filterMap.getFilterName().equals(filterDef.getFilterName())) {
for (String urlPattern : filterMap.getURLPatterns()) {
result.add(urlPattern);
}
}
}
return result;
}
@Override
public String getClassName() {
return filterDef.getFilterClass();
}
@Override
public String getInitParameter(String name) {
return filterDef.getParameterMap().get(name);
}
@Override
public Map<String, String> getInitParameters() {
ParameterMap<String,String> result = new ParameterMap<>();
result.putAll(filterDef.getParameterMap());
result.setLocked(true);
return result;
}
@Override
public String getName() {
return filterDef.getFilterName();
}
@Override
public boolean setInitParameter(String name, String value) {
if (name == null || value == null) {
throw new IllegalArgumentException(
sm.getString("applicationFilterRegistration.nullInitParam",
name, value));
}
if (getInitParameter(name) != null) {
return false;
}
filterDef.addInitParameter(name, value);
return true;
}
@Override
public Set<String> setInitParameters(Map<String, String> initParameters) {
Set<String> conflicts = new HashSet<>();
for (Map.Entry<String, String> entry : initParameters.entrySet()) {
if (entry.getKey() == null || entry.getValue() == null) {
throw new IllegalArgumentException(sm.getString(
"applicationFilterRegistration.nullInitParams",
entry.getKey(), entry.getValue()));
}
if (getInitParameter(entry.getKey()) != null) {
conflicts.add(entry.getKey());
}
}
// Have to add in a separate loop since spec requires no updates at all
// if there is an issue
for (Map.Entry<String, String> entry : initParameters.entrySet()) {
setInitParameter(entry.getKey(), entry.getValue());
}
return conflicts;
}
@Override
public void setAsyncSupported(boolean asyncSupported) {
filterDef.setAsyncSupported(Boolean.valueOf(asyncSupported).toString());
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,373 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.io.IOException;
import java.util.Locale;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
/**
* Wrapper around a <code>javax.servlet.http.HttpServletResponse</code>
* that transforms an application response object (which might be the original
* one passed to a servlet, or might be based on the 2.3
* <code>javax.servlet.http.HttpServletResponseWrapper</code> class)
* back into an internal <code>org.apache.catalina.HttpResponse</code>.
* <p>
* <strong>WARNING</strong>: Due to Java's lack of support for multiple
* inheritance, all of the logic in <code>ApplicationResponse</code> is
* duplicated in <code>ApplicationHttpResponse</code>. Make sure that you
* keep these two classes in synchronization when making changes!
*
* @author Craig R. McClanahan
*/
class ApplicationHttpResponse extends HttpServletResponseWrapper {
// ----------------------------------------------------------- Constructors
/**
* Construct a new wrapped response around the specified servlet response.
*
* @param response The servlet response being wrapped
* @param included <code>true</code> if this response is being processed
* by a <code>RequestDispatcher.include()</code> call
*/
public ApplicationHttpResponse(HttpServletResponse response,
boolean included) {
super(response);
setIncluded(included);
}
// ----------------------------------------------------- Instance Variables
/**
* Is this wrapped response the subject of an <code>include()</code>
* call?
*/
protected boolean included = false;
// ------------------------------------------------ ServletResponse Methods
/**
* Disallow <code>reset()</code> calls on a included response.
*
* @exception IllegalStateException if the response has already
* been committed
*/
@Override
public void reset() {
// If already committed, the wrapped response will throw ISE
if (!included || getResponse().isCommitted())
getResponse().reset();
}
/**
* Disallow <code>setContentLength(int)</code> calls on an included
* response.
*
* @param len The new content length
*/
@Override
public void setContentLength(int len) {
if (!included)
getResponse().setContentLength(len);
}
/**
* Disallow <code>setContentLengthLong(long)</code> calls on an included
* response.
*
* @param len The new content length
*/
@Override
public void setContentLengthLong(long len) {
if (!included)
getResponse().setContentLengthLong(len);
}
/**
* Disallow <code>setContentType()</code> calls on an included response.
*
* @param type The new content type
*/
@Override
public void setContentType(String type) {
if (!included)
getResponse().setContentType(type);
}
/**
* Disallow <code>setLocale()</code> calls on an included response.
*
* @param loc The new locale
*/
@Override
public void setLocale(Locale loc) {
if (!included)
getResponse().setLocale(loc);
}
/**
* Ignore <code>setBufferSize()</code> calls on an included response.
*
* @param size The buffer size
*/
@Override
public void setBufferSize(int size) {
if (!included)
getResponse().setBufferSize(size);
}
// -------------------------------------------- HttpServletResponse Methods
/**
* Disallow <code>addCookie()</code> calls on an included response.
*
* @param cookie The new cookie
*/
@Override
public void addCookie(Cookie cookie) {
if (!included)
((HttpServletResponse) getResponse()).addCookie(cookie);
}
/**
* Disallow <code>addDateHeader()</code> calls on an included response.
*
* @param name The new header name
* @param value The new header value
*/
@Override
public void addDateHeader(String name, long value) {
if (!included)
((HttpServletResponse) getResponse()).addDateHeader(name, value);
}
/**
* Disallow <code>addHeader()</code> calls on an included response.
*
* @param name The new header name
* @param value The new header value
*/
@Override
public void addHeader(String name, String value) {
if (!included)
((HttpServletResponse) getResponse()).addHeader(name, value);
}
/**
* Disallow <code>addIntHeader()</code> calls on an included response.
*
* @param name The new header name
* @param value The new header value
*/
@Override
public void addIntHeader(String name, int value) {
if (!included)
((HttpServletResponse) getResponse()).addIntHeader(name, value);
}
/**
* Disallow <code>sendError()</code> calls on an included response.
*
* @param sc The new status code
*
* @exception IOException if an input/output error occurs
*/
@Override
public void sendError(int sc) throws IOException {
if (!included)
((HttpServletResponse) getResponse()).sendError(sc);
}
/**
* Disallow <code>sendError()</code> calls on an included response.
*
* @param sc The new status code
* @param msg The new message
*
* @exception IOException if an input/output error occurs
*/
@Override
public void sendError(int sc, String msg) throws IOException {
if (!included)
((HttpServletResponse) getResponse()).sendError(sc, msg);
}
/**
* Disallow <code>sendRedirect()</code> calls on an included response.
*
* @param location The new location
*
* @exception IOException if an input/output error occurs
*/
@Override
public void sendRedirect(String location) throws IOException {
if (!included)
((HttpServletResponse) getResponse()).sendRedirect(location);
}
/**
* Disallow <code>setDateHeader()</code> calls on an included response.
*
* @param name The new header name
* @param value The new header value
*/
@Override
public void setDateHeader(String name, long value) {
if (!included)
((HttpServletResponse) getResponse()).setDateHeader(name, value);
}
/**
* Disallow <code>setHeader()</code> calls on an included response.
*
* @param name The new header name
* @param value The new header value
*/
@Override
public void setHeader(String name, String value) {
if (!included)
((HttpServletResponse) getResponse()).setHeader(name, value);
}
/**
* Disallow <code>setIntHeader()</code> calls on an included response.
*
* @param name The new header name
* @param value The new header value
*/
@Override
public void setIntHeader(String name, int value) {
if (!included)
((HttpServletResponse) getResponse()).setIntHeader(name, value);
}
/**
* Disallow <code>setStatus()</code> calls on an included response.
*
* @param sc The new status code
*/
@Override
public void setStatus(int sc) {
if (!included)
((HttpServletResponse) getResponse()).setStatus(sc);
}
/**
* Disallow <code>setStatus()</code> calls on an included response.
*
* @param sc The new status code
* @param msg The new message
* @deprecated As of version 2.1, due to ambiguous meaning of the message
* parameter. To set a status code use
* <code>setStatus(int)</code>, to send an error with a
* description use <code>sendError(int, String)</code>.
*/
@Deprecated
@Override
public void setStatus(int sc, String msg) {
if (!included)
((HttpServletResponse) getResponse()).setStatus(sc, msg);
}
// -------------------------------------------------------- Package Methods
/**
* Set the included flag for this response.
*
* @param included The new included flag
*/
void setIncluded(boolean included) {
this.included = included;
}
/**
* Set the response that we are wrapping.
*
* @param response The new wrapped response
*/
void setResponse(HttpServletResponse response) {
super.setResponse(response);
}
}

View File

@@ -0,0 +1,124 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import org.apache.catalina.mapper.MappingData;
import org.apache.catalina.servlet4preview.http.HttpServletMapping;
import org.apache.catalina.servlet4preview.http.MappingMatch;
public class ApplicationMapping {
private final MappingData mappingData;
private volatile HttpServletMapping mapping = null;
public ApplicationMapping(MappingData mappingData) {
this.mappingData = mappingData;
}
public HttpServletMapping getHttpServletMapping() {
if (mapping == null) {
if (mappingData == null) {
// This can happen when dispatching from an application provided
// request object that does not provide the Servlet 4.0 mapping
// data.
mapping = new MappingImpl("", "", null, "");
} else {
String servletName;
if (mappingData.wrapper == null) {
servletName = "";
} else {
servletName = mappingData.wrapper.getName();
}
if (mappingData.matchType == null) {
mapping = new MappingImpl("", "", null, servletName);
} else {
switch (mappingData.matchType) {
case CONTEXT_ROOT:
mapping = new MappingImpl("", "", mappingData.matchType, servletName);
break;
case DEFAULT:
mapping = new MappingImpl("", "/", mappingData.matchType, servletName);
break;
case EXACT:
mapping = new MappingImpl(mappingData.wrapperPath.toString().substring(1),
mappingData.wrapperPath.toString(), mappingData.matchType, servletName);
break;
case EXTENSION:
String path = mappingData.wrapperPath.toString();
int extIndex = path.lastIndexOf('.');
mapping = new MappingImpl(path.substring(1, extIndex),
"*" + path.substring(extIndex), mappingData.matchType, servletName);
break;
case PATH:
String matchValue;
if (mappingData.pathInfo.isNull()) {
matchValue = null;
} else {
matchValue = mappingData.pathInfo.toString().substring(1);
}
mapping = new MappingImpl(matchValue, mappingData.wrapperPath.toString() + "/*",
mappingData.matchType, servletName);
break;
}
}
}
}
return mapping;
}
public void recycle() {
mapping = null;
}
private static class MappingImpl implements HttpServletMapping {
private final String matchValue;
private final String pattern;
private final MappingMatch mappingType;
private final String servletName;
public MappingImpl(String matchValue, String pattern, MappingMatch mappingType,
String servletName) {
this.matchValue = matchValue;
this.pattern = pattern;
this.mappingType = mappingType;
this.servletName = servletName;
}
@Override
public String getMatchValue() {
return matchValue;
}
@Override
public String getPattern() {
return pattern;
}
@Override
public MappingMatch getMappingMatch() {
return mappingType;
}
@Override
public String getServletName() {
return servletName;
}
}
}

View File

@@ -0,0 +1,168 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Locale;
import java.util.Map;
import javax.servlet.http.Part;
import org.apache.tomcat.util.http.fileupload.FileItem;
import org.apache.tomcat.util.http.fileupload.ParameterParser;
import org.apache.tomcat.util.http.fileupload.disk.DiskFileItem;
import org.apache.tomcat.util.http.parser.HttpParser;
/**
* Adaptor to allow {@link FileItem} objects generated by the package renamed
* commons-upload to be used by the Servlet 3.0 upload API that expects
* {@link Part}s.
*/
public class ApplicationPart implements Part {
private final FileItem fileItem;
private final File location;
public ApplicationPart(FileItem fileItem, File location) {
this.fileItem = fileItem;
this.location = location;
}
@Override
public void delete() throws IOException {
fileItem.delete();
}
@Override
public String getContentType() {
return fileItem.getContentType();
}
@Override
public String getHeader(String name) {
if (fileItem instanceof DiskFileItem) {
return ((DiskFileItem) fileItem).getHeaders().getHeader(name);
}
return null;
}
@Override
public Collection<String> getHeaderNames() {
if (fileItem instanceof DiskFileItem) {
LinkedHashSet<String> headerNames = new LinkedHashSet<>();
Iterator<String> iter =
((DiskFileItem) fileItem).getHeaders().getHeaderNames();
while (iter.hasNext()) {
headerNames.add(iter.next());
}
return headerNames;
}
return Collections.emptyList();
}
@Override
public Collection<String> getHeaders(String name) {
if (fileItem instanceof DiskFileItem) {
LinkedHashSet<String> headers = new LinkedHashSet<>();
Iterator<String> iter =
((DiskFileItem) fileItem).getHeaders().getHeaders(name);
while (iter.hasNext()) {
headers.add(iter.next());
}
return headers;
}
return Collections.emptyList();
}
@Override
public InputStream getInputStream() throws IOException {
return fileItem.getInputStream();
}
@Override
public String getName() {
return fileItem.getFieldName();
}
@Override
public long getSize() {
return fileItem.getSize();
}
@Override
public void write(String fileName) throws IOException {
File file = new File(fileName);
if (!file.isAbsolute()) {
file = new File(location, fileName);
}
try {
fileItem.write(file);
} catch (Exception e) {
throw new IOException(e);
}
}
public String getString(String encoding) throws UnsupportedEncodingException {
return fileItem.getString(encoding);
}
/*
* Adapted from FileUploadBase.getFileName()
*/
@Override
public String getSubmittedFileName() {
String fileName = null;
String cd = getHeader("Content-Disposition");
if (cd != null) {
String cdl = cd.toLowerCase(Locale.ENGLISH);
if (cdl.startsWith("form-data") || cdl.startsWith("attachment")) {
ParameterParser paramParser = new ParameterParser();
paramParser.setLowerCaseNames(true);
// Parameter parser can handle null input
Map<String,String> params = paramParser.parse(cd, ';');
if (params.containsKey("filename")) {
fileName = params.get("filename");
// The parser will remove surrounding '"' but will not
// unquote any \x sequences.
if (fileName != null) {
// RFC 6266. This is either a token or a quoted-string
if (fileName.indexOf('\\') > -1) {
// This is a quoted-string
fileName = HttpParser.unquote(fileName.trim());
} else {
// This is a token
fileName = fileName.trim();
}
} else {
// Even if there is no value, the parameter is present,
// so we return an empty file name rather than no file
// name.
fileName = "";
}
}
}
}
return fileName;
}
}

View File

@@ -0,0 +1,446 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.servlet.SessionTrackingMode;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.catalina.Context;
import org.apache.catalina.authenticator.AuthenticatorBase;
import org.apache.catalina.connector.Request;
import org.apache.catalina.servlet4preview.http.PushBuilder;
import org.apache.catalina.util.SessionConfig;
import org.apache.coyote.ActionCode;
import org.apache.tomcat.util.buf.HexUtils;
import org.apache.tomcat.util.buf.MessageBytes;
import org.apache.tomcat.util.collections.CaseInsensitiveKeyMap;
import org.apache.tomcat.util.http.CookieProcessor;
import org.apache.tomcat.util.http.parser.HttpParser;
import org.apache.tomcat.util.res.StringManager;
public class ApplicationPushBuilder implements PushBuilder {
private static final StringManager sm = StringManager.getManager(ApplicationPushBuilder.class);
private static final Set<String> DISALLOWED_METHODS = new HashSet<>();
static {
DISALLOWED_METHODS.add("POST");
DISALLOWED_METHODS.add("PUT");
DISALLOWED_METHODS.add("DELETE");
DISALLOWED_METHODS.add("CONNECT");
DISALLOWED_METHODS.add("OPTIONS");
DISALLOWED_METHODS.add("TRACE");
}
private final HttpServletRequest baseRequest;
private final Request catalinaRequest;
private final org.apache.coyote.Request coyoteRequest;
private final String sessionCookieName;
private final String sessionPathParameterName;
private final boolean addSessionCookie;
private final boolean addSessionPathParameter;
private final Map<String,List<String>> headers = new CaseInsensitiveKeyMap<>();
private final List<Cookie> cookies = new ArrayList<>();
private String method = "GET";
private String path;
private String queryString;
private String sessionId;
private String userName;
public ApplicationPushBuilder(Request catalinaRequest, HttpServletRequest request) {
baseRequest = request;
this.catalinaRequest = catalinaRequest;
coyoteRequest = catalinaRequest.getCoyoteRequest();
// Populate the initial list of HTTP headers
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
List<String> values = new ArrayList<>();
headers.put(headerName, values);
Enumeration<String> headerValues = request.getHeaders(headerName);
while (headerValues.hasMoreElements()) {
values.add(headerValues.nextElement());
}
}
// Remove the headers
headers.remove("if-match");
headers.remove("if-none-match");
headers.remove("if-modified-since");
headers.remove("if-unmodified-since");
headers.remove("if-range");
headers.remove("range");
headers.remove("expect");
headers.remove("authorization");
headers.remove("referer");
// Also remove the cookie header since it will be regenerated
headers.remove("cookie");
// set the referer header
StringBuffer referer = request.getRequestURL();
if (request.getQueryString() != null) {
referer.append('?');
referer.append(request.getQueryString());
}
addHeader("referer", referer.toString());
// Session
Context context = catalinaRequest.getContext();
sessionCookieName = SessionConfig.getSessionCookieName(context);
sessionPathParameterName = SessionConfig.getSessionUriParamName(context);
HttpSession session = request.getSession(false);
if (session != null) {
sessionId = session.getId();
}
if (sessionId == null) {
sessionId = request.getRequestedSessionId();
}
if (!request.isRequestedSessionIdFromCookie() && !request.isRequestedSessionIdFromURL() &&
sessionId != null) {
Set<SessionTrackingMode> sessionTrackingModes =
request.getServletContext().getEffectiveSessionTrackingModes();
addSessionCookie = sessionTrackingModes.contains(SessionTrackingMode.COOKIE);
addSessionPathParameter = sessionTrackingModes.contains(SessionTrackingMode.URL);
} else {
addSessionCookie = request.isRequestedSessionIdFromCookie();
addSessionPathParameter = request.isRequestedSessionIdFromURL();
}
// Cookies
if (request.getCookies() != null) {
for (Cookie requestCookie : request.getCookies()) {
cookies.add(requestCookie);
}
}
for (Cookie responseCookie : catalinaRequest.getResponse().getCookies()) {
if (responseCookie.getMaxAge() < 0) {
// Path information not available so can only remove based on
// name.
Iterator<Cookie> cookieIterator = cookies.iterator();
while (cookieIterator.hasNext()) {
Cookie cookie = cookieIterator.next();
if (cookie.getName().equals(responseCookie.getName())) {
cookieIterator.remove();
}
}
} else {
cookies.add(new Cookie(responseCookie.getName(), responseCookie.getValue()));
}
}
List<String> cookieValues = new ArrayList<>(1);
cookieValues.add(generateCookieHeader(cookies,
catalinaRequest.getContext().getCookieProcessor()));
headers.put("cookie", cookieValues);
// Authentication
if (catalinaRequest.getPrincipal() != null) {
if ((session == null) || catalinaRequest.getSessionInternal(false).getPrincipal() == null
|| !(context.getAuthenticator() instanceof AuthenticatorBase)
|| !((AuthenticatorBase) context.getAuthenticator()).getCache()) {
// Set a username only if there is no session cache for the principal
userName = catalinaRequest.getPrincipal().getName();
}
setHeader("authorization", "x-push");
}
}
@Override
public ApplicationPushBuilder path(String path) {
if (path.startsWith("/")) {
this.path = path;
} else {
String contextPath = baseRequest.getContextPath();
int len = contextPath.length() + path.length() + 1;
StringBuilder sb = new StringBuilder(len);
sb.append(contextPath);
sb.append('/');
sb.append(path);
this.path = sb.toString();
}
return this;
}
@Override
public String getPath() {
return path;
}
@Override
public ApplicationPushBuilder method(String method) {
String upperMethod = method.trim().toUpperCase(Locale.ENGLISH);
if (DISALLOWED_METHODS.contains(upperMethod) || upperMethod.length() == 0) {
throw new IllegalArgumentException(
sm.getString("applicationPushBuilder.methodInvalid", upperMethod));
}
// Check a token was supplied
for (char c : upperMethod.toCharArray()) {
if (!HttpParser.isToken(c)) {
throw new IllegalArgumentException(
sm.getString("applicationPushBuilder.methodNotToken", upperMethod));
}
}
this.method = method;
return this;
}
@Override
public String getMethod() {
return method;
}
@Override
public ApplicationPushBuilder queryString(String queryString) {
this.queryString = queryString;
return this;
}
@Override
public String getQueryString() {
return queryString;
}
@Override
public ApplicationPushBuilder sessionId(String sessionId) {
this.sessionId = sessionId;
return this;
}
@Override
public String getSessionId() {
return sessionId;
}
@Override
public ApplicationPushBuilder addHeader(String name, String value) {
List<String> values = headers.get(name);
if (values == null) {
values = new ArrayList<>();
headers.put(name, values);
}
values.add(value);
return this;
}
@Override
public ApplicationPushBuilder setHeader(String name, String value) {
List<String> values = headers.get(name);
if (values == null) {
values = new ArrayList<>();
headers.put(name, values);
} else {
values.clear();
}
values.add(value);
return this;
}
@Override
public ApplicationPushBuilder removeHeader(String name) {
headers.remove(name);
return this;
}
@Override
public Set<String> getHeaderNames() {
return Collections.unmodifiableSet(headers.keySet());
}
@Override
public String getHeader(String name) {
List<String> values = headers.get(name);
if (values == null) {
return null;
} else {
return values.get(0);
}
}
@Override
public void push() {
if (path == null) {
throw new IllegalStateException(sm.getString("pushBuilder.noPath"));
}
org.apache.coyote.Request pushTarget = new org.apache.coyote.Request();
pushTarget.method().setString(method);
// The next three are implied by the Javadoc getPath()
pushTarget.serverName().setString(baseRequest.getServerName());
pushTarget.setServerPort(baseRequest.getServerPort());
pushTarget.scheme().setString(baseRequest.getScheme());
// Copy headers
for (Map.Entry<String,List<String>> header : headers.entrySet()) {
for (String value : header.getValue()) {
pushTarget.getMimeHeaders().addValue(header.getKey()).setString(value);
}
}
// Path and query string
int queryIndex = path.indexOf('?');
String pushPath;
String pushQueryString = null;
if (queryIndex > -1) {
pushPath = path.substring(0, queryIndex);
if (queryIndex + 1 < path.length()) {
pushQueryString = path.substring(queryIndex + 1);
}
} else {
pushPath = path;
}
// Session ID (do this before setting the path since it may change it)
if (sessionId != null) {
if (addSessionPathParameter) {
pushPath = pushPath + ";" + sessionPathParameterName + "=" + sessionId;
pushTarget.addPathParameter(sessionPathParameterName, sessionId);
}
if (addSessionCookie) {
String sessionCookieHeader = sessionCookieName + "=" + sessionId;
MessageBytes mb = pushTarget.getMimeHeaders().getValue("cookie");
if (mb == null) {
mb = pushTarget.getMimeHeaders().addValue("cookie");
mb.setString(sessionCookieHeader);
} else {
mb.setString(mb.getString() + ";" + sessionCookieHeader);
}
}
}
// Undecoded path - just %nn encoded
pushTarget.requestURI().setString(pushPath);
pushTarget.decodedURI().setString(decode(pushPath,
catalinaRequest.getConnector().getURICharset()));
// Query string
if (pushQueryString == null && queryString != null) {
pushTarget.queryString().setString(queryString);
} else if (pushQueryString != null && queryString == null) {
pushTarget.queryString().setString(pushQueryString);
} else if (pushQueryString != null && queryString != null) {
pushTarget.queryString().setString(pushQueryString + "&" +queryString);
}
// Authorization
if (userName != null) {
pushTarget.getRemoteUser().setString(userName);
pushTarget.setRemoteUserNeedsAuthorization(true);
}
coyoteRequest.action(ActionCode.PUSH_REQUEST, pushTarget);
// Reset for next call to this method
path = null;
headers.remove("if-none-match");
headers.remove("if-modified-since");
}
// Package private so it can be tested. charsetName must be in lower case.
static String decode(String input, Charset charset) {
int start = input.indexOf('%');
int end = 0;
// Shortcut
if (start == -1) {
return input;
}
StringBuilder result = new StringBuilder(input.length());
while (start != -1) {
// Found the start of a %nn sequence. Copy everything from the last
// end to this start to the output.
result.append(input.substring(end, start));
// Advance the end 3 characters: %nn
end = start + 3;
while (end <input.length() && input.charAt(end) == '%') {
end += 3;
}
result.append(decodePercentSequence(input.substring(start, end), charset));
start = input.indexOf('%', end);
}
// Append the remaining text
result.append(input.substring(end));
return result.toString();
}
private static String decodePercentSequence(String sequence, Charset charset) {
byte[] bytes = new byte[sequence.length()/3];
for (int i = 0; i < bytes.length; i += 3) {
bytes[i] = (byte) ((HexUtils.getDec(sequence.charAt(1 + 3 * i)) << 4) +
HexUtils.getDec(sequence.charAt(2 + 3 * i)));
}
return new String(bytes, charset);
}
private static String generateCookieHeader(List<Cookie> cookies, CookieProcessor cookieProcessor) {
StringBuilder result = new StringBuilder();
boolean first = true;
for (Cookie cookie : cookies) {
if (first) {
first = false;
} else {
result.append(';');
}
// The cookie header value generated by the CookieProcessor was
// originally intended for the Set-Cookie header on the response.
// However, if passed a Cookie with just a name and value set it
// will generate an appropriate header for the Cookie header on the
// pushed request.
result.append(cookieProcessor.generateHeader(cookie));
}
return result.toString();
}
}

View File

@@ -0,0 +1,209 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestWrapper;
/**
* Wrapper around a <code>javax.servlet.ServletRequest</code>
* that transforms an application request object (which might be the original
* one passed to a servlet, or might be based on the 2.3
* <code>javax.servlet.ServletRequestWrapper</code> class)
* back into an internal <code>org.apache.catalina.Request</code>.
* <p>
* <strong>WARNING</strong>: Due to Java's lack of support for multiple
* inheritance, all of the logic in <code>ApplicationRequest</code> is
* duplicated in <code>ApplicationHttpRequest</code>. Make sure that you
* keep these two classes in synchronization when making changes!
*
* @author Craig R. McClanahan
*/
class ApplicationRequest extends ServletRequestWrapper {
// ------------------------------------------------------- Static Variables
/**
* The set of attribute names that are special for request dispatchers.
*/
protected static final String specials[] =
{ RequestDispatcher.INCLUDE_REQUEST_URI,
RequestDispatcher.INCLUDE_CONTEXT_PATH,
RequestDispatcher.INCLUDE_SERVLET_PATH,
RequestDispatcher.INCLUDE_PATH_INFO,
RequestDispatcher.INCLUDE_QUERY_STRING,
RequestDispatcher.FORWARD_REQUEST_URI,
RequestDispatcher.FORWARD_CONTEXT_PATH,
RequestDispatcher.FORWARD_SERVLET_PATH,
RequestDispatcher.FORWARD_PATH_INFO,
RequestDispatcher.FORWARD_QUERY_STRING };
// ----------------------------------------------------------- Constructors
/**
* Construct a new wrapped request around the specified servlet request.
*
* @param request The servlet request being wrapped
*/
public ApplicationRequest(ServletRequest request) {
super(request);
setRequest(request);
}
// ----------------------------------------------------- Instance Variables
/**
* The request attributes for this request. This is initialized from the
* wrapped request, but updates are allowed.
*/
protected final HashMap<String, Object> attributes = new HashMap<>();
// ------------------------------------------------- ServletRequest Methods
/**
* Override the <code>getAttribute()</code> method of the wrapped request.
*
* @param name Name of the attribute to retrieve
*/
@Override
public Object getAttribute(String name) {
synchronized (attributes) {
return attributes.get(name);
}
}
/**
* Override the <code>getAttributeNames()</code> method of the wrapped
* request.
*/
@Override
public Enumeration<String> getAttributeNames() {
synchronized (attributes) {
return Collections.enumeration(attributes.keySet());
}
}
/**
* Override the <code>removeAttribute()</code> method of the
* wrapped request.
*
* @param name Name of the attribute to remove
*/
@Override
public void removeAttribute(String name) {
synchronized (attributes) {
attributes.remove(name);
if (!isSpecial(name))
getRequest().removeAttribute(name);
}
}
/**
* Override the <code>setAttribute()</code> method of the
* wrapped request.
*
* @param name Name of the attribute to set
* @param value Value of the attribute to set
*/
@Override
public void setAttribute(String name, Object value) {
synchronized (attributes) {
attributes.put(name, value);
if (!isSpecial(name))
getRequest().setAttribute(name, value);
}
}
// ------------------------------------------ ServletRequestWrapper Methods
/**
* Set the request that we are wrapping.
*
* @param request The new wrapped request
*/
@Override
public void setRequest(ServletRequest request) {
super.setRequest(request);
// Initialize the attributes for this request
synchronized (attributes) {
attributes.clear();
Enumeration<String> names = request.getAttributeNames();
while (names.hasMoreElements()) {
String name = names.nextElement();
Object value = request.getAttribute(name);
attributes.put(name, value);
}
}
}
// ------------------------------------------------------ Protected Methods
/**
* Is this attribute name one of the special ones that is added only for
* included servlets?
*
* @param name Attribute name to be tested
*/
protected boolean isSpecial(String name) {
for (int i = 0; i < specials.length; i++) {
if (specials[i].equals(name))
return true;
}
return false;
}
}

View File

@@ -0,0 +1,183 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.util.Locale;
import javax.servlet.ServletResponse;
import javax.servlet.ServletResponseWrapper;
/**
* Wrapper around a <code>javax.servlet.ServletResponse</code>
* that transforms an application response object (which might be the original
* one passed to a servlet, or might be based on the 2.3
* <code>javax.servlet.ServletResponseWrapper</code> class)
* back into an internal <code>org.apache.catalina.Response</code>.
* <p>
* <strong>WARNING</strong>: Due to Java's lack of support for multiple
* inheritance, all of the logic in <code>ApplicationResponse</code> is
* duplicated in <code>ApplicationHttpResponse</code>. Make sure that you
* keep these two classes in synchronization when making changes!
*
* @author Craig R. McClanahan
*/
class ApplicationResponse extends ServletResponseWrapper {
// ----------------------------------------------------------- Constructors
/**
* Construct a new wrapped response around the specified servlet response.
*
* @param response The servlet response being wrapped
* @param included <code>true</code> if this response is being processed
* by a <code>RequestDispatcher.include()</code> call
*/
public ApplicationResponse(ServletResponse response, boolean included) {
super(response);
setIncluded(included);
}
// ----------------------------------------------------- Instance Variables
/**
* Is this wrapped response the subject of an <code>include()</code>
* call?
*/
protected boolean included = false;
// ------------------------------------------------ ServletResponse Methods
/**
* Disallow <code>reset()</code> calls on a included response.
*
* @exception IllegalStateException if the response has already
* been committed
*/
@Override
public void reset() {
// If already committed, the wrapped response will throw ISE
if (!included || getResponse().isCommitted())
getResponse().reset();
}
/**
* Disallow <code>setContentLength(int)</code> calls on an included
* response.
*
* @param len The new content length
*/
@Override
public void setContentLength(int len) {
if (!included)
getResponse().setContentLength(len);
}
/**
* Disallow <code>setContentLengthLong(long)</code> calls on an included
* response.
*
* @param len The new content length
*/
@Override
public void setContentLengthLong(long len) {
if (!included)
getResponse().setContentLengthLong(len);
}
/**
* Disallow <code>setContentType()</code> calls on an included response.
*
* @param type The new content type
*/
@Override
public void setContentType(String type) {
if (!included)
getResponse().setContentType(type);
}
/**
* Ignore <code>setLocale()</code> calls on an included response.
*
* @param loc The new locale
*/
@Override
public void setLocale(Locale loc) {
if (!included)
getResponse().setLocale(loc);
}
/**
* Ignore <code>setBufferSize()</code> calls on an included response.
*
* @param size The buffer size
*/
@Override
public void setBufferSize(int size) {
if (!included)
getResponse().setBufferSize(size);
}
// ----------------------------------------- ServletResponseWrapper Methods
/**
* Set the response that we are wrapping.
*
* @param response The new wrapped response
*/
@Override
public void setResponse(ServletResponse response) {
super.setResponse(response);
}
// -------------------------------------------------------- Package Methods
/**
* Set the included flag for this response.
*
* @param included The new included flag
*/
void setIncluded(boolean included) {
this.included = included;
}
}

View File

@@ -0,0 +1,228 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletRegistration;
import javax.servlet.ServletSecurityElement;
import org.apache.catalina.Context;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.Wrapper;
import org.apache.catalina.util.ParameterMap;
import org.apache.tomcat.util.buf.UDecoder;
import org.apache.tomcat.util.res.StringManager;
public class ApplicationServletRegistration
implements ServletRegistration.Dynamic {
/**
* The string manager for this package.
*/
private static final StringManager sm =
StringManager.getManager(Constants.Package);
private final Wrapper wrapper;
private final Context context;
private ServletSecurityElement constraint;
public ApplicationServletRegistration(Wrapper wrapper,
Context context) {
this.wrapper = wrapper;
this.context = context;
}
@Override
public String getClassName() {
return wrapper.getServletClass();
}
@Override
public String getInitParameter(String name) {
return wrapper.findInitParameter(name);
}
@Override
public Map<String, String> getInitParameters() {
ParameterMap<String,String> result = new ParameterMap<>();
String[] parameterNames = wrapper.findInitParameters();
for (String parameterName : parameterNames) {
result.put(parameterName, wrapper.findInitParameter(parameterName));
}
result.setLocked(true);
return result;
}
@Override
public String getName() {
return wrapper.getName();
}
@Override
public boolean setInitParameter(String name, String value) {
if (name == null || value == null) {
throw new IllegalArgumentException(
sm.getString("applicationFilterRegistration.nullInitParam",
name, value));
}
if (getInitParameter(name) != null) {
return false;
}
wrapper.addInitParameter(name, value);
return true;
}
@Override
public Set<String> setInitParameters(Map<String, String> initParameters) {
Set<String> conflicts = new HashSet<>();
for (Map.Entry<String, String> entry : initParameters.entrySet()) {
if (entry.getKey() == null || entry.getValue() == null) {
throw new IllegalArgumentException(sm.getString(
"applicationFilterRegistration.nullInitParams",
entry.getKey(), entry.getValue()));
}
if (getInitParameter(entry.getKey()) != null) {
conflicts.add(entry.getKey());
}
}
// Have to add in a separate loop since spec requires no updates at all
// if there is an issue
if (conflicts.isEmpty()) {
for (Map.Entry<String, String> entry : initParameters.entrySet()) {
setInitParameter(entry.getKey(), entry.getValue());
}
}
return conflicts;
}
@Override
public void setAsyncSupported(boolean asyncSupported) {
wrapper.setAsyncSupported(asyncSupported);
}
@Override
public void setLoadOnStartup(int loadOnStartup) {
wrapper.setLoadOnStartup(loadOnStartup);
}
@Override
public void setMultipartConfig(MultipartConfigElement multipartConfig) {
wrapper.setMultipartConfigElement(multipartConfig);
}
@Override
public void setRunAsRole(String roleName) {
wrapper.setRunAs(roleName);
}
@Override
public Set<String> setServletSecurity(ServletSecurityElement constraint) {
if (constraint == null) {
throw new IllegalArgumentException(sm.getString(
"applicationServletRegistration.setServletSecurity.iae",
getName(), context.getName()));
}
if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
throw new IllegalStateException(sm.getString(
"applicationServletRegistration.setServletSecurity.ise",
getName(), context.getName()));
}
this.constraint = constraint;
return context.addServletSecurity(this, constraint);
}
@Override
public Set<String> addMapping(String... urlPatterns) {
if (urlPatterns == null) {
return Collections.emptySet();
}
Set<String> conflicts = new HashSet<>();
for (String urlPattern : urlPatterns) {
String wrapperName = context.findServletMapping(urlPattern);
if (wrapperName != null) {
Wrapper wrapper = (Wrapper) context.findChild(wrapperName);
if (wrapper.isOverridable()) {
// Some Wrappers (from global and host web.xml) may be
// overridden rather than generating a conflict
context.removeServletMapping(urlPattern);
} else {
conflicts.add(urlPattern);
}
}
}
if (!conflicts.isEmpty()) {
return conflicts;
}
for (String urlPattern : urlPatterns) {
context.addServletMappingDecoded(
UDecoder.URLDecode(urlPattern, StandardCharsets.UTF_8), wrapper.getName());
}
if (constraint != null) {
context.addServletSecurity(this, constraint);
}
return Collections.emptySet();
}
@Override
public Collection<String> getMappings() {
Set<String> result = new HashSet<>();
String servletName = wrapper.getName();
String[] urlPatterns = context.findServletMappings();
for (String urlPattern : urlPatterns) {
String name = context.findServletMapping(urlPattern);
if (name.equals(servletName)) {
result.add(urlPattern);
}
}
return result;
}
@Override
public String getRunAsRole() {
return wrapper.getRunAs();
}
}

View File

@@ -0,0 +1,204 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import javax.servlet.SessionCookieConfig;
import javax.servlet.http.Cookie;
import org.apache.catalina.Context;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.util.SessionConfig;
import org.apache.tomcat.util.res.StringManager;
public class ApplicationSessionCookieConfig implements SessionCookieConfig {
/**
* The string manager for this package.
*/
private static final StringManager sm = StringManager
.getManager(Constants.Package);
private boolean httpOnly;
private boolean secure;
private int maxAge = -1;
private String comment;
private String domain;
private String name;
private String path;
private StandardContext context;
public ApplicationSessionCookieConfig(StandardContext context) {
this.context = context;
}
@Override
public String getComment() {
return comment;
}
@Override
public String getDomain() {
return domain;
}
@Override
public int getMaxAge() {
return maxAge;
}
@Override
public String getName() {
return name;
}
@Override
public String getPath() {
return path;
}
@Override
public boolean isHttpOnly() {
return httpOnly;
}
@Override
public boolean isSecure() {
return secure;
}
@Override
public void setComment(String comment) {
if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
throw new IllegalStateException(sm.getString(
"applicationSessionCookieConfig.ise", "comment",
context.getPath()));
}
this.comment = comment;
}
@Override
public void setDomain(String domain) {
if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
throw new IllegalStateException(sm.getString(
"applicationSessionCookieConfig.ise", "domain name",
context.getPath()));
}
this.domain = domain;
}
@Override
public void setHttpOnly(boolean httpOnly) {
if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
throw new IllegalStateException(sm.getString(
"applicationSessionCookieConfig.ise", "HttpOnly",
context.getPath()));
}
this.httpOnly = httpOnly;
}
@Override
public void setMaxAge(int maxAge) {
if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
throw new IllegalStateException(sm.getString(
"applicationSessionCookieConfig.ise", "max age",
context.getPath()));
}
this.maxAge = maxAge;
}
@Override
public void setName(String name) {
if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
throw new IllegalStateException(sm.getString(
"applicationSessionCookieConfig.ise", "name",
context.getPath()));
}
this.name = name;
}
@Override
public void setPath(String path) {
if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
throw new IllegalStateException(sm.getString(
"applicationSessionCookieConfig.ise", "path",
context.getPath()));
}
this.path = path;
}
@Override
public void setSecure(boolean secure) {
if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
throw new IllegalStateException(sm.getString(
"applicationSessionCookieConfig.ise", "secure",
context.getPath()));
}
this.secure = secure;
}
/**
* Creates a new session cookie for the given session ID
*
* @param context The Context for the web application
* @param sessionId The ID of the session for which the cookie will be
* created
* @param secure Should session cookie be configured as secure
* @return the cookie for the session
*/
public static Cookie createSessionCookie(Context context,
String sessionId, boolean secure) {
SessionCookieConfig scc =
context.getServletContext().getSessionCookieConfig();
// NOTE: The priority order for session cookie configuration is:
// 1. Context level configuration
// 2. Values from SessionCookieConfig
// 3. Defaults
Cookie cookie = new Cookie(
SessionConfig.getSessionCookieName(context), sessionId);
// Just apply the defaults.
cookie.setMaxAge(scc.getMaxAge());
cookie.setComment(scc.getComment());
if (context.getSessionCookieDomain() == null) {
// Avoid possible NPE
if (scc.getDomain() != null) {
cookie.setDomain(scc.getDomain());
}
} else {
cookie.setDomain(context.getSessionCookieDomain());
}
// Always set secure if the request is secure
if (scc.isSecure() || secure) {
cookie.setSecure(true);
}
// Always set httpOnly if the context is configured for that
if (scc.isHttpOnly() || context.getUseHttpOnly()) {
cookie.setHttpOnly(true);
}
cookie.setPath(SessionConfig.getSessionCookiePath(context));
return cookie;
}
}

View File

@@ -0,0 +1,428 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.jni.Library;
import org.apache.tomcat.jni.LibraryNotFoundError;
import org.apache.tomcat.jni.SSL;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.res.StringManager;
/**
* Implementation of <code>LifecycleListener</code> that will init and
* and destroy APR.
*
* @since 4.1
*/
public class AprLifecycleListener
implements LifecycleListener {
private static final Log log = LogFactory.getLog(AprLifecycleListener.class);
private static boolean instanceCreated = false;
/**
* Info messages during init() are cached until Lifecycle.BEFORE_INIT_EVENT
* so that, in normal (non-error) cases, init() related log messages appear
* at the expected point in the lifecycle.
*/
private static final List<String> initInfoLogMessages = new ArrayList<>(3);
/**
* The string manager for this package.
*/
protected static final StringManager sm =
StringManager.getManager(Constants.Package);
// ---------------------------------------------- Constants
protected static final int TCN_REQUIRED_MAJOR = 1;
protected static final int TCN_REQUIRED_MINOR = 2;
protected static final int TCN_REQUIRED_PATCH = 14;
protected static final int TCN_RECOMMENDED_MINOR = 2;
protected static final int TCN_RECOMMENDED_PV = 23;
// ---------------------------------------------- Properties
protected static String SSLEngine = "on"; //default on
protected static String FIPSMode = "off"; // default off, valid only when SSLEngine="on"
protected static String SSLRandomSeed = "builtin";
protected static boolean sslInitialized = false;
protected static boolean aprInitialized = false;
protected static boolean aprAvailable = false;
protected static boolean useAprConnector = false;
protected static boolean useOpenSSL = true;
protected static boolean fipsModeActive = false;
/**
* The "FIPS mode" level that we use as the argument to OpenSSL method
* <code>FIPS_mode_set()</code> to enable FIPS mode and that we expect as
* the return value of <code>FIPS_mode()</code> when FIPS mode is enabled.
* <p>
* In the future the OpenSSL library might grow support for different
* non-zero "FIPS" modes that specify different allowed subsets of ciphers
* or whatever, but nowadays only "1" is the supported value.
* </p>
* @see <a href="http://wiki.openssl.org/index.php/FIPS_mode_set%28%29">OpenSSL method FIPS_mode_set()</a>
* @see <a href="http://wiki.openssl.org/index.php/FIPS_mode%28%29">OpenSSL method FIPS_mode()</a>
*/
private static final int FIPS_ON = 1;
private static final int FIPS_OFF = 0;
protected static final Object lock = new Object();
public static boolean isAprAvailable() {
//https://bz.apache.org/bugzilla/show_bug.cgi?id=48613
if (instanceCreated) {
synchronized (lock) {
init();
}
}
return aprAvailable;
}
public AprLifecycleListener() {
instanceCreated = true;
}
// ---------------------------------------------- LifecycleListener Methods
/**
* Primary entry point for startup and shutdown events.
*
* @param event The event that has occurred
*/
@Override
public void lifecycleEvent(LifecycleEvent event) {
if (Lifecycle.BEFORE_INIT_EVENT.equals(event.getType())) {
synchronized (lock) {
init();
for (String msg : initInfoLogMessages) {
log.info(msg);
}
initInfoLogMessages.clear();
if (aprAvailable) {
try {
initializeSSL();
} catch (Throwable t) {
t = ExceptionUtils.unwrapInvocationTargetException(t);
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("aprListener.sslInit"), t);
}
}
// Failure to initialize FIPS mode is fatal
if (!(null == FIPSMode || "off".equalsIgnoreCase(FIPSMode)) && !isFIPSModeActive()) {
String errorMessage = sm.getString("aprListener.initializeFIPSFailed");
Error e = new Error(errorMessage);
// Log here, because thrown error might be not logged
log.fatal(errorMessage, e);
throw e;
}
}
} else if (Lifecycle.AFTER_DESTROY_EVENT.equals(event.getType())) {
synchronized (lock) {
if (!aprAvailable) {
return;
}
try {
terminateAPR();
} catch (Throwable t) {
t = ExceptionUtils.unwrapInvocationTargetException(t);
ExceptionUtils.handleThrowable(t);
log.info(sm.getString("aprListener.aprDestroy"));
}
}
}
}
private static void terminateAPR()
throws ClassNotFoundException, NoSuchMethodException,
IllegalAccessException, InvocationTargetException
{
String methodName = "terminate";
Method method = Class.forName("org.apache.tomcat.jni.Library")
.getMethod(methodName, (Class [])null);
method.invoke(null, (Object []) null);
aprAvailable = false;
aprInitialized = false;
sslInitialized = false; // Well we cleaned the pool in terminate.
fipsModeActive = false;
}
private static void init()
{
int major = 0;
int minor = 0;
int patch = 0;
int apver = 0;
int rqver = TCN_REQUIRED_MAJOR * 1000 + TCN_REQUIRED_MINOR * 100 + TCN_REQUIRED_PATCH;
int rcver = TCN_REQUIRED_MAJOR * 1000 + TCN_RECOMMENDED_MINOR * 100 + TCN_RECOMMENDED_PV;
if (aprInitialized) {
return;
}
aprInitialized = true;
try {
Library.initialize(null);
major = Library.TCN_MAJOR_VERSION;
minor = Library.TCN_MINOR_VERSION;
patch = Library.TCN_PATCH_VERSION;
apver = major * 1000 + minor * 100 + patch;
} catch (LibraryNotFoundError lnfe) {
// Library not on path
if (log.isDebugEnabled()) {
log.debug(sm.getString("aprListener.aprInitDebug",
lnfe.getLibraryNames(), System.getProperty("java.library.path"),
lnfe.getMessage()), lnfe);
}
initInfoLogMessages.add(sm.getString("aprListener.aprInit",
System.getProperty("java.library.path")));
return;
} catch (Throwable t) {
// Library present but failed to load
t = ExceptionUtils.unwrapInvocationTargetException(t);
ExceptionUtils.handleThrowable(t);
log.warn(sm.getString("aprListener.aprInitError", t.getMessage()), t);
return;
}
if (apver < rqver) {
log.error(sm.getString("aprListener.tcnInvalid", major + "."
+ minor + "." + patch,
TCN_REQUIRED_MAJOR + "." +
TCN_REQUIRED_MINOR + "." +
TCN_REQUIRED_PATCH));
try {
// Terminate the APR in case the version
// is below required.
terminateAPR();
} catch (Throwable t) {
t = ExceptionUtils.unwrapInvocationTargetException(t);
ExceptionUtils.handleThrowable(t);
}
return;
}
if (apver < rcver) {
initInfoLogMessages.add(sm.getString("aprListener.tcnVersion",
major + "." + minor + "." + patch,
TCN_REQUIRED_MAJOR + "." +
TCN_RECOMMENDED_MINOR + "." +
TCN_RECOMMENDED_PV));
}
initInfoLogMessages.add(sm.getString("aprListener.tcnValid",
major + "." + minor + "." + patch,
Library.APR_MAJOR_VERSION + "." +
Library.APR_MINOR_VERSION + "." +
Library.APR_PATCH_VERSION));
// Log APR flags
initInfoLogMessages.add(sm.getString("aprListener.flags",
Boolean.valueOf(Library.APR_HAVE_IPV6),
Boolean.valueOf(Library.APR_HAS_SENDFILE),
Boolean.valueOf(Library.APR_HAS_SO_ACCEPTFILTER),
Boolean.valueOf(Library.APR_HAS_RANDOM)));
initInfoLogMessages.add(sm.getString("aprListener.config",
Boolean.valueOf(useAprConnector),
Boolean.valueOf(useOpenSSL)));
aprAvailable = true;
}
private static void initializeSSL() throws Exception {
if ("off".equalsIgnoreCase(SSLEngine)) {
return;
}
if (sslInitialized) {
//only once per VM
return;
}
sslInitialized = true;
String methodName = "randSet";
Class<?> paramTypes[] = new Class[1];
paramTypes[0] = String.class;
Object paramValues[] = new Object[1];
paramValues[0] = SSLRandomSeed;
Class<?> clazz = Class.forName("org.apache.tomcat.jni.SSL");
Method method = clazz.getMethod(methodName, paramTypes);
method.invoke(null, paramValues);
methodName = "initialize";
paramValues[0] = "on".equalsIgnoreCase(SSLEngine)?null:SSLEngine;
method = clazz.getMethod(methodName, paramTypes);
method.invoke(null, paramValues);
if (!(null == FIPSMode || "off".equalsIgnoreCase(FIPSMode))) {
fipsModeActive = false;
final boolean enterFipsMode;
int fipsModeState = SSL.fipsModeGet();
if(log.isDebugEnabled()) {
log.debug(sm.getString("aprListener.currentFIPSMode",
Integer.valueOf(fipsModeState)));
}
if ("on".equalsIgnoreCase(FIPSMode)) {
if (fipsModeState == FIPS_ON) {
log.info(sm.getString("aprListener.skipFIPSInitialization"));
fipsModeActive = true;
enterFipsMode = false;
} else {
enterFipsMode = true;
}
} else if ("require".equalsIgnoreCase(FIPSMode)) {
if (fipsModeState == FIPS_ON) {
fipsModeActive = true;
enterFipsMode = false;
} else {
throw new IllegalStateException(
sm.getString("aprListener.requireNotInFIPSMode"));
}
} else if ("enter".equalsIgnoreCase(FIPSMode)) {
if (fipsModeState == FIPS_OFF) {
enterFipsMode = true;
} else {
throw new IllegalStateException(sm.getString(
"aprListener.enterAlreadyInFIPSMode",
Integer.valueOf(fipsModeState)));
}
} else {
throw new IllegalArgumentException(sm.getString(
"aprListener.wrongFIPSMode", FIPSMode));
}
if (enterFipsMode) {
log.info(sm.getString("aprListener.initializingFIPS"));
fipsModeState = SSL.fipsModeSet(FIPS_ON);
if (fipsModeState != FIPS_ON) {
// This case should be handled by the native method,
// but we'll make absolutely sure, here.
String message = sm.getString("aprListener.initializeFIPSFailed");
log.error(message);
throw new IllegalStateException(message);
}
fipsModeActive = true;
log.info(sm.getString("aprListener.initializeFIPSSuccess"));
}
}
log.info(sm.getString("aprListener.initializedOpenSSL", SSL.versionString()));
}
public String getSSLEngine() {
return SSLEngine;
}
public void setSSLEngine(String SSLEngine) {
if (!SSLEngine.equals(AprLifecycleListener.SSLEngine)) {
// Ensure that the SSLEngine is consistent with that used for SSL init
if (sslInitialized) {
throw new IllegalStateException(
sm.getString("aprListener.tooLateForSSLEngine"));
}
AprLifecycleListener.SSLEngine = SSLEngine;
}
}
public String getSSLRandomSeed() {
return SSLRandomSeed;
}
public void setSSLRandomSeed(String SSLRandomSeed) {
if (!SSLRandomSeed.equals(AprLifecycleListener.SSLRandomSeed)) {
// Ensure that the random seed is consistent with that used for SSL init
if (sslInitialized) {
throw new IllegalStateException(
sm.getString("aprListener.tooLateForSSLRandomSeed"));
}
AprLifecycleListener.SSLRandomSeed = SSLRandomSeed;
}
}
public String getFIPSMode() {
return FIPSMode;
}
public void setFIPSMode(String FIPSMode) {
if (!FIPSMode.equals(AprLifecycleListener.FIPSMode)) {
// Ensure that the FIPS mode is consistent with that used for SSL init
if (sslInitialized) {
throw new IllegalStateException(
sm.getString("aprListener.tooLateForFIPSMode"));
}
AprLifecycleListener.FIPSMode = FIPSMode;
}
}
public boolean isFIPSModeActive() {
return fipsModeActive;
}
public void setUseAprConnector(boolean useAprConnector) {
if (useAprConnector != AprLifecycleListener.useAprConnector) {
AprLifecycleListener.useAprConnector = useAprConnector;
}
}
public static boolean getUseAprConnector() {
return useAprConnector;
}
public void setUseOpenSSL(boolean useOpenSSL) {
if (useOpenSSL != AprLifecycleListener.useOpenSSL) {
AprLifecycleListener.useOpenSSL = useOpenSSL;
}
}
public static boolean getUseOpenSSL() {
return useOpenSSL;
}
public static boolean isInstanceCreated() {
return instanceCreated;
}
}

View File

@@ -0,0 +1,592 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.naming.NamingException;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.AsyncDispatcher;
import org.apache.catalina.Context;
import org.apache.catalina.Globals;
import org.apache.catalina.Host;
import org.apache.catalina.Valve;
import org.apache.catalina.connector.Request;
import org.apache.coyote.ActionCode;
import org.apache.coyote.AsyncContextCallback;
import org.apache.coyote.RequestInfo;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.buf.UDecoder;
import org.apache.tomcat.util.res.StringManager;
public class AsyncContextImpl implements AsyncContext, AsyncContextCallback {
private static final Log log = LogFactory.getLog(AsyncContextImpl.class);
protected static final StringManager sm =
StringManager.getManager(Constants.Package);
/* When a request uses a sequence of multiple start(); dispatch() with
* non-container threads it is possible for a previous dispatch() to
* interfere with a following start(). This lock prevents that from
* happening. It is a dedicated object as user code may lock on the
* AsyncContext so if container code also locks on that object deadlocks may
* occur.
*/
private final Object asyncContextLock = new Object();
private volatile ServletRequest servletRequest = null;
private volatile ServletResponse servletResponse = null;
private final List<AsyncListenerWrapper> listeners = new ArrayList<>();
private boolean hasOriginalRequestAndResponse = true;
private volatile Runnable dispatch = null;
private Context context = null;
// Default of 30000 (30s) is set by the connector
private long timeout = -1;
private AsyncEvent event = null;
private volatile Request request;
public AsyncContextImpl(Request request) {
if (log.isDebugEnabled()) {
logDebug("Constructor");
}
this.request = request;
}
@Override
public void complete() {
if (log.isDebugEnabled()) {
logDebug("complete ");
}
check();
request.getCoyoteRequest().action(ActionCode.ASYNC_COMPLETE, null);
}
@Override
public void fireOnComplete() {
if (log.isDebugEnabled()) {
log.debug(sm.getString("asyncContextImpl.fireOnComplete"));
}
List<AsyncListenerWrapper> listenersCopy = new ArrayList<>();
listenersCopy.addAll(listeners);
ClassLoader oldCL = context.bind(Globals.IS_SECURITY_ENABLED, null);
try {
for (AsyncListenerWrapper listener : listenersCopy) {
try {
listener.fireOnComplete(event);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.warn(sm.getString("asyncContextImpl.onCompleteError",
listener.getClass().getName()), t);
}
}
} finally {
context.fireRequestDestroyEvent(request.getRequest());
clearServletRequestResponse();
this.context.decrementInProgressAsyncCount();
context.unbind(Globals.IS_SECURITY_ENABLED, oldCL);
}
}
public boolean timeout() {
AtomicBoolean result = new AtomicBoolean();
request.getCoyoteRequest().action(ActionCode.ASYNC_TIMEOUT, result);
// Avoids NPEs during shutdown. A call to recycle will null this field.
Context context = this.context;
if (result.get()) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("asyncContextImpl.fireOnTimeout"));
}
ClassLoader oldCL = context.bind(false, null);
try {
List<AsyncListenerWrapper> listenersCopy = new ArrayList<>();
listenersCopy.addAll(listeners);
for (AsyncListenerWrapper listener : listenersCopy) {
try {
listener.fireOnTimeout(event);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.warn(sm.getString("asyncContextImpl.onTimeoutError",
listener.getClass().getName()), t);
}
}
request.getCoyoteRequest().action(
ActionCode.ASYNC_IS_TIMINGOUT, result);
} finally {
context.unbind(false, oldCL);
}
}
return !result.get();
}
@Override
public void dispatch() {
check();
String path;
String cpath;
ServletRequest servletRequest = getRequest();
if (servletRequest instanceof HttpServletRequest) {
HttpServletRequest sr = (HttpServletRequest) servletRequest;
path = sr.getRequestURI();
cpath = sr.getContextPath();
} else {
path = request.getRequestURI();
cpath = request.getContextPath();
}
if (cpath.length() > 1) {
path = path.substring(cpath.length());
}
if (!context.getDispatchersUseEncodedPaths()) {
path = UDecoder.URLDecode(path, StandardCharsets.UTF_8);
}
dispatch(path);
}
@Override
public void dispatch(String path) {
check();
dispatch(getRequest().getServletContext(), path);
}
@Override
public void dispatch(ServletContext servletContext, String path) {
synchronized (asyncContextLock) {
if (log.isDebugEnabled()) {
logDebug("dispatch ");
}
check();
if (dispatch != null) {
throw new IllegalStateException(
sm.getString("asyncContextImpl.dispatchingStarted"));
}
if (request.getAttribute(ASYNC_REQUEST_URI)==null) {
request.setAttribute(ASYNC_REQUEST_URI, request.getRequestURI());
request.setAttribute(ASYNC_CONTEXT_PATH, request.getContextPath());
request.setAttribute(ASYNC_SERVLET_PATH, request.getServletPath());
request.setAttribute(ASYNC_PATH_INFO, request.getPathInfo());
request.setAttribute(ASYNC_QUERY_STRING, request.getQueryString());
}
final RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher(path);
if (!(requestDispatcher instanceof AsyncDispatcher)) {
throw new UnsupportedOperationException(
sm.getString("asyncContextImpl.noAsyncDispatcher"));
}
final AsyncDispatcher applicationDispatcher =
(AsyncDispatcher) requestDispatcher;
final ServletRequest servletRequest = getRequest();
final ServletResponse servletResponse = getResponse();
// https://bz.apache.org/bugzilla/show_bug.cgi?id=63246
// Take a local copy as the dispatch may complete the
// request/response and that in turn may trigger recycling of this
// object before the in-progress count can be decremented
final Context context = this.context;
this.dispatch = new AsyncRunnable(
request, applicationDispatcher, servletRequest, servletResponse);
this.request.getCoyoteRequest().action(ActionCode.ASYNC_DISPATCH, null);
clearServletRequestResponse();
context.decrementInProgressAsyncCount();
}
}
@Override
public ServletRequest getRequest() {
check();
if (servletRequest == null) {
throw new IllegalStateException(
sm.getString("asyncContextImpl.request.ise"));
}
return servletRequest;
}
@Override
public ServletResponse getResponse() {
check();
if (servletResponse == null) {
throw new IllegalStateException(
sm.getString("asyncContextImpl.response.ise"));
}
return servletResponse;
}
@Override
public void start(final Runnable run) {
if (log.isDebugEnabled()) {
logDebug("start ");
}
check();
Runnable wrapper = new RunnableWrapper(run, context, this.request.getCoyoteRequest());
this.request.getCoyoteRequest().action(ActionCode.ASYNC_RUN, wrapper);
}
@Override
public void addListener(AsyncListener listener) {
check();
AsyncListenerWrapper wrapper = new AsyncListenerWrapper();
wrapper.setListener(listener);
listeners.add(wrapper);
}
@Override
public void addListener(AsyncListener listener, ServletRequest servletRequest,
ServletResponse servletResponse) {
check();
AsyncListenerWrapper wrapper = new AsyncListenerWrapper();
wrapper.setListener(listener);
wrapper.setServletRequest(servletRequest);
wrapper.setServletResponse(servletResponse);
listeners.add(wrapper);
}
@SuppressWarnings("unchecked")
@Override
public <T extends AsyncListener> T createListener(Class<T> clazz)
throws ServletException {
check();
T listener = null;
try {
listener = (T) context.getInstanceManager().newInstance(
clazz.getName(), clazz.getClassLoader());
} catch (ReflectiveOperationException | NamingException e) {
ServletException se = new ServletException(e);
throw se;
} catch (Exception e) {
ExceptionUtils.handleThrowable(e.getCause());
ServletException se = new ServletException(e);
throw se;
}
return listener;
}
public void recycle() {
if (log.isDebugEnabled()) {
logDebug("recycle ");
}
context = null;
dispatch = null;
event = null;
hasOriginalRequestAndResponse = true;
listeners.clear();
request = null;
clearServletRequestResponse();
timeout = -1;
}
private void clearServletRequestResponse() {
servletRequest = null;
servletResponse = null;
}
public boolean isStarted() {
AtomicBoolean result = new AtomicBoolean(false);
request.getCoyoteRequest().action(
ActionCode.ASYNC_IS_STARTED, result);
return result.get();
}
public void setStarted(Context context, ServletRequest request,
ServletResponse response, boolean originalRequestResponse) {
synchronized (asyncContextLock) {
this.request.getCoyoteRequest().action(
ActionCode.ASYNC_START, this);
this.context = context;
context.incrementInProgressAsyncCount();
this.servletRequest = request;
this.servletResponse = response;
this.hasOriginalRequestAndResponse = originalRequestResponse;
this.event = new AsyncEvent(this, request, response);
List<AsyncListenerWrapper> listenersCopy = new ArrayList<>();
listenersCopy.addAll(listeners);
listeners.clear();
if (log.isDebugEnabled()) {
log.debug(sm.getString("asyncContextImpl.fireOnStartAsync"));
}
for (AsyncListenerWrapper listener : listenersCopy) {
try {
listener.fireOnStartAsync(event);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.warn(sm.getString("asyncContextImpl.onStartAsyncError",
listener.getClass().getName()), t);
}
}
}
}
@Override
public boolean hasOriginalRequestAndResponse() {
check();
return hasOriginalRequestAndResponse;
}
protected void doInternalDispatch() throws ServletException, IOException {
if (log.isDebugEnabled()) {
logDebug("intDispatch");
}
try {
Runnable runnable = dispatch;
dispatch = null;
runnable.run();
if (!request.isAsync()) {
fireOnComplete();
}
} catch (RuntimeException x) {
// doInternalComplete(true);
if (x.getCause() instanceof ServletException) {
throw (ServletException)x.getCause();
}
if (x.getCause() instanceof IOException) {
throw (IOException)x.getCause();
}
throw new ServletException(x);
}
}
@Override
public long getTimeout() {
check();
return timeout;
}
@Override
public void setTimeout(long timeout) {
check();
this.timeout = timeout;
request.getCoyoteRequest().action(ActionCode.ASYNC_SETTIMEOUT,
Long.valueOf(timeout));
}
@Override
public boolean isAvailable() {
Context context = this.context;
if (context == null) {
return false;
}
return context.getState().isAvailable();
}
public void setErrorState(Throwable t, boolean fireOnError) {
if (t!=null) request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
request.getCoyoteRequest().action(ActionCode.ASYNC_ERROR, null);
if (fireOnError) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("asyncContextImpl.fireOnError"));
}
AsyncEvent errorEvent = new AsyncEvent(event.getAsyncContext(),
event.getSuppliedRequest(), event.getSuppliedResponse(), t);
List<AsyncListenerWrapper> listenersCopy = new ArrayList<>();
listenersCopy.addAll(listeners);
for (AsyncListenerWrapper listener : listenersCopy) {
try {
listener.fireOnError(errorEvent);
} catch (Throwable t2) {
ExceptionUtils.handleThrowable(t2);
log.warn(sm.getString("asyncContextImpl.onErrorError",
listener.getClass().getName()), t2);
}
}
}
AtomicBoolean result = new AtomicBoolean();
request.getCoyoteRequest().action(ActionCode.ASYNC_IS_ERROR, result);
if (result.get()) {
// No listener called dispatch() or complete(). This is an error.
// SRV.2.3.3.3 (search for "error dispatch")
// Take a local copy to avoid threading issues if another thread
// clears this (can happen during error handling with non-container
// threads)
ServletResponse servletResponse = this.servletResponse;
if (servletResponse instanceof HttpServletResponse) {
((HttpServletResponse) servletResponse).setStatus(
HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
Host host = (Host) context.getParent();
Valve stdHostValve = host.getPipeline().getBasic();
if (stdHostValve instanceof StandardHostValve) {
((StandardHostValve) stdHostValve).throwable(request,
request.getResponse(), t);
}
request.getCoyoteRequest().action(
ActionCode.ASYNC_IS_ERROR, result);
if (result.get()) {
// Still in the error state. The error page did not call
// complete() or dispatch(). Complete the async processing.
complete();
}
}
}
private void logDebug(String method) {
String rHashCode;
String crHashCode;
String rpHashCode;
String stage;
StringBuilder uri = new StringBuilder();
if (request == null) {
rHashCode = "null";
crHashCode = "null";
rpHashCode = "null";
stage = "-";
uri.append("N/A");
} else {
rHashCode = Integer.toHexString(request.hashCode());
org.apache.coyote.Request coyoteRequest = request.getCoyoteRequest();
if (coyoteRequest == null) {
crHashCode = "null";
rpHashCode = "null";
stage = "-";
} else {
crHashCode = Integer.toHexString(coyoteRequest.hashCode());
RequestInfo rp = coyoteRequest.getRequestProcessor();
if (rp == null) {
rpHashCode = "null";
stage = "-";
} else {
rpHashCode = Integer.toHexString(rp.hashCode());
stage = Integer.toString(rp.getStage());
}
}
uri.append(request.getRequestURI());
if (request.getQueryString() != null) {
uri.append('?');
uri.append(request.getQueryString());
}
}
String threadName = Thread.currentThread().getName();
int len = threadName.length();
if (len > 20) {
threadName = threadName.substring(len - 20, len);
}
String msg = String.format(
"Req: %1$8s CReq: %2$8s RP: %3$8s Stage: %4$s " +
"Thread: %5$20s State: %6$20s Method: %7$11s URI: %8$s",
rHashCode, crHashCode, rpHashCode, stage,
threadName, "N/A", method, uri);
if (log.isTraceEnabled()) {
log.trace(msg, new DebugException());
} else {
log.debug(msg);
}
}
private void check() {
if (request == null) {
// AsyncContext has been recycled and should not be being used
throw new IllegalStateException(sm.getString(
"asyncContextImpl.requestEnded"));
}
}
private static class DebugException extends Exception {
private static final long serialVersionUID = 1L;
}
private static class RunnableWrapper implements Runnable {
private final Runnable wrapped;
private final Context context;
private final org.apache.coyote.Request coyoteRequest;
public RunnableWrapper(Runnable wrapped, Context ctxt,
org.apache.coyote.Request coyoteRequest) {
this.wrapped = wrapped;
this.context = ctxt;
this.coyoteRequest = coyoteRequest;
}
@Override
public void run() {
ClassLoader oldCL = context.bind(Globals.IS_SECURITY_ENABLED, null);
try {
wrapped.run();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
context.getLogger().error(sm.getString("asyncContextImpl.asyncRunnableError"), t);
coyoteRequest.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
org.apache.coyote.Response coyoteResponse = coyoteRequest.getResponse();
coyoteResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
coyoteResponse.setError();
} finally {
context.unbind(Globals.IS_SECURITY_ENABLED, oldCL);
}
// Since this runnable is not executing as a result of a socket
// event, we need to ensure that any registered dispatches are
// executed.
coyoteRequest.action(ActionCode.DISPATCH_EXECUTE, null);
}
}
private static class AsyncRunnable implements Runnable {
private final AsyncDispatcher applicationDispatcher;
private final Request request;
private final ServletRequest servletRequest;
private final ServletResponse servletResponse;
public AsyncRunnable(Request request, AsyncDispatcher applicationDispatcher,
ServletRequest servletRequest, ServletResponse servletResponse) {
this.request = request;
this.applicationDispatcher = applicationDispatcher;
this.servletRequest = servletRequest;
this.servletResponse = servletResponse;
}
@Override
public void run() {
request.getCoyoteRequest().action(ActionCode.ASYNC_DISPATCHED, null);
try {
applicationDispatcher.dispatch(servletRequest, servletResponse);
} catch (Exception e) {
throw new RuntimeException(sm.getString("asyncContextImpl.asyncDispachError"), e);
}
}
}
}

View File

@@ -0,0 +1,81 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.io.IOException;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class AsyncListenerWrapper {
private AsyncListener listener = null;
private ServletRequest servletRequest = null;
private ServletResponse servletResponse = null;
public void fireOnStartAsync(AsyncEvent event) throws IOException {
listener.onStartAsync(customizeEvent(event));
}
public void fireOnComplete(AsyncEvent event) throws IOException {
listener.onComplete(customizeEvent(event));
}
public void fireOnTimeout(AsyncEvent event) throws IOException {
listener.onTimeout(customizeEvent(event));
}
public void fireOnError(AsyncEvent event) throws IOException {
listener.onError(customizeEvent(event));
}
public AsyncListener getListener() {
return listener;
}
public void setListener(AsyncListener listener) {
this.listener = listener;
}
public void setServletRequest(ServletRequest servletRequest) {
this.servletRequest = servletRequest;
}
public void setServletResponse(ServletResponse servletResponse) {
this.servletResponse = servletResponse;
}
private AsyncEvent customizeEvent(AsyncEvent event) {
if (servletRequest != null && servletResponse != null) {
return new AsyncEvent(event.getAsyncContext(), servletRequest, servletResponse,
event.getThrowable());
} else {
return event;
}
}
}

View File

@@ -0,0 +1,26 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
public class Constants {
public static final String Package = "org.apache.catalina.core";
public static final int MAJOR_VERSION = 3;
public static final int MINOR_VERSION = 1;
public static final String JSP_SERVLET_CLASS = "org.apache.jasper.servlet.JspServlet";
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,809 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceUnit;
import javax.xml.ws.WebServiceRef;
import org.apache.catalina.ContainerServlet;
import org.apache.catalina.Globals;
import org.apache.catalina.security.SecurityUtil;
import org.apache.catalina.util.Introspection;
import org.apache.juli.logging.Log;
import org.apache.tomcat.InstanceManager;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.collections.ManagedConcurrentWeakHashMap;
import org.apache.tomcat.util.res.StringManager;
public class DefaultInstanceManager implements InstanceManager {
// Used when there are no annotations in a class
private static final AnnotationCacheEntry[] ANNOTATIONS_EMPTY
= new AnnotationCacheEntry[0];
/**
* The string manager for this package.
*/
protected static final StringManager sm =
StringManager.getManager(Constants.Package);
private static final boolean EJB_PRESENT;
private static final boolean JPA_PRESENT;
private static final boolean WS_PRESENT;
static {
Class<?> clazz = null;
try {
clazz = Class.forName("javax.ejb.EJB");
} catch (ClassNotFoundException cnfe) {
// Expected
}
EJB_PRESENT = (clazz != null);
clazz = null;
try {
clazz = Class.forName("javax.persistence.PersistenceContext");
} catch (ClassNotFoundException cnfe) {
// Expected
}
JPA_PRESENT = (clazz != null);
clazz = null;
try {
clazz = Class.forName("javax.xml.ws.WebServiceRef");
} catch (ClassNotFoundException cnfe) {
// Expected
}
WS_PRESENT = (clazz != null);
}
private final Context context;
private final Map<String, Map<String, String>> injectionMap;
protected final ClassLoader classLoader;
protected final ClassLoader containerClassLoader;
protected final boolean privileged;
protected final boolean ignoreAnnotations;
private final Set<String> restrictedClasses;
private final ManagedConcurrentWeakHashMap<Class<?>, AnnotationCacheEntry[]> annotationCache =
new ManagedConcurrentWeakHashMap<>();
private final Map<String, String> postConstructMethods;
private final Map<String, String> preDestroyMethods;
public DefaultInstanceManager(Context context,
Map<String, Map<String, String>> injectionMap,
org.apache.catalina.Context catalinaContext,
ClassLoader containerClassLoader) {
classLoader = catalinaContext.getLoader().getClassLoader();
privileged = catalinaContext.getPrivileged();
this.containerClassLoader = containerClassLoader;
ignoreAnnotations = catalinaContext.getIgnoreAnnotations();
Log log = catalinaContext.getLogger();
Set<String> classNames = new HashSet<>();
loadProperties(classNames,
"org/apache/catalina/core/RestrictedServlets.properties",
"defaultInstanceManager.restrictedServletsResource", log);
loadProperties(classNames,
"org/apache/catalina/core/RestrictedListeners.properties",
"defaultInstanceManager.restrictedListenersResource", log);
loadProperties(classNames,
"org/apache/catalina/core/RestrictedFilters.properties",
"defaultInstanceManager.restrictedFiltersResource", log);
restrictedClasses = Collections.unmodifiableSet(classNames);
this.context = context;
this.injectionMap = injectionMap;
this.postConstructMethods = catalinaContext.findPostConstructMethods();
this.preDestroyMethods = catalinaContext.findPreDestroyMethods();
}
@Override
public Object newInstance(Class<?> clazz) throws IllegalAccessException,
InvocationTargetException, NamingException, InstantiationException,
IllegalArgumentException, NoSuchMethodException, SecurityException {
return newInstance(clazz.getConstructor().newInstance(), clazz);
}
@Override
public Object newInstance(String className) throws IllegalAccessException,
InvocationTargetException, NamingException, InstantiationException,
ClassNotFoundException, IllegalArgumentException, NoSuchMethodException, SecurityException {
Class<?> clazz = loadClassMaybePrivileged(className, classLoader);
return newInstance(clazz.getConstructor().newInstance(), clazz);
}
@Override
public Object newInstance(final String className, final ClassLoader classLoader)
throws IllegalAccessException, NamingException, InvocationTargetException,
InstantiationException, ClassNotFoundException, IllegalArgumentException,
NoSuchMethodException, SecurityException {
Class<?> clazz = classLoader.loadClass(className);
return newInstance(clazz.getConstructor().newInstance(), clazz);
}
@Override
public void newInstance(Object o)
throws IllegalAccessException, InvocationTargetException, NamingException {
newInstance(o, o.getClass());
}
private Object newInstance(Object instance, Class<?> clazz)
throws IllegalAccessException, InvocationTargetException, NamingException {
if (!ignoreAnnotations) {
Map<String, String> injections = assembleInjectionsFromClassHierarchy(clazz);
populateAnnotationsCache(clazz, injections);
processAnnotations(instance, injections);
postConstruct(instance, clazz);
}
return instance;
}
private Map<String, String> assembleInjectionsFromClassHierarchy(Class<?> clazz) {
Map<String, String> injections = new HashMap<>();
Map<String, String> currentInjections = null;
while (clazz != null) {
currentInjections = this.injectionMap.get(clazz.getName());
if (currentInjections != null) {
injections.putAll(currentInjections);
}
clazz = clazz.getSuperclass();
}
return injections;
}
@Override
public void destroyInstance(Object instance) throws IllegalAccessException,
InvocationTargetException {
if (!ignoreAnnotations) {
preDestroy(instance, instance.getClass());
}
}
/**
* Call postConstruct method on the specified instance recursively from
* deepest superclass to actual class.
*
* @param instance object to call postconstruct methods on
* @param clazz (super) class to examine for postConstruct annotation.
* @throws IllegalAccessException if postConstruct method is inaccessible.
* @throws java.lang.reflect.InvocationTargetException
* if call fails
*/
protected void postConstruct(Object instance, final Class<?> clazz)
throws IllegalAccessException, InvocationTargetException {
if (context == null) {
// No resource injection
return;
}
Class<?> superClass = clazz.getSuperclass();
if (superClass != Object.class) {
postConstruct(instance, superClass);
}
// At the end the postconstruct annotated
// method is invoked
AnnotationCacheEntry[] annotations = annotationCache.get(clazz);
for (AnnotationCacheEntry entry : annotations) {
if (entry.getType() == AnnotationCacheEntryType.POST_CONSTRUCT) {
Method postConstruct = getMethod(clazz, entry);
synchronized (postConstruct) {
boolean accessibility = postConstruct.isAccessible();
postConstruct.setAccessible(true);
postConstruct.invoke(instance);
postConstruct.setAccessible(accessibility);
}
}
}
}
/**
* Call preDestroy method on the specified instance recursively from deepest
* superclass to actual class.
*
* @param instance object to call preDestroy methods on
* @param clazz (super) class to examine for preDestroy annotation.
* @throws IllegalAccessException if preDestroy method is inaccessible.
* @throws java.lang.reflect.InvocationTargetException
* if call fails
*/
protected void preDestroy(Object instance, final Class<?> clazz)
throws IllegalAccessException, InvocationTargetException {
Class<?> superClass = clazz.getSuperclass();
if (superClass != Object.class) {
preDestroy(instance, superClass);
}
// At the end the postconstruct annotated
// method is invoked
AnnotationCacheEntry[] annotations = annotationCache.get(clazz);
if (annotations == null) {
// instance not created through the instance manager
return;
}
for (AnnotationCacheEntry entry : annotations) {
if (entry.getType() == AnnotationCacheEntryType.PRE_DESTROY) {
Method preDestroy = getMethod(clazz, entry);
synchronized (preDestroy) {
boolean accessibility = preDestroy.isAccessible();
preDestroy.setAccessible(true);
preDestroy.invoke(instance);
preDestroy.setAccessible(accessibility);
}
}
}
}
public void backgroundProcess() {
annotationCache.maintain();
}
/**
* Make sure that the annotations cache has been populated for the provided
* class.
*
* @param clazz clazz to populate annotations for
* @param injections map of injections for this class from xml deployment
* descriptor
* @throws IllegalAccessException if injection target is inaccessible
* @throws javax.naming.NamingException if value cannot be looked up in jndi
* @throws java.lang.reflect.InvocationTargetException
* if injection fails
*/
protected void populateAnnotationsCache(Class<?> clazz,
Map<String, String> injections) throws IllegalAccessException,
InvocationTargetException, NamingException {
List<AnnotationCacheEntry> annotations = null;
Set<String> injectionsMatchedToSetter = new HashSet<>();
while (clazz != null) {
AnnotationCacheEntry[] annotationsArray = annotationCache.get(clazz);
if (annotationsArray == null) {
if (annotations == null) {
annotations = new ArrayList<>();
} else {
annotations.clear();
}
// Initialize methods annotations
Method[] methods = Introspection.getDeclaredMethods(clazz);
Method postConstruct = null;
String postConstructFromXml = postConstructMethods.get(clazz.getName());
Method preDestroy = null;
String preDestroyFromXml = preDestroyMethods.get(clazz.getName());
for (Method method : methods) {
if (context != null) {
// Resource injection only if JNDI is enabled
if (injections != null && Introspection.isValidSetter(method)) {
String fieldName = Introspection.getPropertyName(method);
injectionsMatchedToSetter.add(fieldName);
if (injections.containsKey(fieldName)) {
annotations.add(new AnnotationCacheEntry(
method.getName(),
method.getParameterTypes(),
injections.get(fieldName),
AnnotationCacheEntryType.SETTER));
continue;
}
}
Resource resourceAnnotation;
Annotation ejbAnnotation;
Annotation webServiceRefAnnotation;
Annotation persistenceContextAnnotation;
Annotation persistenceUnitAnnotation;
if ((resourceAnnotation = method.getAnnotation(Resource.class)) != null) {
annotations.add(new AnnotationCacheEntry(
method.getName(),
method.getParameterTypes(),
resourceAnnotation.name(),
AnnotationCacheEntryType.SETTER));
} else if (EJB_PRESENT &&
(ejbAnnotation = method.getAnnotation(EJB.class)) != null) {
annotations.add(new AnnotationCacheEntry(
method.getName(),
method.getParameterTypes(),
((EJB) ejbAnnotation).name(),
AnnotationCacheEntryType.SETTER));
} else if (WS_PRESENT && (webServiceRefAnnotation =
method.getAnnotation(WebServiceRef.class)) != null) {
annotations.add(new AnnotationCacheEntry(
method.getName(),
method.getParameterTypes(),
((WebServiceRef) webServiceRefAnnotation).name(),
AnnotationCacheEntryType.SETTER));
} else if (JPA_PRESENT && (persistenceContextAnnotation =
method.getAnnotation(PersistenceContext.class)) != null) {
annotations.add(new AnnotationCacheEntry(
method.getName(),
method.getParameterTypes(),
((PersistenceContext) persistenceContextAnnotation).name(),
AnnotationCacheEntryType.SETTER));
} else if (JPA_PRESENT && (persistenceUnitAnnotation =
method.getAnnotation(PersistenceUnit.class)) != null) {
annotations.add(new AnnotationCacheEntry(
method.getName(),
method.getParameterTypes(),
((PersistenceUnit) persistenceUnitAnnotation).name(),
AnnotationCacheEntryType.SETTER));
}
}
postConstruct = findPostConstruct(postConstruct, postConstructFromXml, method);
preDestroy = findPreDestroy(preDestroy, preDestroyFromXml, method);
}
if (postConstruct != null) {
annotations.add(new AnnotationCacheEntry(
postConstruct.getName(),
postConstruct.getParameterTypes(), null,
AnnotationCacheEntryType.POST_CONSTRUCT));
} else if (postConstructFromXml != null) {
throw new IllegalArgumentException("Post construct method "
+ postConstructFromXml + " for class " + clazz.getName()
+ " is declared in deployment descriptor but cannot be found.");
}
if (preDestroy != null) {
annotations.add(new AnnotationCacheEntry(
preDestroy.getName(),
preDestroy.getParameterTypes(), null,
AnnotationCacheEntryType.PRE_DESTROY));
} else if (preDestroyFromXml != null) {
throw new IllegalArgumentException("Pre destroy method "
+ preDestroyFromXml + " for class " + clazz.getName()
+ " is declared in deployment descriptor but cannot be found.");
}
if (context != null) {
// Initialize fields annotations for resource injection if
// JNDI is enabled
Field[] fields = Introspection.getDeclaredFields(clazz);
for (Field field : fields) {
Resource resourceAnnotation;
Annotation ejbAnnotation;
Annotation webServiceRefAnnotation;
Annotation persistenceContextAnnotation;
Annotation persistenceUnitAnnotation;
String fieldName = field.getName();
if (injections != null && injections.containsKey(fieldName) && !injectionsMatchedToSetter.contains(fieldName)) {
annotations.add(new AnnotationCacheEntry(
fieldName, null,
injections.get(fieldName),
AnnotationCacheEntryType.FIELD));
} else if ((resourceAnnotation =
field.getAnnotation(Resource.class)) != null) {
annotations.add(new AnnotationCacheEntry(fieldName, null,
resourceAnnotation.name(), AnnotationCacheEntryType.FIELD));
} else if (EJB_PRESENT &&
(ejbAnnotation = field.getAnnotation(EJB.class)) != null) {
annotations.add(new AnnotationCacheEntry(fieldName, null,
((EJB) ejbAnnotation).name(), AnnotationCacheEntryType.FIELD));
} else if (WS_PRESENT && (webServiceRefAnnotation =
field.getAnnotation(WebServiceRef.class)) != null) {
annotations.add(new AnnotationCacheEntry(fieldName, null,
((WebServiceRef) webServiceRefAnnotation).name(),
AnnotationCacheEntryType.FIELD));
} else if (JPA_PRESENT && (persistenceContextAnnotation =
field.getAnnotation(PersistenceContext.class)) != null) {
annotations.add(new AnnotationCacheEntry(fieldName, null,
((PersistenceContext) persistenceContextAnnotation).name(),
AnnotationCacheEntryType.FIELD));
} else if (JPA_PRESENT && (persistenceUnitAnnotation =
field.getAnnotation(PersistenceUnit.class)) != null) {
annotations.add(new AnnotationCacheEntry(fieldName, null,
((PersistenceUnit) persistenceUnitAnnotation).name(),
AnnotationCacheEntryType.FIELD));
}
}
}
if (annotations.isEmpty()) {
// Use common object to save memory
annotationsArray = ANNOTATIONS_EMPTY;
} else {
annotationsArray = annotations.toArray(
new AnnotationCacheEntry[annotations.size()]);
}
synchronized (annotationCache) {
annotationCache.put(clazz, annotationsArray);
}
}
clazz = clazz.getSuperclass();
}
}
/**
* Inject resources in specified instance.
*
* @param instance instance to inject into
* @param injections map of injections for this class from xml deployment descriptor
* @throws IllegalAccessException if injection target is inaccessible
* @throws javax.naming.NamingException if value cannot be looked up in jndi
* @throws java.lang.reflect.InvocationTargetException
* if injection fails
*/
protected void processAnnotations(Object instance, Map<String, String> injections)
throws IllegalAccessException, InvocationTargetException, NamingException {
if (context == null) {
// No resource injection
return;
}
Class<?> clazz = instance.getClass();
while (clazz != null) {
AnnotationCacheEntry[] annotations = annotationCache.get(clazz);
for (AnnotationCacheEntry entry : annotations) {
if (entry.getType() == AnnotationCacheEntryType.SETTER) {
lookupMethodResource(context, instance,
getMethod(clazz, entry),
entry.getName(), clazz);
} else if (entry.getType() == AnnotationCacheEntryType.FIELD) {
lookupFieldResource(context, instance,
getField(clazz, entry),
entry.getName(), clazz);
}
}
clazz = clazz.getSuperclass();
}
}
/**
* Makes cache size available to unit tests.
*
* @return the cache size
*/
protected int getAnnotationCacheSize() {
return annotationCache.size();
}
protected Class<?> loadClassMaybePrivileged(final String className,
final ClassLoader classLoader) throws ClassNotFoundException {
Class<?> clazz;
if (SecurityUtil.isPackageProtectionEnabled()) {
try {
clazz = AccessController.doPrivileged(new PrivilegedExceptionAction<Class<?>>() {
@Override
public Class<?> run() throws Exception {
return loadClass(className, classLoader);
}
});
} catch (PrivilegedActionException e) {
Throwable t = e.getCause();
if (t instanceof ClassNotFoundException) {
throw (ClassNotFoundException) t;
}
throw new RuntimeException(t);
}
} else {
clazz = loadClass(className, classLoader);
}
checkAccess(clazz);
return clazz;
}
protected Class<?> loadClass(String className, ClassLoader classLoader)
throws ClassNotFoundException {
if (className.startsWith("org.apache.catalina")) {
return containerClassLoader.loadClass(className);
}
try {
Class<?> clazz = containerClassLoader.loadClass(className);
if (ContainerServlet.class.isAssignableFrom(clazz)) {
return clazz;
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
}
return classLoader.loadClass(className);
}
private void checkAccess(Class<?> clazz) {
if (privileged) {
return;
}
if (ContainerServlet.class.isAssignableFrom(clazz)) {
throw new SecurityException(sm.getString(
"defaultInstanceManager.restrictedContainerServlet", clazz));
}
while (clazz != null) {
if (restrictedClasses.contains(clazz.getName())) {
throw new SecurityException(sm.getString(
"defaultInstanceManager.restrictedClass", clazz));
}
clazz = clazz.getSuperclass();
}
}
/**
* Inject resources in specified field.
*
* @param context jndi context to extract value from
* @param instance object to inject into
* @param field field target for injection
* @param name jndi name value is bound under
* @param clazz class annotation is defined in
* @throws IllegalAccessException if field is inaccessible
* @throws javax.naming.NamingException if value is not accessible in naming context
*/
protected static void lookupFieldResource(Context context,
Object instance, Field field, String name, Class<?> clazz)
throws NamingException, IllegalAccessException {
Object lookedupResource;
boolean accessibility;
String normalizedName = normalize(name);
if ((normalizedName != null) && (normalizedName.length() > 0)) {
lookedupResource = context.lookup(normalizedName);
} else {
lookedupResource =
context.lookup(clazz.getName() + "/" + field.getName());
}
synchronized (field) {
accessibility = field.isAccessible();
field.setAccessible(true);
field.set(instance, lookedupResource);
field.setAccessible(accessibility);
}
}
/**
* Inject resources in specified method.
*
* @param context jndi context to extract value from
* @param instance object to inject into
* @param method field target for injection
* @param name jndi name value is bound under
* @param clazz class annotation is defined in
* @throws IllegalAccessException if method is inaccessible
* @throws javax.naming.NamingException if value is not accessible in naming context
* @throws java.lang.reflect.InvocationTargetException
* if setter call fails
*/
protected static void lookupMethodResource(Context context,
Object instance, Method method, String name, Class<?> clazz)
throws NamingException, IllegalAccessException, InvocationTargetException {
if (!Introspection.isValidSetter(method)) {
throw new IllegalArgumentException(
sm.getString("defaultInstanceManager.invalidInjection"));
}
Object lookedupResource;
boolean accessibility;
String normalizedName = normalize(name);
if ((normalizedName != null) && (normalizedName.length() > 0)) {
lookedupResource = context.lookup(normalizedName);
} else {
lookedupResource = context.lookup(
clazz.getName() + "/" + Introspection.getPropertyName(method));
}
synchronized (method) {
accessibility = method.isAccessible();
method.setAccessible(true);
method.invoke(instance, lookedupResource);
method.setAccessible(accessibility);
}
}
private static void loadProperties(Set<String> classNames, String resourceName,
String messageKey, Log log) {
Properties properties = new Properties();
ClassLoader cl = DefaultInstanceManager.class.getClassLoader();
try (InputStream is = cl.getResourceAsStream(resourceName)) {
if (is == null) {
log.error(sm.getString(messageKey, resourceName));
} else {
properties.load(is);
}
} catch (IOException ioe) {
log.error(sm.getString(messageKey, resourceName), ioe);
}
if (properties.isEmpty()) {
return;
}
for (Map.Entry<Object, Object> e : properties.entrySet()) {
if ("restricted".equals(e.getValue())) {
classNames.add(e.getKey().toString());
} else {
log.warn(sm.getString(
"defaultInstanceManager.restrictedWrongValue",
resourceName, e.getKey(), e.getValue()));
}
}
}
private static String normalize(String jndiName){
if(jndiName != null && jndiName.startsWith("java:comp/env/")){
return jndiName.substring(14);
}
return jndiName;
}
private static Method getMethod(final Class<?> clazz,
final AnnotationCacheEntry entry) {
Method result = null;
if (Globals.IS_SECURITY_ENABLED) {
result = AccessController.doPrivileged(
new PrivilegedAction<Method>() {
@Override
public Method run() {
Method result = null;
try {
result = clazz.getDeclaredMethod(
entry.getAccessibleObjectName(),
entry.getParamTypes());
} catch (NoSuchMethodException e) {
// Should never happen. On that basis don't log
// it.
}
return result;
}
});
} else {
try {
result = clazz.getDeclaredMethod(
entry.getAccessibleObjectName(), entry.getParamTypes());
} catch (NoSuchMethodException e) {
// Should never happen. On that basis don't log it.
}
}
return result;
}
private static Field getField(final Class<?> clazz,
final AnnotationCacheEntry entry) {
Field result = null;
if (Globals.IS_SECURITY_ENABLED) {
result = AccessController.doPrivileged(
new PrivilegedAction<Field>() {
@Override
public Field run() {
Field result = null;
try {
result = clazz.getDeclaredField(
entry.getAccessibleObjectName());
} catch (NoSuchFieldException e) {
// Should never happen. On that basis don't log
// it.
}
return result;
}
});
} else {
try {
result = clazz.getDeclaredField(
entry.getAccessibleObjectName());
} catch (NoSuchFieldException e) {
// Should never happen. On that basis don't log it.
}
}
return result;
}
private static Method findPostConstruct(Method currentPostConstruct,
String postConstructFromXml, Method method) {
return findLifecycleCallback(currentPostConstruct,
postConstructFromXml, method, PostConstruct.class);
}
private static Method findPreDestroy(Method currentPreDestroy,
String preDestroyFromXml, Method method) {
return findLifecycleCallback(currentPreDestroy,
preDestroyFromXml, method, PreDestroy.class);
}
private static Method findLifecycleCallback(Method currentMethod,
String methodNameFromXml, Method method,
Class<? extends Annotation> annotation) {
Method result = currentMethod;
if (methodNameFromXml != null) {
if (method.getName().equals(methodNameFromXml)) {
if (!Introspection.isValidLifecycleCallback(method)) {
throw new IllegalArgumentException(
"Invalid " + annotation.getName() + " annotation");
}
result = method;
}
} else {
if (method.isAnnotationPresent(annotation)) {
if (currentMethod != null || !Introspection.isValidLifecycleCallback(method)) {
throw new IllegalArgumentException(
"Invalid " + annotation.getName() + " annotation");
}
result = method;
}
}
return result;
}
private static final class AnnotationCacheEntry {
private final String accessibleObjectName;
private final Class<?>[] paramTypes;
private final String name;
private final AnnotationCacheEntryType type;
public AnnotationCacheEntry(String accessibleObjectName,
Class<?>[] paramTypes, String name,
AnnotationCacheEntryType type) {
this.accessibleObjectName = accessibleObjectName;
this.paramTypes = paramTypes;
this.name = name;
this.type = type;
}
public String getAccessibleObjectName() {
return accessibleObjectName;
}
public Class<?>[] getParamTypes() {
return paramTypes;
}
public String getName() {
return name;
}
public AnnotationCacheEntryType getType() {
return type;
}
}
private enum AnnotationCacheEntryType {
FIELD, SETTER, POST_CONSTRUCT, PRE_DESTROY
}
}

View File

@@ -0,0 +1,88 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
/**
* An implementation of LifeCycleListener that loads a native library into the JVM.
* <p>
* Native libraries are associated with the class loader of the class that loaded them,
* and the same library may not be loaded by more than one class loader. Due to that
* restriction, loading a native library from a Webapp's class loader makes it impossible
* for other Webapps to load the native library.
* <p>
* Loading the native library using this listener solves the issue as it is loaded
* by a shared class loader (typically the Common class loader, but may vary in some
* configurations).
*/
public class JniLifecycleListener implements LifecycleListener {
private static final Log log = LogFactory.getLog(JniLifecycleListener.class);
private String libraryName = "";
private String libraryPath = "";
@Override
public void lifecycleEvent(LifecycleEvent event) {
if (Lifecycle.BEFORE_START_EVENT.equals(event.getType())) {
if (!libraryName.isEmpty()) {
System.loadLibrary(libraryName);
log.info("Loaded native library " + libraryName);
} else if (!libraryPath.isEmpty()) {
System.load(libraryPath);
log.info("Loaded native library from " + libraryPath);
} else {
throw new IllegalArgumentException("Either libraryName or libraryPath must be set");
}
}
}
public void setLibraryName(String libraryName) {
if (!this.libraryPath.isEmpty()) {
throw new IllegalArgumentException("Either libraryName or libraryPath may be set, not both.");
}
this.libraryName = libraryName;
}
public String getLibraryName() {
return libraryName;
}
public void setLibraryPath(String libraryPath) {
if (!this.libraryName.isEmpty()) {
throw new IllegalArgumentException("Either libraryName or libraryPath may be set, not both.");
}
this.libraryPath = libraryPath;
}
public String getLibraryPath() {
return libraryPath;
}
}

View File

@@ -0,0 +1,494 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLConnection;
import java.sql.DriverManager;
import java.util.StringTokenizer;
import java.util.concurrent.ForkJoinPool;
import javax.imageio.ImageIO;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.startup.SafeForkJoinWorkerThreadFactory;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.compat.JreCompat;
import org.apache.tomcat.util.compat.JreVendor;
import org.apache.tomcat.util.res.StringManager;
import org.w3c.dom.Document;
import org.w3c.dom.ls.DOMImplementationLS;
/**
* Provide a workaround for known places where the Java Runtime environment can
* cause a memory leak or lock files.
* <p>
* Memory leaks occur when JRE code uses
* the context class loader to load a singleton as this will cause a memory leak
* if a web application class loader happens to be the context class loader at
* the time. The work-around is to initialise these singletons when Tomcat's
* common class loader is the context class loader.
* <p>
* Locked files usually occur when a resource inside a JAR is accessed without
* first disabling Jar URL connection caching. The workaround is to disable this
* caching by default.
*/
public class JreMemoryLeakPreventionListener implements LifecycleListener {
private static final Log log =
LogFactory.getLog(JreMemoryLeakPreventionListener.class);
private static final StringManager sm =
StringManager.getManager(Constants.Package);
private static final String FORK_JOIN_POOL_THREAD_FACTORY_PROPERTY =
"java.util.concurrent.ForkJoinPool.common.threadFactory";
/**
* Protect against the memory leak caused when the first call to
* <code>sun.awt.AppContext.getAppContext()</code> is triggered by a web
* application. Defaults to <code>false</code> since
* {@link java.beans.Introspector#flushCaches()} no longer uses AppContext
* from 1.7.0_02 onwards. Also, from 1.7.0_25 onwards, calling this method
* requires a graphical environment and starts an AWT thread.
*/
private boolean appContextProtection = false;
public boolean isAppContextProtection() { return appContextProtection; }
public void setAppContextProtection(boolean appContextProtection) {
this.appContextProtection = appContextProtection;
}
/**
* Protect against the memory leak caused when the first call to
* <code>java.awt.Toolkit.getDefaultToolkit()</code> is triggered
* by a web application. Defaults to <code>false</code> because a new
* Thread is launched.
*/
private boolean awtThreadProtection = false;
public boolean isAWTThreadProtection() { return awtThreadProtection; }
public void setAWTThreadProtection(boolean awtThreadProtection) {
this.awtThreadProtection = awtThreadProtection;
}
/**
* Protect against the memory leak caused when the first call to
* <code>sun.misc.GC.requestLatency(long)</code> is triggered by a web
* application. This first call will start a GC Daemon thread with the
* thread's context class loader configured to be the web application class
* loader. Defaults to <code>true</code>.
*/
private boolean gcDaemonProtection = true;
public boolean isGcDaemonProtection() { return gcDaemonProtection; }
public void setGcDaemonProtection(boolean gcDaemonProtection) {
this.gcDaemonProtection = gcDaemonProtection;
}
/**
* Protect against the memory leak caused when the first call to
* <code>javax.security.auth.Policy</code> is triggered by a web
* application. This first call populate a static variable with a reference
* to the context class loader. Defaults to <code>true</code>.
*/
private boolean securityPolicyProtection = true;
public boolean isSecurityPolicyProtection() {
return securityPolicyProtection;
}
public void setSecurityPolicyProtection(boolean securityPolicyProtection) {
this.securityPolicyProtection = securityPolicyProtection;
}
/**
* Protects against the memory leak caused when the first call to
* <code>javax.security.auth.login.Configuration</code> is triggered by a
* web application. This first call populate a static variable with a
* reference to the context class loader. Defaults to <code>true</code>.
*/
private boolean securityLoginConfigurationProtection = true;
public boolean isSecurityLoginConfigurationProtection() {
return securityLoginConfigurationProtection;
}
public void setSecurityLoginConfigurationProtection(
boolean securityLoginConfigurationProtection) {
this.securityLoginConfigurationProtection = securityLoginConfigurationProtection;
}
/**
* Protect against the memory leak, when the initialization of the
* Java Cryptography Architecture is triggered by initializing
* a MessageDigest during web application deployment.
* This will occasionally start a Token Poller thread with the thread's
* context class loader equal to the web application class loader.
* Instead we initialize JCA early.
* Defaults to <code>true</code>.
*/
private boolean tokenPollerProtection = true;
public boolean isTokenPollerProtection() { return tokenPollerProtection; }
public void setTokenPollerProtection(boolean tokenPollerProtection) {
this.tokenPollerProtection = tokenPollerProtection;
}
/**
* Protect against resources being read for JAR files and, as a side-effect,
* the JAR file becoming locked. Note this disables caching for all
* {@link URLConnection}s, regardless of type. Defaults to
* <code>true</code>.
*/
private boolean urlCacheProtection = true;
public boolean isUrlCacheProtection() { return urlCacheProtection; }
public void setUrlCacheProtection(boolean urlCacheProtection) {
this.urlCacheProtection = urlCacheProtection;
}
/**
* XML parsing can pin a web application class loader in memory. There are
* multiple root causes for this. Some of these are particularly nasty as
* profilers may not identify any GC roots related to the leak. For example,
* with YourKit you need to ensure that HPROF format memory snapshots are
* used to be able to trace some of the leaks.
*/
private boolean xmlParsingProtection = true;
public boolean isXmlParsingProtection() { return xmlParsingProtection; }
public void setXmlParsingProtection(boolean xmlParsingProtection) {
this.xmlParsingProtection = xmlParsingProtection;
}
/**
* <code>com.sun.jndi.ldap.LdapPoolManager</code> class spawns a thread when
* it is initialized if the system property
* <code>com.sun.jndi.ldap.connect.pool.timeout</code> is greater than 0.
* That thread inherits the context class loader of the current thread, so
* that there may be a web application class loader leak if the web app
* is the first to use <code>LdapPoolManager</code>.
*/
private boolean ldapPoolProtection = true;
public boolean isLdapPoolProtection() { return ldapPoolProtection; }
public void setLdapPoolProtection(boolean ldapPoolProtection) {
this.ldapPoolProtection = ldapPoolProtection;
}
/**
* The first access to {@link DriverManager} will trigger the loading of
* all {@link java.sql.Driver}s in the the current class loader. The web
* application level memory leak protection can take care of this in most
* cases but triggering the loading here has fewer side-effects.
*/
private boolean driverManagerProtection = true;
public boolean isDriverManagerProtection() {
return driverManagerProtection;
}
public void setDriverManagerProtection(boolean driverManagerProtection) {
this.driverManagerProtection = driverManagerProtection;
}
/**
* {@link ForkJoinPool} creates a thread pool that, by default,
* creates threads that retain references to the thread context class
* loader.
*/
private boolean forkJoinCommonPoolProtection = true;
public boolean getForkJoinCommonPoolProtection() {
return forkJoinCommonPoolProtection;
}
public void setForkJoinCommonPoolProtection(boolean forkJoinCommonPoolProtection) {
this.forkJoinCommonPoolProtection = forkJoinCommonPoolProtection;
}
/**
* List of comma-separated fully qualified class names to load and initialize during
* the startup of this Listener. This allows to pre-load classes that are known to
* provoke classloader leaks if they are loaded during a request processing.
*/
private String classesToInitialize = null;
public String getClassesToInitialize() {
return classesToInitialize;
}
public void setClassesToInitialize(String classesToInitialize) {
this.classesToInitialize = classesToInitialize;
}
@Override
public void lifecycleEvent(LifecycleEvent event) {
// Initialise these classes when Tomcat starts
if (Lifecycle.BEFORE_INIT_EVENT.equals(event.getType())) {
/*
* First call to this loads all drivers visible to the current class
* loader and its parents.
*
* Note: This is called before the context class loader is changed
* because we want any drivers located in CATALINA_HOME/lib
* and/or CATALINA_HOME/lib to be visible to DriverManager.
* Users wishing to avoid having JDBC drivers loaded by this
* class loader should add the JDBC driver(s) to the class
* path so they are loaded by the system class loader.
*/
if (driverManagerProtection) {
DriverManager.getDrivers();
}
ClassLoader loader = Thread.currentThread().getContextClassLoader();
try
{
// Use the system classloader as the victim for all this
// ClassLoader pinning we're about to do.
Thread.currentThread().setContextClassLoader(
ClassLoader.getSystemClassLoader());
/*
* Several components end up calling:
* sun.awt.AppContext.getAppContext()
*
* Those libraries / components known to trigger memory leaks
* due to eventual calls to getAppContext() are:
* - Google Web Toolkit via its use of javax.imageio
* - Tomcat via its use of java.beans.Introspector.flushCaches()
* in 1.7.0 to 1.7.0_01. From 1.7.0_02 onwards use of
* AppContext by Introspector.flushCaches() was replaced with
* ThreadGroupContext
* - others TBD
*
* From 1.7.0_25 onwards, a call to
* sun.awt.AppContext.getAppContext() results in a thread being
* started named AWT-AppKit that requires a graphic environment
* to be available.
*/
// Trigger a call to sun.awt.AppContext.getAppContext(). This
// will pin the system class loader in memory but that shouldn't
// be an issue.
if (appContextProtection && !JreCompat.isJre8Available()) {
ImageIO.getCacheDirectory();
}
// Trigger the creation of the AWT (AWT-Windows, AWT-XAWT,
// etc.) thread
if (awtThreadProtection && !JreCompat.isJre9Available()) {
java.awt.Toolkit.getDefaultToolkit();
}
/*
* Several components end up calling
* sun.misc.GC.requestLatency(long) which creates a daemon
* thread without setting the TCCL.
*
* Those libraries / components known to trigger memory leaks
* due to eventual calls to requestLatency(long) are:
* - javax.management.remote.rmi.RMIConnectorServer.start()
*
* Note: Long.MAX_VALUE is a special case that causes the thread
* to terminate
*
*/
if (gcDaemonProtection && !JreCompat.isJre9Available()) {
try {
Class<?> clazz = Class.forName("sun.misc.GC");
Method method = clazz.getDeclaredMethod(
"requestLatency",
new Class[] {long.class});
method.invoke(null, Long.valueOf(Long.MAX_VALUE - 1));
} catch (ClassNotFoundException e) {
if (JreVendor.IS_ORACLE_JVM) {
log.error(sm.getString(
"jreLeakListener.gcDaemonFail"), e);
} else {
log.debug(sm.getString(
"jreLeakListener.gcDaemonFail"), e);
}
} catch (SecurityException | NoSuchMethodException | IllegalArgumentException |
IllegalAccessException e) {
log.error(sm.getString("jreLeakListener.gcDaemonFail"),
e);
} catch (InvocationTargetException e) {
ExceptionUtils.handleThrowable(e.getCause());
log.error(sm.getString("jreLeakListener.gcDaemonFail"),
e);
}
}
/*
* Calling getPolicy retains a static reference to the context
* class loader.
*/
if (securityPolicyProtection && !JreCompat.isJre8Available()) {
try {
// Policy.getPolicy();
Class<?> policyClass = Class
.forName("javax.security.auth.Policy");
Method method = policyClass.getMethod("getPolicy");
method.invoke(null);
} catch(ClassNotFoundException e) {
// Ignore. The class is deprecated.
} catch(SecurityException e) {
// Ignore. Don't need call to getPolicy() to be
// successful, just need to trigger static initializer.
} catch (NoSuchMethodException e) {
log.warn(sm.getString("jreLeakListener.authPolicyFail"),
e);
} catch (IllegalArgumentException e) {
log.warn(sm.getString("jreLeakListener.authPolicyFail"),
e);
} catch (IllegalAccessException e) {
log.warn(sm.getString("jreLeakListener.authPolicyFail"),
e);
} catch (InvocationTargetException e) {
ExceptionUtils.handleThrowable(e.getCause());
log.warn(sm.getString("jreLeakListener.authPolicyFail"),
e);
}
}
/*
* Initializing javax.security.auth.login.Configuration retains a static reference to the context
* class loader.
*/
if (securityLoginConfigurationProtection && !JreCompat.isJre8Available()) {
try {
Class.forName("javax.security.auth.login.Configuration", true, ClassLoader.getSystemClassLoader());
} catch(ClassNotFoundException e) {
// Ignore
}
}
/*
* Creating a MessageDigest during web application startup
* initializes the Java Cryptography Architecture. Under certain
* conditions this starts a Token poller thread with TCCL equal
* to the web application class loader.
*
* Instead we initialize JCA right now.
*
* Fixed in Java 9 onwards (from early access build 133)
*/
if (tokenPollerProtection && !JreCompat.isJre9Available()) {
java.security.Security.getProviders();
}
/*
* Several components end up opening JarURLConnections without
* first disabling caching. This effectively locks the file.
* Whilst more noticeable and harder to ignore on Windows, it
* affects all operating systems.
*
* Those libraries/components known to trigger this issue
* include:
* - log4j versions 1.2.15 and earlier
* - javax.xml.bind.JAXBContext.newInstance()
*
* Java 9 onwards disables caching for JAR URLConnections
* Java 8 and earlier disables caching for all URLConnections
*/
// Set the default URL caching policy to not to cache
if (urlCacheProtection) {
try {
JreCompat.getInstance().disableCachingForJarUrlConnections();
} catch (IOException e) {
log.error(sm.getString("jreLeakListener.jarUrlConnCacheFail"), e);
}
}
/*
* Fixed in Java 9 onwards (from early access build 133)
*/
if (xmlParsingProtection && !JreCompat.isJre9Available()) {
// There are two known issues with XML parsing that affect
// Java 7+. The issues both relate to cached Exception
// instances that retain a link to the TCCL via the
// backtrace field. Note that YourKit only shows this field
// when using the HPROF format memory snapshots.
// https://bz.apache.org/bugzilla/show_bug.cgi?id=58486
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder documentBuilder = factory.newDocumentBuilder();
// Issue 1
// com.sun.org.apache.xml.internal.serialize.DOMSerializerImpl
Document document = documentBuilder.newDocument();
document.createElement("dummy");
DOMImplementationLS implementation =
(DOMImplementationLS)document.getImplementation();
implementation.createLSSerializer().writeToString(document);
// Issue 1
// com.sun.org.apache.xerces.internal.dom.DOMNormalizer
document.normalize();
} catch (ParserConfigurationException e) {
log.error(sm.getString("jreLeakListener.xmlParseFail"),
e);
}
}
if (ldapPoolProtection && !JreCompat.isJre9Available()) {
try {
Class.forName("com.sun.jndi.ldap.LdapPoolManager");
} catch (ClassNotFoundException e) {
if (JreVendor.IS_ORACLE_JVM) {
log.error(sm.getString(
"jreLeakListener.ldapPoolManagerFail"), e);
} else {
log.debug(sm.getString(
"jreLeakListener.ldapPoolManagerFail"), e);
}
}
}
/*
* Present in Java 7 onwards
* Work-around only available in Java 8.
* Fixed in Java 9 (from early access build 156)
*/
if (forkJoinCommonPoolProtection && JreCompat.isJre8Available() &&
!JreCompat.isJre9Available()) {
// Don't override any explicitly set property
if (System.getProperty(FORK_JOIN_POOL_THREAD_FACTORY_PROPERTY) == null) {
System.setProperty(FORK_JOIN_POOL_THREAD_FACTORY_PROPERTY,
SafeForkJoinWorkerThreadFactory.class.getName());
}
}
if (classesToInitialize != null) {
StringTokenizer strTok =
new StringTokenizer(classesToInitialize, ", \r\n\t");
while (strTok.hasMoreTokens()) {
String classNameToLoad = strTok.nextToken();
try {
Class.forName(classNameToLoad);
} catch (ClassNotFoundException e) {
log.error(
sm.getString("jreLeakListener.classToInitializeFail",
classNameToLoad), e);
// continue with next class to load
}
}
}
} finally {
Thread.currentThread().setContextClassLoader(loader);
}
}
}
}

View File

@@ -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.
applicationContext.addFilter.ise=Filters cannot be added to context [{0}] as the context has been initialised
applicationContext.addJspFile.iae=The JSP file [{0}] is not valid
applicationContext.addListener.iae.cnfe=Unable to create an instance of type [{0}]
applicationContext.addListener.iae.init=Unable to add an instance of type [{0}] as a listener
applicationContext.addListener.iae.sclNotAllowed=Once the first ServletContextListener has been called, no more ServletContextListeners may be added.
applicationContext.addListener.iae.wrongType=The type specified [{0}] is not one of the expected listener types
applicationContext.addListener.ise=Listeners cannot be added to context [{0}] as the context has been initialised
applicationContext.addRole.ise=Roles cannot be added to context [{0}] as the context has been initialised
applicationContext.addServlet.ise=Servlets cannot be added to context [{0}] as the context has been initialised
applicationContext.attributeEvent=Exception thrown by attributes event listener
applicationContext.illegalDispatchPath=An application attempted to obtain a request dispatcher with an illegal path [{0}] that was rejected because it contained an encoded directory traversal attempt
applicationContext.invalidFilterName=Unable to add filter definition due to invalid filter name [{0}].
applicationContext.invalidServletName=Unable to add servlet definition due to invalid servlet name [{0}].
applicationContext.lookup.error=Failed to locate resource [{0}] in context [{1}]
applicationContext.mapping.error=Error during mapping
applicationContext.requestDispatcher.iae=Path [{0}] does not start with a "/" character
applicationContext.resourcePaths.iae=Path [{0}] does not start with a "/" character
applicationContext.role.iae=An individual role to declare for context [{0}] may not be null nor the empty string
applicationContext.roles.iae=Array of roles to declare for context [{0}] cannot be null
applicationContext.setAttribute.namenull=Name cannot be null
applicationContext.setInitParam.ise=Initialization parameters cannot be set after the context has been initialized
applicationContext.setRequestEncoding.ise=The request encoding cannot be set for context [{0}] as the context has been initialised
applicationContext.setResponseEncoding.ise=The response encoding cannot be set for context [{0}] as the context has been initialised
applicationContext.setSessionTimeout.ise=The session timeout cannot be set for context [{0}] as the context has been initialised
applicationContext.setSessionTracking.iae.invalid=The session tracking mode [{0}] requested for context [{1}] is not supported by that context
applicationContext.setSessionTracking.iae.ssl=The session tracking modes requested for context [{0}] included SSL and at least one other mode. SSL may not be configured with other modes.
applicationContext.setSessionTracking.ise=The session tracking modes for context [{0}] cannot be set whilst the context is running
applicationDispatcher.allocateException=Allocate exception for servlet [{0}]
applicationDispatcher.deallocateException=Deallocate exception for servlet [{0}]
applicationDispatcher.forward.ise=Cannot forward after response has been committed
applicationDispatcher.isUnavailable=Servlet [{0}] is currently unavailable
applicationDispatcher.serviceException=Servlet.service() for servlet [{0}] threw exception
applicationDispatcher.specViolation.request=Original ServletRequest or wrapped original ServletRequest not passed to RequestDispatcher in violation of SRV.8.2 and SRV.14.2.5.1
applicationDispatcher.specViolation.response=Original ServletResponse or wrapped original ServletResponse not passed to RequestDispatcher in violation of SRV.8.2 and SRV.14.2.5.1
applicationFilterConfig.jmxRegisterFail=JMX registration failed for filter of type [{0}] and name [{1}]
applicationFilterConfig.jmxUnregister=JMX de-registration complete for filter of type [{0}] and name [{1}]
applicationFilterConfig.jmxUnregisterFail=JMX de-registration failed for filter of type [{0}] and name [{1}]
applicationFilterConfig.preDestroy=Failed the call to preDestroy for the filter named [{0}] of type [{1}]
applicationFilterConfig.release=Failed to destroy the filter named [{0}] of type [{1}]
applicationFilterRegistration.nullInitParam=Unable to set initialisation parameter for filter due to null name and/or value. Name [{0}], Value [{1}]
applicationFilterRegistration.nullInitParams=Unable to set initialisation parameters for filter due to null name and/or value. Name [{0}], Value [{1}]
applicationHttpRequest.fragmentInDispatchPath=The fragment in dispatch path [{0}] has been removed
applicationPushBuilder.methodInvalid=The HTTP method for a push request must be both cacheable and safe but [{0}] is not
applicationPushBuilder.methodNotToken=HTTP methods must be tokens but [{0}] contains a non-token character
applicationPushBuilder.noCoyoteRequest=Unable to find the underlying Coyote request object (which is required to create a push request) from the request of type [{0}]
applicationServletRegistration.setServletSecurity.iae=Null constraint specified for servlet [{0}] deployed to context with name [{1}]
applicationServletRegistration.setServletSecurity.ise=Security constraints can''t be added to servlet [{0}] deployed to context with name [{1}] as the context has already been initialised
applicationSessionCookieConfig.ise=Property [{0}] cannot be added to SessionCookieConfig for context [{1}] as the context has been initialised
aprListener.aprDestroy=Failed shutdown of APR based Apache Tomcat Native library
aprListener.aprInit=The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [{0}]
aprListener.aprInitDebug=The APR based Apache Tomcat Native library could not be found using names [{0}] on the java.library.path [{1}]. The errors reported were [{2}]
aprListener.aprInitError=The APR based Apache Tomcat Native library failed to load. The error reported was [{0}]
aprListener.config=APR/OpenSSL configuration: useAprConnector [{0}], useOpenSSL [{1}]
aprListener.currentFIPSMode=Current FIPS mode: [{0}]
aprListener.enterAlreadyInFIPSMode=AprLifecycleListener is configured to force entering FIPS mode, but library is already in FIPS mode [{0}]
aprListener.flags=APR capabilities: IPv6 [{0}], sendfile [{1}], accept filters [{2}], random [{3}].
aprListener.initializeFIPSFailed=Failed to enter FIPS mode
aprListener.initializeFIPSSuccess=Successfully entered FIPS mode
aprListener.initializedOpenSSL=OpenSSL successfully initialized [{0}]
aprListener.initializingFIPS=Initializing FIPS mode...
aprListener.requireNotInFIPSMode=AprLifecycleListener is configured to require the library to already be in FIPS mode, but it was not in FIPS mode
aprListener.skipFIPSInitialization=Already in FIPS mode; skipping FIPS initialization.
aprListener.sslInit=Failed to initialize the SSLEngine.
aprListener.tcnInvalid=An incompatible version [{0}] of the APR based Apache Tomcat Native library is installed, while Tomcat requires version [{1}]
aprListener.tcnValid=Loaded APR based Apache Tomcat Native library [{0}] using APR version [{1}].
aprListener.tcnVersion=An older version [{0}] of the APR based Apache Tomcat Native library is installed, while Tomcat recommends a minimum version of [{1}]
aprListener.tooLateForFIPSMode=Cannot setFIPSMode: SSL has already been initialized
aprListener.tooLateForSSLEngine=Cannot setSSLEngine: SSL has already been initialized
aprListener.tooLateForSSLRandomSeed=Cannot setSSLRandomSeed: SSL has already been initialized
aprListener.wrongFIPSMode=Unexpected value of FIPSMode option of AprLifecycleListener: [{0}]
asyncContextImpl.asyncDispachError=Error during asynchronous dispatch
asyncContextImpl.asyncRunnableError=Error during processing of asynchronous Runnable via AsyncContext.start()
asyncContextImpl.dispatchingStarted=Asynchronous dispatch operation has already been called. Additional asynchronous dispatch operation within the same asynchronous cycle is not allowed.
asyncContextImpl.fireOnComplete=Firing onComplete() event for any AsyncListeners
asyncContextImpl.fireOnError=Firing onError() event for any AsyncListeners
asyncContextImpl.fireOnStartAsync=Firing onStartAsync() event for any AsyncListeners
asyncContextImpl.fireOnTimeout=Firing onTimeout() event for any AsyncListeners
asyncContextImpl.noAsyncDispatcher=The dispatcher returned from the ServletContext does not support asynchronous dispatching
asyncContextImpl.onCompleteError=onComplete() call failed for listener of type [{0}]
asyncContextImpl.onErrorError=onError() call failed for listener of type [{0}]
asyncContextImpl.onStartAsyncError=onStartAsync() call failed for listener of type [{0}]
asyncContextImpl.onTimeoutError=onTimeout() call failed for listener of type [{0}]
asyncContextImpl.request.ise=It is illegal to call getRequest() after complete() or any of the dispatch() methods has been called
asyncContextImpl.requestEnded=The request associated with the AsyncContext has already completed processing.
asyncContextImpl.response.ise=It is illegal to call getResponse() after complete() or any of the dispatch() methods has been called
containerBase.backgroundProcess.cluster=Exception processing cluster [{0}] background process
containerBase.backgroundProcess.realm=Exception processing realm [{0}] background process
containerBase.backgroundProcess.unexpectedThreadDeath=Unexpected death of background thread [{0}]
containerBase.backgroundProcess.valve=Exception processing valve [{0}] background process
containerBase.nullName=Container name cannot be null
containerBase.threadedStartFailed=A child container failed during start
containerBase.threadedStopFailed=A child container failed during stop
defaultInstanceManager.invalidInjection=Invalid method resource injection annotation
defaultInstanceManager.restrictedClass=Access to class [{0}] is forbidden. It is a restricted class. A web application must be configured as privileged to be able to load it
defaultInstanceManager.restrictedContainerServlet=Access to class [{0}] is forbidden. It is a restricted class (implements ContainerServlet interface). A web application must be configured as privileged to be able to load it
defaultInstanceManager.restrictedFiltersResource=Restricted filters property file not found [{0}]
defaultInstanceManager.restrictedListenersResource=Restricted listeners property file not found [{0}]
defaultInstanceManager.restrictedServletsResource=Restricted servlets property file not found [{0}]
defaultInstanceManager.restrictedWrongValue=Wrong value in restricted classes property file [{0}] for class name [{1}]. Expected value: [restricted], actual value: [{2}]
filterChain.filter=Filter execution threw an exception
filterChain.servlet=Servlet execution threw an exception
jreLeakListener.authPolicyFail=Error whilst attempting to prevent memory leak in javax.security.auth.Policy class
jreLeakListener.classToInitializeFail=Failed to load class [{0}] during Tomcat start to prevent possible memory leaks.
jreLeakListener.gcDaemonFail=Failed to trigger creation of the GC Daemon thread during Tomcat start to prevent possible memory leaks. This is expected on non-Sun JVMs.
jreLeakListener.jarUrlConnCacheFail=Failed to disable Jar URL connection caching by default
jreLeakListener.ldapPoolManagerFail=Failed to trigger creation of the com.sun.jndi.ldap.LdapPoolManager class during Tomcat start to prevent possible memory leaks. This is expected on non-Sun JVMs.
jreLeakListener.xmlParseFail=Error whilst attempting to prevent memory leaks during XML parsing
naming.addEnvEntry=Adding environment entry [{0}]
naming.addResourceEnvRef=Adding resource env ref [{0}]
naming.bindFailed=Failed to bind object: [{0}]
naming.invalidEnvEntryType=Environment entry [{0}] has an invalid type
naming.invalidEnvEntryValue=Environment entry [{0}] has an invalid value
naming.jmxRegistrationFailed=Failed to register in JMX: [{0}]
naming.namingContextCreationFailed=Creation of the naming context failed: [{0}]
naming.unbindFailed=Failed to unbind object: [{0}]
naming.wsdlFailed=Failed to find wsdl file: [{0}]
noPluggabilityServletContext.notAllowed=Section 4.4 of the Servlet 3.0 specification does not permit this method to be called from a ServletContextListener that was not defined in web.xml, a web-fragment.xml file nor annotated with @WebListener
pushBuilder.noPath=It is illegal to call push() before setting a path
standardContext.applicationListener=Error configuring application listener of class [{0}]
standardContext.applicationSkipped=Skipped installing application listeners due to previous error(s)
standardContext.backgroundProcess.instanceManager=Exception processing instance manager [{0}] background process
standardContext.backgroundProcess.loader=Exception processing loader [{0}] background process
standardContext.backgroundProcess.manager=Exception processing manager [{0}] background process
standardContext.backgroundProcess.resources=Exception processing resources [{0}] background process
standardContext.cluster.noManager=No manager found. Checking if cluster manager should be used. Cluster configured: [{0}], Application distributable: [{1}]
standardContext.configurationFail=One or more components marked the context as not correctly configured
standardContext.cookieProcessor.null=It is not permitted to set the CookieProcessor for a Context to null
standardContext.duplicateListener=The listener [{0}] is already configured for this context. The duplicate definition has been ignored.
standardContext.errorPage.error=Error page location [{0}] must start with a ''/''
standardContext.errorPage.required=ErrorPage cannot be null
standardContext.errorPage.warning=WARNING: Error page location [{0}] must start with a ''/'' in Servlet 2.4
standardContext.extensionValidationError=Error while attempting to validate required application extensions
standardContext.filterFail=One or more Filters failed to start. Full details will be found in the appropriate container log file
standardContext.filterMap.either=Filter mapping must specify either a <url-pattern> or a <servlet-name>
standardContext.filterMap.name=Filter mapping specifies an unknown filter name [{0}]
standardContext.filterMap.pattern=Invalid <url-pattern> [{0}] in filter mapping
standardContext.filterStart=Exception starting filter [{0}]
standardContext.invalidWrapperClass=[{0}] is not a subclass of StandardWrapper
standardContext.isUnavailable=This application is not currently available
standardContext.listenerFail=One or more listeners failed to start. Full details will be found in the appropriate container log file
standardContext.listenerStart=Exception sending context initialized event to listener instance of class [{0}]
standardContext.listenerStop=Exception sending context destroyed event to listener instance of class [{0}]
standardContext.loadOnStartup.loadException=Servlet [{1}] in web application [{0}] threw load() exception
standardContext.loginConfig.errorPage=Form error page [{0}] must start with a ''/''
standardContext.loginConfig.errorWarning=WARNING: Form error page [{0}] must start with a ''/'' in Servlet 2.4
standardContext.loginConfig.loginPage=Form login page [{0}] must start with a ''/''
standardContext.loginConfig.loginWarning=WARNING: Form login page [{0}] must start with a ''/'' in Servlet 2.4
standardContext.loginConfig.required=LoginConfig cannot be null
standardContext.manager=Configured a manager of class [{0}]
standardContext.managerFail=The session manager failed to start
standardContext.namingResource.destroy.fail=Failed to destroy old naming resources
standardContext.namingResource.init.fail=Failed to init new naming resources
standardContext.notStarted=Context with name [{0}] has not yet been started
standardContext.notWrapper=Child of a Context must be a Wrapper
standardContext.parameter.duplicate=Duplicate context initialization parameter [{0}]
standardContext.parameter.required=Both parameter name and parameter value are required
standardContext.pathInvalid=A context path must either be an empty string or start with a ''/'' and do not end with a ''/''. The path [{0}] does not meet these criteria and has been changed to [{1}]
standardContext.postconstruct.duplicate=Duplicate post construct method definition for class [{0}]
standardContext.postconstruct.required=Both fully qualified class name and method name are required
standardContext.predestroy.duplicate=Duplicate @PreDestroy method definition for class [{0}]
standardContext.predestroy.required=Both fully qualified class name and method name are required
standardContext.reloadingCompleted=Reloading Context with name [{0}] is completed
standardContext.reloadingStarted=Reloading Context with name [{0}] has started
standardContext.requestListener.requestInit=Exception sending request initialized lifecycle event to listener instance of class [{0}]
standardContext.resourcesInit=Error initializing static Resources
standardContext.resourcesStart=Error starting static Resources
standardContext.resourcesStop=Error stopping static Resources
standardContext.sciFail=Error during ServletContainerInitializer processing
standardContext.securityConstraint.mixHttpMethod=It is not permitted to mix <http-method> and <http-method-omission> in the same web resource collection
standardContext.securityConstraint.pattern=Invalid <url-pattern> [{0}] in security constraint
standardContext.servletFail=One or more Servlets failed to load on startup. Full details will be found in the appropriate container log file
standardContext.servletMap.name=Servlet mapping specifies an unknown servlet name [{0}]
standardContext.servletMap.pattern=Invalid <url-pattern> [{0}] in servlet mapping
standardContext.startFailed=Context [{0}] startup failed due to previous errors
standardContext.startingContext=Exception starting Context with name [{0}]
standardContext.stop.asyncWaitInterrupted=Interrupt received while waiting unloadDelay milliseconds for in-flight asynchronous requests to complete. Context stop will continue without further delay.
standardContext.stoppingContext=Exception stopping Context with name [{0}]
standardContext.threadBindingListenerError=An error occurred in the thread binding listener configured for Context [{0}]
standardContext.urlPattern.patternWarning=WARNING: URL pattern [{0}] must start with a ''/'' in Servlet 2.4
standardContext.webappClassLoader.missingProperty=Unable to set the web application class loader property [{0}] to [{1}] as the property does not exist.
standardContext.workCreateException=Failed to determine absolute work directory from directory [{0}] and CATALINA_HOME [{1}] for context [{2}]
standardContext.workCreateFail=Failed to create work directory [{0}] for context [{1}]
standardContext.workPath=Exception obtaining work path for context [{0}]
standardContextValve.acknowledgeException=Failed to acknowledge request with a 100 (Continue) response
standardEngine.jvmRouteFail=Failed to set Engine's jvmRoute attribute from system property
standardEngine.noHost=No Host matches server name [{0}]
standardEngine.notHost=Child of an Engine must be a Host
standardEngine.notParent=Engine cannot have a parent Container
standardHost.clientAbort=Remote Client Aborted Request, IOException: [{0}]
standardHost.invalidErrorReportValveClass=Couldn''t load specified error report valve class: [{0}]
standardHost.noContext=No Context configured to process this request
standardHost.notContext=Child of a Host must be a Context
standardHost.nullName=Host name is required
standardHost.problematicAppBase=Using an empty string for appBase on host [{0}] will set it to CATALINA_BASE, which is a bad idea
standardHostValue.customStatusFailed=Custom error page [{0}] could not be dispatched correctly
standardPipeline.basic.start=Error starting new basic Valve
standardPipeline.basic.stop=Error stopping old basic Valve
standardPipeline.valve.destroy=Error destroying Valve
standardPipeline.valve.start=Error starting Valve
standardPipeline.valve.stop=Error stopping Valve
standardServer.accept.error=An IO exception occurred trying to accept on the socket listening for the shutdown command
standardServer.accept.readError=An IO exception occurred trying to read the shutdown command
standardServer.accept.security=A security error occurred trying to accept on the socket listening for the shutdown command
standardServer.accept.timeout=The socket listening for the shutdown command experienced an unexpected timeout [{0}] milliseconds after the call to accept(). Is this an instance of bug 56684?
standardServer.invalidShutdownCommand=Invalid shutdown command [{0}] received
standardServer.shutdownViaPort=A valid shutdown command was received via the shutdown port. Stopping the Server instance.
standardServer.storeConfig.contextError=Error storing context [{0}] configuration
standardServer.storeConfig.error=Error storing server configuration
standardServer.storeConfig.notAvailable=No StoreConfig implementation was registered as an MBean named [{0}] so no configuration could be saved. A suitable MBean is normally registered via the StoreConfigLifecycleListener.
standardService.connector.destroyFailed=Failed to destroy connector [{0}]
standardService.connector.initFailed=Failed to initialize connector [{0}]
standardService.connector.pauseFailed=Failed to pause connector [{0}]
standardService.connector.startFailed=Failed to start connector [{0}]
standardService.connector.stopFailed=Failed to stop connector [{0}]
standardService.engine.startFailed=Failed to start associated Engine
standardService.engine.stopFailed=Failed to stop associated Engine
standardService.mapperListener.startFailed=Failed to start associated MapperListener
standardService.mapperListener.stopFailed=Failed to stop associated MapperListener
standardService.start.name=Starting service [{0}]
standardService.stop.name=Stopping service [{0}]
standardWrapper.allocate=Error allocating a servlet instance
standardWrapper.allocateException=Allocate exception for servlet [{0}]
standardWrapper.deallocateException=Deallocate exception for servlet [{0}]
standardWrapper.destroyException=Servlet.destroy() for servlet [{0}] threw exception
standardWrapper.destroyInstance=InstanceManager.destroy() for servlet [{0}] threw exception
standardWrapper.initException=Servlet.init() for servlet [{0}] threw exception
standardWrapper.instantiate=Error instantiating servlet class [{0}]
standardWrapper.isUnavailable=Servlet [{0}] is currently unavailable
standardWrapper.notChild=Wrapper container may not have child containers
standardWrapper.notClass=No servlet class has been specified for servlet [{0}]
standardWrapper.notContext=Parent container of a Wrapper must be a Context
standardWrapper.notFound=Servlet [{0}] is not available
standardWrapper.notServlet=Class [{0}] is not a Servlet
standardWrapper.releaseFilters=Release filters exception for servlet [{0}]
standardWrapper.serviceException=Servlet.service() for servlet [{0}] in context with path [{1}] threw exception
standardWrapper.serviceExceptionRoot=Servlet.service() for servlet [{0}] in context with path [{1}] threw exception [{2}] with root cause
standardWrapper.unavailable=Marking servlet [{0}] as unavailable
standardWrapper.unloadException=Servlet [{0}] threw unload() exception
standardWrapper.unloading=Cannot allocate servlet [{0}] because it is being unloaded
standardWrapper.waiting=Waiting for [{0}] instance(s) to be deallocated for Servlet [{1}]
threadLocalLeakPreventionListener.containerEvent.error=Exception processing container event [{0}]
threadLocalLeakPreventionListener.lifecycleEvent.error=Exception processing lifecycle event [{0}]

View File

@@ -0,0 +1,59 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
applicationContext.addJspFile.iae=Die JSP Datei [{0}] ist nicht gültig.
applicationContext.addListener.iae.cnfe=Eine Instanz vom Typ [{0}] konnte nicht erzeugt werden
applicationContext.addListener.iae.wrongType=Der spezifierte Typ [{0}] ist keiner der erwarteten Typen für einen Listener
applicationContext.addRole.ise=Es können keine Rollen zu dem Context [{0}] hinzugefügt werden, da er nicht initialisiert wurde
applicationContext.invalidServletName=Kann Servlet-Definition nicht hinzunehmen, da der Servlet Name [{0}] ungültig ist.
applicationContext.setAttribute.namenull=Der Name darf nicht 'null' sein.
applicationFilterRegistration.nullInitParams=Kann Initialisierungs Parameter für Filter nicht setzen, da Name oder Wert null sind. Name [{0}], Wert [{0}]
aprListener.initializingFIPS=FIPS-Modus wird initialisiert...
containerBase.backgroundProcess.cluster=Ausnahme beim Abarbeiten des Cluster [{0}] Hintergrundprozesses
containerBase.backgroundProcess.unexpectedThreadDeath=Unerwarteter Tod des Hintergrund-Threads [{0}]
defaultInstanceManager.invalidInjection=Ungültige ressource injection Annotation
filterChain.filter=Während der Filter Bearbeitung trat eine Exception auf
jreLeakListener.ldapPoolManagerFail=Konnte die Erzeugung der Klasse com.sun.jndi.ldap.LdapPoolManager während des Starts von Tomcat nicht auslösen. Dies sollte zur Vermeidung von Memory-Leaks dienen. Der Fehlschlag ist ein erwartetes Verhalten bei nicht-Sun JVMs.
naming.addEnvEntry=Füge Umgebungseintrag [{0}] hinzu
naming.namingContextCreationFailed=Erzeugung des Naming-Contexts ist fehlgeschlagen: [{0}]
naming.wsdlFailed=Die WSDL Datei [{0}] wurde nicht gefunden.
standardContext.filterStart=Ausnahme beim Starten des Filters [{0}]
standardContext.invalidWrapperClass=[{0}] ist keine Unterklasse von StandardWrapper
standardContext.isUnavailable=Die Anwendung ist derzeit nicht verfügbar
standardContext.listenerStart=Fehler beim Senden der ''Context Initialized'' Benachrichtigung an den Listener aus der Klasse [{0}]
standardContext.loginConfig.errorPage=Formularfehlerseite [{0}] muss mit einem ''/'' beginnen
standardContext.loginConfig.errorWarning=WARNING: Form Fehler Seite [{0}] muss bei Servlet 2.4 mit einem ''/'' starten
standardContext.manager=Habe einen Manager der Klasse [{0}] konfiguriert
standardContext.notStarted=Context mit Name [{0}] wurde noch nicht gestartet
standardContext.parameter.duplicate=Doppelter Parameter [{0}] zur Kontext Initialisierung
standardContext.securityConstraint.mixHttpMethod=<http-method> und <http-method-ommission> dürfen nicht in derselben Web-Ressource-Kollektion verwendet werden
standardContext.securityConstraint.pattern=Ungültiges <url-pattern> [{0}] im Security Constraint
standardContext.startingContext=Ausnahme beim Starten des Kontextes [{0}]
standardEngine.notParent=Engine kann keinen Eltern-Container haben
standardHost.nullName=Hostname wird benötigt
standardWrapper.isUnavailable=Das Servlet [{0}] ist zur Zeit nicht verfügbar
standardWrapper.notFound=Servlet [{0}] ist nicht verfügbar
standardWrapper.unloading=Das Servlet [{0}] kann nicht allokiert werden, weil es entladen wurde

View File

@@ -0,0 +1,190 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
applicationContext.addFilter.ise=No se pueden añadir filtros al contexto [{0}] ya que éste ha sido inicializado
applicationContext.addJspFile.iae=El archivo JSP [{0}] no es válido
applicationContext.addListener.iae.cnfe=No puedo crear una instancia del tipo [{0}]
applicationContext.addListener.iae.sclNotAllowed=Una vez que el primer ServletContextListener ha sido llamado, no se pueden añadir más ServletContextListeners.
applicationContext.addListener.iae.wrongType=El tipo especificado [{0}] no es uno de los tipos de escuchador esperados
applicationContext.addListener.ise=No se pueden añadir escuchadores al contexto [{0}], una vez que ha sido inicializado.
applicationContext.addRole.ise=No se pueden añadir roles al contexto [{0}], una vez que ha sido inicializado.
applicationContext.addServlet.ise=No se pueden añadir servlets al contexto [{0}], una vez que ha sido inicializado.
applicationContext.attributeEvent=Excepción lanzada por escuchador de eventos de atributos
applicationContext.invalidServletName=Incapaz de añadir la definición servlet devido a que el nombre servlet no es válido [{0}].
applicationContext.lookup.error=No pude localizar el recurso [{0}] en el contexto [{1}]
applicationContext.mapping.error=Error durante mapeo
applicationContext.requestDispatcher.iae=La Trayectoria [{0}] no comienza con carácter "/"
applicationContext.resourcePaths.iae=La Trayectoria [{0}] no comienza con carácter "/"
applicationContext.role.iae=Un rol individual que se ha de declarar para el contexto [{0}] no puede ser nulo o cadena vacía
applicationContext.roles.iae=Un arreglo de roles que se ha de declarar para el contexto [{0}] no puede ser nulo o cadena vacía
applicationContext.setAttribute.namenull=El nombre no puede ser nulo
applicationContext.setSessionTimeout.ise=El timeout de la sesión no pudo ser fijado para el contexto [{0}] debido a que el contexto ha sido inicializado
applicationContext.setSessionTracking.iae.invalid=El modo de seguimiento de sesión [{0}] requerido para el contexto [{1}] no está soportado por este contexto
applicationContext.setSessionTracking.iae.ssl=Los modos de seguimiento de sesión requeridos para el contexto [{0}], incluyó SSL y al menos otro modo. SSL no se puede configurar con otros modos.
applicationContext.setSessionTracking.ise=No se pueden poner los modos de seguimiento de sesión para el contexto [{0}] mientras el contexto se está ejecutando.
applicationDispatcher.allocateException=Excepción de reserva de espacio para servlet [{0}]
applicationDispatcher.deallocateException=Excepción de recuperación de espacio para servlet [{0}]
applicationDispatcher.forward.ise=No puedo reenviar después de que la respuesta se haya llevado a cabo.
applicationDispatcher.isUnavailable=El Servlet [{0}] no está disponible en este momento
applicationDispatcher.serviceException=El Servlet.service() para servlet [{0}] lanzó una excepción
applicationDispatcher.specViolation.request=SevletRequest original o ServletRequest original arropado no pasó a RequestDispatcher en violación de SRV.8.2 y SRV.14.2.5.1
applicationDispatcher.specViolation.response=SevletResponse original o ServletResponse original arropado no pasó a RequestDispatcher en violación de SRV.8.2 y SRV.14.2.5.1
applicationFilterConfig.jmxRegisterFail=Ha fallado el registro JMX para el filtro del tipo [{0}] y nombre [{1}]
applicationFilterConfig.jmxUnregister=Se ha completado el desregistro JMX para el filtro del tipo [{0}] y nombre [{1}]
applicationFilterConfig.jmxUnregisterFail=Ha fallado el desregistro JMX para el filtro del tipo [{0}] y nombre [{1}]
applicationFilterRegistration.nullInitParam=No puedo poner el parámetro de inicialización para el filtro debido a un nombre nulo y/o valor. Nombre [{0}], Valor [{1}]
applicationFilterRegistration.nullInitParams=No puedo poner los parámetros de inicialización para el filtro debido a un nombre nulo y/o valor. Nombre [{0}], Valor [{1}]
applicationServletRegistration.setServletSecurity.iae=Se ha especificado restricción Null para el servlet [{0}] desplegado en el contexto con el nombre [{1}]
applicationServletRegistration.setServletSecurity.ise=No se pueden añadir restricciones de seguridad al servlet [{0}] desplegado en el contexto con el nombre [{1}] ya que el contexto ya ha sido inicializado.
aprListener.aprDestroy=No pude apagar la biblioteca nativa de Apache Tomcat
aprListener.aprInit=La biblioteca nativa de Apache Tomcat basada en ARP que permite un rendimiento óptimo en entornos de desarrollo no ha sido hallada en java.library.path: [{0}]
aprListener.flags=Capacidades APR: IPv6 [{0}], enviar fichero [{1}], aceptar filtros [{2}], aleatorio [{3}].
aprListener.initializedOpenSSL=OpenSSL inicializado correctamente [{0}]
aprListener.initializingFIPS=Inicializando modo FIPS...
aprListener.sslInit=No pude inicializar el SSLEngine (Motor SSL)
aprListener.tcnInvalid=Se encuentra instalada una versión incompatible [{0}] de la biblioteca nativa APR de Apache Tomcat, mientras que Tomcat necesita la versión [{1}]
aprListener.tcnValid=Cargada la biblioteca nativa APR de Apache Tomcat [{0}] con la versión APR [{1}].
aprListener.tcnVersion=Se encuentra instalada una versión muy vieja [{0}] de la biblioteca nativa APR de Apache Tomcat, mientras que Tomcat recomienda una versión mayor de [{1}]
aprListener.tooLateForFIPSMode=No se pudo fijar setFIPSMode: SSL ya ha sido inicializado
asyncContextImpl.requestEnded=El requerimiento asociado con AsyncContext ya ha completado su procesamiento.
containerBase.backgroundProcess.cluster=Excepción al procesar clúster [{0}] de proceso en segundo plano
containerBase.backgroundProcess.realm=Excepción al procesar reino [{0}] de proceso en segundo plano
containerBase.backgroundProcess.unexpectedThreadDeath=Muerte inesperada de un hilo en segudo plano [{0}]\n
containerBase.backgroundProcess.valve=Excepción al procesar válvula [{0}] de proceso en segundo plano
defaultInstanceManager.invalidInjection=Método inválido para el recurso de inserción de anotación
defaultInstanceManager.restrictedContainerServlet=El acceso a la clase [{0}] esta prohibido. Esta es una clase restringida ( implementa la interface ContainerServlet ). Una applicación web debe ser configurada como privilegiada para ser capaz de cargarla
defaultInstanceManager.restrictedFiltersResource=No se ha hallado el fichero de propiedades restringidas de filtros
defaultInstanceManager.restrictedListenersResource=No se ha hallado el fichero de propiedades restringidas de escuchadores
defaultInstanceManager.restrictedServletsResource=No se ha hallado el fichero de propiedades restringidas de servlets
filterChain.filter=La ejecución del Filtro lanzó una excepción
filterChain.servlet=La ejecución del Servlet lanzó una excepción
jreLeakListener.authPolicyFail=Error mientras intentaba prevenir fallos de memoria en javax.security.auth.Policy class
jreLeakListener.gcDaemonFail=No pude disparar la creación del hilo Daemon GC durante el arranque de Tomcat para prevenir posibles fallos de memoria. Esto es lo esperado en JVMs no Sun.
jreLeakListener.jarUrlConnCacheFail=No pude desactivar la caché de conexión URL de Jar por defecto
jreLeakListener.ldapPoolManagerFail=No pude disparar la creación de la clase com.sun.jndi.ldap.LdapPoolManager durante el arranque de Tomcat para prevenir posibles fallos de memoria. Esto es lo que se espera si las JVMs no son Sun.
jreLeakListener.xmlParseFail=Error mientras intentaba prevenir fallos de memoria durante el análisis XML
naming.addEnvEntry=Adicionando entrada de ambiente [{0}]\n
naming.bindFailed=No pude cambiar (bind) objeto: [{0}]
naming.invalidEnvEntryType=La entrada de Entorno [{0}] tiene un tipo inválido
naming.invalidEnvEntryValue=La entrada de Entorno [{0}] tiene un valor inválido
naming.jmxRegistrationFailed=No pude registrar en JMX: [{0}]
naming.namingContextCreationFailed=Falló la creación del contexto de nombres (naming): [{0}]
naming.unbindFailed=No pude descambiar (unbind) objecto: [{0}]
naming.wsdlFailed=No pude hallar fichero wsdl: [{0}]
standardContext.applicationListener=Error configurando escuchador de aplicación de clase [{0}]
standardContext.applicationSkipped=Se ha saltado la instalación de escuchadores de aplicación debido a error(es) previo(s)
standardContext.backgroundProcess.loader=Excepción al procesar cargador [{0}] de proceso en segundo plano
standardContext.backgroundProcess.manager=Excepción al procesar gestor [{0}] de proceso en segundo plano
standardContext.cluster.noManager=No se ha hallado el gestor. Revisando si hay que usar el gestor de clúster. Clúster configurado: [{0}], Aplicación distribuíble: [{1}]
standardContext.duplicateListener=El escuchador [{0}] ya está configurado para este contexto. La definición duplicada ha sido ignorada.
standardContext.errorPage.error=La localización de la página de error [{0}] debe de comenzar con ''/''
standardContext.errorPage.required=ErrorPage no puede ser nulo
standardContext.errorPage.warning=AVISO: La localización de la página de error [{0}] debe de comenzar con ''/'' en Servlet 2.4
standardContext.filterMap.either=El mapeo de filtro debe de especificar o un <url-pattern> o un <servlet-name>
standardContext.filterMap.name=El mapeo de filtro especifica un nombre desconocido de filtro [{0}]
standardContext.filterMap.pattern=<url-pattern> [{0}] inválido en mapeo de filtro
standardContext.filterStart=Excepción arrancando filtro [{0}]
standardContext.invalidWrapperClass=[{0}] no es una subclase de StandardWrapper
standardContext.isUnavailable=Esta aplicación no está disponible en este momento
standardContext.listenerStart=Excepción al enviar evento inicializado de contexto a instancia de escuchador de clase [{0}]
standardContext.listenerStop=Excepción enviando evento de contexto destruído a instancia de escuchador de clase [{0}]
standardContext.loginConfig.errorPage=La Página de error de Formulario [{0}] debe de comenzar con ''/''
standardContext.loginConfig.errorWarning=AVISO: La página de error de Formulario [{0}] debe de comenzar con ''/'' en Servlet 2.4
standardContext.loginConfig.loginPage=La página de login de Formulario [{0}] debe de comenzar con ''/''
standardContext.loginConfig.loginWarning=AVISO: La página de login de Formulario [{0}] debe de comenzar con ''/'' en Servlet 2.4
standardContext.loginConfig.required=LoginConfig no puede ser nula
standardContext.manager=Configurado un gestor de la clase [{0}]
standardContext.managerFail=El manejador de sesiones falló al iniciar
standardContext.namingResource.destroy.fail=No pude destruir recursos de viejo nombre
standardContext.namingResource.init.fail=No pude inicializar recursos de nuevo nombre
standardContext.notStarted=Aún no se ha arrancado el Contexto [{0}]
standardContext.notWrapper=El Hijo de un Contexto debe de ser un Arropador (Wrapper)
standardContext.parameter.duplicate=Duplicado parámetro de inicialización de contexto [{0}]
standardContext.parameter.required=Es necesario poner nombre de parámetro y valor de parámetro
standardContext.pathInvalid=Una ruta de contexto debe de ser o una cadena vacía o comenzar con "/". La ruta [{0}] no cumple con estos criterios y ha sido cambiada por [{1}]
standardContext.predestroy.duplicate=Definición duplicada de método @PreDestroy para clase {0}]
standardContext.reloadingCompleted=Se ha completado la recarga de este Contexto
standardContext.reloadingStarted=Ha comenzado la recarga de Contexto [{0}]
standardContext.requestListener.requestInit=Una excepción durante el envío de requerimiento ha iniciado un evento de ciclo de vida (lifecycle event) para la instancia de clase a la escucha (listener) [{0}]
standardContext.resourcesStart=Error arrancando Recursos estáticos
standardContext.securityConstraint.mixHttpMethod=No está permitido mezclar <http-method> y <http-method-omission> en la misma colección de recursos web
standardContext.securityConstraint.pattern=<url-pattern> [{0}] inválida en restricción de seguridad
standardContext.servletMap.name=El mapeo de Servlet especifica un nombre de servlet desconocido [{0}]
standardContext.servletMap.pattern=<url-pattern> [{0}] inválida en mapeo de servlet
standardContext.startFailed=Falló en arranque del Contexto [{0}] debido a errores previos
standardContext.startingContext=Excepción arrancando Contexto con nombre [{0}]
standardContext.stoppingContext=Excepción parando Context [{0}]
standardContext.urlPattern.patternWarning=AVISO: el patrón URL [{0}] debe de comenzar con ''/'' en Servlet 2.4
standardContext.workCreateException=No pude determinar directorio absoluto de trabajo a partir del directorio [{0}] y CATALINA_HOME [{1}] para el contexto [{2}]
standardContext.workCreateFail=No pude crear el directorio de trabajo [{0}] para el contexto [{1}]
standardContext.workPath=Excepción obteniendo ruta de trabajo para el contexto [{0}]
standardContextValve.acknowledgeException=No pude reconocer el requerimiento con una respuesta 100 (Continuar)
standardEngine.jvmRouteFail=No pude poner el atributo jvmRoute del Motor para la propiedad del sistema
standardEngine.noHost=No hay Máquina que coincida con nombre de servidor [{0}]
standardEngine.notHost=El Hijo de un Motor debe de ser un Máquina
standardEngine.notParent=El Motor no puede tener un Contenedor padre
standardHost.clientAbort=El Cliente Remoto Abortó el Requerimiento, IOException: [{0}]
standardHost.invalidErrorReportValveClass=No pude cargar clase especifiada de válvula de informe de error: [{0}]
standardHost.noContext=No se ha configurado Contexto para procesar este requerimiento
standardHost.notContext=El Hijo de una Máquina debe de ser un Contexto
standardHost.nullName=Es necesario poner el nombre de Máquina
standardServer.shutdownViaPort=Se ha recibido un comando de apagado a través del puerto de apagado. Parando la instancia del Servidor.
standardServer.storeConfig.notAvailable=No se registró ninguna implementación de StoreConfig registrada con nombre n MBean [{0}] por eso no se pudo salvar la configuración. Un MBean adecuado es normalmente registrado via el StoreConfigLifecycleListener.
standardService.connector.initFailed=No pude inicializar el conector [{0}]
standardService.connector.pauseFailed=No pude pausar el conector [{0}]
standardService.connector.startFailed=No pude arrancar el conector [{0}]
standardService.connector.stopFailed=No pude parar el conector [{0}]
standardService.start.name=Arrancando servicio [{0}]
standardService.stop.name=Parando servicio [{0}]
standardWrapper.allocate=Error reservando espacio para una instancia de servlet
standardWrapper.allocateException=Excepción de reserva de espacio para servlet [{0}]
standardWrapper.deallocateException=Excepción de recuperación de espacio para servlet [{0}]
standardWrapper.destroyException=Servlet.destroy() para servlet [{0}] lanzó excepción
standardWrapper.initException=Servlet.init() para servlet [{0}] lanzó excepción
standardWrapper.instantiate=Error instanciando clase de servlet [{0}]
standardWrapper.isUnavailable=El Servlet [{0}] no está disponible en este momento
standardWrapper.notChild=El contenedor de Arropador (Wrapper) no puede tener contenedores hijo
standardWrapper.notClass=No se ha especificado clase de servlet para servlet [{0}]
standardWrapper.notContext=El contenedor padre para un Arropador (Wrapper) debe de ser un Contexto
standardWrapper.notFound=No está disponible el Servlet [{0}]
standardWrapper.notServlet=La Clase [{0}] no es un Servlet
standardWrapper.releaseFilters=Excepción de Liberación de filtros para servlet [{0}]
standardWrapper.serviceException=Servlet.service() para servlet [{0}] lanzó excepción
standardWrapper.serviceExceptionRoot=El Servlet.service() para el servlet [{0}] en el contexto con ruta [{1}] lanzó la excepción [{2}] con causa raíz
standardWrapper.unavailable=Marcando el servlet [{0}] como no disponible
standardWrapper.unloadException=El Servlet [{0}] lanzó excepción unload()
standardWrapper.unloading=No se puede reservar espacio para servlet [{0}] porque está siendo descargado
standardWrapper.waiting=Esperando por [{0}] instancia(s) para recuperar su espacio reservado
threadLocalLeakPreventionListener.containerEvent.error=Excepción procesando evento de contenedor [{0}]
threadLocalLeakPreventionListener.lifecycleEvent.error=Excepción procesando evento de ciclo de vida [{0}]

View File

@@ -0,0 +1,277 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
applicationContext.addFilter.ise=Des filtres ne peuvent plus être ajoutés au contexte [{0}] car il a déjà été initialisé
applicationContext.addJspFile.iae=Le fichier JSP [{0}] est invalide
applicationContext.addListener.iae.cnfe=Incapable de créer une instance de type [{0}]
applicationContext.addListener.iae.init=Impossible d''ajouter une instance du type [{0}] comme écouteur
applicationContext.addListener.iae.sclNotAllowed=Il est impossible d'ajouter un ServletContextListener après qu'un ait été appelé
applicationContext.addListener.iae.wrongType=Le type spécifié [{0}] n''est pas un type attendu de "listener"
applicationContext.addListener.ise=Des Listener ne peuvent plus être ajoutés au contexte [{0}] car il a déjà été initialisé
applicationContext.addRole.ise=Vous ne pouvez pas ajouter de rôles au contexte [{0}], parce qu''il a déjà été initialisé
applicationContext.addServlet.ise=Des Servlets ne peuvent plus être ajoutés au contexte [{0}] car il a déjà été initialisé
applicationContext.attributeEvent=Exception lancée par l'écouteur (listener) d'évènement attributs
applicationContext.illegalDispatchPath=La tentative d''obtenir un dispatcher de requêtes avec le chemin illégal [{0}] a été refusée car il contenait une tentative de traversée de répertoire encodée
applicationContext.invalidFilterName=Impossible d''ajouter la définition du filtre à cause d''un nom de filtre invalide [{0}]
applicationContext.invalidServletName=Impossible d''ajouter la définition de la servlet à cause de son nom invalide [{0}]
applicationContext.lookup.error=Impossible de trouver la ressource [{0}] dans le contexte [{1}]
applicationContext.mapping.error=Erreur lors du mapping
applicationContext.requestDispatcher.iae=Le chemin [{0}] ne commence pas par le caractère "/"
applicationContext.resourcePaths.iae=Le chemin [{0}] ne démarre pas avec un caractère "/"
applicationContext.role.iae=Un rôle individuel à déclarer pour le contexte [{0}] ne peut être null ou une chaîne vide
applicationContext.roles.iae=Le tableaux de rôles à déclarer pour le contexte [{0}] ne peut pas être null
applicationContext.setAttribute.namenull=le nom ne peut être nul
applicationContext.setInitParam.ise=les paramètres d''initialisation ne peuvent pas être configurés sur le contexte [{0}] car il a déjà été initialisé
applicationContext.setRequestEncoding.ise=L''encodage de la requête ne peut pas être configuré sur le contexte [{0}] car il a déjà été initialisé
applicationContext.setResponseEncoding.ise=L''encodage de la réponse ne peut pas être configuré sur le contexte [{0}] car il a déjà été initialisé
applicationContext.setSessionTimeout.ise=Le timeout de session ne peut pas être changé pour le contexte [{0}] car il a déjà été initialisé
applicationContext.setSessionTracking.iae.invalid=Le mode de suivi de la session [{0}] demandé par le contexte [{1}] n''est pas supporté par ce contexte
applicationContext.setSessionTracking.iae.ssl=Les modes de suivi de session pour le contexte [{0}] incluent SSL et au moins un autre mode. SSL ne peut pas être configuré avec d''autres modes.
applicationContext.setSessionTracking.ise=Les modes de suivi de session ("session tracking") du contexte [{0}] ne peuvent être définis pendant que le contexte est en cours d''exécution
applicationDispatcher.allocateException=Exception d''allocation pour la servlet [{0}]
applicationDispatcher.deallocateException=Exception de désallocation pour la servlet [{0}]
applicationDispatcher.forward.ise=Impossible d'utiliser faire-suivre (forward) après que la réponse ait été envoyée
applicationDispatcher.isUnavailable=La servlet [{0}] est actuellement indisponible
applicationDispatcher.serviceException="Servlet.service()" pour la servlet [{0}] a lancé une exception
applicationDispatcher.specViolation.request=La ServletRequest d'origine ou la ServletRequest d'origine enrobée n'a pas été passée au RequestDispatcher en violation de SRV.8.2 et SRV.14.2.5.1
applicationDispatcher.specViolation.response=La ServletResponse originale ou la ServletResponse enveloppée (wrapped) n'a pas été transmise au RequestDispatcher, en violation de SRV.8.2 et SRV.14.2.5.1
applicationFilterConfig.jmxRegisterFail=L''enregistrement JMX a échoué pour le filtre de type [{0}] et nommé [{0}]
applicationFilterConfig.jmxUnregister=Le désenregistrement JMX est terminé pour le filtre de type [{0}] nommé [{1}]
applicationFilterConfig.jmxUnregisterFail=Le désenregistrement JMX du filtre de type [{0}] nommé [{1}] a échoué
applicationFilterConfig.preDestroy=Echec lors de l''appel de preDestroy pour le filtre nommé [{0}] de type [{1}]
applicationFilterConfig.release=Impossible de détruite le filtre nommé [{0}] de type [{1}]
applicationFilterRegistration.nullInitParam=Impossible de fixer le paramètre d''initialisation du filtre, à cause d''un nom ou d''une valeur nulle, nom [{0}], valeur [{1}]
applicationFilterRegistration.nullInitParams=Impossible de fixer les paramètres d''initialisation du filtre, à cause d''un nom ou d''une valeur nulle, nom [{0}], valeur [{1}]
applicationHttpRequest.fragmentInDispatchPath=Le fragment dans le chemin de dispatch [{0}] a été enlevé
applicationPushBuilder.methodInvalid=La méthode HTTP pour une requête push doit être à la fois être sans danger et pouvoir être mise en cache, mais [{0}] ne correspond pas
applicationPushBuilder.methodNotToken=Les méthodes HTTP doivent être des "token", mais [{0}] contient un caractère invalide dans un token.
applicationServletRegistration.setServletSecurity.iae=Contrainte nulle spécifiée pour le Servlet [{0}] déployé dans le contexte avec le nom [{1}]
applicationServletRegistration.setServletSecurity.ise=Les contraintes de sécurité ne peuvent pas être ajoutées au Servlet [{0}] déployé dans le contexte [{1}] car le contexte a déjà été initialisé
applicationSessionCookieConfig.ise=La propriété [{0}] ne peut pas être ajoutée au SessionCookieConfig pour le contexte [{1}] car le contexte a déjà été initialisé
aprListener.aprDestroy=Echec de l'arrêt de la librairie Apache Tomcat Native basée sur APR
aprListener.aprInit=La librairie Apache Tomcat Native basée sur APR qui permet des performances optimales dans les environnements de production n''a pas été trouvée sur le java.library.path: [{0}]
aprListener.aprInitDebug=La librairie Apache Tomcat Native basée sur APR n''a pas été trouvée en utilisant les noms [{0}] dans le java.library.path [{1}], les erreurs retournées sont [{2}]
aprListener.aprInitError=La librairie Apache Tomcat Native basée sur APR n''a pas pu être chargée, l''erreur retournée est [{0}]
aprListener.config=Configuration de APR/OpenSSL: useAprConnector [{0}], useOpenSSL [{1}]
aprListener.currentFIPSMode=Mode FIPS actuel: [{0}]
aprListener.enterAlreadyInFIPSMode=AprLifecycleListener est configuré pour forcer le mode FIPS mais la librairie est déjà en mode FIPS [{0}]
aprListener.flags=Fonctionnalités d''APR: IPv6 [{0}], sendfile [{1}], accept filters [{2}], random [{3}]
aprListener.initializeFIPSFailed=Echec d'entrée en mode FIPS
aprListener.initializeFIPSSuccess=Entrée avec succès en mode FIPS
aprListener.initializedOpenSSL=OpenSSL a été initialisé avec succès [{0}]
aprListener.initializingFIPS=Initialisation du mode FIPS...
aprListener.requireNotInFIPSMode=AprLifecycleListener est configuré pour demander que la librarie soit déjà en mode FIPS et elle ne l'était pas
aprListener.skipFIPSInitialization=Déjà en mode FIPS, l'initialisation de FIPS n'est pas effectuée
aprListener.sslInit=Impossible d'initialiser le SSLEngine
aprListener.tcnInvalid=Une version incompatible [{0}] de la librairie Apache Tomcat Native basée sur APR est installée, alors que Tomcat nécessite la version [{1}]
aprListener.tcnValid=Chargement de la librairie Apache Tomcat Native [{0}] en utilisant APR version [{1}]
aprListener.tcnVersion=Un version ancienne [{0}] de la bibliothèque Apache Tomcat Native basée sur APR est installée, alors que Tomcat recommande au minimum la version [{1}]
aprListener.tooLateForFIPSMode=Ne peut pas passer en mode FIPS, SSL a déjà été initialisé
aprListener.tooLateForSSLEngine=Impossible d'appeler setSSEEngine, SSL a déjà été initialisé
aprListener.tooLateForSSLRandomSeed=setSSLRandomSeed impossible: SSL a déjà été initialisé
aprListener.wrongFIPSMode=Valuer inattendue de l''option FIPSMode de AprLifecycleListener: [{0}]
asyncContextImpl.asyncDispachError=Erreur lors d'un dispatch asynchrone
asyncContextImpl.asyncRunnableError=Erreur lors du traitement asynchrone du Runnable via AsyncContext.start()
asyncContextImpl.dispatchingStarted=Une opération de dispatch asynchrone a déjà été appelée, plusieurs dispatch au cours d'un même cycle asynchrone n'est pas autorisé
asyncContextImpl.fireOnComplete=Déclenchement de l'évènement onComplete() sur tous les AsyncListeners
asyncContextImpl.fireOnError=Déclenchement de l'évènement onError() sur tous les AsyncListeners
asyncContextImpl.fireOnStartAsync=Déclenchement de l'évènement onStartAsync() sur tous les AsyncListeners
asyncContextImpl.fireOnTimeout=Déclenchement de l'évènement onTimeout() sur tous les AsyncListeners
asyncContextImpl.noAsyncDispatcher=Le Servlet dispatcher retourné par le ServletContext ne supporte pas de dispatch asynchrone
asyncContextImpl.onCompleteError=L''appel à onComplete() a échoué pour l''écouteur de type [{0}]
asyncContextImpl.onErrorError=L''appel à onError() a échoué pour l''écouteur de type [{0}]
asyncContextImpl.onStartAsyncError=L''appel à onStartAsync() a échoué pour l''écouteur de type [{0}]
asyncContextImpl.onTimeoutError=L''appel à onTimeout() a échoué pour l''écouteur de type [{0}]
asyncContextImpl.request.ise=Il est illégal d'appeler getRequest() après que complete() ou une autre des méthodes dispatch() ait été appelé
asyncContextImpl.requestEnded=La requête associée avec l'AsyncContext est déjà terminée
asyncContextImpl.response.ise=Il est illégal d'appeler getResponse() après que complete() ou n'importe laquelle des méthodes de dispatch a été appelée
containerBase.backgroundProcess.cluster=Une exception s''est produite lors du traitement d''arrière plan du cluster [{0}]
containerBase.backgroundProcess.realm=Exception lors du traitement d''arrière plan du realm [{0}]
containerBase.backgroundProcess.unexpectedThreadDeath=Mort inattendue du fil d''exécution d''arrière-plan ("background thread") [{0}]
containerBase.backgroundProcess.valve=Exception lors du traitement d''arrière plan de la valve [{0}]
containerBase.nullName=Le nom d'un conteneur ne peut être null
containerBase.threadedStartFailed=Un conteneur fils a échoué pendant son démarrage
containerBase.threadedStopFailed=Erreur lors de l'arrêt d'un conteneur fils
defaultInstanceManager.invalidInjection=Annotation invalide pour l'injection d'une resource méthode
defaultInstanceManager.restrictedClass=L''accès à la classe à accès restreint [{0}] est interdit, une application web doit être marquée comme étant privilégiée pour pouvoir la charger
defaultInstanceManager.restrictedContainerServlet=L''accès à la classe [{0}] est interdit. C''est une classe restreinte qui (implémente l''interface ContainerServlet). Une application web doit être privilégiée pour pouvoir la charger.
defaultInstanceManager.restrictedFiltersResource=Le fichier de propriétés contenant la liste des filtres restreints n''a pas été trouvée [{0}]
defaultInstanceManager.restrictedListenersResource=Le fichier de propriétés concernant les écouteurs à accès restreint n''a pas été trouvé [{0}]
defaultInstanceManager.restrictedServletsResource=Le fichier de propriétés contenant la liste des Servlets restreints n''a pas été trouvée [{0}]
defaultInstanceManager.restrictedWrongValue=Mauvaise valeur dans le fichier de propriété [{0}] contenant la liste des classes à accès restreint pour le nom de classe [{1}], valeur attendue: [restricted], valeur donnée: [{2}]
filterChain.filter=L'exécution du filtre (Filter) a lancé une exception
filterChain.servlet=L'exécution de la servlet a lancé une exception
jreLeakListener.authPolicyFail=Erreur en essayant de prévenir une fuite de mémoire dans la classe javax.security.auth.Policy
jreLeakListener.classToInitializeFail=Echec du chargement de la classe [{0}] pendant le démarrage de Tomcat, effectué pour empêcher de possibles fuites de mémoire
jreLeakListener.gcDaemonFail=Echec de la création du thread GC Daemon durant le démarrage de Tomcat pour éviter une fuite de mémoire, cela est normal sur toutes les JVMs non Oracle
jreLeakListener.jarUrlConnCacheFail=Échec de la désactivation du cache par défaut des URL de connexion de JAR
jreLeakListener.ldapPoolManagerFail=Echec de la création de la classe com.sun.jndi.ldap.LdapPoolManager durant le démarrage de Tomcat pour éviter une fuite de mémoire, cela est normal sur toutes les JVMs non Oracle
jreLeakListener.xmlParseFail=Erreur en essayant de prévenir une fuite de mémoire lors du traitement de contenu XML
naming.addEnvEntry=Ajout de l''entrée d''environnement [{0}]
naming.addResourceEnvRef=Ajout de la référence de ressource d''environnement [{0}]
naming.bindFailed=Echec lors du liage à l''objet: [{0}]
naming.invalidEnvEntryType=L''entrée environnement [{0}] a un type invalide
naming.invalidEnvEntryValue=L''entrée environnement [{0}] a une valeur invalide
naming.jmxRegistrationFailed=Echec d''enregistrement dans JMX: [{0}]
naming.namingContextCreationFailed=La création du contexte de nommage (naming context) a échoué : [{0}]
naming.unbindFailed=Echec lors du déliage à l''objet : [{0}]
naming.wsdlFailed=fichier wsdl [{0}] non trouvé
noPluggabilityServletContext.notAllowed=La section 4.4 de la spécification Servlet 3.0 ne permet pas à cette méthode d'être appelée à partir d'un ServletContextListener qui n'a pas été déclaré dans web.xml, un web-fragment.xml, ou annoté avec @WebListener
pushBuilder.noPath=Il est interdit d'appeler push() avant de fixer un chemin
standardContext.applicationListener=Erreur lors de la configuration de la classe d''écoute de l''application (application listener) [{0}]
standardContext.applicationSkipped=L'installation des écouteurs (listeners) de l'application a été sautée suite aux erreurs précédentes
standardContext.backgroundProcess.instanceManager=Exception lors du traitement d''arrière plan du gestionnaire d''instances [{0}]
standardContext.backgroundProcess.loader=Exception lors du traitement d''arrière plan du loader [{0}]
standardContext.backgroundProcess.manager=Exception lors du traitement d''arrière plan du gestionnaire de sessions [{0}]
standardContext.backgroundProcess.resources=Exception lors du traitement d''arrière plan des ressources [{0}]
standardContext.cluster.noManager=Aucun gestionnaire de session trouvé, vérification de l''utilisation éventuelle du gestionnaire de session fourni par le cluster; cluster configuré: [{0}], application distribuable: [{1}]
standardContext.configurationFail=Un ou plusieurs composants ont marqué ce contexte comme n'étant pas correctement configuré
standardContext.cookieProcessor.null=Il est interdit de mettre un CookieProcessor null pour un contexte
standardContext.duplicateListener=L''écouteur [{0}] est déjà configuré pour le contexte, la double déclaration a été ignorée
standardContext.errorPage.error=La position de la page d''erreur (ErrorPage) [{0}] doit commencer par un ''/''
standardContext.errorPage.required=La page d'erreur (ErrorPage) ne peut être nulle
standardContext.errorPage.warning=WARNING: La position de la page d''erreur (ErrorPage) [{0}] doit commencer par un ''/'' dans l''API Servlet 2.4
standardContext.extensionValidationError=Erreur lors de la validation des extensions requises par l'application
standardContext.filterFail=Un ou plusieurs filtres n'ont pas pu démarrer, les détails sont dans le fichier log du conteneur
standardContext.filterMap.either=L'association de filtre (filter mapping) doit indiquer soit une <url-pattern> soit une <servlet-name>
standardContext.filterMap.name=L''association de filtre (filter mapping) indique un nom de filtre inconnu [{0}]
standardContext.filterMap.pattern=<url-pattern> [{0}] invalide dans l''association de filtre (filter mapping)
standardContext.filterStart=Exception au démarrage du filtre [{0}]
standardContext.invalidWrapperClass=[{0}] n''est pas une sous-classe de StandardWrapper
standardContext.isUnavailable=Cette application n'est pas disponible actuellement
standardContext.listenerFail=Un ou plusieurs écouteurs n'ont pas pu démarrer, les détails sont dans le fichier de log du conteneur
standardContext.listenerStart=Exception lors de l''envoi de l''évènement contexte initialisé (context initialized) à l''instance de classe d''écoute (listener) [{0}]
standardContext.listenerStop=Exception lors de l''envoi de l''évènement contexte détruit (context destroyed) à l''instance de classe d''écoute [{0}]
standardContext.loadOnStartup.loadException=Le Servlet [{1}] dans l''application web [{0}] a retourné une exception lors de son chargement
standardContext.loginConfig.errorPage=La page d''erreur de Form [{0}] doit commencer par un ''/''
standardContext.loginConfig.errorWarning=La page d''erreur de Form [{0}] doit commencer par un ''/'' dans l''API Servlet 2.4
standardContext.loginConfig.loginPage=La page de connexion du formulaire [{0}] doit commencer par un ''/''
standardContext.loginConfig.loginWarning=WARNING: La page de connexion du formulaire [{0}] doit commencer par un ''/'' dans l''API Servlet 2.4
standardContext.loginConfig.required="LoginConfig" ne peut être nul
standardContext.manager=Configuré un gestionnaire de la classe [{0}]
standardContext.managerFail=Echec lors du démarrage du gestionnaire de sessions
standardContext.namingResource.destroy.fail=Echec de destruction des anciennes ressources JNDI
standardContext.namingResource.init.fail=Echec d'initialisation des nouvelles ressources JNDI
standardContext.notStarted=Le contexte [{0}] n''a pas encore été démarré
standardContext.notWrapper=Le fils du contexte (child of context) doit être un enrobeur (wrapper)
standardContext.parameter.duplicate=Paramètre d''initialisation de contexte dupliqué [{0}]
standardContext.parameter.required=Le nom de paramètre ainsi que la valeur du paramètre sont requis
standardContext.pathInvalid=Un chemin de contexte doit être soit une chaîne vide soit commencer par un ''/'' et ne pas finir par un ''/'', le chemin [{0}] ne répond pas à ces conditions et a été changé en [{1}]
standardContext.postconstruct.duplicate=La méthode post construct est définie en double dans la classe [{0}]
standardContext.postconstruct.required=A la fois le nom complet qualifié et le nom de la méthode sont requis
standardContext.predestroy.duplicate=Définition dupliquée de la méthode de destruction "pre" pour la classe [{0}]
standardContext.predestroy.required=Les noms qualifiés de la classe et de la méthode sont tous deux requis
standardContext.reloadingCompleted=Le rechargement de ce contexte est terminé
standardContext.reloadingStarted=Le rechargement du contexte [{0}] a démarré
standardContext.requestListener.requestInit=Une exception lors de l''envoi de requête a initié un évènement cycle de vie (lifecycle event) pour l''instance de classe à l''écoute (listener) [{0}]
standardContext.resourcesInit=Erreur d'initialisation des ressources statiques
standardContext.resourcesStart=Erreur lors du démarrage des ressources statiques
standardContext.resourcesStop=Erreur lors de l'arrêt des ressources statiques
standardContext.sciFail=Erreur lors du traitement de ServletContainerInitializer
standardContext.securityConstraint.mixHttpMethod=Il n'est pas permis de combiner <http-method> et <http-method-omission> dans la même collection de resources web
standardContext.securityConstraint.pattern=<url-pattern> [{0}] invalide d''après les contraintes de sécurité (security constraint)
standardContext.servletFail=Un ou plusieurs Servlets n'ont pas pu démarrer, les détails sont dans le fichier log du conteneur
standardContext.servletMap.name=L''association de servlet (servlet mapping) indique un nom de servlet inconnu [{0}]
standardContext.servletMap.pattern=<url-pattern> [{0}] invalide dans l''association de servlet (servlet mapping)
standardContext.startFailed=Erreur de démarrage du contexte [{0}] suite aux erreurs précédentes
standardContext.startingContext=Exception lors du démarrage du contexte [{0}]
standardContext.stop.asyncWaitInterrupted=Une interruption a été reçue en attendant unloadDelay millisecondes pour permettre aux requêtes asynchrones en cours de se terminer, l'arrêt du contexte va se poursuivre sans délai supplémentaire
standardContext.stoppingContext=Exception à l''arrêt du Context [{0}]
standardContext.threadBindingListenerError=Une erreur s''est produite dans l''écouteur de l''association de thread configuré pour le contexte [{0}]
standardContext.urlPattern.patternWarning=WARNING: Le modèle (pattern) d''URL [{0}] doit commencer par un ''/'' dans l''API Servlet 2.4
standardContext.webappClassLoader.missingProperty=Impossible de fixer la propriété [{0}] du chargeur de classes de l''application web à [{1}] car cette propriété n''existe pas
standardContext.workCreateException=Impossible de déterminer le chemin absolu pour le répertoire de travail à partir du répertoire [{0}] et de CATALINA_HOME [{1}] pour le contexte [{2}]
standardContext.workCreateFail=Impossible de créer le répertoire de travail [{0}] pour le contexte [{1}]
standardContext.workPath=Impossible d''obtenir le chemin de travail pour le contexte [{0}]
standardContextValve.acknowledgeException=Impossible de confirmer la requête avec une réponse 100 (continuer)
standardEngine.jvmRouteFail=Impossible de fixer la jvmRoute de l'Engine à partir d'une propriété système
standardEngine.noHost=Aucune hôte (host) ne correspond au nom de serveur [{0}]
standardEngine.notHost=Le fils d'un moteur (child of an Engine) doit être un hôte
standardEngine.notParent=Un moteur (engine) ne peut avoir de conteneur parent (container)
standardHost.clientAbort=Le client distant a abandonné la requête, IOException: [{0}]
standardHost.invalidErrorReportValveClass=Impossible de charger la classe valve de rapport d''erreur: [{0}]
standardHost.noContext=Aucun contexte n'est configuré pour traiter cette requête
standardHost.notContext=Le fils d'un hôte (child of a Host) doit être un contexte
standardHost.nullName=Le nom d'hôte est requis
standardHost.problematicAppBase=Utiliser une chaîne vide pour l''appBase de l''hôte [{0}] la fera correspondre à CATALINA_BASE, ce qui causera des problèmes
standardHostValue.customStatusFailed=La page d''erreur personnalisée [{0}] n''a pu être redirigée correctement
standardPipeline.basic.start=Erreur lors du démarrage de la nouvelle valve de base
standardPipeline.basic.stop=Erreur lors de l'arrêt de l'ancienne valve de base
standardPipeline.valve.destroy=Erreur lors de la destruction de la valve
standardPipeline.valve.start=Erreur lors du démarrage de la valve
standardPipeline.valve.stop=Erreur lors de l'arrêt de la valve
standardServer.accept.error=Une erreur d'IO s'est produite en essayant d'accepter sur le socket qui attend la commande d'arrêt
standardServer.accept.readError=Une erreur d'IO s'est produite lors de la lecture de la commande d'arrêt
standardServer.accept.security=Une erreur de sécurité s'est produite en essayant d'accepter sur le socket qui attend la commande d'arrêt
standardServer.accept.timeout=Le socket qui écoute en attendant la commande d''arrêt a rencontré un délai d''attente dépassé inattendu [{0}] millisecondes après l''appel à accept()
standardServer.invalidShutdownCommand=Une commande d''arrêt invalide [{0}] a été reçue
standardServer.shutdownViaPort=Une commande d'arrêt valide a été reçue sur le port d'arrêt, arrêt de l'instance du serveur
standardServer.storeConfig.contextError=Erreur lors de l''enregistrement de la configuration du contexte [{0}]
standardServer.storeConfig.error=Erreur lors de l'enregistrement de la configuration du serveur
standardServer.storeConfig.notAvailable=Aucune implémentation de StoreConfig n''a été enregistrée comme un MBean nommé [{0}], et aucune configuration n''a donc été enregistrée. Un MBean adéquat est normalement référencé via le StoreConfigLifecycleListener
standardService.engine.startFailed=Impossible de démarrer l'Engine associé
standardService.engine.stopFailed=Echec de l'arrêt du moteur associé
standardService.mapperListener.startFailed=Impossible de démarrer le MapperListener associé
standardService.mapperListener.stopFailed=Impossible d'arrêter le MapperListener associé
standardService.start.name=Démarrage du service [{0}]
standardService.stop.name=Arrêt du service [{0}]
standardWrapper.allocate=Erreur d'allocation à une instance de servlet
standardWrapper.allocateException=Exception lors de l''allocation pour la servlet [{0}]
standardWrapper.deallocateException=Exception à la désallocation pour la servlet [{0}]
standardWrapper.destroyException="Servlet.destroy()" de la servlet [{0}] a généré une exception
standardWrapper.destroyInstance=InstanceManager.destroy() pour le Servlet [{0}] a renvoyé une exception
standardWrapper.initException="Servlet.init()" pour la servlet [{0}] a généré une exception
standardWrapper.instantiate=Erreur à l''instantiation de la classe servlet [{0}]
standardWrapper.isUnavailable=La servlet [{0}] est actuellement indisponible
standardWrapper.notChild=L'enrobeur de conteneur (wrapper container) ne peut pas avoir de conteneurs fils
standardWrapper.notClass=Aucune classe servlet n''a été spécifiée pour la servlet [{0}]
standardWrapper.notContext=Le conteneur parent d'un enrobeur (wrapper) doit être un contexte
standardWrapper.notFound=Servlet [{0}] n''est pas disponible.
standardWrapper.notServlet=La classe [{0}] n''est pas une servlet
standardWrapper.releaseFilters=Exception des filtres de sortie (release filters) pour la servlet [{0}]
standardWrapper.serviceException="Servlet.service()" pour la servlet [{0}] a généré une exception
standardWrapper.serviceExceptionRoot=Servlet.service() du Servlet [{0}] dans le contexte au chemin [{1}] a retourné une exception [{2}] avec la cause
standardWrapper.unavailable=La servlet [{0}] est marqué comme indisponible
standardWrapper.unloadException=La servlet [{0}] a généré une exception "unload()"
standardWrapper.unloading=Impossible d''allouer la servlet [{0}] car elle a été déchargée
standardWrapper.waiting=Attente de la désallocation de [{0}] instance(s) du Servlet [{1}]
threadLocalLeakPreventionListener.containerEvent.error=Exception lors du traitement de l''évènement du conteneur [{0}]
threadLocalLeakPreventionListener.lifecycleEvent.error=Exception lors du traitement de l''évènement [{0}] du cycle de vie du composant

View File

@@ -0,0 +1,270 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
applicationContext.addFilter.ise=コンテキストが初期化されたため、フィルタをコンテキスト[{0}]に追加できません
applicationContext.addJspFile.iae=不正な JSP ファイル [{0}] です。
applicationContext.addListener.iae.cnfe=クラス [{0}] のインスタンスを作成できません。
applicationContext.addListener.iae.init=[{0}]型のインスタンスをリスナーとして追加できません。
applicationContext.addListener.iae.sclNotAllowed=最初のServletContextListenerが呼び出されると、それ以上ServletContextListenerを追加することはできません。
applicationContext.addListener.iae.wrongType=指定されたクラス [{0}] はリスナークラスのインスタンスではありません。
applicationContext.addListener.ise=コンテキストが初期化されているため、リスナーをコンテキスト[{0}]に追加できません。
applicationContext.addRole.ise=コンテキスト [{0}] は初期化済みのためロールを追加できません。
applicationContext.addServlet.ise=コンテキストが初期化済みなため、Servletをコンテキスト[{0}]に追加できません。
applicationContext.attributeEvent=属性イベントリスナによって例外が投げられました
applicationContext.illegalDispatchPath=アプリケーションが、エンコードされたディレクトリトラバーサル試行を含むために拒否された不正なパス[{0}]を持つ要求ディスパッチャを取得しようとしました。
applicationContext.invalidFilterName=無効なフィルタ名[{0}]のためにフィルタ定義を追加できません。
applicationContext.invalidServletName=不正なサーブレット名 [{0}] のため、サーブレット定義を追加できません。
applicationContext.lookup.error=コンテキスト[{1}]でリソース[{0}]の場所を特定できませんでした。
applicationContext.mapping.error=マッピング中のエラーです
applicationContext.requestDispatcher.iae=パス [{0}] が"/"文字で始まりません
applicationContext.resourcePaths.iae=パス[{0}]は「/」文字で始まっていません。
applicationContext.role.iae=コンテキスト[{0}]を宣言する個々のロールは、nullでも空の文字列でもありません。
applicationContext.roles.iae=コンテキスト[{0}]に対して宣言するロールの配列はnullにできません。
applicationContext.setAttribute.namenull=nameがnullではいけません
applicationContext.setInitParam.ise=初期化パラメータは、コンテキストが初期化された後に設定することはできません。
applicationContext.setRequestEncoding.ise=コンテキスト [{0}] は初期化済みのためリクエストエンコーディングを構成できません。
applicationContext.setResponseEncoding.ise=コンテキスト [{0}] は初期化済みのため、レスポンスエンコーディングを構成できません。
applicationContext.setSessionTimeout.ise=コンテキストが初期化されているため、コンテキスト[{0}]にセッションタイムアウトを設定できません
applicationContext.setSessionTracking.iae.invalid=コンテキスト[{1}]に対して要求されたセッション追跡モード[{0}]は、そのコンテキストではサポートされていません。
applicationContext.setSessionTracking.iae.ssl=コンテキスト[{0}]に対して要求されたセッショントラッキングモードには、SSLと少なくとも1つの他のモードが含まれていました。 SSLは他のモードでは設定できません。
applicationContext.setSessionTracking.ise=コンテキスト [{0}] は実行中のためセッション追跡モードを構成できません。
applicationDispatcher.allocateException=サーブレット [{0}] に例外を割り当てます
applicationDispatcher.deallocateException=サーブレット [{0}] の例外を解除します
applicationDispatcher.forward.ise=レスポンスをコミットした後でフォワードできません
applicationDispatcher.isUnavailable=サーブレット [{0}] は現在利用できません
applicationDispatcher.serviceException=サーブレット [{0}] のServlet.service()が例外を投げました
applicationDispatcher.specViolation.request=元のServletRequestまたはラップされた元のServletRequestはSRV.8.2およびSRV.14.2.5.1に違反しするのでRequestDispatcherに渡されません。
applicationDispatcher.specViolation.response=SRV.8.2 および SRV.14.2.5.1 に違反しているため、オリジナルあるいはラップされた ServletResponse は RequestDispatcher を通過しませんでした。
applicationFilterConfig.jmxRegisterFail=クラス [{0}] 名前 [{1}] のフィルターを JMX に登録できません。
applicationFilterConfig.jmxUnregister=タイプ[{0}]および名前[{1}]のフィルタのJMX登録解除が完了しました。
applicationFilterConfig.jmxUnregisterFail=クラス [{0}] 名前 [{1}] の JMX フィルターを登録解除できません。
applicationFilterConfig.preDestroy=[{1}]型の名[{0}]というフィルタのpreDestroyへの呼び出しに失敗しました
applicationFilterConfig.release=タイプ[{1}]の名前[{0}]のフィルタを破棄できませんでした。
applicationFilterRegistration.nullInitParam=NULLの名前や値のためにフィルターの初期化パラメーターを設定できません。 名前[{0}]、値[{1}]
applicationFilterRegistration.nullInitParams=キー [{0}] または値 [{1}] のいずれかが null のためフィルターの初期化パラメータを設定できませんでした。
applicationPushBuilder.methodInvalid=プッシュリクエストの HTTP メソッドはキャッシュ可能、かつ、安全でなければなりません。[{0}] は指定できません。
applicationPushBuilder.methodNotToken=HTTP メソッド [{0}] にトークンとして利用できない文字が含まれています。
applicationServletRegistration.setServletSecurity.iae=サーブレット[{0}]に指定されたNULL制約が、名前[{1}]のコンテキストにデプロイされました
applicationServletRegistration.setServletSecurity.ise=コンテキストが既に初期化されているため、名前[{1}]のコンテキストにデプロイされたサーブレット[{0}]にセキュリティ制約を追加できません。
applicationSessionCookieConfig.ise=コンテキスト[{1}]が初期化済みなので、プロパティ[{0}]をSessionCookieConfigに追加することはできません。
aprListener.aprDestroy=APRベースのApache Tomcatネイティブライブラリのシャットダウンに失敗しました。
aprListener.aprInit=商用環境に最適な性能を発揮する APR ベースの Tomcat ネイティブライブラリが java.library.path [{0}] に存在しません。
aprListener.aprInitDebug=APRベースのApache Tomcatネイティブライブラリは、java.library.path [{1}]上の名前[{0}]を使用して見つかりませんでした。 報告されたエラーは[{2}]
aprListener.aprInitError=APRベースのApache Tomcatネイティブライブラリをロードできませんでした。 報告されたエラーは[{0}]でした
aprListener.config=APR/OpenSSL設定useAprConnector [{0}]、useOpenSSL [{1}]
aprListener.currentFIPSMode=現在のFIPSモード[{0}]
aprListener.enterAlreadyInFIPSMode=AprLifecycleListenerは強制的にFIPSモードに入るように設定されていますが、ライブラリはすでにFIPSモードになっています[{0}]
aprListener.flags=APR機能IPv6 [{0}]、sendfile {1}]、受け入れフィルタ[{2}]、ランダム[{3}]
aprListener.initializeFIPSFailed=FIPS モードに変更できません。
aprListener.initializeFIPSSuccess=FIPS モードに入りました。
aprListener.initializedOpenSSL=OpenSSLは[{0}]を正常に初期化しました。
aprListener.initializingFIPS=FIPSモードを初期化しています。
aprListener.requireNotInFIPSMode=AprLifecycleListenerはライブラリが既にFIPSモードになっている必要があるように設定されていますが、FIPSモードではありませんでした。
aprListener.skipFIPSInitialization=すでにFIPSモードになっています。 FIPS初期化をスキップします。
aprListener.sslInit=SSLEngineの初期化に失敗しました。
aprListener.tcnInvalid=APRベースのApache Tomcatネイティブライブラリの互換性のないバージョン[{0}]がインストールされていますが、Tomcatにはバージョン[{1}]が必要です。
aprListener.tcnValid=APRバージョン[{1}]を使用してAPRベースのApache Tomcatネイティブライブラリ[{0}]をロードしました。
aprListener.tcnVersion=インストールされた Apache Tomcat ネイティブライブラリの APR バージョンは [{0}] ですが、推奨する最小バージョンは [{1}] です。
aprListener.tooLateForFIPSMode=FIPSModeを設定できませんSSLは既に初期化されています。
aprListener.tooLateForSSLEngine=setSSLEngine出来ませんSSLはすでに初期化されています
aprListener.tooLateForSSLRandomSeed=setSSLRandomSeedできませんSSLは既に初期化されています。
aprListener.wrongFIPSMode=AprLifecycleListener の設定 FIPSMode に予期せぬ値 [{0}] が指定されました。
asyncContextImpl.asyncDispachError=非同期ディスパッチの処理中にエラーが発生しました。
asyncContextImpl.dispatchingStarted=非同期ディスパッチ操作は既に呼び出されています。 同じ非同期サイクル内の追加の非同期ディスパッチ操作は許可されません。
asyncContextImpl.noAsyncDispatcher=ServletContextから返されたディスパッチャは非同期ディスパッチをサポートしていません。
asyncContextImpl.onCompleteError=クラス [{0}] のリスナーオブジェクトで onComplete() の呼び出しに失敗しました。
asyncContextImpl.onErrorError=クラス [{0}] のリスナーオブジェクトで onError() の呼び出しに失敗しました。
asyncContextImpl.onStartAsyncError=クラス [{0}] のリスナーオブジェクトで onStartAsync() の呼び出しに失敗しました。
asyncContextImpl.onTimeoutError=クラス [{0}] のリスナーオブジェクトで onTimeout() の呼び出しに失敗しました。
asyncContextImpl.request.ise=complete()の後、またはdispatch()メソッドのどれかが呼び出された不正なgetRequest()の呼び出し
asyncContextImpl.requestEnded=AsyncContextに関連付けられたリクエストは、すでに処理を完了しています。
asyncContextImpl.response.ise=complete()、またはdispatch()メソッドのいずれかが呼び出された後での、不正なgetResponse()呼び出し。
containerBase.backgroundProcess.cluster=クラスター [{0}] でバックグランド処理を実行中に例外が発生しました。
containerBase.backgroundProcess.realm=Realm [{0}] のバックグラウンド処理中に例外が発生しました。
containerBase.backgroundProcess.unexpectedThreadDeath=バックグラウンドスレッド [{0}] は予期せぬ理由で終了しました。
containerBase.backgroundProcess.valve=Valve [{0}] のバックグラウンドプロセス処理中の例外
containerBase.nullName=コンテナー名は null にできません。
containerBase.threadedStartFailed=子コンテナーを開始できません。
containerBase.threadedStopFailed=停止中に子コンテナが失敗しました。
defaultInstanceManager.invalidInjection=不正なメソッドリソースアノテーションです。
defaultInstanceManager.restrictedClass=制限されたクラス [{0}] へのアクセスは拒否されました。制限されたクラスを読み込むには Web アプリケーションに特権を構成しなければなりません。
defaultInstanceManager.restrictedContainerServlet=クラス [{0}] へのアクセスは禁止されています。制限クラスです (ContainerServlet インターフェイスを実装しています)。アクセス可能にするにはWebアプリケーションに特権を構成しなければなりません。
defaultInstanceManager.restrictedFiltersResource=制限フィルターのプロパティファイルが見つかりません [{0}]
defaultInstanceManager.restrictedListenersResource=制限付きリスナープロパティファイルが見つかりませんでした[{0}]
defaultInstanceManager.restrictedServletsResource=Restricted サーブレットプロパティファイルが見つかりません。[{0}]
defaultInstanceManager.restrictedWrongValue=クラス名[{1}]の制限付きクラスのプロパティファイル[{0}]の値が間違っています。 期待値:[制限]、実際値:[{2}]
filterChain.filter=フィルタの実行により例外を投げました
filterChain.servlet=サーブレットの実行により例外を投げました
jreLeakListener.authPolicyFail=javax.security.auth.Policyクラスのメモリリークの防止を試みる際にエラーが発生しました。
jreLeakListener.classToInitializeFail=Tomcat起動中に可能なメモリーリークを防止するためのクラス[{0}]をロードすることに失敗しました。
jreLeakListener.gcDaemonFail=Tomcat の開始時に潜在的なメモリーリークを防ぐ GC デーモンスレッドの作成を開始できませんでした。Sun の JVM ではない可能性があります。
jreLeakListener.jarUrlConnCacheFail=デフォルトでJar URL接続のキャッシュを無効にできませんでした。
jreLeakListener.ldapPoolManagerFail=Tomcatの起動時にメモリリークを防ぐ為にcom.sun.jndi.ldap.LdapPoolManagerクラスの作成をトリガーすることができませんでした。 これはSun以外のJVMであることが予想されます。
jreLeakListener.xmlParseFail=XML解析のメモリリークを防止しようとする際にエラーが発しました。
naming.addEnvEntry=環境変数 [{0}] を追加します。
naming.addResourceEnvRef=リソースenv ref [{0}]を追加しています。
naming.bindFailed=オブジェクトのバインドに失敗しました: [{0}]
naming.invalidEnvEntryType=環境エントリ [{0}] は無効な型を持っています
naming.invalidEnvEntryValue=環境エントリ [{0}] は無効な値を持っています
naming.jmxRegistrationFailed=JMX に登録できませんでした: [{0}]
naming.namingContextCreationFailed=名前付きコンテキストの生成に失敗しました: [{0}]
naming.unbindFailed=オブジェクトのアンバインドに失敗しました: [{0}]
naming.wsdlFailed=wsdl ファイル [{0}] が見つかりませんでした。
noPluggabilityServletContext.notAllowed=Servlet 3.0仕様の4.4節では、web.xmlに定義されていないServletContextListener、web-fragment.xmlファイル、@WebListenerアテーションからこのメソッドを呼び出すことはできません。
pushBuilder.noPath=path を設定する前に push() を呼び出すことはできません。
standardContext.applicationListener=クラス [{0}] のアプリケーションリスナの設定中にエラーが発生しました
standardContext.applicationSkipped=前のエラーのためにアプリケーションリスナのインストールをスキップします
standardContext.backgroundProcess.instanceManager=インスタンスマネージャ[{0}]のバックグラウンドプロセス処理中の例外
standardContext.backgroundProcess.loader=Loader[{0}]のバックグラウンドプロセス処理中に例外が発生
standardContext.backgroundProcess.manager=マネージャ[{0}]のバックグラウンドプロセス処理中の例外
standardContext.backgroundProcess.resources=リソース[{0}]バックグラウンドプロセス処理中の例外
standardContext.cluster.noManager=Managerが見つかりませんでした。 ClusterManagerを使用するかどうかの確認。 クラスタ構成:[{0}]、アプリケーション配布可能:[{1}]
standardContext.configurationFail=コンテキストが正しく設定されていないとマークされた1つ以上のコンポーネント
standardContext.cookieProcessor.null=コンテキストの CookieProcessor には null を指定できません。
standardContext.duplicateListener=リスナー[{0}]は、すでにこのコンテキストに構成されています。 重複定義は無視されました。
standardContext.errorPage.error=エラーページの位置 [{0}] は''/''で始まらなければいけません
standardContext.errorPage.required=ErrorPageがnullではいけません
standardContext.errorPage.warning=警告: Servlet 2.4ではエラーページの位置 [{0}] は''/''で始まらなければいけません
standardContext.extensionValidationError=必要なアプリケーション拡張の検証中にエラーが発生しました
standardContext.filterFail=1つまたは複数のフィルタを開始できませんでした。 完全な詳細は適切なコンテナログファイルにあります。
standardContext.filterMap.either=フィルタマッピングは<url-pattern>又は<servlet-name>のどちらかを指定しなければいけません
standardContext.filterMap.name=フィルタマッピングは未知のフィルタ名 [{0}] を指定しました
standardContext.filterMap.pattern=フィルタマッピング中に無効な <url-pattern> [{0}] があります
standardContext.filterStart=フィルタ [{0}] の起動中の例外です
standardContext.invalidWrapperClass=クラス [{0}] は StandardWrapper の派生クラスではありません。
standardContext.isUnavailable=このアプリケーションは現在利用できません
standardContext.listenerFail=1つまたは複数のリスナーが開始に失敗しました。 完全な詳細は適切なコンテナログファイルにあります。
standardContext.listenerStart=クラス [{0}] のリスナインスタンスにコンテキスト初期化イベントを送信中の例外です
standardContext.listenerStop=クラス [{0}] のリスナインスタンスにコンテキスト破棄イベントを送信中の例外です
standardContext.loadOnStartup.loadException=Web アプリケーション [{0}] のサーブレット [{1}] の load() メソッドは例外を投げました。
standardContext.loginConfig.errorPage=フォームのエラーページ [{0}] は''/''で始まらなければいけません
standardContext.loginConfig.errorWarning=警告: Servlet 2.4ではフォームのエラーページ [{0}] は''/''で始まらなければいけません
standardContext.loginConfig.loginPage=フォームのログインページ [{0}] は''/''で始まらなければいけません
standardContext.loginConfig.loginWarning=警告: Servlet 2.4ではフォームのログインページ [{0}] は''/''で始まらなければいけません
standardContext.loginConfig.required=LoginConfigはnullではいけません
standardContext.manager=クラス [{0}] をManagerとして構成しました。
standardContext.managerFail=セッションマネージャーを開始できません。
standardContext.namingResource.destroy.fail=以前の名前付きリソースを破棄できませんでした。
standardContext.namingResource.init.fail=新しいネーミングリソースの初期化に失敗しました。
standardContext.notStarted=コンテキストはまだ起動されていません
standardContext.notWrapper=コンテキストの子供はラッパでなければいけません
standardContext.parameter.duplicate=コンテキスト初期化パラメタ [{0}] が重複しています
standardContext.parameter.required=パラメタ名とパラメタ値の両方が必要です
standardContext.pathInvalid=コンテキストパスは空文字列あるいは "/" で開始し "/" で終了しない文字列でなければなりません。パス [{0}] はこの条件を満たさないため [{1}] へ変更しました。
standardContext.postconstruct.duplicate=クラス[{0}]のpost constructメソッド定義が重複しています。
standardContext.postconstruct.required=完全限定クラス名とメソッド名の両方が必要です。
standardContext.predestroy.duplicate=クラス [{0}] のメソッド定義に @PreDestroy が重複しています。
standardContext.predestroy.required=完全修飾クラス名とメソッド名の両方が必要です。
standardContext.reloadingCompleted=このコンテキストの再ロードが完了しました
standardContext.reloadingStarted=このコンテキストの再ロードを開始しました
standardContext.requestListener.requestInit=クラス [{0}] のリスナインスタンスに初期化するライフサイクルイベントのリクエストを送信中の例外です
standardContext.resourcesInit=静的リソースの初期化エラー
standardContext.resourcesStart=静的リソースの起動中のエラーです
standardContext.resourcesStop=静的リソースの停止中のエラー
standardContext.sciFail=ServletContainerInitializer の処理中にエラーが発生しました。
standardContext.securityConstraint.mixHttpMethod=1つの Web リソースコレクションに <http-method> と <http-method-omission> を両方指定することはできません。
standardContext.securityConstraint.pattern=セキュリティの制約の中に無効な <url-pattern> [{0}] があります
standardContext.servletFail=起動時に一つ以上のサーブレットの読み込みが失敗しました。詳細は適切なコンテナーのログファイルを確認してください。
standardContext.servletMap.name=サーブレットマッピングは未知のサーブレット名 [{0}] を指定しています
standardContext.servletMap.pattern=サーブレットマッピング中に無効な <url-pattern> [{0}] があります
standardContext.startFailed=以前のエラーのためにコンテキストの起動が失敗しました [{0}]
standardContext.startingContext=名前[{0}]のコンテキストを開始する際の例外
standardContext.stop.asyncWaitInterrupted=実行中の非同期要求が完了するのをunloadDelayミリ秒待っている間に割り込みを受信しました。 コンテキスト停止はさらに遅れることなく続行されます。
standardContext.stoppingContext=ローダを停止中の例外です
standardContext.threadBindingListenerError=コンテキスト [{0}] に構成されたリスナーを束縛するスレッドで異常が発生しました。
standardContext.urlPattern.patternWarning=警告: Servlet 2.4ではURLパターン [{0}] は''/''で始まらなければいけません
standardContext.webappClassLoader.missingProperty=プロパティが存在しないため、Webアプリケーションクラスローダプロパティ[{0}]を[{1}]に設定できません。
standardContext.workCreateException=コンテキスト[{2}]のディレクトリ[{0}]とCATALINA_HOME [{1}]からの絶対workディレクトリを特定できませんでした
standardContext.workCreateFail=コンテキスト [{1}] の作業ディレクトリ [{0}] を作成できません。
standardContext.workPath=コンテキスト[{0}]のworkパスを取得中の例外
standardContextValve.acknowledgeException=100 (Continue) レスポンスでリクエストを確認できませんでした。
standardEngine.jvmRouteFail=EngineのjvmRoute属性をシステムプロパティから設定できませんでした
standardEngine.noHost=サーバ名 [{0}] に一致するホストが存在しません
standardEngine.notHost=Engineの子供はHostでなければいけません
standardEngine.notParent=エンジンは親のコンテナを持つことはできません
standardHost.clientAbort=リモートクライアントがリクエストを中止しました, IOException: [{0}]
standardHost.invalidErrorReportValveClass=指定されたErrorReportValveクラスをロードできません: [{0}]
standardHost.noContext=このリクエストを処理するために設定されたコンテキストがありません
standardHost.notContext=Host の子供はContextでなければいけません
standardHost.nullName=ホスト名が必要です
standardHost.problematicAppBase=ホスト[{0}]のappBaseに空の文字列を使用すると、CATALINA_BASEに設定されますが、これは悪い考えです。
standardHostValue.customStatusFailed=カスタムエラーページ[{0}]を正しくディスパッチできませんでした。
standardPipeline.basic.start=新しい基本 Valve を開始できません。
standardPipeline.basic.stop=古い基本 Valve を停止できません。
standardPipeline.valve.destroy=Valve を破棄できません。
standardPipeline.valve.start=Valve を開始できません。
standardPipeline.valve.stop=Valve を停止できません。
standardServer.accept.error=シャットダウンコマンドを受信するソケットの accept で入出力例外が発生しました。
standardServer.accept.readError=シャットダウンコマンドの読み取り時に入出力例外が発生しました。
standardServer.accept.security=シャットダウンコマンドを受信するソケットの accept でセキュリティエラーを発生しました。
standardServer.accept.timeout=シャットダウンコマンドをリスンするソケットは、accept()の呼び出し後に予期しないタイムアウト[{0}]ミリ秒を経験しました。 これはバグ56684の一例ですか
standardServer.invalidShutdownCommand=不正なシャットダウンコマンド [{0}] を受信しました。
standardServer.shutdownViaPort=有効なシャットダウンコマンドがシャットダウンポート経由で受信されました。 サーバーインスタンスを停止します。
standardServer.storeConfig.contextError=コンテキスト [{0}] の構成の格納時にエラーが発生しました。
standardServer.storeConfig.error=サーバー構成を格納できません。
standardServer.storeConfig.notAvailable=StoreConfig実装は[{0}]という名前のMBeanとして登録されていないため、設定を保存することはできません。 適切なMBeanは通常StoreConfigLifecycleListenerを介して登録されます。
standardService.engine.startFailed=関連するEngineの起動に失敗しました
standardService.engine.stopFailed=関連するEngineの停止に失敗しました。
standardService.mapperListener.startFailed=関連するMapperListenerの起動に失敗しました。
standardService.mapperListener.stopFailed=関連するMapperListenerの停止に失敗しました。
standardService.start.name=サービス [{0}] を起動します
standardService.stop.name=サービス [{0}] を停止します
standardWrapper.allocate=サーブレットインスタンスを割り当て中のエラーです
standardWrapper.allocateException=サーブレット [{0}] に例外を割り当てます
standardWrapper.deallocateException=サーブレット [{0}] に対する例外の割り当てを解除します
standardWrapper.destroyException=サーブレット [{0}] のServlet.destroy()が例外を投げました
standardWrapper.destroyInstance=サーブレット [{0}] の InstanceManager.destroy() が例外を送出しました。
standardWrapper.initException=サーブレット [{0}] のServlet.init()が例外を投げました
standardWrapper.instantiate=サーブレットクラス [{0}] を初期化中にエラーが発生しました
standardWrapper.isUnavailable=サーブレット [{0}] は現在利用できません
standardWrapper.notChild=Wrapper コンテナは子供のコンテナを持つことはできません
standardWrapper.notClass=サーブレット [{0}] に指定されたサーブレットクラスがありません
standardWrapper.notContext=Wrapper の親のコンテナはContextでなければいけません
standardWrapper.notFound=サーブレット [{0}] が利用できません
standardWrapper.notServlet=クラス [{0}] はServletではありません
standardWrapper.releaseFilters=サーブレット [{0}] のフィルタ例外を解除します
standardWrapper.serviceException=サーブレット [{0}] のServlet.service()が例外を投げました
standardWrapper.serviceExceptionRoot=パス[{1}]を持つコンテキスト内のサーブレット[{0}]のServlet.service() が例外[{2}]が根本的要因と共に投げられました。
standardWrapper.unavailable=サーブレット [{0}] を利用不可能にマークします
standardWrapper.unloadException=サーブレット [{0}] がunload()例外を投げました
standardWrapper.unloading=サーブレット [{0}] がロードされていないので、割り当てることができません
standardWrapper.waiting=[{0}] インスタンスが割り当て解除されるのを待っています
threadLocalLeakPreventionListener.containerEvent.error=コンテナーイベント [{0}] の処理中に例外が発生しました。
threadLocalLeakPreventionListener.lifecycleEvent.error=ライフサイクルイベント [{0}] を処理中に例外が発生しました。

View File

@@ -0,0 +1,276 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
applicationContext.addFilter.ise=컨텍스트가 이미 초기화되었기 때문에, 필터들은 컨텍스트 [{0}]에 추가될 수 없습니다.
applicationContext.addJspFile.iae=JSP 파일 [{0}]은(는) 유효하지 않습니다.
applicationContext.addListener.iae.cnfe=타입 [{0}]의 인스턴스를 생성할 수 없습니다.
applicationContext.addListener.iae.init=타입 [{0}]의 인스턴스를 리스너로서 추가할 수 없습니다.
applicationContext.addListener.iae.sclNotAllowed=첫번째 ServletContextListener가 호출되고 나면, 더 이상 ServletContextListener들을 추가할 수 없습니다.
applicationContext.addListener.iae.wrongType=지정된 타입 [{0}]이(가) 요구되는 리스너 타입들 중의 하나가 아닙니다.
applicationContext.addListener.ise=컨텍스트가 이미 초기화 되었기에, 컨텍스트 [{0}]에 리스너를 추가할 수 없습니다.
applicationContext.addRole.ise=해당 컨텍스트가 이미 초기화되어 있기에, 역할들이 컨텍스트 [{0}]에 추가될 수 없습니다.
applicationContext.addServlet.ise=컨텍스트 [{0}]이(가) 이미 초기화되었기에, 서블릿들이 추가될 수 없습니다.
applicationContext.attributeEvent=속성 이벤트 리스너가 예외를 발생시켰습니다.
applicationContext.illegalDispatchPath=애플리케이션이 불허된 경로 [{0}](으)로 RequestDispatcher를 얻으려 시도했지만, 해당 경로가 인코딩된 디렉토리 경로 이동 시도를 포함하고 있기 때문에, 거부되었습니다.
applicationContext.invalidFilterName=유효하지 않은 필터 이름 [{0}]으로 인하여, 필터 정의를 추가할 수 없습니다.
applicationContext.invalidServletName=유효하지 않은 서블릿 이름 ([{0}]) 때문에, 서블릿 정의를 추가할 수 없습니다.
applicationContext.lookup.error=컨텍스트 [{1}] 내의 리소스 [{0}]의 위치를 결정하지 못했습니다.
applicationContext.mapping.error=매핑 중 오류 발생
applicationContext.requestDispatcher.iae=경로 [{0}]이(가) "/" 문자로 시작하지 않습니다.
applicationContext.resourcePaths.iae=경로 [{0}]이(가) "/" 문자로 시작하지 않습니다.
applicationContext.role.iae=컨텍스트 [{0}]을(를) 위해 선언되는 개별 역할이, 널이거나 빈 문자열이어서는 안됩니다.
applicationContext.roles.iae=컨텍스트 [{0}]을(를) 위해 선언된 역할들의 배열이 널이어서는 안됩니다.
applicationContext.setAttribute.namenull=속성 이름이 널이어서는 안됩니다.
applicationContext.setInitParam.ise=컨텍스트가 이미 초기화된 후에, 초기화 파라미터들이 설정될 수 없습니다.
applicationContext.setRequestEncoding.ise=컨텍스트가 이미 초기화되었기에, 요청된 인코딩은 컨텍스트 [{0}]을(를) 위해 설정될 수 없습니다.
applicationContext.setResponseEncoding.ise=컨텍스트가 이미 초기화되었으므로, 컨텍스트 [{0}]을(를) 위한 응답 인코딩을 설정할 수 없습니다.
applicationContext.setSessionTimeout.ise=컨텍스트 [{0}]이(가) 이미 초기화되었기에, 세션 제한시간이 설정할 수 없습니다.
applicationContext.setSessionTracking.iae.invalid=컨텍스트 [{1}]를 위해 요청된 세션 트랙킹 모드 [{0}]은(는), 이 컨텍스트에서 지원되지 않습니다.
applicationContext.setSessionTracking.iae.ssl=컨텍스트 [{0}]을(를) 위해 요청된 세션 트랙킹 모드들이, SSL과 적어도 다른 하나 이상의 모드들을 포함했습니다. SSL은 다른 모드들과 함께 설정될 수 없습니다.
applicationContext.setSessionTracking.ise=컨텍스트 [{0}]을(를) 위한 세션 트랙킹 모드들은, 컨텍스트가 실행되고 있는 중에 설정될 수 없습니다.
applicationDispatcher.allocateException=서블릿 [{0}]을(를) 위한 할당 중 예외 발생
applicationDispatcher.deallocateException=서블릿 [{0}]을(를) 위한 할당 해제 작업 중 예외 발생
applicationDispatcher.forward.ise=응답이 이미 커밋된 후에는 forward할 수 없습니다.
applicationDispatcher.isUnavailable=서블릿 [{0}]은(는) 현재 가용하지 않습니다.
applicationDispatcher.serviceException=서블릿 [{0}]을(를) 위한 Servlet.service() 호출이 예외를 발생시켰습니다.
applicationDispatcher.specViolation.request=원본 ServletRequest 또는 wrap된 원본 ServletRequest가 RequestDispatcher로 전달되지 않았으며, 이는 SRV.8.2와 SRV.14.2.5.1에 대한 위반입니다.
applicationDispatcher.specViolation.response=원래의 ServletResponse 또는 wrapping된 원래의 ServletResponse가 RequestDispatcher에 전달되지 않았으며, 이는 SRV.8.2와 SRV.14.2.5.1을 위반합니다.
applicationFilterConfig.jmxRegisterFail=타입이 [{0}](이)고 이름이 [{1}]인 필터를 위한 JMX 등록이 실패했습니다.
applicationFilterConfig.jmxUnregister=타입이 [{0}](이)고 이름이 [{1}]인 필터를 위해, JMX 등록 제거가 완료되었습니다.
applicationFilterConfig.jmxUnregisterFail=타입이 [{0}](이)고 이름이 [{1}]인 필터를 위한, JMX 등록을 제거하지 못했습니다.
applicationFilterConfig.preDestroy=타입이 [{1}]이고 이름이 [{0}]인 필터에 대해 preDestroy를 호출하지 못했습니다.
applicationFilterConfig.release=타입이 [{1}](이)고 이름이 [{0}]인 필터를 소멸시키지 못했습니다.
applicationFilterRegistration.nullInitParam=이름 또는 값 또는 둘 다 널이어서, 필터를 위한 초기화 파라미터를 설정할 수 없습니다. 이름: [{0}], 값: [{1}]
applicationFilterRegistration.nullInitParams=널인 이름 또는 값 때문에, 필터의 초기화 파라미터를 설정할 수 없습니다. 이름: [{0}], 값: [{1}]
applicationHttpRequest.fragmentInDispatchPath=디스패치 경로 [{0}](으)로부터 URI fragment를 제거했습니다.
applicationPushBuilder.methodInvalid=PUSH 요청을 위한 HTTP 메소드는 반드시 캐시 가능하고 안전해야 하는데, [{0}]은(는) 그렇지 않습니다.
applicationPushBuilder.methodNotToken=HTTP 메소드들은 토큰들이어야 하지만, [{0}]은(는) 토큰이 아닌 문자를 포함하고 있습니다.
applicationServletRegistration.setServletSecurity.iae=[{1}](이)라는 이름의 컨텍스트에 배치된 서블릿 [{0}]을(를) 위해, 널 constraint가 지정되었습니다.
applicationServletRegistration.setServletSecurity.ise=컨텍스트가 이미 초기화되었기에, [{1}](이)라는 이름의 컨텍스트에 배치된 서블릿 [{0}]에 security constraint들이 추가될 수 없습니다.
applicationSessionCookieConfig.ise=컨텍스트가 이미 초기화되었기에, 컨텍스트 [{1}]을(를) 위한 SessionCookieConfig에 프로퍼티 [{0}]이(가) 추가될 수 없습니다.
aprListener.aprDestroy=APR 기반 Apache Tomcat Native 라이브러리를 셧다운하지 못했습니다.
aprListener.aprInit=프로덕션 환경들에서 최적의 성능을 제공하는, APR 기반 Apache Tomcat Native 라이브러리가, 다음 java.library.path에서 발견되지 않습니다: [{0}]
aprListener.aprInitDebug=[{0}](이)라는 이름들을 사용하여, java.library.path [{1}]에서, APR 기반 Apache Tomcat Native 라이브러리를 찾을 수 없습니다. 보고된 오류들: [{2}]
aprListener.aprInitError=APR 기반 Apache Tomcat Native 라이브러리를 로드하지 못했습니다. 보고된 오류는 [{0}]입니다.
aprListener.config=APR/OpenSSL 설정: useAprConnector [{0}], useOpenSSL [{1}]
aprListener.currentFIPSMode=현재의 FIPS 모드: [{0}]
aprListener.enterAlreadyInFIPSMode=AprLifecycleListener가 강제로 FIPS 모드로 들어가도록 설정되었으나, 라이브러리가 이미 FIPS 모드 [{0}]에 있습니다.
aprListener.flags=APR 용량정보들: IPv6 [{0}], sendfile [{1}], accept filters [{2}], random [{3}].
aprListener.initializeFIPSFailed=FIPS 모드로 진입하지 못했습니다.
aprListener.initializeFIPSSuccess=FIPS 모드로 성공적으로 진입했습니다.
aprListener.initializedOpenSSL=OpenSSL이 성공적으로 초기화되었습니다: [{0}]
aprListener.initializingFIPS=FIPS 모드 초기화...
aprListener.requireNotInFIPSMode=AprLifecycleListener는 라이브러리가 이미 FIPS 모드에 있어야만 하도록 설정되어 있는데, FIPS 모드에 있지 않았습니다.
aprListener.skipFIPSInitialization=이미 FIPS 모드에 있습니다. FIPS 초기화는 건너뜁니다.
aprListener.sslInit=SSLEngine을 초기화하지 못했습니다.
aprListener.tcnInvalid=APR 기반의 Apache Tomcat Native 라이브러리가 호환되지 않는 버전 [{0}]이(가) 설치되어 있습니다. Tomcat은 버전 [{1}]을(를) 요구합니다.
aprListener.tcnValid=APR 버전 [{1}]을(를) 사용한, APR 기반 Apache Tomcat Native 라이브러리 [{0}]을(를) 로드했습니다.
aprListener.tcnVersion=APR 기반의 Apache Tomcat Native 라이브러리의 예전 버전 [{0}](이)가 설치되어 있습니다. Tomcat은 최소 버전으로서 [{1}]을(를) 추천합니다.
aprListener.tooLateForFIPSMode=setFIPSMode를 수행할 수 없습니다: SSL이 이미 초기화되었습니다.
aprListener.tooLateForSSLEngine=setSSLEngine을 호출할 수 없습니다: SSL이 이미 초기화 되었습니다.
aprListener.tooLateForSSLRandomSeed=setSSLRandomSeed를 호출할 수 없습니다: SSL이 이미 초기화되어 있습니다.
aprListener.wrongFIPSMode=예기치 않은 AprLifecycleListener의 FIPSMode 옵션 값: [{0}]
asyncContextImpl.asyncDispachError=비동기 디스패치 도중 오류 발생
asyncContextImpl.asyncRunnableError=AsyncContext.start()를 통해, 비동기로 Runnable을 처리하는 도중 오류 발생
asyncContextImpl.dispatchingStarted=비동기 디스패치 오퍼레이션이 이미 호출되었습니다. 동일한 비동기 사이클 내에서, 추가적인 비동기 디스패치 오퍼레이션은 허용되지 않습니다.
asyncContextImpl.fireOnComplete=등록된 AsyncListener들에 onComplete() 이벤트를 호출합니다.
asyncContextImpl.fireOnError=등록된 AsyncListener들에 onError() 이벤트를 호출합니다.
asyncContextImpl.fireOnStartAsync=등록된 AsyncListener들에 onStartAsync() 이벤트를 호출합니다.
asyncContextImpl.fireOnTimeout=등록된 AsyncListener들에 onTimeout() 이벤트를 호출합니다.
asyncContextImpl.noAsyncDispatcher=ServletContext로부터 반환된 디스패처는 비동기 디스패치를 지원하지 않습니다.
asyncContextImpl.onCompleteError=타입 [{0}]의 리스너를 위한 onComplete() 호출이 실패했습니다.
asyncContextImpl.onErrorError=타입 [{0}]의 리스너를 위한 onError() 호출이 실패했습니다.
asyncContextImpl.onStartAsyncError=타입 [{0}]의 리스너를 위한 onStartAsync() 호출이 실패했습니다.
asyncContextImpl.onTimeoutError=타입이 [{0}]인 리스너를 위한, onTimeout() 호출이 실패했습니다.
asyncContextImpl.request.ise=complete() 또는 어떠한 종류의 dispatch() 메소드들이 호출된 후에, getRequest()를 호출하는 것은 불허됩니다.
asyncContextImpl.requestEnded=AsyncContext와 연관된 요청은 이미 처리를 완료했습니다.
asyncContextImpl.response.ise=complete() 또는 어떤 종류의 dispatch() 메소드라도 호출된 이후에는, getResponse()를 호출하는 것은 불허됩니다.
containerBase.backgroundProcess.cluster=클러스터 [{0}]을(를) 백그라운드 프로세스에서 처리하는 중 오류 발생
containerBase.backgroundProcess.realm=Realm [{0}]을(를) 백그라운드 프로세스에서 처리 중 예외 발생
containerBase.backgroundProcess.unexpectedThreadDeath=백그라운드 쓰레드 [{0}]이(가) 예기치 않게 종료되었습니다.
containerBase.backgroundProcess.valve=Valve [{0}]의 백그라운드 프로세스를 처리하는 중 예외 발생
containerBase.nullName=컨테이너 이름은 널일 수 없습니다.
containerBase.threadedStartFailed=자식 컨테이너를 시작 중 실패했습니다.
containerBase.threadedStopFailed=자식 컨테이너가 중지되는 중 실패했습니다.
defaultInstanceManager.invalidInjection=유효하지 않은 메소드 리소스 injection annotation
defaultInstanceManager.restrictedClass=클래스 [{0}]에 대한 접근이 금지되었습니다. 접근 제한된 클래스입니다. 그것을 로드할 수 있으려면, 웹 애플리케이션이 반드시 privileged 된 것으로 설정되어야 합니다.
defaultInstanceManager.restrictedContainerServlet=클래스 [{0}]을(를) 접근하는 것은 금지되어 있습니다. 해당 클래스는 (ContainerServlet 인터페이스를 구현하고 있는) 접근 제한 클래스입니다. 웹 애플리케이션이 만약 접근하고자 한다면 로드할 수 있는 권한이 설정되어야 합니다.
defaultInstanceManager.restrictedFiltersResource=제한 필터들에 대한 설정 파일을 찾을 수 없습니다: [{0}]
defaultInstanceManager.restrictedListenersResource=RestrictedListeners.properties 파일을 찾을 수 없습니다: [{0}]
defaultInstanceManager.restrictedServletsResource=제한 서블릿들에 대한 프로퍼티 파일을 찾을 수 없습니다: [{0}]
defaultInstanceManager.restrictedWrongValue=제한 클래스들 프로퍼티 파일 [{0}]에 클래스 이름 [{1}]을(를) 위한 잘못된 값이 설정되었습니다. 요구되는 값: [restricted], 실제 값: [{2}]
filterChain.filter=필터 실행에서 예외가 발생했습니다.
filterChain.servlet=서블릿 실행이 예외를 발생시켰습니다.
jreLeakListener.authPolicyFail=javax.security.auth.Policy 클래스에서 메모리 누수를 방지하려 시도하는 중 오류 발생
jreLeakListener.classToInitializeFail=Tomcat을 시작하던 중, 발생 가능성 있는 메모리 누수를 방지하기 위한 클래스 [{0}]을(를) 로드하지 못했습니다.
jreLeakListener.gcDaemonFail=Tomcat이 시작하는 동안, 가능성 있는 메모리 누수들을 방지하기 위한 GC Daemon 쓰레드 생성을 개시하지 못했습니다. 이는 Sun JVM들이 아닌 환경에서 발생할 수 있습니다.
jreLeakListener.jarUrlConnCacheFail=기본 설정으로서, Jar URL 연결 캐싱을 사용불능 상태로 설정하지 못했습니다.
jreLeakListener.ldapPoolManagerFail=가능성 있는 메모리 누수들을 방지하기 위하여, Tomcat이 시작하는 동안, com.sun.jndi.ldap.LdapPoolManager 클래스 생성을 개시하지 못했습니다. 이는 Sun JVM들이 아닌 환경에서 발생할 수 있습니다.
jreLeakListener.xmlParseFail=XML 파싱하는 과정에서, 메모리 누수들을 방지하려 시도하는 중 오류 발생
naming.addEnvEntry=Environment 엔트리 [{0}]을(를) 추가합니다.
naming.addResourceEnvRef=리소스 env ref [{0}]을(를) 추가합니다.
naming.bindFailed=객체를 바인딩하지 못했습니다: [{0}]
naming.invalidEnvEntryType=Environment 엔트리 [{0}]이(가) 유효하지 않은 타입을 가지고 있습니다.
naming.invalidEnvEntryValue=Environment 엔트리 [{0}]이(가) 유효하지 않은 값을 가지고 있습니다.
naming.jmxRegistrationFailed=JMX 내에서 등록 실패했습니다: [{0}]
naming.namingContextCreationFailed=Naming Context 생성 실패: [{0}]
naming.unbindFailed=객체 [{0}]을(를) 바인딩 해제하지 못했습니다.
naming.wsdlFailed=wsdl 파일을 찾지 못했습니다: [{0}]
noPluggabilityServletContext.notAllowed=Servlet 3.0 스펙의 4.4 장에 따르면, web.xml 또는 web-fragment.xml 파일에 정의되지 않거나 @WebListener로 annotate되지 않은, ServletContextListener에서 이 메소드를 호출하는 것은 허용되지 않습니다.
pushBuilder.noPath=경로를 설정하기 전에 push()를 호출하는 것은 불허됩니다.
standardContext.applicationListener=클래스 [{0}]의 애플리케이션 리스너를 설정하는 중 오류 발생
standardContext.applicationSkipped=이전 오류(들)로 인하여, 애플리케이션 리스너들을 설치하는 것을 건너뛰었습니다.
standardContext.backgroundProcess.instanceManager=인스턴스 매니저 [{0}]을(를) 백그라운드 프로세스에서 처리 중 예외 발생
standardContext.backgroundProcess.loader=로더 [{0}]을(를) 백그라운드 프로세스로 처리 중 예외 발생
standardContext.backgroundProcess.manager=매니저 [{0}]을(를) 백그라운드 프로세스로 처리하는 중 예외 발생
standardContext.backgroundProcess.resources=리소스 [{0}]을(를) 백그라운드 프로세스로 처리하는 중 예외 발생
standardContext.cluster.noManager=매니저가 발견되지 않습니다. 클러스터 매니저가 사용되어야 하는지 점검합니다. 설정된 클러스터: [{0}], 배포할 수 있는 애플리케이션: [{1}]
standardContext.configurationFail=하나 이상의 구성요소(들)이, 해당 컨텍스트가 올바로 설정되지 않았다고 표시했습니다.
standardContext.cookieProcessor.null=컨텍스트를 위한 CookieProcessor를 널로 설정하는 것은 허용되지 않습니다.
standardContext.duplicateListener=리스너 [{0}]이(가) 이미 이 컨텍스트를 위해 설정되어 있습니다. 중복된 정의는 무시되었습니다.
standardContext.errorPage.error=오류 페이지 위치 [{0}]은(는) 반드시 ''/''로 시작해야 합니다.
standardContext.errorPage.required=ErrorPage는 널이어서는 안됩니다.
standardContext.errorPage.warning=경고: Servlet 2.4에서 오류 페이지 위치 [{0}]은(는) 반드시 ''/''로 시작해야 합니다.
standardContext.extensionValidationError=필수적으로 요구되는 애플리케이션 extension들이 유효한지 확인하려 시도하는 중 오류 발생
standardContext.filterFail=하나 이상의 필터들이 시작하지 못했습니다. 모든 상세 사항은 적절한 컨테이너 로그 파일에서 찾을 수 있습니다.
standardContext.filterMap.either=필터 매핑은 반드시 <url-pattern> 또는 <servlet-name>, 둘 중 하나를 지정해야 합니다.
standardContext.filterMap.name=필터 매핑이 알 수 없는 필터 이름 [{0}]을(를) 지정하고 있습니다.
standardContext.filterMap.pattern=필터 매핑에서 유효하지 않은 <url-pattern>: [{0}]
standardContext.filterStart=필터 [{0}]을(를) 시작하는 중 오류 발생
standardContext.invalidWrapperClass=[{0}]은(는) StandardWrapper의 하위 클래스가 아닙니다.
standardContext.isUnavailable=이 애플리케이션은 현재 가용 상태가 아닙니다.
standardContext.listenerFail=하나 이상의 리스너들이 시작하지 못했습니다. 상세 내역은 적절한 컨테이너 로그 파일에서 찾을 수 있습니다.
standardContext.listenerStart=Context initialized 이벤트를 [{0}] 클래스의 인스턴스인 리스너에 전송하는 동안 예외 발생
standardContext.listenerStop=클래스 [{0}]의 인스턴스인 리스너에게 contextDestroyed 이벤트를 전송하는 중 예외 발생
standardContext.loadOnStartup.loadException=웹 애플리케이션 [{0}] 내의 서블릿 [{1}]이(가) load() 예외를 발생시켰습니다.
standardContext.loginConfig.errorPage=폼 오류 페이지 [{0}]은(는) 반드시 "/"로 시작해야 합니다.
standardContext.loginConfig.errorWarning=주의: Servlet 2.4에서 폼 오류 페이지 [{0}]은(는) 반드시 "/" 로 시작해야 합니다.
standardContext.loginConfig.loginPage=폼 로그인 페이지 [{0}]은(는) 반드시 ''/''로 시작해야 합니다.
standardContext.loginConfig.loginWarning=경고: Servlet 2.4에서 폼 로그인 페이지 [{0}]은(는) 반드시 ''/''로 시작해야 합니다.
standardContext.loginConfig.required=LoginConfig은(는) 널일 수 없습니다.
standardContext.manager=클래스 [{0}]의 매니저 객체를 설정했습니다.
standardContext.managerFail=세션 매니저가 시작하지 못했습니다.
standardContext.namingResource.destroy.fail=이전 Naming 리소스를 소멸시키지 못했습니다.
standardContext.namingResource.init.fail=새로운 Naming 리소스들을 초기화하지 못했습니다.
standardContext.notStarted=[{0}](이)라는 이름을 가진 컨텍스트는 아직 시작되지 않았습니다.
standardContext.notWrapper=컨텍스트의 자식은 반드시 Wrapper여야 합니다.
standardContext.parameter.duplicate=중복된 컨텍스트 초기화 파라미터: [{0}]
standardContext.parameter.required=파라미터 이름과 파라미터 값, 둘 다 필수적입니다.
standardContext.pathInvalid=컨텍스트 경로는 반드시 빈 문자열이거나, 또는 ''/''로 시작하고 ''/''로 끝나지 않는 문자열이어야 합니다. 해당 경로 [{0}]은(는) 이 조건을 충족시키지 않아 [{1}](으)로 변경되었습니다.
standardContext.postconstruct.duplicate=클래스 [{0}]에서 중복된 PostConstruct 메소드 정의가 발견됨
standardContext.postconstruct.required=Fully qualified 클래스 이름과 메소드 이름, 둘 다 필수적입니다.
standardContext.predestroy.duplicate=클래스 [{0}]을(를) 위해, 중복된 @PreDestroy 메소드 정의입니다.
standardContext.predestroy.required=Fully qualified 클래스 이름과 메소드 이름, 둘 다 필수적으로 요구됩니다.
standardContext.reloadingCompleted=이름이 [{0}]인 컨텍스트를 다시 로드하는 것을 완료했습니다.
standardContext.reloadingStarted=이름이 [{0}]인 컨텍스트를 다시 로드하는 작업이 시작되었습니다.
standardContext.requestListener.requestInit=클래스 [{0}]의 리스너 인스턴스에게, request initialized Lifecycle 이벤트를 보내는 중 예외 발생
standardContext.resourcesInit=정적 리소스들을 초기화하는 중 오류 발생
standardContext.resourcesStart=정적 리소스들을 시작하는 중 오류 발생
standardContext.resourcesStop=정적 리소스들을 중지시키는 중 오류 발생
standardContext.sciFail=ServletContainerInitializer 처리 중 오류 발생
standardContext.securityConstraint.mixHttpMethod=<http-method>와 <http-method-omission>을 동일한 web resource collection에서 섞어서 사용하는 것은 허용되지 않습니다.
standardContext.securityConstraint.pattern=Security constraint 엘리먼트에서 유효하지 않은 <url-pattern> [{0}]입니다.
standardContext.servletFail=하나 이상의 서블릿들이 시작 시에 제대로 로드되지 않았습니다. 상세 정보는 적절한 컨테이너 로그 파일에서 찾을 수 있습니다.
standardContext.servletMap.name=서블릿 매핑이 알 수 없는 서블릿 이름 [{0}]을(를) 지정하고 있습니다.
standardContext.servletMap.pattern=서블릿 매핑에서 유효하지 않은 <url-pattern> [{0}]
standardContext.startFailed=이전 오류들로 인해 컨텍스트 [{0}]의 시작이 실패했습니다.
standardContext.startingContext=이름이 [{0}]인 컨텍스트를 시작하는 중 예외 발생
standardContext.stop.asyncWaitInterrupted=처리 중인 비동기 요청이 완료되기를 기다리기 위해 unloadDelay 밀리초를 대기하는 동안 인터럽트를 받았습니다. 더 이상의 지체 없이 컨텍스트 중지 작업을 계속할 것입니다.
standardContext.stoppingContext=이름이 [{0}]인 컨텍스트를 중지시키는 중 예외 발생
standardContext.threadBindingListenerError=컨텍스트 [{0}]을(를) 위해 설정된 쓰레드 바인딩 리스너에서 오류가 발생했습니다.
standardContext.urlPattern.patternWarning=경고: Servlet 2.4에서 URL 패턴 [{0}]은(는) 반드시 ''/''로 시작해야 합니다.
standardContext.webappClassLoader.missingProperty=해당 프로퍼티가 존재하지 않기에, 웹 애플리케이션 클래스로더 프로퍼티 [{0}]을(를) [{1}](으)로 설정할 수 없습니다.
standardContext.workCreateException=디렉토리 [{0}]와(과) CATALINA_HOME [{1}](으)로부터, 컨텍스트 [{2}]을(를) 위한 작업 디렉토리의 절대 경로를 결정하지 못했습니다.
standardContext.workCreateFail=컨텍스트 [{1}]을(를) 위한 작업 디렉토리 [{0}]을(를) 생성하지 못했습니다.
standardContext.workPath=컨텍스트 [{0}]을(를) 위한 작업 경로를 구하는 중 예외 발생
standardContextValve.acknowledgeException=요청에 대해, 100 (Continue) 응답과 함께, ACK을 보내지 못했습니다.
standardEngine.jvmRouteFail=엔진의 jvmRoute 속성을 시스템 프로퍼티로부터 설정하지 못했습니다.
standardEngine.notHost=엔진의 자식은 반드시 호스트여야 합니다.
standardEngine.notParent=엔진은 부모 컨테이너를 가질 수 없습니다.
standardHost.clientAbort=원격 클라이언트가 요청을 중단시켰습니다. IOException: [{0}]
standardHost.invalidErrorReportValveClass=지정된 오류 보고 Valve 클래스 [{0}]을(를) 로드할 수 없었습니다.
standardHost.noContext=이 요청을 처리하기 위한 컨텍스트가 설정되지 않았습니다.
standardHost.notContext=호스트의 자식은 반드시 컨텍스트이어야 합니다.
standardHost.nullName=호스트 이름이 필수적입니다.
standardHost.problematicAppBase=호스트 [{0}]에서 appBase를 위해 빈 문자열을 사용하는 것은, 결국 appBase를 CATALINA_BASE로 설정하게 되는데, 이는 좋은 생각이 아닙니다.
standardHostValue.customStatusFailed=커스텀 오류 페이지 [{0}]은(는) 올바르게 디스패치될 수 없었습니다.
standardPipeline.basic.start=새로운 기본 Valve를 시작하는 중 오류 발생
standardPipeline.basic.stop=이전 기본 Valve를 중지시키는 중 오류 발생
standardPipeline.valve.destroy=Valve를 소멸시키는 중 오류 발생
standardPipeline.valve.start=Valve를 시작시키는 중 오류 발생
standardPipeline.valve.stop=Valve를 중지시키는 중 오류 발생
standardServer.accept.error=셧다운 명령을 위해 listen하고 있는 소켓에서, accept를 시도하는 중, IOException이 발생했습니다.
standardServer.accept.readError=셧다운 명령을 읽으려 시도하는 중 IOException이 발생했습니다.
standardServer.accept.security=셧다운 명령을 위해 listen하고 있는 소켓에서, accept를 시도하는 중, 보안 오류가 발생했습니다.
standardServer.accept.timeout=셧다운 명령을 위해 listen하고 있는 소켓이, accept()를 호출 한 후, 예기치 않은 제한 시간 초과([{0}] 밀리초)를 발생시켰습니다. 버그 56684가 발생한 경우일까요?
standardServer.invalidShutdownCommand=유효하지 않은 셧다운 명령 [{0}]을(를) 받았습니다.
standardServer.shutdownViaPort=셧다운 포트를 통해 유효한 셧다운 명령을 받았습니다. 서버 인스턴스를 중지시킵니다.
standardServer.storeConfig.contextError=컨텍스트 [{0}]의 설정을 저장하는 중 오류 발생
standardServer.storeConfig.error=서버 설정을 저장하는 중 오류 발생
standardServer.storeConfig.notAvailable=[{0}](이)라는 이름의 MBean으로서 StoreConfig 구현 객체가 등록되지 않았으므로, 어떤 설정도 저장될 수 없었습니다. 보통 StoreConfigLifecycleListener을 통하여 적절한 MBean이 등록됩니다.
standardService.engine.startFailed=연관된 엔진을 시작하지 못했습니다.
standardService.engine.stopFailed=연관된 엔진을 중지시키지 못했습니다.
standardService.mapperListener.startFailed=연관된 MapperListener를 시작하지 못했습니다.
standardService.mapperListener.stopFailed=연관된 MapperListener를 중지시키지 못했습니다.
standardService.start.name=서비스 [{0}]을(를) 시작합니다.
standardService.stop.name=서비스 [{0}]을(를) 중지시킵니다.
standardWrapper.allocate=서블릿 인스턴스를 할당하는 중 오류 발생
standardWrapper.allocateException=서블릿 [{0}]을(를) 위해 할당하던 중 예외 발생
standardWrapper.deallocateException=서블릿 [{0}]을(를) 위한 할당 해제 처리 중 예외 발생
standardWrapper.destroyException=서블릿 [{0}]을(를) 위한 Servlet.destroy() 호출 중 익셉션이 발생했습니다.
standardWrapper.destroyInstance=서블릿 [{0}]을(를) 위한 InstanceManager.destroy() 호출이 예외를 발생시켰습니다.
standardWrapper.initException=서블릿 [{0}]을(를) 위한 Servlet.init() 호출이 예외를 발생시켰습니다.
standardWrapper.instantiate=서블릿 클래스 [{0}](으)로부터 인스턴스 생성하는 중 오류 발생
standardWrapper.isUnavailable=서블릿 [{0}]은(는) 현재 가용하지 않습니다.
standardWrapper.notChild=Wrapper 컨테이너는 자식 컨테이너들을 가질 수 없습니다.
standardWrapper.notClass=서블릿 [{0}]을(를) 위한 서블릿 클래스가 지정되지 않았습니다.
standardWrapper.notContext=Wrapper의 부모 컨테이너는 반드시 컨텍스트여야 합니다.
standardWrapper.notFound=서블릿 [{0}]은(는) 가용하지 않습니다.
standardWrapper.notServlet=클래스 [{0}]은(는) 서블릿이 아닙니다,
standardWrapper.releaseFilters=서블릿 [{0}]을(를) 위해 필터를 해제하는 중 예외 발생
standardWrapper.serviceException=경로가 [{1}]인 컨텍스트의 서블릿 [{0}]을(를) 위한 Servlet.service() 호출이 예외를 발생시켰습니다.
standardWrapper.serviceExceptionRoot=경로 [{1}]의 컨텍스트 내의 서블릿 [{0}]을(를) 위한 Servlet.service() 호출이, 근본 원인(root cause)과 함께, 예외 [{2}]을(를) 발생시켰습니다.
standardWrapper.unavailable=서블릿 [{0}]을(를) 가용하지 않은 상태로 표시합니다.
standardWrapper.unloadException=서블릿 [{0}]을(를) 위한 unload() 호출 시, 예외를 발생시켰습니다.
standardWrapper.unloading=서블릿이 언로드되었기 때문에, 서블릿 [{0}]을(를) 할당할 수 없습니다.
standardWrapper.waiting=서블릿 [{1}]을(를) 위해, [{0}]개의 인스턴스(들)이 할당 해제되기를 기다립니다.
threadLocalLeakPreventionListener.containerEvent.error=컨테이너 이벤트 [{0}]을(를) 처리하는 중 예외 발생
threadLocalLeakPreventionListener.lifecycleEvent.error=Lifecycle 이벤트 [{0}]을(를) 처리하는 중 예외 발생

View File

@@ -0,0 +1,20 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
applicationContext.addJspFile.iae=Файл JSP [{0}] содержит ошибки
applicationContext.addListener.iae.cnfe=Невозможно создать экземпляр типа [{0}]
applicationContext.setAttribute.namenull=Имя не может быть пустым
standardWrapper.isUnavailable=Сервлет [{0}] временно недоступен

View File

@@ -0,0 +1,147 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
applicationContext.addJspFile.iae=JSP 文件 [{0}] 不可用
applicationContext.addListener.iae.cnfe=无法创建类型为 [{0}] 的实例
applicationContext.addListener.iae.wrongType=指定的类型[{0}]不是预期的侦听器类型之一
applicationContext.addRole.ise=上下文被初始化后,角色不能再被添加到[{0}]中
applicationContext.addServlet.ise=无法将servlet添加到上下文[{0}]中,因为该上下文已初始化
applicationContext.attributeEvent=属性事件监听器引发的异常
applicationContext.invalidFilterName=由于筛选器名称[{0}]无效,无法添加筛选器定义。
applicationContext.invalidServletName=由于servlet名称[{0}]无效无法添加对应servlet的定义。
applicationContext.mapping.error=映射中.的错误
applicationContext.resourcePaths.iae=路径[{0}]不以“/”字符开头
applicationContext.setAttribute.namenull=Name 不能为 null
applicationContext.setSessionTimeout.ise=(:无法为上下文[{0}]设置会话超时,因为该上下文已初始化
applicationContext.setSessionTracking.iae.ssl=为上下文 [{0}] 请求的 session 跟踪模式包括 SSL 和至少一种其他模式。 SSL可能未配置其他模式。
applicationContext.setSessionTracking.ise=当上下文正在运行,无法设置上下文[{0}]的会话跟踪模式
applicationDispatcher.serviceException=Servlet[{0}]的Servlet.service()抛出异常
applicationDispatcher.specViolation.response=原始的ServletResponse或包装后的ServletResponse未传递给RequestDispatcher原因违反了SRV.8.2和SRV.14.2.5.1\n\
\n
applicationFilterConfig.preDestroy=):为类型为[{1}]的名为[{0}]的筛选器调用preDestroy 失败
applicationFilterConfig.release=失败的销毁过滤器类型为[{1}]名称为[{0}]
applicationFilterRegistration.nullInitParams=由于name和(或)value为null无法为过滤器设置初始化参数。name为 [{0}]value为 [{1}]
applicationPushBuilder.methodNotToken=HTTP方法必须是令牌(token),但 [{0}] 包含非令牌字符
applicationServletRegistration.setServletSecurity.iae=为部署到名为[{1}]的上下文的Servlet[{0}]指定的空约束
aprListener.aprInitError=基于APR的本地库加载失败.错误报告为[{0}]
aprListener.config=APR/OpenSSL配置useAprConnector[{0}]useOpenSSL[{1}]
aprListener.enterAlreadyInFIPSMode=AprLifecycleListener 配置为强制进入FIPS模式但库已处于FIPS模式[{0}]
aprListener.initializeFIPSSuccess=成功的进入FIPS 模式
aprListener.initializingFIPS=初始化FIPS模式...
aprListener.tcnVersion=安装了基于APR的Apache Tomcat Native库的旧版本[{0}]而Tomcat建议使用[{1}]的最低版本
aprListener.tooLateForFIPSMode=无法设置FIPSModeSSL已初始化
aprListener.tooLateForSSLRandomSeed=无法设置 SSLRandomSeedSSL已经初始化
asyncContextImpl.noAsyncDispatcher=从ServletContext 返回的调度程序不支持异步调度
asyncContextImpl.request.ise=调用方法complete()后或者任意一个dispatch()方法调用后调用getRequest()方法是非法的
asyncContextImpl.requestEnded=AsyncContext关联的请求已经完成处理。
containerBase.backgroundProcess.cluster=异常处理集群[{0}]后台进程
containerBase.backgroundProcess.unexpectedThreadDeath=后台线程[{0}]意外结束
containerBase.backgroundProcess.valve=处理阀门[{0}]后台进程异常
containerBase.nullName=容器名称不能为null
containerBase.threadedStartFailed=子容器启动失败
defaultInstanceManager.invalidInjection=方法资源注入注解无效
defaultInstanceManager.restrictedContainerServlet=禁止访问类 [{0}]。 它是一个受限制的类(实现了 ContainerServlet 接口)。 必须将 Web 应用程序配置为特权才能加载它
defaultInstanceManager.restrictedFiltersResource=找不到受限制的过滤器属性文件[{0}]
defaultInstanceManager.restrictedListenersResource=无法找到RestrictedListener的配置文件[{0}]
filterChain.filter=Filter 执行抛出一个异常
jreLeakListener.classToInitializeFail=在tomcat启动期间未能加载类[{0}],以防止可能的内存泄漏。
naming.addEnvEntry=添加环境条目 [{0}]
naming.addResourceEnvRef=添加资源环境引用 [{0}]
naming.invalidEnvEntryType=环境条目[{0}]没有一个有效哦的类型
naming.jmxRegistrationFailed=注册到JMX失败[{0}]
naming.namingContextCreationFailed=创建上下文名称失败
naming.unbindFailed=解绑对象[{0}]失败
naming.wsdlFailed=未找到 wsdl 文件:[{0}]
standardContext.applicationListener=配置应用程序监听器[{0}]错误
standardContext.applicationSkipped=由于以前的错误,已跳过安装应用程序侦听器
standardContext.backgroundProcess.loader=异常处理加载程序[{0}]后台进程
standardContext.backgroundProcess.resources=异常处理资源[{0}] 后台进程
standardContext.cookieProcessor.null=不允许将上下文的CookieProcessor 设置为null
standardContext.duplicateListener=当前上下文已经配置了监听器[{0}],重复的定义将被忽略。
standardContext.errorPage.required=ErrorPage不能为null
standardContext.errorPage.warning=警告在Servlet 2.4中,错误页位置 [{0}] 必须以"/"开头
standardContext.extensionValidationError=尝试校验必需的应用程序扩展时发生错误
standardContext.filterFail=一个或多个筛选器启动失败。完整的详细信息将在相应的容器日志文件中找到
standardContext.filterMap.either=过滤器映射必须指定 <url-pattern> 或 <servlet-name>
standardContext.filterMap.name=Filter mapping 指定了一个未知的 filter名称 [{0}]
standardContext.filterMap.pattern=过滤器映射中的<url-pattern> [{0}] 无效
standardContext.filterStart=启动过滤器异常
standardContext.invalidWrapperClass=[{0}] 不是StandardWrapper的子类
standardContext.isUnavailable=此应用程序目前不可用
standardContext.listenerStart=异常将上下文初始化事件发送到类的侦听器实例.[{0}]
standardContext.listenerStop=例外情况发送上下文删除事件[{0}],以便列表实例
standardContext.loginConfig.errorPage=表单错误页[{0}]必须以"/"开始
standardContext.loginConfig.errorWarning=警告Servlet 2.4中,表单错误页[{0}]必须以"/"开始
standardContext.loginConfig.loginPage=表单登录页面 [{0}] 必须以''/''开头
standardContext.loginConfig.loginWarning=警告在Servlet 2.4 中 Form 登录页[{0}] 必须以 "/" 开头
standardContext.manager=配置类为[{0}]的管理器
standardContext.managerFail=会话管理器无法启动
standardContext.namingResource.init.fail=未能初始化新的命名资源
standardContext.notStarted=名称为[{0}]的上下文还没有启动
standardContext.parameter.duplicate=重复的上下文初始化参数[{0}]
standardContext.predestroy.duplicate=类 [{0}] 的 @PreDestroy 方法定义重复
standardContext.resourcesInit=初始化静态变量错误
standardContext.resourcesStart=启动静态资源出错
standardContext.resourcesStop=停止静态资源时出错
standardContext.securityConstraint.mixHttpMethod=在相同的web资源集合中不允许混用: <http-method> 和 <http-method-omission>
standardContext.securityConstraint.pattern=安全约束中的<url-pattern> [{0}] 无效
standardContext.servletFail=启动时无法加载一个或多个Servlet。 全部的详细信息可在相应的容器日志文件中找到
standardContext.startingContext=启动Context[{0}]出现异常
standardContext.stop.asyncWaitInterrupted=等待卸载延迟毫秒以完成飞行中的异步请求时收到中断。上下文停止将继续,不会有进一步的延迟。
standardContext.stoppingContext=异常停止的上下文使用名为[{0}]
standardContext.threadBindingListenerError=上下文[{0}]配置的线程绑定监听器发生错误
standardContext.urlPattern.patternWarning=警告在Servlet 2.4中URL模式[{0}]必须以“/”开头
standardContext.workCreateException=无法从目录[{0}]和catalina_home[{1}]中为上下文[{2}]确定绝对工作目录
standardContext.workCreateFail=无法为上下文[{1}]创建工作目录[{0}]
standardContext.workPath=获取上下文[{0}]的工作路径时发生异常
standardContextValve.acknowledgeException=以100继续响应确认请求失败
standardEngine.jvmRouteFail=无法从系统属性设置引擎的jvmRoute 属性
standardEngine.notParent=引擎不能有父容器
standardHost.noContext=没有配置上下文来处理此请求
standardHost.notContext=主机的子节点必须有上下文
standardHost.nullName=主机名是必需的
standardServer.accept.timeout=在调用accept()方法之后侦听shutdown命令的套接字经历了意外的超时[{0}]毫秒。 这是bug 56684的一个例子
standardServer.storeConfig.notAvailable=没有将StoreConfig实现注册为名为[{0}]的MBean因此无法保存配置。合适的MBean通常通过StoreConfigLifecycleListener注册。
standardService.engine.stopFailed=失败停止关联的引擎
standardService.stop.name=正在停止服务[{0}]
standardWrapper.allocate=分配一个servlet实例错误
standardWrapper.destroyInstance=servlet[{0}]实例管理销毁(destroy) 抛出异常
standardWrapper.instantiate=实例化Servlet类[{0}]异常
standardWrapper.isUnavailable=Servlet [{0}]当前不可用。
standardWrapper.notChild=Wrapper容器内部不允许有子容器。
standardWrapper.notFound=Servlet [{0}] 不可用
standardWrapper.serviceException=在路径为[{1}]的上下文中servlet[{0}]的Servlet.service()引发异常
standardWrapper.unloading=无法分配servlet [{0}],因为它没有被加载
threadLocalLeakPreventionListener.containerEvent.error=异常处理容器事件[{0}]

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
org.apache.catalina.ssi.SSIFilter=restricted

View File

@@ -0,0 +1,15 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

View File

@@ -0,0 +1,19 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
org.apache.catalina.ssi.SSIServlet=restricted
org.apache.catalina.servlets.CGIServlet=restricted
org.apache.catalina.manager.JMXProxyServlet=restricted
org.apache.catalina.manager.StatusManagerServlet=restricted

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,98 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.Wrapper;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;
import org.apache.tomcat.util.buf.MessageBytes;
import org.apache.tomcat.util.res.StringManager;
/**
* Valve that implements the default basic behavior for the
* <code>StandardContext</code> container implementation.
* <p>
* <b>USAGE CONSTRAINT</b>: This implementation is likely to be useful only
* when processing HTTP requests.
*
* @author Craig R. McClanahan
*/
final class StandardContextValve extends ValveBase {
private static final StringManager sm = StringManager.getManager(StandardContextValve.class);
public StandardContextValve() {
super(true);
}
/**
* Select the appropriate child Wrapper to process this request,
* based on the specified request URI. If no matching Wrapper can
* be found, return an appropriate HTTP error.
*
* @param request Request to be processed
* @param response Response to be produced
*
* @exception IOException if an input/output error occurred
* @exception ServletException if a servlet error occurred
*/
@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// Disallow any direct access to resources under WEB-INF or META-INF
MessageBytes requestPathMB = request.getRequestPathMB();
if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/META-INF"))
|| (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
// Select the Wrapper to be used for this Request
Wrapper wrapper = request.getWrapper();
if (wrapper == null || wrapper.isUnavailable()) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
// Acknowledge the request
try {
response.sendAcknowledgement();
} catch (IOException ioe) {
container.getLogger().error(sm.getString(
"standardContextValve.acknowledgeException"), ioe);
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, ioe);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(wrapper.getPipeline().isAsyncSupported());
}
wrapper.getPipeline().getFirst().invoke(request, response);
}
}

View File

@@ -0,0 +1,493 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.catalina.AccessLog;
import org.apache.catalina.Container;
import org.apache.catalina.ContainerEvent;
import org.apache.catalina.ContainerListener;
import org.apache.catalina.Context;
import org.apache.catalina.Engine;
import org.apache.catalina.Host;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Realm;
import org.apache.catalina.Server;
import org.apache.catalina.Service;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.realm.NullRealm;
import org.apache.catalina.util.ServerInfo;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
/**
* Standard implementation of the <b>Engine</b> interface. Each
* child container must be a Host implementation to process the specific
* fully qualified host name of that virtual host. <br>
* You can set the jvmRoute direct or with the System.property <b>jvmRoute</b>.
*
* @author Craig R. McClanahan
*/
public class StandardEngine extends ContainerBase implements Engine {
private static final Log log = LogFactory.getLog(StandardEngine.class);
// ----------------------------------------------------------- Constructors
/**
* Create a new StandardEngine component with the default basic Valve.
*/
public StandardEngine() {
super();
pipeline.setBasic(new StandardEngineValve());
/* Set the jmvRoute using the system property jvmRoute */
try {
setJvmRoute(System.getProperty("jvmRoute"));
} catch(Exception ex) {
log.warn(sm.getString("standardEngine.jvmRouteFail"));
}
// By default, the engine will hold the reloading thread
backgroundProcessorDelay = 10;
}
// ----------------------------------------------------- Instance Variables
/**
* Host name to use when no server host, or an unknown host,
* is specified in the request.
*/
private String defaultHost = null;
/**
* The <code>Service</code> that owns this Engine, if any.
*/
private Service service = null;
/**
* The JVM Route ID for this Tomcat instance. All Route ID's must be unique
* across the cluster.
*/
private String jvmRouteId;
/**
* Default access log to use for request/response pairs where we can't ID
* the intended host and context.
*/
private final AtomicReference<AccessLog> defaultAccessLog =
new AtomicReference<>();
// ------------------------------------------------------------- Properties
/**
* Obtain the configured Realm and provide a default Realm implementation
* when no explicit configuration is set.
*
* @return configured realm, or a {@link NullRealm} by default
*/
@Override
public Realm getRealm() {
Realm configured = super.getRealm();
// If no set realm has been called - default to NullRealm
// This can be overridden at engine, context and host level
if (configured == null) {
configured = new NullRealm();
this.setRealm(configured);
}
return configured;
}
/**
* Return the default host.
*/
@Override
public String getDefaultHost() {
return defaultHost;
}
/**
* Set the default host.
*
* @param host The new default host
*/
@Override
public void setDefaultHost(String host) {
String oldDefaultHost = this.defaultHost;
if (host == null) {
this.defaultHost = null;
} else {
this.defaultHost = host.toLowerCase(Locale.ENGLISH);
}
support.firePropertyChange("defaultHost", oldDefaultHost,
this.defaultHost);
}
/**
* Set the cluster-wide unique identifier for this Engine.
* This value is only useful in a load-balancing scenario.
* <p>
* This property should not be changed once it is set.
*/
@Override
public void setJvmRoute(String routeId) {
jvmRouteId = routeId;
}
/**
* Retrieve the cluster-wide unique identifier for this Engine.
* This value is only useful in a load-balancing scenario.
*/
@Override
public String getJvmRoute() {
return jvmRouteId;
}
/**
* Return the <code>Service</code> with which we are associated (if any).
*/
@Override
public Service getService() {
return this.service;
}
/**
* Set the <code>Service</code> with which we are associated (if any).
*
* @param service The service that owns this Engine
*/
@Override
public void setService(Service service) {
this.service = service;
}
// --------------------------------------------------------- Public Methods
/**
* Add a child Container, only if the proposed child is an implementation
* of Host.
*
* @param child Child container to be added
*/
@Override
public void addChild(Container child) {
if (!(child instanceof Host))
throw new IllegalArgumentException
(sm.getString("standardEngine.notHost"));
super.addChild(child);
}
/**
* Disallow any attempt to set a parent for this Container, since an
* Engine is supposed to be at the top of the Container hierarchy.
*
* @param container Proposed parent Container
*/
@Override
public void setParent(Container container) {
throw new IllegalArgumentException
(sm.getString("standardEngine.notParent"));
}
@Override
protected void initInternal() throws LifecycleException {
// Ensure that a Realm is present before any attempt is made to start
// one. This will create the default NullRealm if necessary.
getRealm();
super.initInternal();
}
/**
* Start this component and implement the requirements
* of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
@Override
protected synchronized void startInternal() throws LifecycleException {
// Log our server identification information
if(log.isInfoEnabled())
log.info( "Starting Servlet Engine: " + ServerInfo.getServerInfo());
// Standard container startup
super.startInternal();
}
/**
* Override the default implementation. If no access log is defined for the
* Engine, look for one in the Engine's default host and then the default
* host's ROOT context. If still none is found, return the default NoOp
* access log.
*/
@Override
public void logAccess(Request request, Response response, long time,
boolean useDefault) {
boolean logged = false;
if (getAccessLog() != null) {
accessLog.log(request, response, time);
logged = true;
}
if (!logged && useDefault) {
AccessLog newDefaultAccessLog = defaultAccessLog.get();
if (newDefaultAccessLog == null) {
// If we reached this point, this Engine can't have an AccessLog
// Look in the defaultHost
Host host = (Host) findChild(getDefaultHost());
Context context = null;
if (host != null && host.getState().isAvailable()) {
newDefaultAccessLog = host.getAccessLog();
if (newDefaultAccessLog != null) {
if (defaultAccessLog.compareAndSet(null,
newDefaultAccessLog)) {
AccessLogListener l = new AccessLogListener(this,
host, null);
l.install();
}
} else {
// Try the ROOT context of default host
context = (Context) host.findChild("");
if (context != null &&
context.getState().isAvailable()) {
newDefaultAccessLog = context.getAccessLog();
if (newDefaultAccessLog != null) {
if (defaultAccessLog.compareAndSet(null,
newDefaultAccessLog)) {
AccessLogListener l = new AccessLogListener(
this, null, context);
l.install();
}
}
}
}
}
if (newDefaultAccessLog == null) {
newDefaultAccessLog = new NoopAccessLog();
if (defaultAccessLog.compareAndSet(null,
newDefaultAccessLog)) {
AccessLogListener l = new AccessLogListener(this, host,
context);
l.install();
}
}
}
newDefaultAccessLog.log(request, response, time);
}
}
/**
* Return the parent class loader for this component.
*/
@Override
public ClassLoader getParentClassLoader() {
if (parentClassLoader != null)
return parentClassLoader;
if (service != null) {
return service.getParentClassLoader();
}
return ClassLoader.getSystemClassLoader();
}
@Override
public File getCatalinaBase() {
if (service != null) {
Server s = service.getServer();
if (s != null) {
File base = s.getCatalinaBase();
if (base != null) {
return base;
}
}
}
// Fall-back
return super.getCatalinaBase();
}
@Override
public File getCatalinaHome() {
if (service != null) {
Server s = service.getServer();
if (s != null) {
File base = s.getCatalinaHome();
if (base != null) {
return base;
}
}
}
// Fall-back
return super.getCatalinaHome();
}
// -------------------- JMX registration --------------------
@Override
protected String getObjectNameKeyProperties() {
return "type=Engine";
}
@Override
protected String getDomainInternal() {
return getName();
}
// ----------------------------------------------------------- Inner classes
protected static final class NoopAccessLog implements AccessLog {
@Override
public void log(Request request, Response response, long time) {
// NOOP
}
@Override
public void setRequestAttributesEnabled(
boolean requestAttributesEnabled) {
// NOOP
}
@Override
public boolean getRequestAttributesEnabled() {
// NOOP
return false;
}
}
protected static final class AccessLogListener
implements PropertyChangeListener, LifecycleListener,
ContainerListener {
private final StandardEngine engine;
private final Host host;
private final Context context;
private volatile boolean disabled = false;
public AccessLogListener(StandardEngine engine, Host host,
Context context) {
this.engine = engine;
this.host = host;
this.context = context;
}
public void install() {
engine.addPropertyChangeListener(this);
if (host != null) {
host.addContainerListener(this);
host.addLifecycleListener(this);
}
if (context != null) {
context.addLifecycleListener(this);
}
}
private void uninstall() {
disabled = true;
if (context != null) {
context.removeLifecycleListener(this);
}
if (host != null) {
host.removeLifecycleListener(this);
host.removeContainerListener(this);
}
engine.removePropertyChangeListener(this);
}
@Override
public void lifecycleEvent(LifecycleEvent event) {
if (disabled) return;
String type = event.getType();
if (Lifecycle.AFTER_START_EVENT.equals(type) ||
Lifecycle.BEFORE_STOP_EVENT.equals(type) ||
Lifecycle.BEFORE_DESTROY_EVENT.equals(type)) {
// Container is being started/stopped/removed
// Force re-calculation and disable listener since it won't
// be re-used
engine.defaultAccessLog.set(null);
uninstall();
}
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (disabled) return;
if ("defaultHost".equals(evt.getPropertyName())) {
// Force re-calculation and disable listener since it won't
// be re-used
engine.defaultAccessLog.set(null);
uninstall();
}
}
@Override
public void containerEvent(ContainerEvent event) {
// Only useful for hosts
if (disabled) return;
if (Container.ADD_CHILD_EVENT.equals(event.getType())) {
Context context = (Context) event.getData();
if ("".equals(context.getPath())) {
// Force re-calculation and disable listener since it won't
// be re-used
engine.defaultAccessLog.set(null);
uninstall();
}
}
}
}
}

View File

@@ -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.catalina.core;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.Host;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;
import org.apache.tomcat.util.res.StringManager;
/**
* Valve that implements the default basic behavior for the
* <code>StandardEngine</code> container implementation.
* <p>
* <b>USAGE CONSTRAINT</b>: This implementation is likely to be useful only
* when processing HTTP requests.
*
* @author Craig R. McClanahan
*/
final class StandardEngineValve extends ValveBase {
//------------------------------------------------------ Constructor
public StandardEngineValve() {
super(true);
}
// ----------------------------------------------------- Instance Variables
/**
* The string manager for this package.
*/
private static final StringManager sm =
StringManager.getManager(Constants.Package);
// --------------------------------------------------------- Public Methods
/**
* Select the appropriate child Host to process this request,
* based on the requested server name. If no matching Host can
* be found, return an appropriate HTTP error.
*
* @param request Request to be processed
* @param response Response to be produced
*
* @exception IOException if an input/output error occurred
* @exception ServletException if a servlet error occurred
*/
@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// Select the Host to be used for this Request
Host host = request.getHost();
if (host == null) {
response.sendError
(HttpServletResponse.SC_BAD_REQUEST,
sm.getString("standardEngine.noHost",
request.getServerName()));
return;
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(host.getPipeline().isAsyncSupported());
}
// Ask this Host to process this request
host.getPipeline().getFirst().invoke(request, response);
}
}

View File

@@ -0,0 +1,881 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ExecutorService;
import java.util.regex.Pattern;
import javax.management.ObjectName;
import org.apache.catalina.Container;
import org.apache.catalina.Context;
import org.apache.catalina.Engine;
import org.apache.catalina.Globals;
import org.apache.catalina.Host;
import org.apache.catalina.JmxEnabled;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Valve;
import org.apache.catalina.loader.WebappClassLoaderBase;
import org.apache.catalina.util.ContextName;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.ExceptionUtils;
/**
* Standard implementation of the <b>Host</b> interface. Each
* child container must be a Context implementation to process the
* requests directed to a particular web application.
*
* @author Craig R. McClanahan
* @author Remy Maucherat
*/
public class StandardHost extends ContainerBase implements Host {
private static final Log log = LogFactory.getLog(StandardHost.class);
// ----------------------------------------------------------- Constructors
/**
* Create a new StandardHost component with the default basic Valve.
*/
public StandardHost() {
super();
pipeline.setBasic(new StandardHostValve());
}
// ----------------------------------------------------- Instance Variables
/**
* The set of aliases for this Host.
*/
private String[] aliases = new String[0];
private final Object aliasesLock = new Object();
/**
* The application root for this Host.
*/
private String appBase = "webapps";
private volatile File appBaseFile = null;
/**
* The XML root for this Host.
*/
private String xmlBase = null;
/**
* host's default config path
*/
private volatile File hostConfigBase = null;
/**
* The auto deploy flag for this Host.
*/
private boolean autoDeploy = true;
/**
* The Java class name of the default context configuration class
* for deployed web applications.
*/
private String configClass =
"org.apache.catalina.startup.ContextConfig";
/**
* The Java class name of the default Context implementation class for
* deployed web applications.
*/
private String contextClass =
"org.apache.catalina.core.StandardContext";
/**
* The deploy on startup flag for this Host.
*/
private boolean deployOnStartup = true;
/**
* deploy Context XML config files property.
*/
private boolean deployXML = !Globals.IS_SECURITY_ENABLED;
/**
* Should XML files be copied to
* $CATALINA_BASE/conf/&lt;engine&gt;/&lt;host&gt; by default when
* a web application is deployed?
*/
private boolean copyXML = false;
/**
* The Java class name of the default error reporter implementation class
* for deployed web applications.
*/
private String errorReportValveClass =
"org.apache.catalina.valves.ErrorReportValve";
/**
* Unpack WARs property.
*/
private boolean unpackWARs = true;
/**
* Work Directory base for applications.
*/
private String workDir = null;
/**
* Should we create directories upon startup for appBase and xmlBase
*/
private boolean createDirs = true;
/**
* Track the class loaders for the child web applications so memory leaks
* can be detected.
*/
private final Map<ClassLoader, String> childClassLoaders =
new WeakHashMap<>();
/**
* Any file or directory in {@link #appBase} that this pattern matches will
* be ignored by the automatic deployment process (both
* {@link #deployOnStartup} and {@link #autoDeploy}).
*/
private Pattern deployIgnore = null;
private boolean undeployOldVersions = false;
private boolean failCtxIfServletStartFails = false;
// ------------------------------------------------------------- Properties
@Override
public boolean getUndeployOldVersions() {
return undeployOldVersions;
}
@Override
public void setUndeployOldVersions(boolean undeployOldVersions) {
this.undeployOldVersions = undeployOldVersions;
}
@Override
public ExecutorService getStartStopExecutor() {
return startStopExecutor;
}
/**
* Return the application root for this Host. This can be an absolute
* pathname, a relative pathname, or a URL.
*/
@Override
public String getAppBase() {
return this.appBase;
}
/**
* ({@inheritDoc}
*/
@Override
public File getAppBaseFile() {
if (appBaseFile != null) {
return appBaseFile;
}
File file = new File(getAppBase());
// If not absolute, make it absolute
if (!file.isAbsolute()) {
file = new File(getCatalinaBase(), file.getPath());
}
// Make it canonical if possible
try {
file = file.getCanonicalFile();
} catch (IOException ioe) {
// Ignore
}
this.appBaseFile = file;
return file;
}
/**
* Set the application root for this Host. This can be an absolute
* pathname, a relative pathname, or a URL.
*
* @param appBase The new application root
*/
@Override
public void setAppBase(String appBase) {
if (appBase.trim().equals("")) {
log.warn(sm.getString("standardHost.problematicAppBase", getName()));
}
String oldAppBase = this.appBase;
this.appBase = appBase;
support.firePropertyChange("appBase", oldAppBase, this.appBase);
this.appBaseFile = null;
}
/**
* ({@inheritDoc}
*/
@Override
public String getXmlBase() {
return this.xmlBase;
}
/**
* ({@inheritDoc}
*/
@Override
public void setXmlBase(String xmlBase) {
String oldXmlBase = this.xmlBase;
this.xmlBase = xmlBase;
support.firePropertyChange("xmlBase", oldXmlBase, this.xmlBase);
}
/**
* ({@inheritDoc}
*/
@Override
public File getConfigBaseFile() {
if (hostConfigBase != null) {
return hostConfigBase;
}
String path = null;
if (getXmlBase()!=null) {
path = getXmlBase();
} else {
StringBuilder xmlDir = new StringBuilder("conf");
Container parent = getParent();
if (parent instanceof Engine) {
xmlDir.append('/');
xmlDir.append(parent.getName());
}
xmlDir.append('/');
xmlDir.append(getName());
path = xmlDir.toString();
}
File file = new File(path);
if (!file.isAbsolute())
file = new File(getCatalinaBase(), path);
try {
file = file.getCanonicalFile();
} catch (IOException e) {// ignore
}
this.hostConfigBase = file;
return file;
}
/**
* @return <code>true</code> if the Host will attempt to create directories for appBase and xmlBase
* unless they already exist.
*/
@Override
public boolean getCreateDirs() {
return createDirs;
}
/**
* Set to <code>true</code> if the Host should attempt to create directories for xmlBase and appBase upon startup
* @param createDirs the new flag value
*/
@Override
public void setCreateDirs(boolean createDirs) {
this.createDirs = createDirs;
}
/**
* @return the value of the auto deploy flag. If true, it indicates that
* this host's child webapps will be dynamically deployed.
*/
@Override
public boolean getAutoDeploy() {
return this.autoDeploy;
}
/**
* Set the auto deploy flag value for this host.
*
* @param autoDeploy The new auto deploy flag
*/
@Override
public void setAutoDeploy(boolean autoDeploy) {
boolean oldAutoDeploy = this.autoDeploy;
this.autoDeploy = autoDeploy;
support.firePropertyChange("autoDeploy", oldAutoDeploy,
this.autoDeploy);
}
/**
* @return the Java class name of the context configuration class
* for new web applications.
*/
@Override
public String getConfigClass() {
return this.configClass;
}
/**
* Set the Java class name of the context configuration class
* for new web applications.
*
* @param configClass The new context configuration class
*/
@Override
public void setConfigClass(String configClass) {
String oldConfigClass = this.configClass;
this.configClass = configClass;
support.firePropertyChange("configClass",
oldConfigClass, this.configClass);
}
/**
* @return the Java class name of the Context implementation class
* for new web applications.
*/
public String getContextClass() {
return this.contextClass;
}
/**
* Set the Java class name of the Context implementation class
* for new web applications.
*
* @param contextClass The new context implementation class
*/
public void setContextClass(String contextClass) {
String oldContextClass = this.contextClass;
this.contextClass = contextClass;
support.firePropertyChange("contextClass",
oldContextClass, this.contextClass);
}
/**
* @return the value of the deploy on startup flag. If <code>true</code>, it indicates
* that this host's child webapps should be discovered and automatically
* deployed at startup time.
*/
@Override
public boolean getDeployOnStartup() {
return this.deployOnStartup;
}
/**
* Set the deploy on startup flag value for this host.
*
* @param deployOnStartup The new deploy on startup flag
*/
@Override
public void setDeployOnStartup(boolean deployOnStartup) {
boolean oldDeployOnStartup = this.deployOnStartup;
this.deployOnStartup = deployOnStartup;
support.firePropertyChange("deployOnStartup", oldDeployOnStartup,
this.deployOnStartup);
}
/**
* @return <code>true</code> if XML context descriptors should be deployed.
*/
public boolean isDeployXML() {
return deployXML;
}
/**
* Deploy XML Context config files flag mutator.
*
* @param deployXML <code>true</code> if context descriptors should be deployed
*/
public void setDeployXML(boolean deployXML) {
this.deployXML = deployXML;
}
/**
* @return the copy XML config file flag for this component.
*/
public boolean isCopyXML() {
return this.copyXML;
}
/**
* Set the copy XML config file flag for this component.
*
* @param copyXML The new copy XML flag
*/
public void setCopyXML(boolean copyXML) {
this.copyXML = copyXML;
}
/**
* @return the Java class name of the error report valve class
* for new web applications.
*/
public String getErrorReportValveClass() {
return this.errorReportValveClass;
}
/**
* Set the Java class name of the error report valve class
* for new web applications.
*
* @param errorReportValveClass The new error report valve class
*/
public void setErrorReportValveClass(String errorReportValveClass) {
String oldErrorReportValveClassClass = this.errorReportValveClass;
this.errorReportValveClass = errorReportValveClass;
support.firePropertyChange("errorReportValveClass",
oldErrorReportValveClassClass,
this.errorReportValveClass);
}
/**
* @return the canonical, fully qualified, name of the virtual host
* this Container represents.
*/
@Override
public String getName() {
return name;
}
/**
* Set the canonical, fully qualified, name of the virtual host
* this Container represents.
*
* @param name Virtual host name
*
* @exception IllegalArgumentException if name is null
*/
@Override
public void setName(String name) {
if (name == null)
throw new IllegalArgumentException
(sm.getString("standardHost.nullName"));
name = name.toLowerCase(Locale.ENGLISH); // Internally all names are lower case
String oldName = this.name;
this.name = name;
support.firePropertyChange("name", oldName, this.name);
}
/**
* @return <code>true</code> if WARs should be unpacked on deployment.
*/
public boolean isUnpackWARs() {
return unpackWARs;
}
/**
* Unpack WARs flag mutator.
*
* @param unpackWARs <code>true</code> to unpack WARs on deployment
*/
public void setUnpackWARs(boolean unpackWARs) {
this.unpackWARs = unpackWARs;
}
/**
* @return host work directory base.
*/
public String getWorkDir() {
return workDir;
}
/**
* Set host work directory base.
*
* @param workDir the new base work folder for this host
*/
public void setWorkDir(String workDir) {
this.workDir = workDir;
}
/**
* @return the regular expression that defines the files and directories in
* the host's {@link #getAppBase} that will be ignored by the automatic
* deployment process.
*/
@Override
public String getDeployIgnore() {
if (deployIgnore == null) {
return null;
}
return this.deployIgnore.toString();
}
/**
* @return the compiled regular expression that defines the files and
* directories in the host's {@link #getAppBase} that will be ignored by the
* automatic deployment process.
*/
@Override
public Pattern getDeployIgnorePattern() {
return this.deployIgnore;
}
/**
* Set the regular expression that defines the files and directories in
* the host's {@link #getAppBase} that will be ignored by the automatic
* deployment process.
*
* @param deployIgnore the regexp
*/
@Override
public void setDeployIgnore(String deployIgnore) {
String oldDeployIgnore;
if (this.deployIgnore == null) {
oldDeployIgnore = null;
} else {
oldDeployIgnore = this.deployIgnore.toString();
}
if (deployIgnore == null) {
this.deployIgnore = null;
} else {
this.deployIgnore = Pattern.compile(deployIgnore);
}
support.firePropertyChange("deployIgnore",
oldDeployIgnore,
deployIgnore);
}
/**
* @return <code>true</code> if a webapp start should fail if a Servlet startup fails
*/
public boolean isFailCtxIfServletStartFails() {
return failCtxIfServletStartFails;
}
/**
* Change the behavior of Servlet startup errors on web application starts.
* @param failCtxIfServletStartFails <code>false</code> to ignore errors on Servlets which
* are stated when the web application starts
*/
public void setFailCtxIfServletStartFails(
boolean failCtxIfServletStartFails) {
boolean oldFailCtxIfServletStartFails = this.failCtxIfServletStartFails;
this.failCtxIfServletStartFails = failCtxIfServletStartFails;
support.firePropertyChange("failCtxIfServletStartFails",
oldFailCtxIfServletStartFails,
failCtxIfServletStartFails);
}
// --------------------------------------------------------- Public Methods
/**
* Add an alias name that should be mapped to this same Host.
*
* @param alias The alias to be added
*/
@Override
public void addAlias(String alias) {
alias = alias.toLowerCase(Locale.ENGLISH);
synchronized (aliasesLock) {
// Skip duplicate aliases
for (int i = 0; i < aliases.length; i++) {
if (aliases[i].equals(alias))
return;
}
// Add this alias to the list
String newAliases[] = Arrays.copyOf(aliases, aliases.length + 1);
newAliases[aliases.length] = alias;
aliases = newAliases;
}
// Inform interested listeners
fireContainerEvent(ADD_ALIAS_EVENT, alias);
}
/**
* Add a child Container, only if the proposed child is an implementation
* of Context.
*
* @param child Child container to be added
*/
@Override
public void addChild(Container child) {
if (!(child instanceof Context))
throw new IllegalArgumentException
(sm.getString("standardHost.notContext"));
child.addLifecycleListener(new MemoryLeakTrackingListener());
// Avoid NPE for case where Context is defined in server.xml with only a
// docBase
Context context = (Context) child;
if (context.getPath() == null) {
ContextName cn = new ContextName(context.getDocBase(), true);
context.setPath(cn.getPath());
}
super.addChild(child);
}
/**
* Used to ensure the regardless of {@link Context} implementation, a record
* is kept of the class loader used every time a context starts.
*/
private class MemoryLeakTrackingListener implements LifecycleListener {
@Override
public void lifecycleEvent(LifecycleEvent event) {
if (event.getType().equals(Lifecycle.AFTER_START_EVENT)) {
if (event.getSource() instanceof Context) {
Context context = ((Context) event.getSource());
childClassLoaders.put(context.getLoader().getClassLoader(),
context.getServletContext().getContextPath());
}
}
}
}
/**
* Attempt to identify the contexts that have a class loader memory leak.
* This is usually triggered on context reload. Note: This method attempts
* to force a full garbage collection. This should be used with extreme
* caution on a production system.
*
* @return a list of possibly leaking contexts
*/
public String[] findReloadedContextMemoryLeaks() {
System.gc();
List<String> result = new ArrayList<>();
for (Map.Entry<ClassLoader, String> entry :
childClassLoaders.entrySet()) {
ClassLoader cl = entry.getKey();
if (cl instanceof WebappClassLoaderBase) {
if (!((WebappClassLoaderBase) cl).getState().isAvailable()) {
result.add(entry.getValue());
}
}
}
return result.toArray(new String[result.size()]);
}
/**
* @return the set of alias names for this Host. If none are defined,
* a zero length array is returned.
*/
@Override
public String[] findAliases() {
synchronized (aliasesLock) {
return this.aliases;
}
}
/**
* Remove the specified alias name from the aliases for this Host.
*
* @param alias Alias name to be removed
*/
@Override
public void removeAlias(String alias) {
alias = alias.toLowerCase(Locale.ENGLISH);
synchronized (aliasesLock) {
// Make sure this alias is currently present
int n = -1;
for (int i = 0; i < aliases.length; i++) {
if (aliases[i].equals(alias)) {
n = i;
break;
}
}
if (n < 0)
return;
// Remove the specified alias
int j = 0;
String results[] = new String[aliases.length - 1];
for (int i = 0; i < aliases.length; i++) {
if (i != n)
results[j++] = aliases[i];
}
aliases = results;
}
// Inform interested listeners
fireContainerEvent(REMOVE_ALIAS_EVENT, alias);
}
/**
* Start this component and implement the requirements
* of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
@Override
protected synchronized void startInternal() throws LifecycleException {
// Set error report valve
String errorValve = getErrorReportValveClass();
if ((errorValve != null) && (!errorValve.equals(""))) {
try {
boolean found = false;
Valve[] valves = getPipeline().getValves();
for (Valve valve : valves) {
if (errorValve.equals(valve.getClass().getName())) {
found = true;
break;
}
}
if(!found) {
Valve valve =
(Valve) Class.forName(errorValve).getConstructor().newInstance();
getPipeline().addValve(valve);
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString(
"standardHost.invalidErrorReportValveClass",
errorValve), t);
}
}
super.startInternal();
}
// -------------------- JMX --------------------
/**
* @return the MBean Names of the Valves associated with this Host
*
* @exception Exception if an MBean cannot be created or registered
*/
public String[] getValveNames() throws Exception {
Valve [] valves = this.getPipeline().getValves();
String [] mbeanNames = new String[valves.length];
for (int i = 0; i < valves.length; i++) {
if (valves[i] instanceof JmxEnabled) {
ObjectName oname = ((JmxEnabled) valves[i]).getObjectName();
if (oname != null) {
mbeanNames[i] = oname.toString();
}
}
}
return mbeanNames;
}
public String[] getAliases() {
synchronized (aliasesLock) {
return aliases;
}
}
@Override
protected String getObjectNameKeyProperties() {
StringBuilder keyProperties = new StringBuilder("type=Host");
keyProperties.append(getMBeanKeyProperties());
return keyProperties.toString();
}
}

View File

@@ -0,0 +1,410 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.servlet.DispatcherType;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.Context;
import org.apache.catalina.Globals;
import org.apache.catalina.Wrapper;
import org.apache.catalina.connector.ClientAbortException;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;
import org.apache.coyote.ActionCode;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.descriptor.web.ErrorPage;
import org.apache.tomcat.util.res.StringManager;
/**
* Valve that implements the default basic behavior for the
* <code>StandardHost</code> container implementation.
* <p>
* <b>USAGE CONSTRAINT</b>: This implementation is likely to be useful only
* when processing HTTP requests.
*
* @author Craig R. McClanahan
* @author Remy Maucherat
*/
final class StandardHostValve extends ValveBase {
private static final Log log = LogFactory.getLog(StandardHostValve.class);
// Saves a call to getClassLoader() on very request. Under high load these
// calls took just long enough to appear as a hot spot (although a very
// minor one) in a profiler.
private static final ClassLoader MY_CLASSLOADER =
StandardHostValve.class.getClassLoader();
static final boolean STRICT_SERVLET_COMPLIANCE;
static final boolean ACCESS_SESSION;
static {
STRICT_SERVLET_COMPLIANCE = Globals.STRICT_SERVLET_COMPLIANCE;
String accessSession = System.getProperty(
"org.apache.catalina.core.StandardHostValve.ACCESS_SESSION");
if (accessSession == null) {
ACCESS_SESSION = STRICT_SERVLET_COMPLIANCE;
} else {
ACCESS_SESSION = Boolean.parseBoolean(accessSession);
}
}
//------------------------------------------------------ Constructor
public StandardHostValve() {
super(true);
}
// ----------------------------------------------------- Instance Variables
/**
* The string manager for this package.
*/
private static final StringManager sm =
StringManager.getManager(Constants.Package);
// --------------------------------------------------------- Public Methods
/**
* Select the appropriate child Context to process this request,
* based on the specified request URI. If no matching Context can
* be found, return an appropriate HTTP error.
*
* @param request Request to be processed
* @param response Response to be produced
*
* @exception IOException if an input/output error occurred
* @exception ServletException if a servlet error occurred
*/
@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// Select the Context to be used for this Request
Context context = request.getContext();
if (context == null) {
return;
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(context.getPipeline().isAsyncSupported());
}
boolean asyncAtStart = request.isAsync();
try {
context.bind(Globals.IS_SECURITY_ENABLED, MY_CLASSLOADER);
if (!asyncAtStart && !context.fireRequestInitEvent(request.getRequest())) {
// Don't fire listeners during async processing (the listener
// fired for the request that called startAsync()).
// If a request init listener throws an exception, the request
// is aborted.
return;
}
// Ask this Context to process this request. Requests that are
// already in error must have been routed here to check for
// application defined error pages so DO NOT forward them to the the
// application for processing.
try {
if (!response.isErrorReportRequired()) {
context.getPipeline().getFirst().invoke(request, response);
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
container.getLogger().error("Exception Processing " + request.getRequestURI(), t);
// If a new error occurred while trying to report a previous
// error allow the original error to be reported.
if (!response.isErrorReportRequired()) {
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
throwable(request, response, t);
}
}
// Now that the request/response pair is back under container
// control lift the suspension so that the error handling can
// complete and/or the container can flush any remaining data
response.setSuspended(false);
Throwable t = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
// Protect against NPEs if the context was destroyed during a
// long running request.
if (!context.getState().isAvailable()) {
return;
}
// Look for (and render if found) an application level error page
if (response.isErrorReportRequired()) {
// If an error has occurred that prevents further I/O, don't waste time
// producing an error report that will never be read
AtomicBoolean result = new AtomicBoolean(false);
response.getCoyoteResponse().action(ActionCode.IS_IO_ALLOWED, result);
if (result.get()) {
if (t != null) {
throwable(request, response, t);
} else {
status(request, response);
}
}
}
if (!request.isAsync() && !asyncAtStart) {
context.fireRequestDestroyEvent(request.getRequest());
}
} finally {
// Access a session (if present) to update last accessed time, based
// on a strict interpretation of the specification
if (ACCESS_SESSION) {
request.getSession(false);
}
context.unbind(Globals.IS_SECURITY_ENABLED, MY_CLASSLOADER);
}
}
// -------------------------------------------------------- Private Methods
/**
* Handle the HTTP status code (and corresponding message) generated
* while processing the specified Request to produce the specified
* Response. Any exceptions that occur during generation of the error
* report are logged and swallowed.
*
* @param request The request being processed
* @param response The response being generated
*/
private void status(Request request, Response response) {
int statusCode = response.getStatus();
// Handle a custom error page for this status code
Context context = request.getContext();
if (context == null) {
return;
}
/* Only look for error pages when isError() is set.
* isError() is set when response.sendError() is invoked. This
* allows custom error pages without relying on default from
* web.xml.
*/
if (!response.isError()) {
return;
}
ErrorPage errorPage = context.findErrorPage(statusCode);
if (errorPage == null) {
// Look for a default error page
errorPage = context.findErrorPage(0);
}
if (errorPage != null && response.isErrorReportRequired()) {
response.setAppCommitted(false);
request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE,
Integer.valueOf(statusCode));
String message = response.getMessage();
if (message == null) {
message = "";
}
request.setAttribute(RequestDispatcher.ERROR_MESSAGE, message);
request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR,
errorPage.getLocation());
request.setAttribute(Globals.DISPATCHER_TYPE_ATTR,
DispatcherType.ERROR);
Wrapper wrapper = request.getWrapper();
if (wrapper != null) {
request.setAttribute(RequestDispatcher.ERROR_SERVLET_NAME,
wrapper.getName());
}
request.setAttribute(RequestDispatcher.ERROR_REQUEST_URI,
request.getRequestURI());
if (custom(request, response, errorPage)) {
response.setErrorReported();
try {
response.finishResponse();
} catch (ClientAbortException e) {
// Ignore
} catch (IOException e) {
container.getLogger().warn("Exception Processing " + errorPage, e);
}
}
}
}
/**
* Handle the specified Throwable encountered while processing
* the specified Request to produce the specified Response. Any
* exceptions that occur during generation of the exception report are
* logged and swallowed.
*
* @param request The request being processed
* @param response The response being generated
* @param throwable The exception that occurred (which possibly wraps
* a root cause exception
*/
protected void throwable(Request request, Response response,
Throwable throwable) {
Context context = request.getContext();
if (context == null) {
return;
}
Throwable realError = throwable;
if (realError instanceof ServletException) {
realError = ((ServletException) realError).getRootCause();
if (realError == null) {
realError = throwable;
}
}
// If this is an aborted request from a client just log it and return
if (realError instanceof ClientAbortException ) {
if (log.isDebugEnabled()) {
log.debug
(sm.getString("standardHost.clientAbort",
realError.getCause().getMessage()));
}
return;
}
ErrorPage errorPage = context.findErrorPage(throwable);
if ((errorPage == null) && (realError != throwable)) {
errorPage = context.findErrorPage(realError);
}
if (errorPage != null) {
if (response.setErrorReported()) {
response.setAppCommitted(false);
request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR,
errorPage.getLocation());
request.setAttribute(Globals.DISPATCHER_TYPE_ATTR,
DispatcherType.ERROR);
request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE,
Integer.valueOf(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
request.setAttribute(RequestDispatcher.ERROR_MESSAGE,
throwable.getMessage());
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION,
realError);
Wrapper wrapper = request.getWrapper();
if (wrapper != null) {
request.setAttribute(RequestDispatcher.ERROR_SERVLET_NAME,
wrapper.getName());
}
request.setAttribute(RequestDispatcher.ERROR_REQUEST_URI,
request.getRequestURI());
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE,
realError.getClass());
if (custom(request, response, errorPage)) {
try {
response.finishResponse();
} catch (IOException e) {
container.getLogger().warn("Exception Processing " + errorPage, e);
}
}
}
} else {
// A custom error-page has not been defined for the exception
// that was thrown during request processing. Check if an
// error-page for error code 500 was specified and if so,
// send that page back as the response.
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
// The response is an error
response.setError();
status(request, response);
}
}
/**
* Handle an HTTP status code or Java exception by forwarding control
* to the location included in the specified errorPage object. It is
* assumed that the caller has already recorded any request attributes
* that are to be forwarded to this page. Return <code>true</code> if
* we successfully utilized the specified error page location, or
* <code>false</code> if the default error report should be rendered.
*
* @param request The request being processed
* @param response The response being generated
* @param errorPage The errorPage directive we are obeying
*/
private boolean custom(Request request, Response response,
ErrorPage errorPage) {
if (container.getLogger().isDebugEnabled()) {
container.getLogger().debug("Processing " + errorPage);
}
try {
// Forward control to the specified location
ServletContext servletContext =
request.getContext().getServletContext();
RequestDispatcher rd =
servletContext.getRequestDispatcher(errorPage.getLocation());
if (rd == null) {
container.getLogger().error(
sm.getString("standardHostValue.customStatusFailed", errorPage.getLocation()));
return false;
}
if (response.isCommitted()) {
// Response is committed - including the error page is the
// best we can do
rd.include(request.getRequest(), response.getResponse());
} else {
// Reset the response (keeping the real error code and message)
response.resetBuffer(true);
response.setContentLength(-1);
rd.forward(request.getRequest(), response.getResponse());
// If we forward, the response is suspended again
response.setSuspended(false);
}
// Indicate that we have successfully processed this custom page
return true;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
// Report our failure to process this custom page
container.getLogger().error("Exception Processing " + errorPage, t);
return false;
}
}
}

View File

@@ -0,0 +1,467 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.management.ObjectName;
import org.apache.catalina.Contained;
import org.apache.catalina.Container;
import org.apache.catalina.JmxEnabled;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.Pipeline;
import org.apache.catalina.Valve;
import org.apache.catalina.util.LifecycleBase;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.res.StringManager;
/**
* Standard implementation of a processing <b>Pipeline</b> that will invoke
* a series of Valves that have been configured to be called in order. This
* implementation can be used for any type of Container.
*
* <b>IMPLEMENTATION WARNING</b> - This implementation assumes that no
* calls to <code>addValve()</code> or <code>removeValve</code> are allowed
* while a request is currently being processed. Otherwise, the mechanism
* by which per-thread state is maintained will need to be modified.
*
* @author Craig R. McClanahan
*/
public class StandardPipeline extends LifecycleBase
implements Pipeline, Contained {
private static final Log log = LogFactory.getLog(StandardPipeline.class);
private static final StringManager sm = StringManager.getManager(Constants.Package);
// ----------------------------------------------------------- Constructors
/**
* Construct a new StandardPipeline instance with no associated Container.
*/
public StandardPipeline() {
this(null);
}
/**
* Construct a new StandardPipeline instance that is associated with the
* specified Container.
*
* @param container The container we should be associated with
*/
public StandardPipeline(Container container) {
super();
setContainer(container);
}
// ----------------------------------------------------- Instance Variables
/**
* The basic Valve (if any) associated with this Pipeline.
*/
protected Valve basic = null;
/**
* The Container with which this Pipeline is associated.
*/
protected Container container = null;
/**
* The first valve associated with this Pipeline.
*/
protected Valve first = null;
// --------------------------------------------------------- Public Methods
@Override
public boolean isAsyncSupported() {
Valve valve = (first!=null)?first:basic;
boolean supported = true;
while (supported && valve!=null) {
supported = supported & valve.isAsyncSupported();
valve = valve.getNext();
}
return supported;
}
@Override
public void findNonAsyncValves(Set<String> result) {
Valve valve = (first!=null) ? first : basic;
while (valve != null) {
if (!valve.isAsyncSupported()) {
result.add(valve.getClass().getName());
}
valve = valve.getNext();
}
}
// ------------------------------------------------------ Contained Methods
/**
* Return the Container with which this Pipeline is associated.
*/
@Override
public Container getContainer() {
return this.container;
}
/**
* Set the Container with which this Pipeline is associated.
*
* @param container The new associated container
*/
@Override
public void setContainer(Container container) {
this.container = container;
}
@Override
protected void initInternal() {
// NOOP
}
/**
* Start {@link Valve}s) in this pipeline and implement the requirements
* of {@link LifecycleBase#startInternal()}.
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
@Override
protected synchronized void startInternal() throws LifecycleException {
// Start the Valves in our pipeline (including the basic), if any
Valve current = first;
if (current == null) {
current = basic;
}
while (current != null) {
if (current instanceof Lifecycle)
((Lifecycle) current).start();
current = current.getNext();
}
setState(LifecycleState.STARTING);
}
/**
* Stop {@link Valve}s) in this pipeline and implement the requirements
* of {@link LifecycleBase#stopInternal()}.
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
@Override
protected synchronized void stopInternal() throws LifecycleException {
setState(LifecycleState.STOPPING);
// Stop the Valves in our pipeline (including the basic), if any
Valve current = first;
if (current == null) {
current = basic;
}
while (current != null) {
if (current instanceof Lifecycle)
((Lifecycle) current).stop();
current = current.getNext();
}
}
@Override
protected void destroyInternal() {
Valve[] valves = getValves();
for (Valve valve : valves) {
removeValve(valve);
}
}
/**
* Return a String representation of this component.
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder("Pipeline[");
sb.append(container);
sb.append(']');
return sb.toString();
}
// ------------------------------------------------------- Pipeline Methods
/**
* <p>Return the Valve instance that has been distinguished as the basic
* Valve for this Pipeline (if any).
*/
@Override
public Valve getBasic() {
return this.basic;
}
/**
* <p>Set the Valve instance that has been distinguished as the basic
* Valve for this Pipeline (if any). Prior to setting the basic Valve,
* the Valve's <code>setContainer()</code> will be called, if it
* implements <code>Contained</code>, with the owning Container as an
* argument. The method may throw an <code>IllegalArgumentException</code>
* if this Valve chooses not to be associated with this Container, or
* <code>IllegalStateException</code> if it is already associated with
* a different Container.</p>
*
* @param valve Valve to be distinguished as the basic Valve
*/
@Override
public void setBasic(Valve valve) {
// Change components if necessary
Valve oldBasic = this.basic;
if (oldBasic == valve)
return;
// Stop the old component if necessary
if (oldBasic != null) {
if (getState().isAvailable() && (oldBasic instanceof Lifecycle)) {
try {
((Lifecycle) oldBasic).stop();
} catch (LifecycleException e) {
log.error(sm.getString("standardPipeline.basic.stop"), e);
}
}
if (oldBasic instanceof Contained) {
try {
((Contained) oldBasic).setContainer(null);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
}
}
}
// Start the new component if necessary
if (valve == null)
return;
if (valve instanceof Contained) {
((Contained) valve).setContainer(this.container);
}
if (getState().isAvailable() && valve instanceof Lifecycle) {
try {
((Lifecycle) valve).start();
} catch (LifecycleException e) {
log.error(sm.getString("standardPipeline.basic.start"), e);
return;
}
}
// Update the pipeline
Valve current = first;
while (current != null) {
if (current.getNext() == oldBasic) {
current.setNext(valve);
break;
}
current = current.getNext();
}
this.basic = valve;
}
/**
* <p>Add a new Valve to the end of the pipeline associated with this
* Container. Prior to adding the Valve, the Valve's
* <code>setContainer()</code> method will be called, if it implements
* <code>Contained</code>, with the owning Container as an argument.
* The method may throw an
* <code>IllegalArgumentException</code> if this Valve chooses not to
* be associated with this Container, or <code>IllegalStateException</code>
* if it is already associated with a different Container.</p>
*
* @param valve Valve to be added
*
* @exception IllegalArgumentException if this Container refused to
* accept the specified Valve
* @exception IllegalArgumentException if the specified Valve refuses to be
* associated with this Container
* @exception IllegalStateException if the specified Valve is already
* associated with a different Container
*/
@Override
public void addValve(Valve valve) {
// Validate that we can add this Valve
if (valve instanceof Contained)
((Contained) valve).setContainer(this.container);
// Start the new component if necessary
if (getState().isAvailable()) {
if (valve instanceof Lifecycle) {
try {
((Lifecycle) valve).start();
} catch (LifecycleException e) {
log.error(sm.getString("standardPipeline.valve.start"), e);
}
}
}
// Add this Valve to the set associated with this Pipeline
if (first == null) {
first = valve;
valve.setNext(basic);
} else {
Valve current = first;
while (current != null) {
if (current.getNext() == basic) {
current.setNext(valve);
valve.setNext(basic);
break;
}
current = current.getNext();
}
}
container.fireContainerEvent(Container.ADD_VALVE_EVENT, valve);
}
/**
* Return the set of Valves in the pipeline associated with this
* Container, including the basic Valve (if any). If there are no
* such Valves, a zero-length array is returned.
*/
@Override
public Valve[] getValves() {
List<Valve> valveList = new ArrayList<>();
Valve current = first;
if (current == null) {
current = basic;
}
while (current != null) {
valveList.add(current);
current = current.getNext();
}
return valveList.toArray(new Valve[0]);
}
public ObjectName[] getValveObjectNames() {
List<ObjectName> valveList = new ArrayList<>();
Valve current = first;
if (current == null) {
current = basic;
}
while (current != null) {
if (current instanceof JmxEnabled) {
valveList.add(((JmxEnabled) current).getObjectName());
}
current = current.getNext();
}
return valveList.toArray(new ObjectName[0]);
}
/**
* Remove the specified Valve from the pipeline associated with this
* Container, if it is found; otherwise, do nothing. If the Valve is
* found and removed, the Valve's <code>setContainer(null)</code> method
* will be called if it implements <code>Contained</code>.
*
* @param valve Valve to be removed
*/
@Override
public void removeValve(Valve valve) {
Valve current;
if(first == valve) {
first = first.getNext();
current = null;
} else {
current = first;
}
while (current != null) {
if (current.getNext() == valve) {
current.setNext(valve.getNext());
break;
}
current = current.getNext();
}
if (first == basic) first = null;
if (valve instanceof Contained)
((Contained) valve).setContainer(null);
if (valve instanceof Lifecycle) {
// Stop this valve if necessary
if (getState().isAvailable()) {
try {
((Lifecycle) valve).stop();
} catch (LifecycleException e) {
log.error(sm.getString("standardPipeline.valve.stop"), e);
}
}
try {
((Lifecycle) valve).destroy();
} catch (LifecycleException e) {
log.error(sm.getString("standardPipeline.valve.destroy"), e);
}
}
container.fireContainerEvent(Container.REMOVE_VALVE_EVENT, valve);
}
@Override
public Valve getFirst() {
if (first != null) {
return first;
}
return basic;
}
}

View File

@@ -0,0 +1,926 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.AccessControlException;
import java.util.Random;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.ObjectName;
import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.Server;
import org.apache.catalina.Service;
import org.apache.catalina.deploy.NamingResourcesImpl;
import org.apache.catalina.mbeans.MBeanFactory;
import org.apache.catalina.startup.Catalina;
import org.apache.catalina.util.ExtensionValidator;
import org.apache.catalina.util.LifecycleMBeanBase;
import org.apache.catalina.util.ServerInfo;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.buf.StringCache;
import org.apache.tomcat.util.res.StringManager;
/**
* Standard implementation of the <b>Server</b> interface, available for use
* (but not required) when deploying and starting Catalina.
*
* @author Craig R. McClanahan
*/
public final class StandardServer extends LifecycleMBeanBase implements Server {
private static final Log log = LogFactory.getLog(StandardServer.class);
// ------------------------------------------------------------ Constructor
/**
* Construct a default instance of this class.
*/
public StandardServer() {
super();
globalNamingResources = new NamingResourcesImpl();
globalNamingResources.setContainer(this);
if (isUseNaming()) {
namingContextListener = new NamingContextListener();
addLifecycleListener(namingContextListener);
} else {
namingContextListener = null;
}
}
// ----------------------------------------------------- Instance Variables
/**
* Global naming resources context.
*/
private javax.naming.Context globalNamingContext = null;
/**
* Global naming resources.
*/
private NamingResourcesImpl globalNamingResources = null;
/**
* The naming context listener for this web application.
*/
private final NamingContextListener namingContextListener;
/**
* The port number on which we wait for shutdown commands.
*/
private int port = 8005;
/**
* The address on which we wait for shutdown commands.
*/
private String address = "localhost";
/**
* A random number generator that is <strong>only</strong> used if
* the shutdown command string is longer than 1024 characters.
*/
private Random random = null;
/**
* The set of Services associated with this Server.
*/
private Service services[] = new Service[0];
private final Object servicesLock = new Object();
/**
* The shutdown command string we are looking for.
*/
private String shutdown = "SHUTDOWN";
/**
* The string manager for this package.
*/
private static final StringManager sm =
StringManager.getManager(Constants.Package);
/**
* The property change support for this component.
*/
final PropertyChangeSupport support = new PropertyChangeSupport(this);
private volatile boolean stopAwait = false;
private Catalina catalina = null;
private ClassLoader parentClassLoader = null;
/**
* Thread that currently is inside our await() method.
*/
private volatile Thread awaitThread = null;
/**
* Server socket that is used to wait for the shutdown command.
*/
private volatile ServerSocket awaitSocket = null;
private File catalinaHome = null;
private File catalinaBase = null;
private final Object namingToken = new Object();
// ------------------------------------------------------------- Properties
@Override
public Object getNamingToken() {
return namingToken;
}
/**
* Return the global naming resources context.
*/
@Override
public javax.naming.Context getGlobalNamingContext() {
return this.globalNamingContext;
}
/**
* Set the global naming resources context.
*
* @param globalNamingContext The new global naming resource context
*/
public void setGlobalNamingContext(javax.naming.Context globalNamingContext) {
this.globalNamingContext = globalNamingContext;
}
/**
* Return the global naming resources.
*/
@Override
public NamingResourcesImpl getGlobalNamingResources() {
return this.globalNamingResources;
}
/**
* Set the global naming resources.
*
* @param globalNamingResources The new global naming resources
*/
@Override
public void setGlobalNamingResources
(NamingResourcesImpl globalNamingResources) {
NamingResourcesImpl oldGlobalNamingResources =
this.globalNamingResources;
this.globalNamingResources = globalNamingResources;
this.globalNamingResources.setContainer(this);
support.firePropertyChange("globalNamingResources",
oldGlobalNamingResources,
this.globalNamingResources);
}
/**
* Report the current Tomcat Server Release number
* @return Tomcat release identifier
*/
public String getServerInfo() {
return ServerInfo.getServerInfo();
}
/**
* Return the current server built timestamp
* @return server built timestamp.
*/
public String getServerBuilt() {
return ServerInfo.getServerBuilt();
}
/**
* Return the current server's version number.
* @return server's version number.
*/
public String getServerNumber() {
return ServerInfo.getServerNumber();
}
/**
* Return the port number we listen to for shutdown commands.
*/
@Override
public int getPort() {
return this.port;
}
/**
* Set the port number we listen to for shutdown commands.
*
* @param port The new port number
*/
@Override
public void setPort(int port) {
this.port = port;
}
/**
* Return the address on which we listen to for shutdown commands.
*/
@Override
public String getAddress() {
return this.address;
}
/**
* Set the address on which we listen to for shutdown commands.
*
* @param address The new address
*/
@Override
public void setAddress(String address) {
this.address = address;
}
/**
* Return the shutdown command string we are waiting for.
*/
@Override
public String getShutdown() {
return this.shutdown;
}
/**
* Set the shutdown command we are waiting for.
*
* @param shutdown The new shutdown command
*/
@Override
public void setShutdown(String shutdown) {
this.shutdown = shutdown;
}
/**
* Return the outer Catalina startup/shutdown component if present.
*/
@Override
public Catalina getCatalina() {
return catalina;
}
/**
* Set the outer Catalina startup/shutdown component if present.
*/
@Override
public void setCatalina(Catalina catalina) {
this.catalina = catalina;
}
// --------------------------------------------------------- Server Methods
/**
* Add a new Service to the set of defined Services.
*
* @param service The Service to be added
*/
@Override
public void addService(Service service) {
service.setServer(this);
synchronized (servicesLock) {
Service results[] = new Service[services.length + 1];
System.arraycopy(services, 0, results, 0, services.length);
results[services.length] = service;
services = results;
if (getState().isAvailable()) {
try {
service.start();
} catch (LifecycleException e) {
// Ignore
}
}
// Report this property change to interested listeners
support.firePropertyChange("service", null, service);
}
}
public void stopAwait() {
stopAwait=true;
Thread t = awaitThread;
if (t != null) {
ServerSocket s = awaitSocket;
if (s != null) {
awaitSocket = null;
try {
s.close();
} catch (IOException e) {
// Ignored
}
}
t.interrupt();
try {
t.join(1000);
} catch (InterruptedException e) {
// Ignored
}
}
}
/**
* Wait until a proper shutdown command is received, then return.
* This keeps the main thread alive - the thread pool listening for http
* connections is daemon threads.
*/
@Override
public void await() {
// Negative values - don't wait on port - tomcat is embedded or we just don't like ports
if (port == -2) {
// undocumented yet - for embedding apps that are around, alive.
return;
}
if (port==-1) {
try {
awaitThread = Thread.currentThread();
while(!stopAwait) {
try {
Thread.sleep( 10000 );
} catch( InterruptedException ex ) {
// continue and check the flag
}
}
} finally {
awaitThread = null;
}
return;
}
// Set up a server socket to wait on
try {
awaitSocket = new ServerSocket(port, 1,
InetAddress.getByName(address));
} catch (IOException e) {
log.error("StandardServer.await: create[" + address
+ ":" + port
+ "]: ", e);
return;
}
try {
awaitThread = Thread.currentThread();
// Loop waiting for a connection and a valid command
while (!stopAwait) {
ServerSocket serverSocket = awaitSocket;
if (serverSocket == null) {
break;
}
// Wait for the next connection
Socket socket = null;
StringBuilder command = new StringBuilder();
try {
InputStream stream;
long acceptStartTime = System.currentTimeMillis();
try {
socket = serverSocket.accept();
socket.setSoTimeout(10 * 1000); // Ten seconds
stream = socket.getInputStream();
} catch (SocketTimeoutException ste) {
// This should never happen but bug 56684 suggests that
// it does.
log.warn(sm.getString("standardServer.accept.timeout",
Long.valueOf(System.currentTimeMillis() - acceptStartTime)), ste);
continue;
} catch (AccessControlException ace) {
log.warn(sm.getString("standardServer.accept.security"), ace);
continue;
} catch (IOException e) {
if (stopAwait) {
// Wait was aborted with socket.close()
break;
}
log.error(sm.getString("standardServer.accept.error"), e);
break;
}
// Read a set of characters from the socket
int expected = 1024; // Cut off to avoid DoS attack
while (expected < shutdown.length()) {
if (random == null)
random = new Random();
expected += (random.nextInt() % 1024);
}
while (expected > 0) {
int ch = -1;
try {
ch = stream.read();
} catch (IOException e) {
log.warn(sm.getString("standardServer.accept.readError"), e);
ch = -1;
}
// Control character or EOF (-1) terminates loop
if (ch < 32 || ch == 127) {
break;
}
command.append((char) ch);
expected--;
}
} finally {
// Close the socket now that we are done with it
try {
if (socket != null) {
socket.close();
}
} catch (IOException e) {
// Ignore
}
}
// Match against our command string
boolean match = command.toString().equals(shutdown);
if (match) {
log.info(sm.getString("standardServer.shutdownViaPort"));
break;
} else
log.warn(sm.getString("standardServer.invalidShutdownCommand", command.toString()));
}
} finally {
ServerSocket serverSocket = awaitSocket;
awaitThread = null;
awaitSocket = null;
// Close the server socket and return
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
// Ignore
}
}
}
}
/**
* @return the specified Service (if it exists); otherwise return
* <code>null</code>.
*
* @param name Name of the Service to be returned
*/
@Override
public Service findService(String name) {
if (name == null) {
return null;
}
synchronized (servicesLock) {
for (int i = 0; i < services.length; i++) {
if (name.equals(services[i].getName())) {
return services[i];
}
}
}
return null;
}
/**
* @return the set of Services defined within this Server.
*/
@Override
public Service[] findServices() {
return services;
}
/**
* @return the JMX service names.
*/
public ObjectName[] getServiceNames() {
ObjectName onames[]=new ObjectName[ services.length ];
for( int i=0; i<services.length; i++ ) {
onames[i]=((StandardService)services[i]).getObjectName();
}
return onames;
}
/**
* Remove the specified Service from the set associated from this
* Server.
*
* @param service The Service to be removed
*/
@Override
public void removeService(Service service) {
synchronized (servicesLock) {
int j = -1;
for (int i = 0; i < services.length; i++) {
if (service == services[i]) {
j = i;
break;
}
}
if (j < 0)
return;
try {
services[j].stop();
} catch (LifecycleException e) {
// Ignore
}
int k = 0;
Service results[] = new Service[services.length - 1];
for (int i = 0; i < services.length; i++) {
if (i != j)
results[k++] = services[i];
}
services = results;
// Report this property change to interested listeners
support.firePropertyChange("service", service, null);
}
}
@Override
public File getCatalinaBase() {
if (catalinaBase != null) {
return catalinaBase;
}
catalinaBase = getCatalinaHome();
return catalinaBase;
}
@Override
public void setCatalinaBase(File catalinaBase) {
this.catalinaBase = catalinaBase;
}
@Override
public File getCatalinaHome() {
return catalinaHome;
}
@Override
public void setCatalinaHome(File catalinaHome) {
this.catalinaHome = catalinaHome;
}
// --------------------------------------------------------- Public Methods
/**
* Add a property change listener to this component.
*
* @param listener The listener to add
*/
public void addPropertyChangeListener(PropertyChangeListener listener) {
support.addPropertyChangeListener(listener);
}
/**
* Remove a property change listener from this component.
*
* @param listener The listener to remove
*/
public void removePropertyChangeListener(PropertyChangeListener listener) {
support.removePropertyChangeListener(listener);
}
/**
* Return a String representation of this component.
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder("StandardServer[");
sb.append(getPort());
sb.append("]");
return sb.toString();
}
/**
* Write the configuration information for this entire <code>Server</code>
* out to the server.xml configuration file.
*
* @exception InstanceNotFoundException
* if the managed resource object cannot be found
* @exception MBeanException
* if the initializer of the object throws an exception, or
* persistence is not supported
* @exception javax.management.RuntimeOperationsException
* if an exception is reported by the persistence mechanism
*/
public synchronized void storeConfig() throws InstanceNotFoundException, MBeanException {
try {
// Note: Hard-coded domain used since this object is per Server/JVM
ObjectName sname = new ObjectName("Catalina:type=StoreConfig");
if (mserver.isRegistered(sname)) {
mserver.invoke(sname, "storeConfig", null, null);
} else {
log.error(sm.getString("standardServer.storeConfig.notAvailable", sname));
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("standardServer.storeConfig.error"), t);
}
}
/**
* Write the configuration information for <code>Context</code>
* out to the specified configuration file.
*
* @param context the context which should save its configuration
* @exception InstanceNotFoundException
* if the managed resource object cannot be found
* @exception MBeanException
* if the initializer of the object throws an exception
* or persistence is not supported
* @exception javax.management.RuntimeOperationsException
* if an exception is reported by the persistence mechanism
*/
public synchronized void storeContext(Context context) throws InstanceNotFoundException, MBeanException {
try {
// Note: Hard-coded domain used since this object is per Server/JVM
ObjectName sname = new ObjectName("Catalina:type=StoreConfig");
if (mserver.isRegistered(sname)) {
mserver.invoke(sname, "store",
new Object[] {context},
new String [] { "java.lang.String"});
} else {
log.error(sm.getString("standardServer.storeConfig.notAvailable", sname));
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("standardServer.storeConfig.contextError", context.getName()), t);
}
}
/**
* @return <code>true</code> if naming should be used.
*/
private boolean isUseNaming() {
boolean useNaming = true;
// Reading the "catalina.useNaming" environment variable
String useNamingProperty = System.getProperty("catalina.useNaming");
if ((useNamingProperty != null)
&& (useNamingProperty.equals("false"))) {
useNaming = false;
}
return useNaming;
}
/**
* Start nested components ({@link Service}s) and implement the requirements
* of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
@Override
protected void startInternal() throws LifecycleException {
fireLifecycleEvent(CONFIGURE_START_EVENT, null);
setState(LifecycleState.STARTING);
globalNamingResources.start();
// Start our defined Services
synchronized (servicesLock) {
for (int i = 0; i < services.length; i++) {
services[i].start();
}
}
}
/**
* Stop nested components ({@link Service}s) and implement the requirements
* of {@link org.apache.catalina.util.LifecycleBase#stopInternal()}.
*
* @exception LifecycleException if this component detects a fatal error
* that needs to be reported
*/
@Override
protected void stopInternal() throws LifecycleException {
setState(LifecycleState.STOPPING);
fireLifecycleEvent(CONFIGURE_STOP_EVENT, null);
// Stop our defined Services
for (int i = 0; i < services.length; i++) {
services[i].stop();
}
globalNamingResources.stop();
stopAwait();
}
/**
* Invoke a pre-startup initialization. This is used to allow connectors
* to bind to restricted ports under Unix operating environments.
*/
@Override
protected void initInternal() throws LifecycleException {
super.initInternal();
// Register global String cache
// Note although the cache is global, if there are multiple Servers
// present in the JVM (may happen when embedding) then the same cache
// will be registered under multiple names
onameStringCache = register(new StringCache(), "type=StringCache");
// Register the MBeanFactory
MBeanFactory factory = new MBeanFactory();
factory.setContainer(this);
onameMBeanFactory = register(factory, "type=MBeanFactory");
// Register the naming resources
globalNamingResources.init();
// Populate the extension validator with JARs from common and shared
// class loaders
if (getCatalina() != null) {
ClassLoader cl = getCatalina().getParentClassLoader();
// Walk the class loader hierarchy. Stop at the system class loader.
// This will add the shared (if present) and common class loaders
while (cl != null && cl != ClassLoader.getSystemClassLoader()) {
if (cl instanceof URLClassLoader) {
URL[] urls = ((URLClassLoader) cl).getURLs();
for (URL url : urls) {
if (url.getProtocol().equals("file")) {
try {
File f = new File (url.toURI());
if (f.isFile() &&
f.getName().endsWith(".jar")) {
ExtensionValidator.addSystemResource(f);
}
} catch (URISyntaxException e) {
// Ignore
} catch (IOException e) {
// Ignore
}
}
}
}
cl = cl.getParent();
}
}
// Initialize our defined Services
for (int i = 0; i < services.length; i++) {
services[i].init();
}
}
@Override
protected void destroyInternal() throws LifecycleException {
// Destroy our defined Services
for (int i = 0; i < services.length; i++) {
services[i].destroy();
}
globalNamingResources.destroy();
unregister(onameMBeanFactory);
unregister(onameStringCache);
super.destroyInternal();
}
/**
* Return the parent class loader for this component.
*/
@Override
public ClassLoader getParentClassLoader() {
if (parentClassLoader != null)
return parentClassLoader;
if (catalina != null) {
return catalina.getParentClassLoader();
}
return ClassLoader.getSystemClassLoader();
}
/**
* Set the parent class loader for this server.
*
* @param parent The new parent class loader
*/
@Override
public void setParentClassLoader(ClassLoader parent) {
ClassLoader oldParentClassLoader = this.parentClassLoader;
this.parentClassLoader = parent;
support.firePropertyChange("parentClassLoader", oldParentClassLoader,
this.parentClassLoader);
}
private ObjectName onameStringCache;
private ObjectName onameMBeanFactory;
/**
* Obtain the MBean domain for this server. The domain is obtained using
* the following search order:
* <ol>
* <li>Name of first {@link org.apache.catalina.Engine}.</li>
* <li>Name of first {@link Service}.</li>
* </ol>
*/
@Override
protected String getDomainInternal() {
String domain = null;
Service[] services = findServices();
if (services.length > 0) {
Service service = services[0];
if (service != null) {
domain = service.getDomain();
}
}
return domain;
}
@Override
protected final String getObjectNameKeyProperties() {
return "type=Server";
}
}

View File

@@ -0,0 +1,648 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import javax.management.ObjectName;
import org.apache.catalina.Container;
import org.apache.catalina.Engine;
import org.apache.catalina.Executor;
import org.apache.catalina.JmxEnabled;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.Server;
import org.apache.catalina.Service;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.mapper.Mapper;
import org.apache.catalina.mapper.MapperListener;
import org.apache.catalina.util.LifecycleMBeanBase;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.res.StringManager;
/**
* Standard implementation of the <code>Service</code> interface. The
* associated Container is generally an instance of Engine, but this is
* not required.
*
* @author Craig R. McClanahan
*/
public class StandardService extends LifecycleMBeanBase implements Service {
private static final Log log = LogFactory.getLog(StandardService.class);
// ----------------------------------------------------- Instance Variables
/**
* The name of this service.
*/
private String name = null;
/**
* The string manager for this package.
*/
private static final StringManager sm =
StringManager.getManager(Constants.Package);
/**
* The <code>Server</code> that owns this Service, if any.
*/
private Server server = null;
/**
* The property change support for this component.
*/
protected final PropertyChangeSupport support = new PropertyChangeSupport(this);
/**
* The set of Connectors associated with this Service.
*/
protected Connector connectors[] = new Connector[0];
private final Object connectorsLock = new Object();
/**
*
*/
protected final ArrayList<Executor> executors = new ArrayList<>();
private Engine engine = null;
private ClassLoader parentClassLoader = null;
/**
* Mapper.
*/
protected final Mapper mapper = new Mapper();
/**
* Mapper listener.
*/
protected final MapperListener mapperListener = new MapperListener(this);
// ------------------------------------------------------------- Properties
@Override
public Mapper getMapper() {
return mapper;
}
@Override
public Engine getContainer() {
return engine;
}
@Override
public void setContainer(Engine engine) {
Engine oldEngine = this.engine;
if (oldEngine != null) {
oldEngine.setService(null);
}
this.engine = engine;
if (this.engine != null) {
this.engine.setService(this);
}
if (getState().isAvailable()) {
if (this.engine != null) {
try {
this.engine.start();
} catch (LifecycleException e) {
log.error(sm.getString("standardService.engine.startFailed"), e);
}
}
// Restart MapperListener to pick up new engine.
try {
mapperListener.stop();
} catch (LifecycleException e) {
log.error(sm.getString("standardService.mapperListener.stopFailed"), e);
}
try {
mapperListener.start();
} catch (LifecycleException e) {
log.error(sm.getString("standardService.mapperListener.startFailed"), e);
}
if (oldEngine != null) {
try {
oldEngine.stop();
} catch (LifecycleException e) {
log.error(sm.getString("standardService.engine.stopFailed"), e);
}
}
}
// Report this property change to interested listeners
support.firePropertyChange("container", oldEngine, this.engine);
}
/**
* Return the name of this Service.
*/
@Override
public String getName() {
return name;
}
/**
* Set the name of this Service.
*
* @param name The new service name
*/
@Override
public void setName(String name) {
this.name = name;
}
/**
* Return the <code>Server</code> with which we are associated (if any).
*/
@Override
public Server getServer() {
return this.server;
}
/**
* Set the <code>Server</code> with which we are associated (if any).
*
* @param server The server that owns this Service
*/
@Override
public void setServer(Server server) {
this.server = server;
}
// --------------------------------------------------------- Public Methods
/**
* Add a new Connector to the set of defined Connectors, and associate it
* with this Service's Container.
*
* @param connector The Connector to be added
*/
@Override
public void addConnector(Connector connector) {
synchronized (connectorsLock) {
connector.setService(this);
Connector results[] = new Connector[connectors.length + 1];
System.arraycopy(connectors, 0, results, 0, connectors.length);
results[connectors.length] = connector;
connectors = results;
if (getState().isAvailable()) {
try {
connector.start();
} catch (LifecycleException e) {
log.error(sm.getString(
"standardService.connector.startFailed",
connector), e);
}
}
// Report this property change to interested listeners
support.firePropertyChange("connector", null, connector);
}
}
public ObjectName[] getConnectorNames() {
ObjectName results[] = new ObjectName[connectors.length];
for (int i=0; i<results.length; i++) {
results[i] = connectors[i].getObjectName();
}
return results;
}
/**
* Add a property change listener to this component.
*
* @param listener The listener to add
*/
public void addPropertyChangeListener(PropertyChangeListener listener) {
support.addPropertyChangeListener(listener);
}
/**
* Find and return the set of Connectors associated with this Service.
*/
@Override
public Connector[] findConnectors() {
return connectors;
}
/**
* Remove the specified Connector from the set associated from this
* Service. The removed Connector will also be disassociated from our
* Container.
*
* @param connector The Connector to be removed
*/
@Override
public void removeConnector(Connector connector) {
synchronized (connectorsLock) {
int j = -1;
for (int i = 0; i < connectors.length; i++) {
if (connector == connectors[i]) {
j = i;
break;
}
}
if (j < 0)
return;
if (connectors[j].getState().isAvailable()) {
try {
connectors[j].stop();
} catch (LifecycleException e) {
log.error(sm.getString(
"standardService.connector.stopFailed",
connectors[j]), e);
}
}
connector.setService(null);
int k = 0;
Connector results[] = new Connector[connectors.length - 1];
for (int i = 0; i < connectors.length; i++) {
if (i != j)
results[k++] = connectors[i];
}
connectors = results;
// Report this property change to interested listeners
support.firePropertyChange("connector", connector, null);
}
}
/**
* Remove a property change listener from this component.
*
* @param listener The listener to remove
*/
public void removePropertyChangeListener(PropertyChangeListener listener) {
support.removePropertyChangeListener(listener);
}
/**
* Return a String representation of this component.
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder("StandardService[");
sb.append(getName());
sb.append("]");
return sb.toString();
}
/**
* Adds a named executor to the service
* @param ex Executor
*/
@Override
public void addExecutor(Executor ex) {
synchronized (executors) {
if (!executors.contains(ex)) {
executors.add(ex);
if (getState().isAvailable()) {
try {
ex.start();
} catch (LifecycleException x) {
log.error("Executor.start", x);
}
}
}
}
}
/**
* Retrieves all executors
* @return Executor[]
*/
@Override
public Executor[] findExecutors() {
synchronized (executors) {
Executor[] arr = new Executor[executors.size()];
executors.toArray(arr);
return arr;
}
}
/**
* Retrieves executor by name, null if not found
* @param executorName String
* @return Executor
*/
@Override
public Executor getExecutor(String executorName) {
synchronized (executors) {
for (Executor executor: executors) {
if (executorName.equals(executor.getName()))
return executor;
}
}
return null;
}
/**
* Removes an executor from the service
* @param ex Executor
*/
@Override
public void removeExecutor(Executor ex) {
synchronized (executors) {
if ( executors.remove(ex) && getState().isAvailable() ) {
try {
ex.stop();
} catch (LifecycleException e) {
log.error("Executor.stop", e);
}
}
}
}
/**
* Start nested components ({@link Executor}s, {@link Connector}s and
* {@link Container}s) and implement the requirements of
* {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
@Override
protected void startInternal() throws LifecycleException {
if(log.isInfoEnabled())
log.info(sm.getString("standardService.start.name", this.name));
setState(LifecycleState.STARTING);
// Start our defined Container first
if (engine != null) {
synchronized (engine) {
engine.start();
}
}
synchronized (executors) {
for (Executor executor: executors) {
executor.start();
}
}
mapperListener.start();
// Start our defined Connectors second
synchronized (connectorsLock) {
for (Connector connector: connectors) {
try {
// If it has already failed, don't try and start it
if (connector.getState() != LifecycleState.FAILED) {
connector.start();
}
} catch (Exception e) {
log.error(sm.getString(
"standardService.connector.startFailed",
connector), e);
}
}
}
}
/**
* Stop nested components ({@link Executor}s, {@link Connector}s and
* {@link Container}s) and implement the requirements of
* {@link org.apache.catalina.util.LifecycleBase#stopInternal()}.
*
* @exception LifecycleException if this component detects a fatal error
* that needs to be reported
*/
@Override
protected void stopInternal() throws LifecycleException {
// Pause connectors first
synchronized (connectorsLock) {
for (Connector connector: connectors) {
try {
connector.pause();
} catch (Exception e) {
log.error(sm.getString(
"standardService.connector.pauseFailed",
connector), e);
}
// Close server socket if bound on start
// Note: test is in AbstractEndpoint
connector.getProtocolHandler().closeServerSocketGraceful();
}
}
if(log.isInfoEnabled())
log.info(sm.getString("standardService.stop.name", this.name));
setState(LifecycleState.STOPPING);
// Stop our defined Container second
if (engine != null) {
synchronized (engine) {
engine.stop();
}
}
// Now stop the connectors
synchronized (connectorsLock) {
for (Connector connector: connectors) {
if (!LifecycleState.STARTED.equals(
connector.getState())) {
// Connectors only need stopping if they are currently
// started. They may have failed to start or may have been
// stopped (e.g. via a JMX call)
continue;
}
try {
connector.stop();
} catch (Exception e) {
log.error(sm.getString(
"standardService.connector.stopFailed",
connector), e);
}
}
}
// If the Server failed to start, the mapperListener won't have been
// started
if (mapperListener.getState() != LifecycleState.INITIALIZED) {
mapperListener.stop();
}
synchronized (executors) {
for (Executor executor: executors) {
executor.stop();
}
}
}
/**
* Invoke a pre-startup initialization. This is used to allow connectors
* to bind to restricted ports under Unix operating environments.
*/
@Override
protected void initInternal() throws LifecycleException {
super.initInternal();
if (engine != null) {
engine.init();
}
// Initialize any Executors
for (Executor executor : findExecutors()) {
if (executor instanceof JmxEnabled) {
((JmxEnabled) executor).setDomain(getDomain());
}
executor.init();
}
// Initialize mapper listener
mapperListener.init();
// Initialize our defined Connectors
synchronized (connectorsLock) {
for (Connector connector : connectors) {
try {
connector.init();
} catch (Exception e) {
String message = sm.getString(
"standardService.connector.initFailed", connector);
log.error(message, e);
if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"))
throw new LifecycleException(message);
}
}
}
}
@Override
protected void destroyInternal() throws LifecycleException {
mapperListener.destroy();
// Destroy our defined Connectors
synchronized (connectorsLock) {
for (Connector connector : connectors) {
try {
connector.destroy();
} catch (Exception e) {
log.error(sm.getString(
"standardService.connector.destroyFailed", connector), e);
}
}
}
// Destroy any Executors
for (Executor executor : findExecutors()) {
executor.destroy();
}
if (engine != null) {
engine.destroy();
}
super.destroyInternal();
}
/**
* Return the parent class loader for this component.
*/
@Override
public ClassLoader getParentClassLoader() {
if (parentClassLoader != null)
return parentClassLoader;
if (server != null) {
return server.getParentClassLoader();
}
return ClassLoader.getSystemClassLoader();
}
/**
* Set the parent class loader for this server.
*
* @param parent The new parent class loader
*/
@Override
public void setParentClassLoader(ClassLoader parent) {
ClassLoader oldParentClassLoader = this.parentClassLoader;
this.parentClassLoader = parent;
support.firePropertyChange("parentClassLoader", oldParentClassLoader,
this.parentClassLoader);
}
@Override
protected String getDomainInternal() {
String domain = null;
Container engine = getContainer();
// Use the engine name first
if (engine != null) {
domain = engine.getName();
}
// No engine or no engine name, use the service name
if (domain == null) {
domain = getName();
}
// No service name, return null which will trigger the use of the
// default
return domain;
}
@Override
public final String getObjectNameKeyProperties() {
return "type=Service";
}
}

View File

@@ -0,0 +1,335 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import org.apache.catalina.Executor;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.util.LifecycleMBeanBase;
import org.apache.tomcat.util.threads.ResizableExecutor;
import org.apache.tomcat.util.threads.TaskQueue;
import org.apache.tomcat.util.threads.TaskThreadFactory;
import org.apache.tomcat.util.threads.ThreadPoolExecutor;
public class StandardThreadExecutor extends LifecycleMBeanBase
implements Executor, ResizableExecutor {
// ---------------------------------------------- Properties
/**
* Default thread priority
*/
protected int threadPriority = Thread.NORM_PRIORITY;
/**
* Run threads in daemon or non-daemon state
*/
protected boolean daemon = true;
/**
* Default name prefix for the thread name
*/
protected String namePrefix = "tomcat-exec-";
/**
* max number of threads
*/
protected int maxThreads = 200;
/**
* min number of threads
*/
protected int minSpareThreads = 25;
/**
* idle time in milliseconds
*/
protected int maxIdleTime = 60000;
/**
* The executor we use for this component
*/
protected ThreadPoolExecutor executor = null;
/**
* the name of this thread pool
*/
protected String name;
/**
* prestart threads?
*/
protected boolean prestartminSpareThreads = false;
/**
* The maximum number of elements that can queue up before we reject them
*/
protected int maxQueueSize = Integer.MAX_VALUE;
/**
* After a context is stopped, threads in the pool are renewed. To avoid
* renewing all threads at the same time, this delay is observed between 2
* threads being renewed.
*/
protected long threadRenewalDelay =
org.apache.tomcat.util.threads.Constants.DEFAULT_THREAD_RENEWAL_DELAY;
private TaskQueue taskqueue = null;
// ---------------------------------------------- Constructors
public StandardThreadExecutor() {
//empty constructor for the digester
}
// ---------------------------------------------- Public Methods
@Override
protected void initInternal() throws LifecycleException {
super.initInternal();
}
/**
* Start the component and implement the requirements
* of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
@Override
protected void startInternal() throws LifecycleException {
taskqueue = new TaskQueue(maxQueueSize);
TaskThreadFactory tf = new TaskThreadFactory(namePrefix,daemon,getThreadPriority());
executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), maxIdleTime, TimeUnit.MILLISECONDS,taskqueue, tf);
executor.setThreadRenewalDelay(threadRenewalDelay);
if (prestartminSpareThreads) {
executor.prestartAllCoreThreads();
}
taskqueue.setParent(executor);
setState(LifecycleState.STARTING);
}
/**
* Stop the component and implement the requirements
* of {@link org.apache.catalina.util.LifecycleBase#stopInternal()}.
*
* @exception LifecycleException if this component detects a fatal error
* that needs to be reported
*/
@Override
protected void stopInternal() throws LifecycleException {
setState(LifecycleState.STOPPING);
if ( executor != null ) executor.shutdownNow();
executor = null;
taskqueue = null;
}
@Override
protected void destroyInternal() throws LifecycleException {
super.destroyInternal();
}
@Override
public void execute(Runnable command, long timeout, TimeUnit unit) {
if ( executor != null ) {
executor.execute(command,timeout,unit);
} else {
throw new IllegalStateException("StandardThreadExecutor not started.");
}
}
@Override
public void execute(Runnable command) {
if ( executor != null ) {
try {
executor.execute(command);
} catch (RejectedExecutionException rx) {
//there could have been contention around the queue
if ( !( (TaskQueue) executor.getQueue()).force(command) ) throw new RejectedExecutionException("Work queue full.");
}
} else throw new IllegalStateException("StandardThreadPool not started.");
}
public void contextStopping() {
if (executor != null) {
executor.contextStopping();
}
}
public int getThreadPriority() {
return threadPriority;
}
public boolean isDaemon() {
return daemon;
}
public String getNamePrefix() {
return namePrefix;
}
public int getMaxIdleTime() {
return maxIdleTime;
}
@Override
public int getMaxThreads() {
return maxThreads;
}
public int getMinSpareThreads() {
return minSpareThreads;
}
@Override
public String getName() {
return name;
}
public boolean isPrestartminSpareThreads() {
return prestartminSpareThreads;
}
public void setThreadPriority(int threadPriority) {
this.threadPriority = threadPriority;
}
public void setDaemon(boolean daemon) {
this.daemon = daemon;
}
public void setNamePrefix(String namePrefix) {
this.namePrefix = namePrefix;
}
public void setMaxIdleTime(int maxIdleTime) {
this.maxIdleTime = maxIdleTime;
if (executor != null) {
executor.setKeepAliveTime(maxIdleTime, TimeUnit.MILLISECONDS);
}
}
public void setMaxThreads(int maxThreads) {
this.maxThreads = maxThreads;
if (executor != null) {
executor.setMaximumPoolSize(maxThreads);
}
}
public void setMinSpareThreads(int minSpareThreads) {
this.minSpareThreads = minSpareThreads;
if (executor != null) {
executor.setCorePoolSize(minSpareThreads);
}
}
public void setPrestartminSpareThreads(boolean prestartminSpareThreads) {
this.prestartminSpareThreads = prestartminSpareThreads;
}
public void setName(String name) {
this.name = name;
}
public void setMaxQueueSize(int size) {
this.maxQueueSize = size;
}
public int getMaxQueueSize() {
return maxQueueSize;
}
public long getThreadRenewalDelay() {
return threadRenewalDelay;
}
public void setThreadRenewalDelay(long threadRenewalDelay) {
this.threadRenewalDelay = threadRenewalDelay;
if (executor != null) {
executor.setThreadRenewalDelay(threadRenewalDelay);
}
}
// Statistics from the thread pool
@Override
public int getActiveCount() {
return (executor != null) ? executor.getActiveCount() : 0;
}
public long getCompletedTaskCount() {
return (executor != null) ? executor.getCompletedTaskCount() : 0;
}
public int getCorePoolSize() {
return (executor != null) ? executor.getCorePoolSize() : 0;
}
public int getLargestPoolSize() {
return (executor != null) ? executor.getLargestPoolSize() : 0;
}
@Override
public int getPoolSize() {
return (executor != null) ? executor.getPoolSize() : 0;
}
public int getQueueSize() {
return (executor != null) ? executor.getQueue().size() : -1;
}
@Override
public boolean resizePool(int corePoolSize, int maximumPoolSize) {
if (executor == null)
return false;
executor.setCorePoolSize(corePoolSize);
executor.setMaximumPoolSize(maximumPoolSize);
return true;
}
@Override
public boolean resizeQueue(int capacity) {
return false;
}
@Override
protected String getDomainInternal() {
// No way to navigate to Engine. Needs to have domain set.
return null;
}
@Override
protected String getObjectNameKeyProperties() {
StringBuilder name = new StringBuilder("type=Executor,name=");
name.append(getName());
return name.toString();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,100 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.util.Enumeration;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
/**
* Facade for the <b>StandardWrapper</b> object.
*
* @author Remy Maucherat
*/
public final class StandardWrapperFacade
implements ServletConfig {
// ----------------------------------------------------------- Constructors
/**
* Create a new facade around a StandardWrapper.
* @param config the associated wrapper
*/
public StandardWrapperFacade(StandardWrapper config) {
super();
this.config = config;
}
// ----------------------------------------------------- Instance Variables
/**
* Wrapped config.
*/
private final ServletConfig config;
/**
* Wrapped context (facade).
*/
private ServletContext context = null;
// -------------------------------------------------- ServletConfig Methods
@Override
public String getServletName() {
return config.getServletName();
}
@Override
public ServletContext getServletContext() {
if (context == null) {
context = config.getServletContext();
if (context instanceof ApplicationContext) {
context = ((ApplicationContext) context).getFacade();
}
}
return context;
}
@Override
public String getInitParameter(String name) {
return config.getInitParameter(name);
}
@Override
public Enumeration<String> getInitParameterNames() {
return config.getInitParameterNames();
}
}

View File

@@ -0,0 +1,350 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.DispatcherType;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.Context;
import org.apache.catalina.Globals;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.connector.ClientAbortException;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;
import org.apache.coyote.CloseNowException;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.buf.MessageBytes;
import org.apache.tomcat.util.log.SystemLogHandler;
import org.apache.tomcat.util.res.StringManager;
/**
* Valve that implements the default basic behavior for the
* <code>StandardWrapper</code> container implementation.
*
* @author Craig R. McClanahan
*/
final class StandardWrapperValve
extends ValveBase {
//------------------------------------------------------ Constructor
public StandardWrapperValve() {
super(true);
}
// ----------------------------------------------------- Instance Variables
// Some JMX statistics. This valve is associated with a StandardWrapper.
// We expose the StandardWrapper as JMX ( j2eeType=Servlet ). The fields
// are here for performance.
private volatile long processingTime;
private volatile long maxTime;
private volatile long minTime = Long.MAX_VALUE;
private final AtomicInteger requestCount = new AtomicInteger(0);
private final AtomicInteger errorCount = new AtomicInteger(0);
/**
* The string manager for this package.
*/
private static final StringManager sm =
StringManager.getManager(Constants.Package);
// --------------------------------------------------------- Public Methods
/**
* Invoke the servlet we are managing, respecting the rules regarding
* servlet lifecycle and SingleThreadModel support.
*
* @param request Request to be processed
* @param response Response to be produced
*
* @exception IOException if an input/output error occurred
* @exception ServletException if a servlet error occurred
*/
@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// Initialize local variables we may need
boolean unavailable = false;
Throwable throwable = null;
// This should be a Request attribute...
long t1=System.currentTimeMillis();
requestCount.incrementAndGet();
StandardWrapper wrapper = (StandardWrapper) getContainer();
Servlet servlet = null;
Context context = (Context) wrapper.getParent();
// Check for the application being marked unavailable
if (!context.getState().isAvailable()) {
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
sm.getString("standardContext.isUnavailable"));
unavailable = true;
}
// Check for the servlet being marked unavailable
if (!unavailable && wrapper.isUnavailable()) {
container.getLogger().info(sm.getString("standardWrapper.isUnavailable",
wrapper.getName()));
long available = wrapper.getAvailable();
if ((available > 0L) && (available < Long.MAX_VALUE)) {
response.setDateHeader("Retry-After", available);
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
sm.getString("standardWrapper.isUnavailable",
wrapper.getName()));
} else if (available == Long.MAX_VALUE) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
sm.getString("standardWrapper.notFound",
wrapper.getName()));
}
unavailable = true;
}
// Allocate a servlet instance to process this request
try {
if (!unavailable) {
servlet = wrapper.allocate();
}
} catch (UnavailableException e) {
container.getLogger().error(
sm.getString("standardWrapper.allocateException",
wrapper.getName()), e);
long available = wrapper.getAvailable();
if ((available > 0L) && (available < Long.MAX_VALUE)) {
response.setDateHeader("Retry-After", available);
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
sm.getString("standardWrapper.isUnavailable",
wrapper.getName()));
} else if (available == Long.MAX_VALUE) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
sm.getString("standardWrapper.notFound",
wrapper.getName()));
}
} catch (ServletException e) {
container.getLogger().error(sm.getString("standardWrapper.allocateException",
wrapper.getName()), StandardWrapper.getRootCause(e));
throwable = e;
exception(request, response, e);
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
container.getLogger().error(sm.getString("standardWrapper.allocateException",
wrapper.getName()), e);
throwable = e;
exception(request, response, e);
servlet = null;
}
MessageBytes requestPathMB = request.getRequestPathMB();
DispatcherType dispatcherType = DispatcherType.REQUEST;
if (request.getDispatcherType()==DispatcherType.ASYNC) dispatcherType = DispatcherType.ASYNC;
request.setAttribute(Globals.DISPATCHER_TYPE_ATTR,dispatcherType);
request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR,
requestPathMB);
// Create the filter chain for this request
ApplicationFilterChain filterChain =
ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
// Call the filter chain for this request
// NOTE: This also calls the servlet's service() method
try {
if ((servlet != null) && (filterChain != null)) {
// Swallow output if needed
if (context.getSwallowOutput()) {
try {
SystemLogHandler.startCapture();
if (request.isAsyncDispatching()) {
request.getAsyncContextInternal().doInternalDispatch();
} else {
filterChain.doFilter(request.getRequest(),
response.getResponse());
}
} finally {
String log = SystemLogHandler.stopCapture();
if (log != null && log.length() > 0) {
context.getLogger().info(log);
}
}
} else {
if (request.isAsyncDispatching()) {
request.getAsyncContextInternal().doInternalDispatch();
} else {
filterChain.doFilter
(request.getRequest(), response.getResponse());
}
}
}
} catch (ClientAbortException | CloseNowException e) {
if (container.getLogger().isDebugEnabled()) {
container.getLogger().debug(sm.getString(
"standardWrapper.serviceException", wrapper.getName(),
context.getName()), e);
}
throwable = e;
exception(request, response, e);
} catch (IOException e) {
container.getLogger().error(sm.getString(
"standardWrapper.serviceException", wrapper.getName(),
context.getName()), e);
throwable = e;
exception(request, response, e);
} catch (UnavailableException e) {
container.getLogger().error(sm.getString(
"standardWrapper.serviceException", wrapper.getName(),
context.getName()), e);
// throwable = e;
// exception(request, response, e);
wrapper.unavailable(e);
long available = wrapper.getAvailable();
if ((available > 0L) && (available < Long.MAX_VALUE)) {
response.setDateHeader("Retry-After", available);
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
sm.getString("standardWrapper.isUnavailable",
wrapper.getName()));
} else if (available == Long.MAX_VALUE) {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
sm.getString("standardWrapper.notFound",
wrapper.getName()));
}
// Do not save exception in 'throwable', because we
// do not want to do exception(request, response, e) processing
} catch (ServletException e) {
Throwable rootCause = StandardWrapper.getRootCause(e);
if (!(rootCause instanceof ClientAbortException)) {
container.getLogger().error(sm.getString(
"standardWrapper.serviceExceptionRoot",
wrapper.getName(), context.getName(), e.getMessage()),
rootCause);
}
throwable = e;
exception(request, response, e);
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
container.getLogger().error(sm.getString(
"standardWrapper.serviceException", wrapper.getName(),
context.getName()), e);
throwable = e;
exception(request, response, e);
} finally {
// Release the filter chain (if any) for this request
if (filterChain != null) {
filterChain.release();
}
// Deallocate the allocated servlet instance
try {
if (servlet != null) {
wrapper.deallocate(servlet);
}
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
container.getLogger().error(sm.getString("standardWrapper.deallocateException",
wrapper.getName()), e);
if (throwable == null) {
throwable = e;
exception(request, response, e);
}
}
// If this servlet has been marked permanently unavailable,
// unload it and release this instance
try {
if ((servlet != null) &&
(wrapper.getAvailable() == Long.MAX_VALUE)) {
wrapper.unload();
}
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
container.getLogger().error(sm.getString("standardWrapper.unloadException",
wrapper.getName()), e);
if (throwable == null) {
exception(request, response, e);
}
}
long t2=System.currentTimeMillis();
long time=t2-t1;
processingTime += time;
if( time > maxTime) maxTime=time;
if( time < minTime) minTime=time;
}
}
// -------------------------------------------------------- Private Methods
/**
* Handle the specified ServletException encountered while processing
* the specified Request to produce the specified Response. Any
* exceptions that occur during generation of the exception report are
* logged and swallowed.
*
* @param request The request being processed
* @param response The response being generated
* @param exception The exception that occurred (which possibly wraps
* a root cause exception
*/
private void exception(Request request, Response response,
Throwable exception) {
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, exception);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.setError();
}
public long getProcessingTime() {
return processingTime;
}
public long getMaxTime() {
return maxTime;
}
public long getMinTime() {
return minTime;
}
public int getRequestCount() {
return requestCount.get();
}
public int getErrorCount() {
return errorCount.get();
}
public void incrementErrorCount() {
errorCount.incrementAndGet();
}
@Override
protected void initInternal() throws LifecycleException {
// NOOP - Don't register this Valve in JMX
}
}

View File

@@ -0,0 +1,230 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.catalina.core;
import java.util.concurrent.Executor;
import org.apache.catalina.Container;
import org.apache.catalina.ContainerEvent;
import org.apache.catalina.ContainerListener;
import org.apache.catalina.Context;
import org.apache.catalina.Engine;
import org.apache.catalina.Host;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Server;
import org.apache.catalina.Service;
import org.apache.catalina.connector.Connector;
import org.apache.coyote.ProtocolHandler;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.res.StringManager;
import org.apache.tomcat.util.threads.ThreadPoolExecutor;
/**
* <p>
* A {@link LifecycleListener} that triggers the renewal of threads in Executor
* pools when a {@link Context} is being stopped to avoid thread-local related
* memory leaks.
* </p>
* <p>
* Note : active threads will be renewed one by one when they come back to the
* pool after executing their task, see
* {@link org.apache.tomcat.util.threads.ThreadPoolExecutor}.afterExecute().
* </p>
*
* This listener must be declared in server.xml to be active.
*
*/
public class ThreadLocalLeakPreventionListener implements LifecycleListener,
ContainerListener {
private static final Log log =
LogFactory.getLog(ThreadLocalLeakPreventionListener.class);
private volatile boolean serverStopping = false;
/**
* The string manager for this package.
*/
protected static final StringManager sm =
StringManager.getManager(Constants.Package);
/**
* Listens for {@link LifecycleEvent} for the start of the {@link Server} to
* initialize itself and then for after_stop events of each {@link Context}.
*/
@Override
public void lifecycleEvent(LifecycleEvent event) {
try {
Lifecycle lifecycle = event.getLifecycle();
if (Lifecycle.AFTER_START_EVENT.equals(event.getType()) &&
lifecycle instanceof Server) {
// when the server starts, we register ourself as listener for
// all context
// as well as container event listener so that we know when new
// Context are deployed
Server server = (Server) lifecycle;
registerListenersForServer(server);
}
if (Lifecycle.BEFORE_STOP_EVENT.equals(event.getType()) &&
lifecycle instanceof Server) {
// Server is shutting down, so thread pools will be shut down so
// there is no need to clean the threads
serverStopping = true;
}
if (Lifecycle.AFTER_STOP_EVENT.equals(event.getType()) &&
lifecycle instanceof Context) {
stopIdleThreads((Context) lifecycle);
}
} catch (Exception e) {
String msg =
sm.getString(
"threadLocalLeakPreventionListener.lifecycleEvent.error",
event);
log.error(msg, e);
}
}
@Override
public void containerEvent(ContainerEvent event) {
try {
String type = event.getType();
if (Container.ADD_CHILD_EVENT.equals(type)) {
processContainerAddChild(event.getContainer(),
(Container) event.getData());
} else if (Container.REMOVE_CHILD_EVENT.equals(type)) {
processContainerRemoveChild(event.getContainer(),
(Container) event.getData());
}
} catch (Exception e) {
String msg =
sm.getString(
"threadLocalLeakPreventionListener.containerEvent.error",
event);
log.error(msg, e);
}
}
private void registerListenersForServer(Server server) {
for (Service service : server.findServices()) {
Engine engine = service.getContainer();
if (engine != null) {
engine.addContainerListener(this);
registerListenersForEngine(engine);
}
}
}
private void registerListenersForEngine(Engine engine) {
for (Container hostContainer : engine.findChildren()) {
Host host = (Host) hostContainer;
host.addContainerListener(this);
registerListenersForHost(host);
}
}
private void registerListenersForHost(Host host) {
for (Container contextContainer : host.findChildren()) {
Context context = (Context) contextContainer;
registerContextListener(context);
}
}
private void registerContextListener(Context context) {
context.addLifecycleListener(this);
}
protected void processContainerAddChild(Container parent, Container child) {
if (log.isDebugEnabled())
log.debug("Process addChild[parent=" + parent + ",child=" + child +
"]");
if (child instanceof Context) {
registerContextListener((Context) child);
} else if (child instanceof Engine) {
registerListenersForEngine((Engine) child);
} else if (child instanceof Host) {
registerListenersForHost((Host) child);
}
}
protected void processContainerRemoveChild(Container parent,
Container child) {
if (log.isDebugEnabled())
log.debug("Process removeChild[parent=" + parent + ",child=" +
child + "]");
if (child instanceof Context) {
Context context = (Context) child;
context.removeLifecycleListener(this);
} else if (child instanceof Host || child instanceof Engine) {
child.removeContainerListener(this);
}
}
/**
* Updates each ThreadPoolExecutor with the current time, which is the time
* when a context is being stopped.
*
* @param context
* the context being stopped, used to discover all the Connectors
* of its parent Service.
*/
private void stopIdleThreads(Context context) {
if (serverStopping) return;
if (!(context instanceof StandardContext) ||
!((StandardContext) context).getRenewThreadsWhenStoppingContext()) {
log.debug("Not renewing threads when the context is stopping. "
+ "It is not configured to do it.");
return;
}
Engine engine = (Engine) context.getParent().getParent();
Service service = engine.getService();
Connector[] connectors = service.findConnectors();
if (connectors != null) {
for (Connector connector : connectors) {
ProtocolHandler handler = connector.getProtocolHandler();
Executor executor = null;
if (handler != null) {
executor = handler.getExecutor();
}
if (executor instanceof ThreadPoolExecutor) {
ThreadPoolExecutor threadPoolExecutor =
(ThreadPoolExecutor) executor;
threadPoolExecutor.contextStopping();
} else if (executor instanceof StandardThreadExecutor) {
StandardThreadExecutor stdThreadExecutor =
(StandardThreadExecutor) executor;
stdThreadExecutor.contextStopping();
}
}
}
}
}

File diff suppressed because it is too large Load Diff