/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT 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;
/** * Standard implementation of <code>ServletContext</code> that represents a web application's execution environment. An * instance of this class is associated with each instance of <code>StandardContext</code>. * * @author Craig R. McClanahan * @author Remy Maucherat
*/ publicclass ApplicationContext implements ServletContext {
/** * Construct a new instance of this class, associated with the specified Context instance. * * @param context The associated Context instance
*/ public ApplicationContext(StandardContext context) { super(); this.context = context; this.service = ((Engine) context.getParent().getParent()).getService(); this.sessionCookieConfig = new ApplicationSessionCookieConfig(context);
/** * Flag that indicates if a new {@link ServletContextListener} may be added to the application. Once the first * {@link ServletContextListener} is called, no more may be added.
*/ privateboolean newServletContextListenerAllowed = true;
@Override public Object getAttribute(String name) { return attributes.get(name);
}
@Override public Enumeration<String> getAttributeNames() {
Set<String> names = new HashSet<>(attributes.keySet()); return Collections.enumeration(names);
}
@Override public ServletContext getContext(String uri) {
// Validate the format of the specified argument if (uri == null || !uri.startsWith("/")) { returnnull;
}
Context child = null; try { // Look for an exact match
Container host = context.getParent();
child = (Context) host.findChild(uri);
// Non-running contexts should be ignored. if (child != null && !child.getState().isAvailable()) {
child = null;
}
// Remove any version information and use the mapper if (child == null) { int i = uri.indexOf("##"); if (i > -1) {
uri = uri.substring(0, i);
} // Note: This could be more efficient with a dedicated Mapper // method but such an implementation would require some // refactoring of the Mapper to avoid copy/paste of // existing code.
MessageBytes hostMB = MessageBytes.newInstance();
hostMB.setString(host.getName());
if (context.getCrossContext()) { // If crossContext is enabled, can always return the context return child.getServletContext();
} elseif (child == context) { // Can still return the current context return context.getServletContext();
} else { // Nothing to return returnnull;
}
}
@Override public String getContextPath() { return context.getPath();
}
@Override public String getInitParameter(final String name) { // Special handling for XML settings as the context setting must // always override anything that might have been set by an application. if (Globals.JASPER_XML_VALIDATION_TLD_INIT_PARAM.equals(name) && context.getTldValidation()) { return"true";
} if (Globals.JASPER_XML_BLOCK_EXTERNAL_INIT_PARAM.equals(name)) { if (!context.getXmlBlockExternal()) { // System admin has explicitly changed the default return"false";
}
} return parameters.get(name);
}
@Override public Enumeration<String> getInitParameterNames() {
Set<String> names = new HashSet<>(parameters.keySet()); // Special handling for XML settings as these attributes will always be // available if they have been set on the context if (context.getTldValidation()) {
names.add(Globals.JASPER_XML_VALIDATION_TLD_INIT_PARAM);
} if (!context.getXmlBlockExternal()) {
names.add(Globals.JASPER_XML_BLOCK_EXTERNAL_INIT_PARAM);
} return Collections.enumeration(names);
}
/** * Return the MIME type of the specified file, or <code>null</code> if the MIME type cannot be determined. * * @param file Filename for which to identify a MIME type
*/
@Override public String getMimeType(String file) {
if (file == null) { returnnull;
} int period = file.lastIndexOf('.'); if (period < 0) { returnnull;
}
String extension = file.substring(period + 1); if (extension.length() < 1) { returnnull;
} return context.findMimeMapping(extension);
}
/** * Return a <code>RequestDispatcher</code> object that acts as a wrapper for the named servlet. * * @param name Name of the servlet for which a dispatcher is requested
*/
@Override public RequestDispatcher getNamedDispatcher(String name) {
// Validate the name argument if (name == null) { returnnull;
}
// Create and return a corresponding request dispatcher
Wrapper wrapper = (Wrapper) context.findChild(name); if (wrapper == null) { returnnull;
}
// Then normalize
String normalizedUri = RequestUtil.normalize(uriNoParams); if (normalizedUri == null) { returnnull;
}
// Mapping is against the normalized uri
if (getContext().getDispatchersUseEncodedPaths()) { // Decode
String decodedUri = UDecoder.URLDecode(normalizedUri, StandardCharsets.UTF_8);
// Security check to catch attempts to encode /../ sequences
normalizedUri = RequestUtil.normalize(decodedUri); if (!decodedUri.equals(normalizedUri)) {
getContext().getLogger().warn(sm.getString("applicationContext.illegalDispatchPath", path), new IllegalArgumentException()); returnnull;
}
// URI needs to include the context path
uri = URLEncoder.DEFAULT.encode(getContextPath(), StandardCharsets.UTF_8) + uri;
} else { // uri is passed to the constructor for ApplicationDispatcher and is // ultimately used as the value for getRequestURI() which returns // encoded values. Therefore, since the value passed in for path // was decoded, encode uri here.
uri = URLEncoder.DEFAULT.encode(getContextPath() + uri, StandardCharsets.UTF_8);
}
// Use the thread local URI and mapping data
DispatchData dd = dispatchData.get(); if (dd == null) {
dd = new DispatchData();
dispatchData.set(dd);
}
// Use the thread local mapping data
MessageBytes uriMB = dd.uriMB;
MappingData mappingData = dd.mappingData;
try { // Map the URI
uriMB.setChars(MessageBytes.EMPTY_CHAR_ARRAY, 0, 0);
CharChunk uriCC = uriMB.getCharChunk(); try {
uriCC.append(context.getPath());
uriCC.append(normalizedUri);
service.getMapper().map(context, uriMB, mappingData); if (mappingData.wrapper == null) { returnnull;
}
} catch (Exception e) { // Should never happen
log(sm.getString("applicationContext.mapping.error"), e); returnnull;
}
// Construct a RequestDispatcher to process this request returnnew ApplicationDispatcher(wrapper, uri, wrapperPath, pathInfo, queryString, mapping, null);
} finally { // Recycle thread local data at the end of the request so references // are not held to a completed request as there is potential for // that to trigger a memory leak if a context is unloaded. Not // strictly necessary here for uriMB but it needs to be recycled at // some point so do it here for consistency with mappingData which // must be recycled here.
uriMB.recycle();
mappingData.recycle();
}
}
/* * Returns null if the input path is not valid or a path that will be acceptable to resources.getResource().
*/ private String validateResourcePath(String path, boolean addMissingInitialSlash) { if (path == null) { returnnull;
}
if (!path.startsWith("/")) { if (addMissingInitialSlash) { return"/" + path;
} else { returnnull;
}
}
return path;
}
@Override public Set<String> getResourcePaths(String path) {
// Validate the path argument if (path == null) { returnnull;
} if (!path.startsWith("/")) { thrownew IllegalArgumentException(sm.getString("applicationContext.resourcePaths.iae", path));
}
// Remove the specified attribute // Check for read only attribute if (readOnlyAttributes.containsKey(name)) { return;
}
value = attributes.remove(name); if (value == null) { return;
}
// Assume a 'complete' FilterRegistration is one that has a class and // a name if (filterDef == null) {
filterDef = new FilterDef();
filterDef.setFilterName(filterName);
context.addFilterDef(filterDef);
} else { if (filterDef.getFilterName() != null && filterDef.getFilterClass() != null) { returnnull;
}
}
if (jspServlet == null) { // No JSP servlet currently defined. // Use default JSP Servlet class name
jspServletClassName = Constants.JSP_SERVLET_CLASS;
} else { // JSP Servlet defined. // Use same JSP Servlet class name
jspServletClassName = jspServlet.getServletClass(); // Use same init parameters
String[] params = jspServlet.findInitParameters(); for (String param : params) {
jspFileInitParams.put(param, jspServlet.findInitParameter(param));
}
}
// Add init parameter to specify JSP file
jspFileInitParams.put("jspFile", jspFile);
// Assume a 'complete' ServletRegistration is one that has a class and // a name if (wrapper == null) {
wrapper = context.createWrapper();
wrapper.setName(servletName);
context.addChild(wrapper);
} else { if (wrapper.getName() != null && wrapper.getServletClass() != null) { if (wrapper.isOverridable()) {
wrapper.setOverridable(false);
} else { returnnull;
}
}
}
@Override public Set<SessionTrackingMode> getDefaultSessionTrackingModes() { return defaultSessionTrackingModes;
}
privatevoid populateSessionTrackingModes() { // URL re-writing is always enabled by default
defaultSessionTrackingModes = EnumSet.of(SessionTrackingMode.URL);
supportedSessionTrackingModes = EnumSet.of(SessionTrackingMode.URL);
if (context.getCookies()) {
defaultSessionTrackingModes.add(SessionTrackingMode.COOKIE);
supportedSessionTrackingModes.add(SessionTrackingMode.COOKIE);
}
// SSL not enabled by default as it can only used on its own // Context > Host > Engine > Service
Connector[] connectors = service.findConnectors(); // Need at least one SSL enabled connector to use the SSL session ID. for (Connector connector : connectors) { if (Boolean.TRUE.equals(connector.getProperty("SSLEnabled"))) {
supportedSessionTrackingModes.add(SessionTrackingMode.SSL); break;
}
}
}
@Override public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() { if (sessionTrackingModes != null) { return sessionTrackingModes;
} return defaultSessionTrackingModes;
}
@Override public SessionCookieConfig getSessionCookieConfig() { return sessionCookieConfig;
}
// Check that only supported tracking modes have been requested for (SessionTrackingMode sessionTrackingMode : sessionTrackingModes) { if (!supportedSessionTrackingModes.contains(sessionTrackingMode)) { thrownew IllegalArgumentException(sm.getString("applicationContext.setSessionTracking.iae.invalid",
sessionTrackingMode.toString(), getContextPath()));
}
}
// Check SSL has not be configured with anything else if (sessionTrackingModes.contains(SessionTrackingMode.SSL)) { if (sessionTrackingModes.size() > 1) { thrownew IllegalArgumentException(
sm.getString("applicationContext.setSessionTracking.iae.ssl", getContextPath()));
}
}
@Override public <T extends EventListener> void addListener(T t) {
checkState("applicationContext.addListener.ise");
boolean match = false; if (t instanceof ServletContextAttributeListener || t instanceof ServletRequestListener ||
t instanceof ServletRequestAttributeListener || t instanceof HttpSessionIdListener ||
t instanceof HttpSessionAttributeListener) {
context.addApplicationEventListener(t);
match = true;
}
if (t instanceof HttpSessionListener ||
(t instanceof ServletContextListener && newServletContextListenerAllowed)) { // Add listener directly to the list of instances rather than to // the list of class names.
context.addApplicationLifecycleListener(t);
match = true;
}
@Override public Map<String,? extends FilterRegistration> getFilterRegistrations() {
Map<String,ApplicationFilterRegistration> result = new HashMap<>();
FilterDef[] filterDefs = context.findFilterDefs(); for (FilterDef filterDef : filterDefs) {
result.put(filterDef.getFilterName(), new ApplicationFilterRegistration(filterDef, context));
}
return result;
}
@Override public JspConfigDescriptor getJspConfigDescriptor() { return context.getJspConfigDescriptor();
}
@Override public Map<String,? extends ServletRegistration> getServletRegistrations() {
Map<String,ApplicationServletRegistration> result = new HashMap<>();
Container[] wrappers = context.findChildren(); for (Container wrapper : wrappers) {
result.put(wrapper.getName(), new ApplicationServletRegistration((Wrapper) wrapper, context));
}
return result;
}
@Override public String getVirtualServerName() { // Constructor will fail if context or its parent is null
Container host = context.getParent();
Container engine = host.getParent(); return engine.getName() + "/" + host.getName();
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.12Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.