EL container integration; support for contextual objects; removal of deprecated Spring 2.0 functionality; Java 5 code style

This commit is contained in:
Juergen Hoeller
2008-11-20 02:10:53 +00:00
parent 369821dd66
commit 347f34c68a
281 changed files with 6120 additions and 9903 deletions

View File

@@ -19,13 +19,11 @@ package org.springframework.remoting.caucho;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import com.caucho.burlap.io.BurlapInput;
import com.caucho.burlap.io.BurlapOutput;
import com.caucho.burlap.server.BurlapSkeleton;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.remoting.support.RemoteExporter;
import org.springframework.util.Assert;
@@ -36,9 +34,7 @@ import org.springframework.util.Assert;
* <p>Burlap is a slim, XML-based RPC protocol.
* For information on Burlap, see the
* <a href="http://www.caucho.com/burlap">Burlap website</a>.
*
* <p>This exporter will work with both Burlap 2.x and 3.x (respectively
* Resin 2.x and 3.x), autodetecting the corresponding skeleton class.
* This exporter requires Burlap 3.x.
*
* @author Juergen Hoeller
* @since 2.5.1
@@ -59,24 +55,9 @@ public class BurlapExporter extends RemoteExporter implements InitializingBean {
* Initialize this service exporter.
*/
public void prepare() {
try {
try {
// Try Burlap 3.x (with service interface argument).
Constructor ctor = BurlapSkeleton.class.getConstructor(new Class[] {Object.class, Class.class});
checkService();
checkServiceInterface();
this.skeleton = (BurlapSkeleton)
ctor.newInstance(new Object[] {getProxyForService(), getServiceInterface()});
}
catch (NoSuchMethodException ex) {
// Fall back to Burlap 2.x (without service interface argument).
Constructor ctor = BurlapSkeleton.class.getConstructor(new Class[] {Object.class});
this.skeleton = (BurlapSkeleton) ctor.newInstance(new Object[] {getProxyForService()});
}
}
catch (Exception ex) {
throw new BeanInitializationException("Burlap skeleton initialization failed", ex);
}
checkService();
checkServiceInterface();
this.skeleton = new BurlapSkeleton(getProxyForService(), getServiceInterface());
}
@@ -97,11 +78,13 @@ public class BurlapExporter extends RemoteExporter implements InitializingBean {
inputStream.close();
}
catch (IOException ex) {
// ignore
}
try {
outputStream.close();
}
catch (IOException ex) {
// ignore
}
resetThreadContextClassLoader(originalClassLoader);
}

View File

@@ -36,9 +36,7 @@ import org.springframework.web.util.NestedServletException;
* <p>Burlap is a slim, XML-based RPC protocol.
* For information on Burlap, see the
* <a href="http://www.caucho.com/burlap">Burlap website</a>.
*
* <p>This exporter will work with both Burlap 2.x and 3.x (respectively
* Resin 2.x and 3.x), autodetecting the corresponding skeleton class.
* This exporter requires Burlap 3.x.
*
* <p>Note: Burlap services exported with this class can be accessed by
* any Burlap client, as there isn't any special handling involved.

View File

@@ -1,89 +0,0 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed 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.springframework.remoting.caucho;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import com.caucho.hessian.io.HessianInput;
import com.caucho.hessian.io.HessianOutput;
import com.caucho.hessian.io.SerializerFactory;
import com.caucho.hessian.server.HessianSkeleton;
import org.springframework.util.ClassUtils;
/**
* Concrete HessianSkeletonInvoker for the Hessian 1 protocol
* (version 3.0.19 or lower).
*
* @author Juergen Hoeller
* @since 2.0
*/
class Hessian1SkeletonInvoker extends HessianSkeletonInvoker {
private static final Method invokeMethod;
private static final boolean applySerializerFactoryToOutput;
static {
invokeMethod = ClassUtils.getMethodIfAvailable(
HessianSkeleton.class, "invoke", new Class[] {HessianInput.class, HessianOutput.class});
applySerializerFactoryToOutput =
ClassUtils.hasMethod(HessianOutput.class, "setSerializerFactory", new Class[] {SerializerFactory.class});
}
public Hessian1SkeletonInvoker(HessianSkeleton skeleton, SerializerFactory serializerFactory) {
super(skeleton, serializerFactory);
if (invokeMethod == null) {
throw new IllegalStateException("Hessian 1 (version 3.0.19-) not present");
}
}
@Override
public void invoke(InputStream inputStream, OutputStream outputStream) throws Throwable {
HessianInput in = new HessianInput(inputStream);
HessianOutput out = new HessianOutput(outputStream);
if (this.serializerFactory != null) {
in.setSerializerFactory(this.serializerFactory);
if (applySerializerFactoryToOutput) {
out.setSerializerFactory(this.serializerFactory);
}
}
try {
invokeMethod.invoke(this.skeleton, new Object[] {in, out});
}
finally {
try {
in.close();
inputStream.close();
}
catch (IOException ex) {
}
try {
out.close();
outputStream.close();
}
catch (IOException ex) {
}
}
}
}

View File

@@ -1,124 +0,0 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed 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.springframework.remoting.caucho;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import com.caucho.hessian.io.AbstractHessianOutput;
import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;
import com.caucho.hessian.io.HessianDebugInputStream;
import com.caucho.hessian.io.HessianDebugOutputStream;
import com.caucho.hessian.io.HessianOutput;
import com.caucho.hessian.io.SerializerFactory;
import com.caucho.hessian.server.HessianSkeleton;
import org.apache.commons.logging.Log;
import org.springframework.util.ClassUtils;
import org.springframework.util.CommonsLogWriter;
/**
* Concrete HessianSkeletonInvoker for the Hessian 2 protocol
* (version 3.0.20 or higher).
*
* @author Juergen Hoeller
* @author Andy Piper
* @since 2.0
*/
class Hessian2SkeletonInvoker extends HessianSkeletonInvoker {
private static final boolean debugOutputStreamAvailable = ClassUtils.isPresent(
"com.caucho.hessian.io.HessianDebugOutputStream", Hessian2SkeletonInvoker.class.getClassLoader());
private final Log debugLogger;
public Hessian2SkeletonInvoker(HessianSkeleton skeleton, SerializerFactory serializerFactory, Log debugLog) {
super(skeleton, serializerFactory);
this.debugLogger = debugLog;
}
@Override
public void invoke(final InputStream inputStream, final OutputStream outputStream) throws Throwable {
InputStream isToUse = inputStream;
OutputStream osToUse = outputStream;
if (this.debugLogger != null && this.debugLogger.isDebugEnabled()) {
PrintWriter debugWriter = new PrintWriter(new CommonsLogWriter(this.debugLogger));
isToUse = new HessianDebugInputStream(inputStream, debugWriter);
if (debugOutputStreamAvailable) {
osToUse = DebugStreamFactory.createDebugOutputStream(outputStream, debugWriter);
}
}
Hessian2Input in = new Hessian2Input(isToUse);
if (this.serializerFactory != null) {
in.setSerializerFactory(this.serializerFactory);
}
int code = in.read();
if (code != 'c') {
throw new IOException("expected 'c' in hessian input at " + code);
}
AbstractHessianOutput out = null;
int major = in.read();
int minor = in.read();
if (major >= 2) {
out = new Hessian2Output(osToUse);
}
else {
out = new HessianOutput(osToUse);
}
if (this.serializerFactory != null) {
out.setSerializerFactory(this.serializerFactory);
}
try {
this.skeleton.invoke(in, out);
}
finally {
try {
in.close();
isToUse.close();
}
catch (IOException ex) {
}
try {
out.close();
osToUse.close();
}
catch (IOException ex) {
}
}
}
/**
* Inner class to avoid hard dependency on Hessian 3.1.3's HessianDebugOutputStream.
*/
private static class DebugStreamFactory {
public static OutputStream createDebugOutputStream(OutputStream os, PrintWriter debug) {
return new HessianDebugOutputStream(os, debug);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,19 +16,26 @@
package org.springframework.remoting.caucho;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.io.PrintWriter;
import com.caucho.hessian.io.AbstractHessianOutput;
import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;
import com.caucho.hessian.io.HessianDebugInputStream;
import com.caucho.hessian.io.HessianDebugOutputStream;
import com.caucho.hessian.io.HessianOutput;
import com.caucho.hessian.io.SerializerFactory;
import com.caucho.hessian.server.HessianSkeleton;
import org.apache.commons.logging.Log;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.remoting.support.RemoteExporter;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CommonsLogWriter;
/**
* General stream-based protocol exporter for a Hessian endpoint.
@@ -36,11 +43,7 @@ import org.springframework.util.ClassUtils;
* <p>Hessian is a slim, binary RPC protocol.
* For information on Hessian, see the
* <a href="http://www.caucho.com/hessian">Hessian website</a>.
*
* <p>This exporter will work with both Hessian 2.x and 3.x (respectively
* Resin 2.x and 3.x), autodetecting the corresponding skeleton class.
* As of Spring 2.0, it is also compatible with the new Hessian 2 protocol
* (a.k.a. Hessian 3.0.20+), while remaining compatible with older versions.
* This exporter requires Hessian 3.0.20 or above.
*
* @author Juergen Hoeller
* @since 2.5.1
@@ -50,15 +53,14 @@ import org.springframework.util.ClassUtils;
*/
public class HessianExporter extends RemoteExporter implements InitializingBean {
private static final boolean hessian2Available =
ClassUtils.isPresent("com.caucho.hessian.io.Hessian2Input", HessianServiceExporter.class.getClassLoader());
private static final boolean debugOutputStreamAvailable = ClassUtils.isPresent(
"com.caucho.hessian.io.HessianDebugOutputStream", HessianExporter.class.getClassLoader());
private SerializerFactory serializerFactory = new SerializerFactory();
private Log debugLogger;
private HessianSkeletonInvoker skeletonInvoker;
private HessianSkeleton skeleton;
/**
@@ -97,35 +99,9 @@ public class HessianExporter extends RemoteExporter implements InitializingBean
* Initialize this exporter.
*/
public void prepare() {
HessianSkeleton skeleton = null;
try {
try {
// Try Hessian 3.x (with service interface argument).
Constructor ctor = HessianSkeleton.class.getConstructor(new Class[] {Object.class, Class.class});
checkService();
checkServiceInterface();
skeleton = (HessianSkeleton)
ctor.newInstance(new Object[] {getProxyForService(), getServiceInterface()});
}
catch (NoSuchMethodException ex) {
// Fall back to Hessian 2.x (without service interface argument).
Constructor ctor = HessianSkeleton.class.getConstructor(new Class[] {Object.class});
skeleton = (HessianSkeleton) ctor.newInstance(new Object[] {getProxyForService()});
}
}
catch (Throwable ex) {
throw new BeanInitializationException("Hessian skeleton initialization failed", ex);
}
if (hessian2Available) {
// Hessian 2 (version 3.0.20+).
this.skeletonInvoker = new Hessian2SkeletonInvoker(skeleton, this.serializerFactory, this.debugLogger);
}
else {
// Hessian 1 (version 3.0.19-).
this.skeletonInvoker = new Hessian1SkeletonInvoker(skeleton, this.serializerFactory);
}
checkService();
checkServiceInterface();
this.skeleton = new HessianSkeleton(getProxyForService(), getServiceInterface());
}
@@ -136,14 +112,81 @@ public class HessianExporter extends RemoteExporter implements InitializingBean
* @throws Throwable if invocation failed
*/
public void invoke(InputStream inputStream, OutputStream outputStream) throws Throwable {
Assert.notNull(this.skeletonInvoker, "Hessian exporter has not been initialized");
Assert.notNull(this.skeleton, "Hessian exporter has not been initialized");
ClassLoader originalClassLoader = overrideThreadContextClassLoader();
try {
this.skeletonInvoker.invoke(inputStream, outputStream);
doInvoke(inputStream, outputStream);
}
finally {
resetThreadContextClassLoader(originalClassLoader);
}
}
public void doInvoke(final InputStream inputStream, final OutputStream outputStream) throws Throwable {
InputStream isToUse = inputStream;
OutputStream osToUse = outputStream;
if (this.debugLogger != null && this.debugLogger.isDebugEnabled()) {
PrintWriter debugWriter = new PrintWriter(new CommonsLogWriter(this.debugLogger));
isToUse = new HessianDebugInputStream(inputStream, debugWriter);
if (debugOutputStreamAvailable) {
osToUse = DebugStreamFactory.createDebugOutputStream(outputStream, debugWriter);
}
}
Hessian2Input in = new Hessian2Input(isToUse);
if (this.serializerFactory != null) {
in.setSerializerFactory(this.serializerFactory);
}
int code = in.read();
if (code != 'c') {
throw new IOException("expected 'c' in hessian input at " + code);
}
AbstractHessianOutput out = null;
int major = in.read();
int minor = in.read();
if (major >= 2) {
out = new Hessian2Output(osToUse);
}
else {
out = new HessianOutput(osToUse);
}
if (this.serializerFactory != null) {
out.setSerializerFactory(this.serializerFactory);
}
try {
this.skeleton.invoke(in, out);
}
finally {
try {
in.close();
isToUse.close();
}
catch (IOException ex) {
// ignore
}
try {
out.close();
osToUse.close();
}
catch (IOException ex) {
// ignore
}
}
}
/**
* Inner class to avoid hard dependency on Hessian 3.1.3's HessianDebugOutputStream.
*/
private static class DebugStreamFactory {
public static OutputStream createDebugOutputStream(OutputStream os, PrintWriter debug) {
return new HessianDebugOutputStream(os, debug);
}
}
}

View File

@@ -36,11 +36,7 @@ import org.springframework.web.util.NestedServletException;
* <p>Hessian is a slim, binary RPC protocol.
* For information on Hessian, see the
* <a href="http://www.caucho.com/hessian">Hessian website</a>.
*
* <p>This exporter will work with both Hessian 2.x and 3.x (respectively
* Resin 2.x and 3.x), autodetecting the corresponding skeleton class.
* As of Spring 2.0, it is also compatible with the new Hessian 2 protocol
* (a.k.a. Hessian 3.0.20+), while remaining compatible with older versions.
* This exporter requires Hessian 3.0.20 or above.
*
* <p>Note: Hessian services exported with this class can be accessed by
* any Hessian client, as there isn't any special handling involved.

View File

@@ -1,67 +0,0 @@
/*
* Copyright 2002-2006 the original author or authors.
*
* Licensed 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.springframework.remoting.caucho;
import java.io.InputStream;
import java.io.OutputStream;
import com.caucho.hessian.server.HessianSkeleton;
import com.caucho.hessian.io.SerializerFactory;
import org.springframework.util.Assert;
/**
* Internal invoker strategy for a Hessian skeleton.
* Allows for common handling of Hessian protocol version 1 and 2.
*
* @author Juergen Hoeller
* @since 2.0
*/
abstract class HessianSkeletonInvoker {
/**
* Wrapped HessianSkeleton, available to subclasses.
*/
protected final HessianSkeleton skeleton;
/**
* Hessian SerializerFactory (if any), available to subclasses.
*/
protected final SerializerFactory serializerFactory;
/**
* Create a new HessianSkeletonInvoker for the given skeleton.
* @param skeleton the HessianSkeleton to wrap
* @param serializerFactory the Hessian SerializerFactory to use, if any
*/
public HessianSkeletonInvoker(HessianSkeleton skeleton, SerializerFactory serializerFactory) {
Assert.notNull(skeleton, "HessianSkeleton must not be null");
this.skeleton = skeleton;
this.serializerFactory = serializerFactory;
}
/**
* Invoke the given skeleton based on the given input/output streams.
* @param inputStream the stream containing the Hessian input
* @param outputStream the stream to receive the Hessian output
* @throws Throwable if the skeleton invocation failed
*/
public abstract void invoke(InputStream inputStream, OutputStream outputStream) throws Throwable;
}

View File

@@ -19,7 +19,7 @@ package org.springframework.web.context;
import java.io.IOException;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.ServletContext;
import org.apache.commons.logging.Log;
@@ -32,14 +32,13 @@ import org.springframework.beans.factory.access.BeanFactoryReference;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextException;
import org.springframework.context.access.ContextSingletonBeanFactoryLocator;
import org.springframework.core.CollectionFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.util.ClassUtils;
/**
* Performs the actual initialization work for the root application context.
* Called by {@link ContextLoaderListener} and {@link ContextLoaderServlet}.
* Called by {@link ContextLoaderListener}.
*
* <p>Looks for a {@link #CONTEXT_CLASS_PARAM "contextClass"} parameter
* at the <code>web.xml</code> context-param level to specify the context
@@ -72,7 +71,6 @@ import org.springframework.util.ClassUtils;
* @author Sam Brannen
* @since 17.02.2003
* @see ContextLoaderListener
* @see ContextLoaderServlet
* @see ConfigurableWebApplicationContext
* @see org.springframework.web.context.support.XmlWebApplicationContext
*/
@@ -150,7 +148,8 @@ public class ContextLoader {
* Often just holding one reference - if the ContextLoader class is
* deployed in the web app ClassLoader itself!
*/
private static final Map currentContextPerThread = CollectionFactory.createConcurrentMapIfPossible(1);
private static final Map<ClassLoader, WebApplicationContext> currentContextPerThread =
new ConcurrentHashMap<ClassLoader, WebApplicationContext>(1);
/**
* The root WebApplicationContext instance that this loader manages.
@@ -380,7 +379,7 @@ public class ContextLoader {
* @see org.springframework.web.context.support.SpringBeanAutowiringSupport
*/
public static WebApplicationContext getCurrentWebApplicationContext() {
return (WebApplicationContext) currentContextPerThread.get(Thread.currentThread().getContextClassLoader());
return currentContextPerThread.get(Thread.currentThread().getContextClassLoader());
}
}

View File

@@ -29,7 +29,6 @@ import javax.servlet.ServletContextListener;
*
* @author Juergen Hoeller
* @since 17.02.2003
* @see ContextLoaderServlet
* @see org.springframework.web.util.Log4jConfigListener
*/
public class ContextLoaderListener implements ServletContextListener {

View File

@@ -1,133 +0,0 @@
/*
* Copyright 2002-2007 the original author or authors.
*
* Licensed 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.springframework.web.context;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Bootstrap servlet to start up Spring's root {@link WebApplicationContext}.
* Simply delegates to {@link ContextLoader}.
*
* <p>This servlet should have a lower <code>load-on-startup</code> value
* in <code>web.xml</code> than any servlets that access the root web
* application context.
*
* <p><i>Note that this class has been deprecated for containers implementing
* Servlet API 2.4 or higher, in favor of {@link ContextLoaderListener}.</i><br>
* According to Servlet 2.4, listeners must be initialized before load-on-startup
* servlets. Many Servlet 2.3 containers already enforce this behavior. If you
* use such a container, this servlet can be replaced with ContextLoaderListener.
*
* <p>Servlet 2.3 containers known to work with bootstrap listeners are:
* <ul>
* <li>Apache Tomcat 4.x+
* <li>Jetty 4.x+
* <li>Resin 2.1.8+
* <li>Orion 2.0.2+
* <li>BEA WebLogic 8.1 SP3
* </ul>
* For working with any of them, ContextLoaderListener is recommended.
*
* <p>Servlet 2.3 containers known <i>not</i> to work with bootstrap listeners are:
* <ul>
* <li>BEA WebLogic up to 8.1 SP2
* <li>IBM WebSphere 5.x
* <li>Oracle OC4J 9.0.3
* </ul>
* If you happen to work with such a server, this servlet has to be used.
*
* <p>So unfortunately, the only context initialization option that is compatible
* with <i>all</i> Servlet 2.3 containers is this servlet.
*
* <p>Note that a startup failure of this servlet will not stop the rest of the
* web application from starting, in contrast to a listener failure. This can
* lead to peculiar side effects if other servlets get started that depend on
* initialization of the root web application context.
*
* @author Juergen Hoeller
* @author Darren Davison
* @see ContextLoaderListener
* @see org.springframework.web.util.Log4jConfigServlet
*/
public class ContextLoaderServlet extends HttpServlet {
private ContextLoader contextLoader;
/**
* Initialize the root web application context.
*/
@Override
public void init() throws ServletException {
this.contextLoader = createContextLoader();
this.contextLoader.initWebApplicationContext(getServletContext());
}
/**
* Create the ContextLoader to use. Can be overridden in subclasses.
* @return the new ContextLoader
*/
protected ContextLoader createContextLoader() {
return new ContextLoader();
}
/**
* Return the ContextLoader used by this servlet.
* @return the current ContextLoader
*/
public ContextLoader getContextLoader() {
return this.contextLoader;
}
/**
* Close the root web application context.
*/
@Override
public void destroy() {
if (this.contextLoader != null) {
this.contextLoader.closeWebApplicationContext(getServletContext());
}
}
/**
* This should never even be called since no mapping to this servlet should
* ever be created in web.xml. That's why a correctly invoked Servlet 2.3
* listener is much more appropriate for initialization work ;-)
*/
@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
getServletContext().log(
"Attempt to call service method on ContextLoaderServlet as [" +
request.getRequestURI() + "] was ignored");
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
}
@Override
public String getServletInfo() {
return "ContextLoaderServlet for Servlet API 2.3 " +
"(deprecated in favor of ContextLoaderListener for Servlet API 2.4)";
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2006 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,17 +24,17 @@ import org.springframework.context.ApplicationContext;
* Interface to provide configuration for a web application. This is read-only while
* the application is running, but may be reloaded if the implementation supports this.
*
* <p>This interface adds a getServletContext method to the generic ApplicationContext
* interface, and defines a well-known application attribute name that the root
* context must be bound to in the bootstrap process.
* <p>This interface adds a <code>getServletContext()</code> method to the generic
* ApplicationContext interface, and defines a well-known application attribute name
* that the root context must be bound to in the bootstrap process.
*
* <p>Like generic application contexts, web application contexts are hierarchical.
* There is a single root context per application, while each servlet in the application
* (including a dispatcher servlet in the MVC framework) has its own child context.
*
* <p>In addition to standard application context lifecycle capabilities,
* WebApplicationContext implementations need to detect ServletContextAware
* beans and invoke the setServletContext method accordingly.
* WebApplicationContext implementations need to detect {@link ServletContextAware}
* beans and invoke the <code>setServletContext</code> method accordingly.
*
* @author Rod Johnson
* @author Juergen Hoeller
@@ -53,7 +53,6 @@ public interface WebApplicationContext extends ApplicationContext {
*/
String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
/**
* Scope identifier for request scope: "request".
* Supported in addition to the standard scopes "singleton" and "prototype".
@@ -72,6 +71,20 @@ public interface WebApplicationContext extends ApplicationContext {
*/
String SCOPE_GLOBAL_SESSION = "globalSession";
/**
* Name of the ServletContext init-params environment bean in the factory.
* @see javax.servlet.ServletContext#getInitParameterNames()
* @see javax.servlet.ServletContext#getInitParameter(String)
*/
String CONTEXT_PROPERTIES_BEAN_NAME = "contextProperties";
/**
* Name of the ServletContext attributes environment bean in the factory.
* @see javax.servlet.ServletContext#getAttributeNames()
* @see javax.servlet.ServletContext#getAttribute(String)
*/
String CONTEXT_ATTRIBUTES_BEAN_NAME = "contextAttributes";
/**
* Return the standard Servlet API ServletContext for this application.

View File

@@ -16,7 +16,6 @@
package org.springframework.web.context.request;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -34,7 +33,7 @@ import org.springframework.util.Assert;
public abstract class AbstractRequestAttributes implements RequestAttributes {
/** Map from attribute name String to destruction callback Runnable */
protected final Map requestDestructionCallbacks = new LinkedHashMap(8);
protected final Map<String, Runnable> requestDestructionCallbacks = new LinkedHashMap<String, Runnable>(8);
private volatile boolean requestActive = true;
@@ -88,8 +87,8 @@ public abstract class AbstractRequestAttributes implements RequestAttributes {
*/
private void executeRequestDestructionCallbacks() {
synchronized (this.requestDestructionCallbacks) {
for (Iterator it = this.requestDestructionCallbacks.values().iterator(); it.hasNext();) {
((Runnable) it.next()).run();
for (Runnable runnable : this.requestDestructionCallbacks.values()) {
runnable.run();
}
this.requestDestructionCallbacks.clear();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2006 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -63,6 +63,10 @@ public abstract class AbstractRequestAttributesScope implements Scope {
attributes.registerDestructionCallback(name, callback, getScope());
}
public Object resolveContextualObject(String key) {
return null;
}
/**
* Template method that determines the actual target scope.

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed 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.springframework.web.context.request;
import java.io.Serializable;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
/**
* Adapter that implements the Servlet 2.3 HttpSessionBindingListener
* interface, wrapping a session destruction callback.
*/
public class DestructionCallbackBindingListener implements HttpSessionBindingListener, Serializable {
private final Runnable destructionCallback;
public DestructionCallbackBindingListener(Runnable destructionCallback) {
this.destructionCallback = destructionCallback;
}
public void valueBound(HttpSessionBindingEvent event) {
}
public void valueUnbound(HttpSessionBindingEvent event) {
this.destructionCallback.run();
}
}

View File

@@ -18,7 +18,6 @@ package org.springframework.web.context.request;
import java.lang.reflect.Method;
import java.util.Map;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
@@ -71,7 +70,7 @@ public class FacesRequestAttributes implements RequestAttributes {
/**
* Return the JSF FacesContext that this adapter operates on.
*/
protected FacesContext getFacesContext() {
protected final FacesContext getFacesContext() {
return this.facesContext;
}
@@ -79,7 +78,7 @@ public class FacesRequestAttributes implements RequestAttributes {
* Return the JSF ExternalContext that this adapter operates on.
* @see javax.faces.context.FacesContext#getExternalContext()
*/
protected ExternalContext getExternalContext() {
protected final ExternalContext getExternalContext() {
return getFacesContext().getExternalContext();
}
@@ -90,7 +89,7 @@ public class FacesRequestAttributes implements RequestAttributes {
* @see #SCOPE_REQUEST
* @see #SCOPE_SESSION
*/
protected Map getAttributeMap(int scope) {
protected Map<String, Object> getAttributeMap(int scope) {
if (scope == SCOPE_REQUEST) {
return getExternalContext().getRequestMap();
}
@@ -113,7 +112,7 @@ public class FacesRequestAttributes implements RequestAttributes {
}
public String[] getAttributeNames(int scope) {
return StringUtils.toStringArray(getAttributeMap(scope).entrySet());
return StringUtils.toStringArray(getAttributeMap(scope).keySet());
}
public void registerDestructionCallback(String name, Runnable callback, int scope) {
@@ -123,6 +122,54 @@ public class FacesRequestAttributes implements RequestAttributes {
}
}
public Object resolveReference(String key) {
if (REFERENCE_REQUEST.equals(key)) {
return getExternalContext().getRequest();
}
else if (REFERENCE_SESSION.equals(key)) {
return getExternalContext().getSession(true);
}
else if ("application".equals(key)) {
return getExternalContext().getContext();
}
else if ("requestScope".equals(key)) {
return getExternalContext().getRequestMap();
}
else if ("sessionScope".equals(key)) {
return getExternalContext().getSessionMap();
}
else if ("applicationScope".equals(key)) {
return getExternalContext().getApplicationMap();
}
else if ("cookie".equals(key)) {
return getExternalContext().getRequestCookieMap();
}
else if ("header".equals(key)) {
return getExternalContext().getRequestHeaderMap();
}
else if ("headerValues".equals(key)) {
return getExternalContext().getRequestHeaderValuesMap();
}
else if ("param".equals(key)) {
return getExternalContext().getRequestParameterMap();
}
else if ("paramValues".equals(key)) {
return getExternalContext().getRequestParameterValuesMap();
}
else if ("initParam".equals(key)) {
return getExternalContext().getInitParameterMap();
}
else if ("view".equals(key)) {
return getFacesContext().getViewRoot();
}
else if ("facesContext".equals(key)) {
return getFacesContext();
}
else {
return null;
}
}
public String getSessionId() {
Object session = getExternalContext().getSession(true);
try {

View File

@@ -19,7 +19,6 @@ package org.springframework.web.context.request;
import java.security.Principal;
import java.util.Locale;
import java.util.Map;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
@@ -53,15 +52,15 @@ public class FacesWebRequest extends FacesRequestAttributes implements NativeWeb
public String getParameter(String paramName) {
return (String) getExternalContext().getRequestParameterMap().get(paramName);
return getExternalContext().getRequestParameterMap().get(paramName);
}
public String[] getParameterValues(String paramName) {
return (String[]) getExternalContext().getRequestParameterValuesMap().get(paramName);
return getExternalContext().getRequestParameterValuesMap().get(paramName);
}
public Map getParameterMap() {
return getExternalContext().getRequestParameterMap();
public Map<String, String[]> getParameterMap() {
return getExternalContext().getRequestParameterValuesMap();
}
public Locale getLocale() {
@@ -95,19 +94,19 @@ public class FacesWebRequest extends FacesRequestAttributes implements NativeWeb
public String getDescription(boolean includeClientInfo) {
ExternalContext externalContext = getExternalContext();
StringBuffer buffer = new StringBuffer();
buffer.append("context=").append(externalContext.getRequestContextPath());
StringBuilder sb = new StringBuilder();
sb.append("context=").append(externalContext.getRequestContextPath());
if (includeClientInfo) {
Object session = externalContext.getSession(false);
if (session != null) {
buffer.append(";session=").append(getSessionId());
sb.append(";session=").append(getSessionId());
}
String user = externalContext.getRemoteUser();
if (StringUtils.hasLength(user)) {
buffer.append(";user=").append(user);
sb.append(";user=").append(user);
}
}
return buffer.toString();
return sb.toString();
}
@Override

View File

@@ -53,6 +53,12 @@ public interface RequestAttributes {
int SCOPE_GLOBAL_SESSION = 2;
String REFERENCE_REQUEST = "request";
String REFERENCE_SESSION = "session";
/**
* Return the value for the scoped attribute of the given name, if any.
* @param name the name of the attribute
@@ -108,6 +114,15 @@ public interface RequestAttributes {
*/
void registerDestructionCallback(String name, Runnable callback, int scope);
/**
* Resolve the contextual reference for the given key, if any.
* <p>At a minimum: the HttpServletRequest/PortletRequest reference for key
* "request", and the HttpSession/PortletSession reference for key "session".
* @param key the contextual key
* @return the corresponding object, or <code>null</code> if none found
*/
Object resolveReference(String key);
/**
* Return an id for the current underlying session.
* @return the session id as String (never <code>null</code>

View File

@@ -16,15 +16,10 @@
package org.springframework.web.context.request;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -55,7 +50,7 @@ public class ServletRequestAttributes extends AbstractRequestAttributes {
private volatile HttpSession session;
private final Map sessionAttributesToUpdate = new HashMap();
private final Map<String, Object> sessionAttributesToUpdate = new HashMap<String, Object>();
/**
@@ -164,6 +159,7 @@ public class ServletRequestAttributes extends AbstractRequestAttributes {
}
}
@SuppressWarnings("unchecked")
public String[] getAttributeNames(int scope) {
if (scope == SCOPE_REQUEST) {
if (!isRequestActive()) {
@@ -195,6 +191,18 @@ public class ServletRequestAttributes extends AbstractRequestAttributes {
}
}
public Object resolveReference(String key) {
if (REFERENCE_REQUEST.equals(key)) {
return this.request;
}
else if (REFERENCE_SESSION.equals(key)) {
return getSession(true);
}
else {
return null;
}
}
public String getSessionId() {
return getSession(true).getId();
}
@@ -216,9 +224,8 @@ public class ServletRequestAttributes extends AbstractRequestAttributes {
synchronized (this.sessionAttributesToUpdate) {
if (this.session != null) {
try {
for (Iterator it = this.sessionAttributesToUpdate.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
String name = (String) entry.getKey();
for (Map.Entry<String, Object> entry : this.sessionAttributesToUpdate.entrySet()) {
String name = entry.getKey();
Object newValue = entry.getValue();
Object oldValue = this.session.getAttribute(name);
if (oldValue == newValue) {
@@ -251,25 +258,4 @@ public class ServletRequestAttributes extends AbstractRequestAttributes {
return this.request.toString();
}
/**
* Adapter that implements the Servlet 2.3 HttpSessionBindingListener
* interface, wrapping a session destruction callback.
*/
private static class DestructionCallbackBindingListener implements HttpSessionBindingListener, Serializable {
private final Runnable destructionCallback;
public DestructionCallbackBindingListener(Runnable destructionCallback) {
this.destructionCallback = destructionCallback;
}
public void valueBound(HttpSessionBindingEvent event) {
}
public void valueUnbound(HttpSessionBindingEvent event) {
this.destructionCallback.run();
}
}
}

View File

@@ -19,7 +19,6 @@ package org.springframework.web.context.request;
import java.security.Principal;
import java.util.Locale;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@@ -87,7 +86,8 @@ public class ServletWebRequest extends ServletRequestAttributes implements Nativ
return getRequest().getParameterValues(paramName);
}
public Map getParameterMap() {
@SuppressWarnings("unchecked")
public Map<String, String[]> getParameterMap() {
return getRequest().getParameterMap();
}
@@ -140,23 +140,23 @@ public class ServletWebRequest extends ServletRequestAttributes implements Nativ
public String getDescription(boolean includeClientInfo) {
HttpServletRequest request = getRequest();
StringBuffer buffer = new StringBuffer();
buffer.append("uri=").append(request.getRequestURI());
StringBuilder sb = new StringBuilder();
sb.append("uri=").append(request.getRequestURI());
if (includeClientInfo) {
String client = request.getRemoteAddr();
if (StringUtils.hasLength(client)) {
buffer.append(";client=").append(client);
sb.append(";client=").append(client);
}
HttpSession session = request.getSession(false);
if (session != null) {
buffer.append(";session=").append(session.getId());
sb.append(";session=").append(session.getId());
}
String user = request.getRemoteUser();
if (StringUtils.hasLength(user)) {
buffer.append(";user=").append(user);
sb.append(";user=").append(user);
}
}
return buffer.toString();
return sb.toString();
}
@Override

View File

@@ -52,7 +52,7 @@ public interface WebRequest extends RequestAttributes {
* <p>A single-value parameter will be exposed as an array with a single element.
* @see javax.servlet.http.HttpServletRequest#getParameterMap()
*/
Map getParameterMap();
Map<String, String[]> getParameterMap();
/**
* Return the primary Locale for this request.

View File

@@ -143,6 +143,7 @@ public abstract class AbstractRefreshableWebApplicationContext extends AbstractR
beanFactory.registerResolvableDependency(ServletConfig.class, this.servletConfig);
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory);
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
}
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -106,6 +106,7 @@ public class GenericWebApplicationContext extends GenericApplicationContext
beanFactory.registerResolvableDependency(ServletContext.class, this.servletContext);
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory);
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
}
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -124,7 +124,7 @@ public class RequestHandledEvent extends ApplicationEvent {
* the most important context data.
*/
public String getShortDescription() {
StringBuffer sb = new StringBuffer();
StringBuilder sb = new StringBuilder();
sb.append("session=[").append(this.sessionId).append("]; ");
sb.append("user=[").append(this.userName).append("]; ");
return sb.toString();
@@ -135,7 +135,7 @@ public class RequestHandledEvent extends ApplicationEvent {
* all available context data.
*/
public String getDescription() {
StringBuffer sb = new StringBuffer();
StringBuilder sb = new StringBuilder();
sb.append("session=[").append(this.sessionId).append("]; ");
sb.append("user=[").append(this.userName).append("]; ");
sb.append("time=[").append(this.processingTimeMillis).append("ms]; ");

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -119,7 +119,7 @@ public class ServletRequestHandledEvent extends RequestHandledEvent {
@Override
public String getShortDescription() {
StringBuffer sb = new StringBuffer();
StringBuilder sb = new StringBuilder();
sb.append("url=[").append(getRequestUrl()).append("]; ");
sb.append("client=[").append(getClientAddress()).append("]; ");
sb.append(super.getShortDescription());
@@ -128,7 +128,7 @@ public class ServletRequestHandledEvent extends RequestHandledEvent {
@Override
public String getDescription() {
StringBuffer sb = new StringBuffer();
StringBuilder sb = new StringBuilder();
sb.append("url=[").append(getRequestUrl()).append("]; ");
sb.append("client=[").append(getClientAddress()).append("]; ");
sb.append("method=[").append(getMethod()).append("]; ");

View File

@@ -134,13 +134,14 @@ public class StaticWebApplicationContext extends StaticApplicationContext
*/
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.registerScope(SCOPE_REQUEST, new RequestScope());
beanFactory.registerScope(SCOPE_SESSION, new SessionScope(false));
beanFactory.registerScope(SCOPE_GLOBAL_SESSION, new SessionScope(true));
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
beanFactory.registerResolvableDependency(ServletContext.class, this.servletContext);
beanFactory.registerResolvableDependency(ServletConfig.class, this.servletConfig);
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory);
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
}
/**

View File

@@ -16,6 +16,10 @@
package org.springframework.web.context.support;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpSession;
@@ -53,8 +57,7 @@ public abstract class WebApplicationContextUtils {
/**
* Find the root WebApplicationContext for this web application, which is
* typically loaded via {@link org.springframework.web.context.ContextLoaderListener} or
* {@link org.springframework.web.context.ContextLoaderServlet}.
* typically loaded via {@link org.springframework.web.context.ContextLoaderListener}.
* <p>Will rethrow an exception that happened on root context startup,
* to differentiate between a failed context startup and no context at all.
* @param sc ServletContext to find the web application context for
@@ -74,8 +77,7 @@ public abstract class WebApplicationContextUtils {
/**
* Find the root WebApplicationContext for this web application, which is
* typically loaded via {@link org.springframework.web.context.ContextLoaderListener} or
* {@link org.springframework.web.context.ContextLoaderServlet}.
* typically loaded via {@link org.springframework.web.context.ContextLoaderListener}.
* <p>Will rethrow an exception that happened on root context startup,
* to differentiate between a failed context startup and no context at all.
* @param sc ServletContext to find the web application context for
@@ -105,9 +107,7 @@ public abstract class WebApplicationContextUtils {
throw (Error) attr;
}
if (attr instanceof Exception) {
IllegalStateException ex = new IllegalStateException();
ex.initCause((Exception) attr);
throw ex;
throw new IllegalStateException((Exception) attr);
}
if (!(attr instanceof WebApplicationContext)) {
throw new IllegalStateException("Context attribute is not of type WebApplicationContext: " + attr);
@@ -121,7 +121,7 @@ public abstract class WebApplicationContextUtils {
* as used by the WebApplicationContext.
* @param beanFactory the BeanFactory to configure
*/
public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory) {
static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory) {
beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope(false));
beanFactory.registerScope(WebApplicationContext.SCOPE_GLOBAL_SESSION, new SessionScope(true));
@@ -146,4 +146,38 @@ public abstract class WebApplicationContextUtils {
});
}
/**
* Register web-specific environment beans with the given BeanFactory,
* as used by the WebApplicationContext.
* @param bf the BeanFactory to configure
* @param sc the ServletContext that we're running within
*/
static void registerEnvironmentBeans(ConfigurableListableBeanFactory bf, ServletContext sc) {
if (!bf.containsBean(WebApplicationContext.CONTEXT_PROPERTIES_BEAN_NAME)) {
Map<String, String> parameterMap = new HashMap<String, String>();
if (sc != null) {
Enumeration paramNameEnum = sc.getInitParameterNames();
while (paramNameEnum.hasMoreElements()) {
String paramName = (String) paramNameEnum.nextElement();
parameterMap.put(paramName, sc.getInitParameter(paramName));
}
}
bf.registerSingleton(WebApplicationContext.CONTEXT_PROPERTIES_BEAN_NAME,
Collections.unmodifiableMap(parameterMap));
}
if (!bf.containsBean(WebApplicationContext.CONTEXT_ATTRIBUTES_BEAN_NAME)) {
Map<String, Object> attributeMap = new HashMap<String, Object>();
if (sc != null) {
Enumeration attrNameEnum = sc.getAttributeNames();
while (attrNameEnum.hasMoreElements()) {
String attrName = (String) attrNameEnum.nextElement();
attributeMap.put(attrName, sc.getAttribute(attrName));
}
}
bf.registerSingleton(WebApplicationContext.CONTEXT_ATTRIBUTES_BEAN_NAME,
Collections.unmodifiableMap(attributeMap));
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -188,28 +188,28 @@ public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter
* and the supplied prefix and suffix.
*/
protected String createMessage(HttpServletRequest request, String prefix, String suffix) {
StringBuffer buffer = new StringBuffer();
buffer.append(prefix);
buffer.append("uri=").append(request.getRequestURI());
StringBuilder msg = new StringBuilder();
msg.append(prefix);
msg.append("uri=").append(request.getRequestURI());
if (isIncludeQueryString()) {
buffer.append('?').append(request.getQueryString());
msg.append('?').append(request.getQueryString());
}
if (isIncludeClientInfo()) {
String client = request.getRemoteAddr();
if (StringUtils.hasLength(client)) {
buffer.append(";client=").append(client);
msg.append(";client=").append(client);
}
HttpSession session = request.getSession(false);
if (session != null) {
buffer.append(";session=").append(session.getId());
msg.append(";session=").append(session.getId());
}
String user = request.getRemoteUser();
if (user != null) {
buffer.append(";user=").append(user);
msg.append(";user=").append(user);
}
}
buffer.append(suffix);
return buffer.toString();
msg.append(suffix);
return msg.toString();
}

View File

@@ -17,14 +17,11 @@
package org.springframework.web.filter;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.util.ClassUtils;
/**
* Servlet 2.3/2.4 Filter that allows one to specify a character encoding for
* requests. This is useful because current browsers typically do not set a
@@ -45,12 +42,6 @@ import org.springframework.util.ClassUtils;
*/
public class CharacterEncodingFilter extends OncePerRequestFilter {
// Determine whether the Servlet 2.4 HttpServletResponse.setCharacterEncoding(String)
// method is available, for use in the "doFilterInternal" implementation.
private final static boolean responseSetCharacterEncodingAvailable = ClassUtils.hasMethod(
HttpServletResponse.class, "setCharacterEncoding", new Class[] {String.class});
private String encoding;
private boolean forceEncoding = false;
@@ -90,7 +81,7 @@ public class CharacterEncodingFilter extends OncePerRequestFilter {
if (this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) {
request.setCharacterEncoding(this.encoding);
if (this.forceEncoding && responseSetCharacterEncodingAvailable) {
if (this.forceEncoding) {
response.setCharacterEncoding(this.encoding);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,53 +19,33 @@ package org.springframework.web.util;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.el.ELException;
import javax.servlet.jsp.el.Expression;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* Convenience methods for transparent access to JSP 2.0's built-in
* {@link javax.servlet.jsp.el.ExpressionEvaluator} or the standalone
* {@link org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager}
* of Jakarta's JSTL implementation.
* Convenience methods for accessing JSP 2.0's
* {@link javax.servlet.jsp.el.ExpressionEvaluator}.
*
* <p>Automatically detects JSP 2.0 or Jakarta JSTL, preferring the JSP 2.0
* mechanism if available. Also detects the JSP 2.0 API being present but
* the runtime JSP engine not actually supporting JSP 2.0, falling back to
* the Jakarta JSTL in this case. Throws an exception when encountering actual
* EL expressions if neither JSP 2.0 nor the Jakarta JSTL is available.
*
* <p>In the case of JSP 2.0, this class will by default use standard
* <code>evaluate</code> calls. If your application server happens to be
* inefficient in that respect, consider setting Spring's "cacheJspExpressions"
* context-param in <code>web.xml</code> to "true", which will use
* <code>parseExpression</code> calls with cached Expression objects instead.
* <p>This class will by default use standard <code>evaluate</code> calls.
* If your application server happens to be inefficient in that respect,
* consider setting Spring's "cacheJspExpressions" context-param in
* <code>web.xml</code> to "true", which will use <code>parseExpression</code>
* calls with cached Expression objects instead.
*
* <p>The evaluation methods check if the value contains "${" before
* invoking the EL evaluator, treating the value as "normal" expression
* (i.e. a literal String value) else.
*
* <p>Note: The evaluation methods do not have a runtime dependency on
* JSP 2.0 or on Jakarta's JSTL implementation, as long as they are not
* asked to process actual EL expressions. This allows for using EL-aware
* tags with Java-based JSP expressions instead, for example.
*
* @author Juergen Hoeller
* @author Alef Arendsen
* @since 11.07.2003
* @see javax.servlet.jsp.el.ExpressionEvaluator#evaluate
* @see javax.servlet.jsp.el.ExpressionEvaluator#parseExpression
* @see org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager
*/
public abstract class ExpressionEvaluationUtils {
@@ -86,40 +66,6 @@ public abstract class ExpressionEvaluationUtils {
private static final String EXPRESSION_CACHE_MAP_CONTEXT_ATTR =
ExpressionEvaluationUtils.class.getName() + ".JSP_EXPRESSION_CACHE";
private static final String JSP_20_CLASS_NAME =
"javax.servlet.jsp.el.ExpressionEvaluator";
private static final String JAKARTA_JSTL_CLASS_NAME =
"org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager";
private static final Log logger = LogFactory.getLog(ExpressionEvaluationUtils.class);
private static ExpressionEvaluationHelper helper;
static {
ClassLoader cl = ExpressionEvaluationUtils.class.getClassLoader();
if (ClassUtils.isPresent(JSP_20_CLASS_NAME, cl)) {
logger.debug("Found JSP 2.0 ExpressionEvaluator");
if (ClassUtils.isPresent(JAKARTA_JSTL_CLASS_NAME, cl)) {
logger.debug("Found Jakarta JSTL ExpressionEvaluatorManager");
helper = new Jsp20ExpressionEvaluationHelper(new JakartaExpressionEvaluationHelper());
}
else {
helper = new Jsp20ExpressionEvaluationHelper(new NoExpressionEvaluationHelper());
}
}
else if (ClassUtils.isPresent(JAKARTA_JSTL_CLASS_NAME, cl)) {
logger.debug("Found Jakarta JSTL ExpressionEvaluatorManager");
helper = new JakartaExpressionEvaluationHelper();
}
else {
logger.debug("JSP expression evaluation not available");
helper = new NoExpressionEvaluationHelper();
}
}
/**
* Check if the given expression value is an EL expression.
@@ -128,7 +74,7 @@ public abstract class ExpressionEvaluationUtils {
* <code>false</code> otherwise
*/
public static boolean isExpressionLanguage(String value) {
return (value != null && value.indexOf(EXPRESSION_PREFIX) != -1);
return (value != null && value.contains(EXPRESSION_PREFIX));
}
/**
@@ -208,7 +154,7 @@ public abstract class ExpressionEvaluationUtils {
throws JspException {
if (isExpressionLanguage(attrValue)) {
return ((Integer) doEvaluate(attrName, attrValue, Integer.class, pageContext)).intValue();
return (Integer) doEvaluate(attrName, attrValue, Integer.class, pageContext);
}
else {
return Integer.parseInt(attrValue);
@@ -227,10 +173,10 @@ public abstract class ExpressionEvaluationUtils {
throws JspException {
if (isExpressionLanguage(attrValue)) {
return ((Boolean) doEvaluate(attrName, attrValue, Boolean.class, pageContext)).booleanValue();
return (Boolean) doEvaluate(attrName, attrValue, Boolean.class, pageContext);
}
else {
return Boolean.valueOf(attrValue).booleanValue();
return Boolean.valueOf(attrValue);
}
}
@@ -247,56 +193,81 @@ public abstract class ExpressionEvaluationUtils {
* @throws JspException in case of parsing errors
*/
private static Object doEvaluate(String attrName, String attrValue, Class resultClass, PageContext pageContext)
throws JspException {
throws JspException {
Assert.notNull(attrValue, "Attribute value must not be null");
Assert.notNull(resultClass, "Result class must not be null");
Assert.notNull(pageContext, "PageContext must not be null");
if (resultClass.isAssignableFrom(String.class)) {
StringBuffer resultValue = null;
int exprPrefixIndex = -1;
int exprSuffixIndex = 0;
do {
exprPrefixIndex = attrValue.indexOf(EXPRESSION_PREFIX, exprSuffixIndex);
if (exprPrefixIndex != -1) {
int prevExprSuffixIndex = exprSuffixIndex;
exprSuffixIndex = attrValue.indexOf(EXPRESSION_SUFFIX, exprPrefixIndex + EXPRESSION_PREFIX.length());
String expr = null;
if (exprSuffixIndex != -1) {
exprSuffixIndex += EXPRESSION_SUFFIX.length();
expr = attrValue.substring(exprPrefixIndex, exprSuffixIndex);
}
else {
expr = attrValue.substring(exprPrefixIndex);
}
if (expr.length() == attrValue.length()) {
// A single expression without static prefix or suffix ->
// parse it with the specified result class rather than String.
return helper.evaluate(attrName, attrValue, resultClass, pageContext);
}
else {
// We actually need to concatenate partial expressions into a String.
if (resultValue == null) {
resultValue = new StringBuffer();
try {
if (resultClass.isAssignableFrom(String.class)) {
StringBuilder resultValue = null;
int exprPrefixIndex = -1;
int exprSuffixIndex = 0;
do {
exprPrefixIndex = attrValue.indexOf(EXPRESSION_PREFIX, exprSuffixIndex);
if (exprPrefixIndex != -1) {
int prevExprSuffixIndex = exprSuffixIndex;
exprSuffixIndex = attrValue.indexOf(EXPRESSION_SUFFIX, exprPrefixIndex + EXPRESSION_PREFIX.length());
String expr = null;
if (exprSuffixIndex != -1) {
exprSuffixIndex += EXPRESSION_SUFFIX.length();
expr = attrValue.substring(exprPrefixIndex, exprSuffixIndex);
}
resultValue.append(attrValue.substring(prevExprSuffixIndex, exprPrefixIndex));
resultValue.append(helper.evaluate(attrName, expr, String.class, pageContext));
else {
expr = attrValue.substring(exprPrefixIndex);
}
if (expr.length() == attrValue.length()) {
// A single expression without static prefix or suffix ->
// parse it with the specified result class rather than String.
return evaluateExpression(attrValue, resultClass, pageContext);
}
else {
// We actually need to concatenate partial expressions into a String.
if (resultValue == null) {
resultValue = new StringBuilder();
}
resultValue.append(attrValue.substring(prevExprSuffixIndex, exprPrefixIndex));
resultValue.append(evaluateExpression(expr, String.class, pageContext));
}
}
else {
if (resultValue == null) {
resultValue = new StringBuilder();
}
resultValue.append(attrValue.substring(exprSuffixIndex));
}
}
else {
if (resultValue == null) {
resultValue = new StringBuffer();
}
resultValue.append(attrValue.substring(exprSuffixIndex));
}
while (exprPrefixIndex != -1 && exprSuffixIndex != -1);
return resultValue.toString();
}
else {
return evaluateExpression(attrValue, resultClass, pageContext);
}
while (exprPrefixIndex != -1 && exprSuffixIndex != -1);
return resultValue.toString();
}
catch (ELException ex) {
throw new JspException("Parsing of JSP EL expression failed for attribute '" + attrName + "'", ex);
}
}
private static Object evaluateExpression(String exprValue, Class resultClass, PageContext pageContext)
throws ELException {
Map<ExpressionCacheKey, Expression> expressionCache = getJspExpressionCache(pageContext);
if (expressionCache != null) {
// We are supposed to explicitly create and cache JSP Expression objects.
ExpressionCacheKey cacheKey = new ExpressionCacheKey(exprValue, resultClass);
Expression expr = expressionCache.get(cacheKey);
if (expr == null) {
expr = pageContext.getExpressionEvaluator().parseExpression(exprValue, resultClass, null);
expressionCache.put(cacheKey, expr);
}
return expr.evaluate(pageContext.getVariableResolver());
}
else {
return helper.evaluate(attrName, attrValue, resultClass, pageContext);
// We're simply calling the JSP 2.0 evaluate method straight away.
return pageContext.getExpressionEvaluator().evaluate(
exprValue, resultClass, pageContext.getVariableResolver(), null);
}
}
@@ -307,17 +278,19 @@ public abstract class ExpressionEvaluationUtils {
* @param pageContext current JSP PageContext
* @return the cache Map, or <code>null</code> if caching is disabled
*/
private static Map getJspExpressionCache(PageContext pageContext) {
@SuppressWarnings("unchecked")
private static Map<ExpressionCacheKey, Expression> getJspExpressionCache(PageContext pageContext) {
ServletContext servletContext = pageContext.getServletContext();
Map cacheMap = (Map) servletContext.getAttribute(EXPRESSION_CACHE_MAP_CONTEXT_ATTR);
Map<ExpressionCacheKey, Expression> cacheMap =
(Map<ExpressionCacheKey, Expression>) servletContext.getAttribute(EXPRESSION_CACHE_MAP_CONTEXT_ATTR);
if (cacheMap == null) {
Boolean cacheFlag = (Boolean) servletContext.getAttribute(EXPRESSION_CACHE_FLAG_CONTEXT_ATTR);
if (cacheFlag == null) {
cacheFlag = Boolean.valueOf(servletContext.getInitParameter(EXPRESSION_CACHE_CONTEXT_PARAM));
servletContext.setAttribute(EXPRESSION_CACHE_FLAG_CONTEXT_ATTR, cacheFlag);
}
if (cacheFlag.booleanValue()) {
cacheMap = Collections.synchronizedMap(new HashMap());
if (cacheFlag) {
cacheMap = Collections.synchronizedMap(new HashMap<ExpressionCacheKey, Expression>());
servletContext.setAttribute(EXPRESSION_CACHE_MAP_CONTEXT_ATTR, cacheMap);
}
}
@@ -325,106 +298,6 @@ public abstract class ExpressionEvaluationUtils {
}
/**
* Internal interface for evaluating a JSP EL expression.
*/
private static interface ExpressionEvaluationHelper {
public Object evaluate(String attrName, String attrValue, Class resultClass, PageContext pageContext)
throws JspException;
}
/**
* Fallback ExpressionEvaluationHelper:
* always throws an exception in case of an actual EL expression.
*/
private static class NoExpressionEvaluationHelper implements ExpressionEvaluationHelper {
public Object evaluate(String attrName, String attrValue, Class resultClass, PageContext pageContext)
throws JspException {
throw new JspException(
"Neither JSP 2.0 nor Jakarta JSTL available - cannot parse JSP EL expression \"" + attrValue + "\"");
}
}
/**
* Actual invocation of the Jakarta ExpressionEvaluatorManager.
* In separate inner class to avoid runtime dependency on Jakarta's
* JSTL implementation, for evaluation of non-EL expressions.
*/
private static class JakartaExpressionEvaluationHelper implements ExpressionEvaluationHelper {
public Object evaluate(String attrName, String attrValue, Class resultClass, PageContext pageContext)
throws JspException {
return ExpressionEvaluatorManager.evaluate(attrName, attrValue, resultClass, pageContext);
}
}
/**
* Actual invocation of the JSP 2.0 ExpressionEvaluator.
* In separate inner class to avoid runtime dependency on JSP 2.0,
* for evaluation of non-EL expressions.
*/
private static class Jsp20ExpressionEvaluationHelper implements ExpressionEvaluationHelper {
private final ExpressionEvaluationHelper fallback;
private boolean fallbackNecessary = false;
public Jsp20ExpressionEvaluationHelper(ExpressionEvaluationHelper fallback) {
this.fallback = fallback;
}
public Object evaluate(String attrName, String attrValue, Class resultClass, PageContext pageContext)
throws JspException {
if (isFallbackNecessary()) {
return this.fallback.evaluate(attrName, attrValue, resultClass, pageContext);
}
try {
Map expressionCache = getJspExpressionCache(pageContext);
if (expressionCache != null) {
// We are supposed to explicitly create and cache JSP Expression objects.
ExpressionCacheKey cacheKey = new ExpressionCacheKey(attrValue, resultClass);
Expression expr = (Expression) expressionCache.get(cacheKey);
if (expr == null) {
expr = pageContext.getExpressionEvaluator().parseExpression(attrValue, resultClass, null);
expressionCache.put(cacheKey, expr);
}
return expr.evaluate(pageContext.getVariableResolver());
}
else {
// We're simply calling the JSP 2.0 evaluate method straight away.
return pageContext.getExpressionEvaluator().evaluate(
attrValue, resultClass, pageContext.getVariableResolver(), null);
}
}
catch (ELException ex) {
throw new JspException("Parsing of JSP EL expression \"" + attrValue + "\" failed", ex);
}
catch (LinkageError err) {
logger.debug("JSP 2.0 ExpressionEvaluator API present but not implemented - using fallback", err);
setFallbackNecessary();
return this.fallback.evaluate(attrName, attrValue, resultClass, pageContext);
}
}
private synchronized boolean isFallbackNecessary() {
return this.fallbackNecessary;
}
private synchronized void setFallbackNecessary() {
this.fallbackNecessary = true;
}
}
/**
* Cache key class for JSP 2.0 Expression objects.
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2005 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,7 +33,7 @@ class HtmlCharacterEntityDecoder {
private final String originalMessage;
private final StringBuffer decodedMessage;
private final StringBuilder decodedMessage;
private int currentPosition = 0;
@@ -45,7 +45,7 @@ class HtmlCharacterEntityDecoder {
public HtmlCharacterEntityDecoder(HtmlCharacterEntityReferences characterEntityReferences, String original) {
this.characterEntityReferences = characterEntityReferences;
this.originalMessage = original;
this.decodedMessage = new StringBuffer(originalMessage.length());
this.decodedMessage = new StringBuilder(originalMessage.length());
}
public String decode() {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -60,7 +60,7 @@ public abstract class HtmlUtils {
if (input == null) {
return null;
}
StringBuffer escaped = new StringBuffer(input.length() * 2);
StringBuilder escaped = new StringBuilder(input.length() * 2);
for (int i = 0; i < input.length(); i++) {
char character = input.charAt(i);
String reference = characterEntityReferences.convertToReference(character);
@@ -90,7 +90,7 @@ public abstract class HtmlUtils {
if (input == null) {
return null;
}
StringBuffer escaped = new StringBuffer(input.length() * 2);
StringBuilder escaped = new StringBuilder(input.length() * 2);
for (int i = 0; i < input.length(); i++) {
char character = input.charAt(i);
if (characterEntityReferences.isMappedToReference(character)) {
@@ -121,7 +121,7 @@ public abstract class HtmlUtils {
if (input == null) {
return null;
}
StringBuffer escaped = new StringBuffer(input.length() * 2);
StringBuilder escaped = new StringBuilder(input.length() * 2);
for (int i = 0; i < input.length(); i++) {
char character = input.charAt(i);
if (characterEntityReferences.isMappedToReference(character)) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2006 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,7 +42,7 @@ public class JavaScriptUtils {
return input;
}
StringBuffer filtered = new StringBuffer(input.length());
StringBuilder filtered = new StringBuilder(input.length());
char prevChar = '\u0000';
char c;
for (int i = 0; i < input.length(); i++) {

View File

@@ -36,9 +36,7 @@ import javax.servlet.ServletContextListener;
* @author Juergen Hoeller
* @since 13.03.2003
* @see Log4jWebConfigurer
* @see Log4jConfigServlet
* @see org.springframework.web.context.ContextLoaderListener
* @see org.springframework.web.context.ContextLoaderServlet
* @see WebAppRootListener
*/
public class Log4jConfigListener implements ServletContextListener {

View File

@@ -1,86 +0,0 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed 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.springframework.web.util;
import java.io.IOException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Bootstrap servlet for custom log4j initialization in a web environment.
* Delegates to {@link Log4jWebConfigurer} (see its javadoc for configuration details).
*
* <b>WARNING: Assumes an expanded WAR file</b>, both for loading the configuration
* file and for writing the log files. If you want to keep your WAR unexpanded or
* don't need application-specific log files within the WAR directory, don't use
* log4j setup within the application (thus, don't use Log4jConfigListener or
* Log4jConfigServlet). Instead, use a global, VM-wide log4j setup (for example,
* in JBoss) or JDK 1.4's <code>java.util.logging</code> (which is global too).
*
* <p>Note: This servlet should have a lower <code>load-on-startup</code> value
* in <code>web.xml</code> than ContextLoaderServlet, when using custom log4j
* initialization.
*
* <p><i>Note that this class has been deprecated for containers implementing
* Servlet API 2.4 or higher, in favor of {@link Log4jConfigListener}.</i><br>
* According to Servlet 2.4, listeners must be initialized before load-on-startup
* servlets. Many Servlet 2.3 containers already enforce this behavior
* (see ContextLoaderServlet javadocs for details). If you use such a container,
* this servlet can be replaced with Log4jConfigListener.
*
* @author Juergen Hoeller
* @author Darren Davison
* @since 12.08.2003
* @see Log4jWebConfigurer
* @see Log4jConfigListener
* @see org.springframework.web.context.ContextLoaderServlet
*/
public class Log4jConfigServlet extends HttpServlet {
@Override
public void init() {
Log4jWebConfigurer.initLogging(getServletContext());
}
@Override
public void destroy() {
Log4jWebConfigurer.shutdownLogging(getServletContext());
}
/**
* This should never even be called since no mapping to this servlet should
* ever be created in web.xml. That's why a correctly invoked Servlet 2.3
* listener is much more appropriate for initialization work ;-)
*/
@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
getServletContext().log(
"Attempt to call service method on Log4jConfigServlet as [" +
request.getRequestURI() + "] was ignored");
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
}
@Override
public String getServletInfo() {
return "Log4jConfigServlet for Servlet API 2.3 " +
"(deprecated in favor of Log4jConfigListener for Servlet API 2.4)";
}
}

View File

@@ -93,7 +93,6 @@ import org.springframework.util.SystemPropertyUtils;
* @since 12.08.2003
* @see org.springframework.util.Log4jConfigurer
* @see Log4jConfigListener
* @see Log4jConfigServlet
*/
public abstract class Log4jWebConfigurer {

View File

@@ -41,28 +41,6 @@ import org.springframework.util.StringUtils;
*/
public class UrlPathHelper {
/**
* @deprecated as of Spring 2.0, in favor of <code>WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE</code>
* @see org.springframework.web.util.WebUtils#INCLUDE_REQUEST_URI_ATTRIBUTE
*/
@Deprecated
public static final String INCLUDE_URI_REQUEST_ATTRIBUTE = WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE;
/**
* @deprecated as of Spring 2.0, in favor of <code>WebUtils.INCLUDE_CONTEXT_PATH_ATTRIBUTE</code>
* @see org.springframework.web.util.WebUtils#INCLUDE_CONTEXT_PATH_ATTRIBUTE
*/
@Deprecated
public static final String INCLUDE_CONTEXT_PATH_REQUEST_ATTRIBUTE = WebUtils.INCLUDE_CONTEXT_PATH_ATTRIBUTE;
/**
* @deprecated as of Spring 2.0, in favor of <code>WebUtils.INCLUDE_SERVLET_PATH_ATTRIBUTE</code>
* @see org.springframework.web.util.WebUtils#INCLUDE_SERVLET_PATH_ATTRIBUTE
*/
@Deprecated
public static final String INCLUDE_SERVLET_PATH_REQUEST_ATTRIBUTE = WebUtils.INCLUDE_SERVLET_PATH_ATTRIBUTE;
private final Log logger = LogFactory.getLog(getClass());
private boolean alwaysUseFullPath = false;