init
This commit is contained in:
64
java/org/apache/catalina/core/AccessLogAdapter.java
Normal file
64
java/org/apache/catalina/core/AccessLogAdapter.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
1414
java/org/apache/catalina/core/ApplicationContext.java
Normal file
1414
java/org/apache/catalina/core/ApplicationContext.java
Normal file
File diff suppressed because it is too large
Load Diff
978
java/org/apache/catalina/core/ApplicationContextFacade.java
Normal file
978
java/org/apache/catalina/core/ApplicationContextFacade.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
1064
java/org/apache/catalina/core/ApplicationDispatcher.java
Normal file
1064
java/org/apache/catalina/core/ApplicationDispatcher.java
Normal file
File diff suppressed because it is too large
Load Diff
348
java/org/apache/catalina/core/ApplicationFilterChain.java
Normal file
348
java/org/apache/catalina/core/ApplicationFilterChain.java
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
409
java/org/apache/catalina/core/ApplicationFilterConfig.java
Normal file
409
java/org/apache/catalina/core/ApplicationFilterConfig.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
290
java/org/apache/catalina/core/ApplicationFilterFactory.java
Normal file
290
java/org/apache/catalina/core/ApplicationFilterFactory.java
Normal 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;
|
||||
}
|
||||
}
|
||||
215
java/org/apache/catalina/core/ApplicationFilterRegistration.java
Normal file
215
java/org/apache/catalina/core/ApplicationFilterRegistration.java
Normal 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());
|
||||
}
|
||||
|
||||
}
|
||||
1009
java/org/apache/catalina/core/ApplicationHttpRequest.java
Normal file
1009
java/org/apache/catalina/core/ApplicationHttpRequest.java
Normal file
File diff suppressed because it is too large
Load Diff
373
java/org/apache/catalina/core/ApplicationHttpResponse.java
Normal file
373
java/org/apache/catalina/core/ApplicationHttpResponse.java
Normal 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);
|
||||
|
||||
}
|
||||
}
|
||||
124
java/org/apache/catalina/core/ApplicationMapping.java
Normal file
124
java/org/apache/catalina/core/ApplicationMapping.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
168
java/org/apache/catalina/core/ApplicationPart.java
Normal file
168
java/org/apache/catalina/core/ApplicationPart.java
Normal 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;
|
||||
}
|
||||
}
|
||||
446
java/org/apache/catalina/core/ApplicationPushBuilder.java
Normal file
446
java/org/apache/catalina/core/ApplicationPushBuilder.java
Normal 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();
|
||||
}
|
||||
}
|
||||
209
java/org/apache/catalina/core/ApplicationRequest.java
Normal file
209
java/org/apache/catalina/core/ApplicationRequest.java
Normal 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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
183
java/org/apache/catalina/core/ApplicationResponse.java
Normal file
183
java/org/apache/catalina/core/ApplicationResponse.java
Normal 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;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
428
java/org/apache/catalina/core/AprLifecycleListener.java
Normal file
428
java/org/apache/catalina/core/AprLifecycleListener.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
592
java/org/apache/catalina/core/AsyncContextImpl.java
Normal file
592
java/org/apache/catalina/core/AsyncContextImpl.java
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
81
java/org/apache/catalina/core/AsyncListenerWrapper.java
Normal file
81
java/org/apache/catalina/core/AsyncListenerWrapper.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
26
java/org/apache/catalina/core/Constants.java
Normal file
26
java/org/apache/catalina/core/Constants.java
Normal 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";
|
||||
}
|
||||
1452
java/org/apache/catalina/core/ContainerBase.java
Normal file
1452
java/org/apache/catalina/core/ContainerBase.java
Normal file
File diff suppressed because it is too large
Load Diff
809
java/org/apache/catalina/core/DefaultInstanceManager.java
Normal file
809
java/org/apache/catalina/core/DefaultInstanceManager.java
Normal 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
|
||||
}
|
||||
}
|
||||
88
java/org/apache/catalina/core/JniLifecycleListener.java
Normal file
88
java/org/apache/catalina/core/JniLifecycleListener.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
283
java/org/apache/catalina/core/LocalStrings.properties
Normal file
283
java/org/apache/catalina/core/LocalStrings.properties
Normal 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}]
|
||||
59
java/org/apache/catalina/core/LocalStrings_de.properties
Normal file
59
java/org/apache/catalina/core/LocalStrings_de.properties
Normal 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
|
||||
190
java/org/apache/catalina/core/LocalStrings_es.properties
Normal file
190
java/org/apache/catalina/core/LocalStrings_es.properties
Normal 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}]
|
||||
277
java/org/apache/catalina/core/LocalStrings_fr.properties
Normal file
277
java/org/apache/catalina/core/LocalStrings_fr.properties
Normal 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
|
||||
270
java/org/apache/catalina/core/LocalStrings_ja.properties
Normal file
270
java/org/apache/catalina/core/LocalStrings_ja.properties
Normal 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}] を処理中に例外が発生しました。
|
||||
276
java/org/apache/catalina/core/LocalStrings_ko.properties
Normal file
276
java/org/apache/catalina/core/LocalStrings_ko.properties
Normal 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}]을(를) 처리하는 중 예외 발생
|
||||
20
java/org/apache/catalina/core/LocalStrings_ru.properties
Normal file
20
java/org/apache/catalina/core/LocalStrings_ru.properties
Normal 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}] временно недоступен
|
||||
147
java/org/apache/catalina/core/LocalStrings_zh_CN.properties
Normal file
147
java/org/apache/catalina/core/LocalStrings_zh_CN.properties
Normal 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=无法设置FIPSMode:SSL已初始化
|
||||
aprListener.tooLateForSSLRandomSeed=无法设置 SSLRandomSeed:SSL已经初始化
|
||||
|
||||
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}]
|
||||
1288
java/org/apache/catalina/core/NamingContextListener.java
Normal file
1288
java/org/apache/catalina/core/NamingContextListener.java
Normal file
File diff suppressed because it is too large
Load Diff
16
java/org/apache/catalina/core/RestrictedFilters.properties
Normal file
16
java/org/apache/catalina/core/RestrictedFilters.properties
Normal 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
|
||||
15
java/org/apache/catalina/core/RestrictedListeners.properties
Normal file
15
java/org/apache/catalina/core/RestrictedListeners.properties
Normal 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.
|
||||
|
||||
19
java/org/apache/catalina/core/RestrictedServlets.properties
Normal file
19
java/org/apache/catalina/core/RestrictedServlets.properties
Normal 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
|
||||
6698
java/org/apache/catalina/core/StandardContext.java
Normal file
6698
java/org/apache/catalina/core/StandardContext.java
Normal file
File diff suppressed because it is too large
Load Diff
98
java/org/apache/catalina/core/StandardContextValve.java
Normal file
98
java/org/apache/catalina/core/StandardContextValve.java
Normal 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);
|
||||
}
|
||||
}
|
||||
493
java/org/apache/catalina/core/StandardEngine.java
Normal file
493
java/org/apache/catalina/core/StandardEngine.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
90
java/org/apache/catalina/core/StandardEngineValve.java
Normal file
90
java/org/apache/catalina/core/StandardEngineValve.java
Normal 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);
|
||||
|
||||
}
|
||||
}
|
||||
881
java/org/apache/catalina/core/StandardHost.java
Normal file
881
java/org/apache/catalina/core/StandardHost.java
Normal 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/<engine>/<host> 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();
|
||||
}
|
||||
|
||||
}
|
||||
410
java/org/apache/catalina/core/StandardHostValve.java
Normal file
410
java/org/apache/catalina/core/StandardHostValve.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
467
java/org/apache/catalina/core/StandardPipeline.java
Normal file
467
java/org/apache/catalina/core/StandardPipeline.java
Normal 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;
|
||||
}
|
||||
}
|
||||
926
java/org/apache/catalina/core/StandardServer.java
Normal file
926
java/org/apache/catalina/core/StandardServer.java
Normal 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";
|
||||
}
|
||||
}
|
||||
648
java/org/apache/catalina/core/StandardService.java
Normal file
648
java/org/apache/catalina/core/StandardService.java
Normal 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";
|
||||
}
|
||||
}
|
||||
335
java/org/apache/catalina/core/StandardThreadExecutor.java
Normal file
335
java/org/apache/catalina/core/StandardThreadExecutor.java
Normal 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();
|
||||
}
|
||||
}
|
||||
1800
java/org/apache/catalina/core/StandardWrapper.java
Normal file
1800
java/org/apache/catalina/core/StandardWrapper.java
Normal file
File diff suppressed because it is too large
Load Diff
100
java/org/apache/catalina/core/StandardWrapperFacade.java
Normal file
100
java/org/apache/catalina/core/StandardWrapperFacade.java
Normal 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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
350
java/org/apache/catalina/core/StandardWrapperValve.java
Normal file
350
java/org/apache/catalina/core/StandardWrapperValve.java
Normal 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
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1781
java/org/apache/catalina/core/mbeans-descriptors.xml
Normal file
1781
java/org/apache/catalina/core/mbeans-descriptors.xml
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user