aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Archer2011-10-19 16:48:26 (EDT)
committerThomas Watson2011-10-19 16:48:26 (EDT)
commit6513742455b898f264df5cb4e3355623eeb9ebaa (patch)
tree6fa17d23863515c415f98e9d80af60e1e0b2c3ce
parent61b96b6e8095d80eab1707f38d6f4be9ec8d5023 (diff)
downloadrt.equinox.bundles-6513742455b898f264df5cb4e3355623eeb9ebaa.zip
rt.equinox.bundles-6513742455b898f264df5cb4e3355623eeb9ebaa.tar.gz
rt.equinox.bundles-6513742455b898f264df5cb4e3355623eeb9ebaa.tar.bz2
bug 341643 - Initial changes.
-rw-r--r--bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/MethodAdvisor.java124
-rw-r--r--bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ProxyServlet.java15
-rw-r--r--bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ServletContextAdaptor.java11
-rw-r--r--bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ServletContextProxyFactory.java54
4 files changed, 196 insertions, 8 deletions
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/MethodAdvisor.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/MethodAdvisor.java
new file mode 100644
index 0000000..f29df9e
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/MethodAdvisor.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 2011, IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.equinox.http.servlet.internal;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashSet;
+import java.util.Set;
+
+class MethodAdvisor extends Object {
+ private final Class subject;
+ private final Set methodsCache;
+ private final boolean methodCacheEnabled;
+
+ // Property to turn off method caching.
+ private static final String DISABLE_METHOD_CACHE = "org.eclipse.equinox.http.servlet.internal.disable.method.cache"; //$NON-NLS-1$
+
+ private static boolean isMethodCacheEnabled() {
+ return Boolean.getBoolean(MethodAdvisor.DISABLE_METHOD_CACHE) == false;
+ }
+
+ MethodAdvisor(Class subject) {
+ super();
+ if (subject == null)
+ throw new IllegalArgumentException("subject must not be null"); //$NON-NLS-1$
+ if (subject.isInterface())
+ throw new IllegalArgumentException("subject must not be an interface"); //$NON-NLS-1$
+ this.subject = subject;
+ this.methodsCache = new HashSet(17);
+ this.methodCacheEnabled = MethodAdvisor.isMethodCacheEnabled();
+ }
+
+ private boolean equals(Method left, Method right) {
+ boolean match;
+ match = hasEqualMethodNames(left, right);
+ if (match == false)
+ return false;
+ match = hasEqualReturnTypes(left, right);
+ if (match == false)
+ return false;
+ match = hasEqualParameterTypes(left, right);
+ if (match == false)
+ return false;
+ return true;
+ }
+
+ private boolean hasEqualMethodNames(Method left, Method right) {
+ String leftName = left.getName();
+ String rightName = right.getName();
+ boolean equal = leftName.equals(rightName);
+ return equal;
+ }
+
+ private boolean hasEqualParameterTypes(Method left, Method right) {
+ Class[] leftParameterTypes = left.getParameterTypes();
+ Class[] rightMethodParameterTypes = right.getParameterTypes();
+ boolean equal = leftParameterTypes.length == rightMethodParameterTypes.length;
+ int i = 0;
+ int count = leftParameterTypes.length - 1;
+ while (equal && i <= count) {
+ Class leftClass = leftParameterTypes[i];
+ Class rightClass = rightMethodParameterTypes[i];
+ equal = leftClass.equals(rightClass);
+ i++;
+ }
+ return equal;
+ }
+
+ private boolean hasEqualReturnTypes(Method left, Method right) {
+ Class leftClass = left.getReturnType();
+ Class rightClass = right.getReturnType();
+ boolean equal = leftClass.equals(rightClass);
+ return equal;
+ }
+
+ private boolean hasValidModifiers(Method declaredMethod) {
+ int modifiers = declaredMethod.getModifiers();
+ boolean valid;
+ valid = Modifier.isPublic(modifiers);
+ if (valid == false)
+ return false;
+ valid = Modifier.isAbstract(modifiers) == false;
+ if (valid == false)
+ return false;
+ return true;
+ }
+
+ private boolean isImplemented(Class clazz, Method method) {
+ if (clazz == null)
+ return false;
+ Method[] declaredMethods = clazz.getDeclaredMethods();
+ for (int i = 0; i < declaredMethods.length; i++) {
+ Method declaredMethod = declaredMethods[i];
+ boolean valid = hasValidModifiers(declaredMethod);
+ if (valid == false)
+ continue;
+ boolean match = equals(method, declaredMethod);
+ if (match == false)
+ continue;
+ methodsCache.add(method);
+ return true; // Implemented and added to cache.
+ }
+ Class parent = clazz.getSuperclass();
+ return isImplemented(parent, method);
+ }
+
+ boolean isImplemented(Method method) {
+ if (method == null)
+ throw new IllegalArgumentException("method must not be null"); //$NON-NLS-1$
+ synchronized (methodsCache) {
+ if (methodCacheEnabled) {
+ boolean exists = methodsCache.contains(method);
+ if (exists)
+ return true; // Implemented and exists in cache.
+ }
+ return isImplemented(subject, method);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ProxyServlet.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ProxyServlet.java
index 73235cd..933c6cb 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ProxyServlet.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ProxyServlet.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2010 Cognos Incorporated, IBM Corporation and others.
+ * Copyright (c) 2005, 2011 Cognos Incorporated, IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -170,8 +170,8 @@ public class ProxyServlet extends HttpServlet {
throw new ServletException("This servlet has already been registered."); //$NON-NLS-1$
ServletRegistration registration = new ServletRegistration(servlet, httpContext);
- ServletContext wrappedServletContext = new ServletContextAdaptor(proxyContext, getServletContext(), httpContext, AccessController.getContext());
- ServletConfig servletConfig = new ServletConfigImpl(servlet, initparams, wrappedServletContext);
+ ServletContext servletContextProxy = createServletContextProxy(httpContext);
+ ServletConfig servletConfig = new ServletConfigImpl(servlet, initparams, servletContextProxy);
boolean initialized = false;
proxyContext.createContextAttributes(httpContext);
@@ -235,8 +235,8 @@ public class ProxyServlet extends HttpServlet {
int filterPriority = findFilterPriority(initparams);
FilterRegistration registration = new FilterRegistration(filter, httpContext, alias, filterPriority);
- ServletContext wrappedServletContext = new ServletContextAdaptor(proxyContext, getServletContext(), httpContext, AccessController.getContext());
- FilterConfig filterConfig = new FilterConfigImpl(filter, initparams, wrappedServletContext);
+ ServletContext servletContextProxy = createServletContextProxy(httpContext);
+ FilterConfig filterConfig = new FilterConfigImpl(filter, initparams, servletContextProxy);
boolean initialized = false;
proxyContext.createContextAttributes(httpContext);
@@ -250,6 +250,11 @@ public class ProxyServlet extends HttpServlet {
filterRegistrations.put(filter, registration);
}
+ private ServletContext createServletContextProxy(HttpContext httpContext) {
+ ServletContextAdaptor adapter = new ServletContextAdaptor(proxyContext, getServletContext(), httpContext, AccessController.getContext());
+ return ServletContextProxyFactory.create(adapter);
+ }
+
private int findFilterPriority(Dictionary initparams) {
if (initparams == null)
return 0;
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ServletContextAdaptor.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ServletContextAdaptor.java
index ffdfa83..dac1650 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ServletContextAdaptor.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ServletContextAdaptor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2007 Cognos Incorporated, IBM Corporation and others.
+ * Copyright (c) 2005, 2011 Cognos Incorporated, IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,7 +11,8 @@
*******************************************************************************/
package org.eclipse.equinox.http.servlet.internal;
-import java.io.*;
+import java.io.IOException;
+import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.security.*;
@@ -26,7 +27,7 @@ public class ServletContextAdaptor implements ServletContext {
private AccessControlContext acc;
private ProxyContext proxyContext;
- public ServletContextAdaptor(ProxyContext proxyContext, ServletContext servletContext, HttpContext httpContext, AccessControlContext acc) {
+ ServletContextAdaptor(ProxyContext proxyContext, ServletContext servletContext, HttpContext httpContext, AccessControlContext acc) {
this.servletContext = servletContext;
this.httpContext = httpContext;
this.acc = acc;
@@ -183,4 +184,8 @@ public class ServletContextAdaptor implements ServletContext {
}
return null;
}
+
+ Object getSubject() {
+ return servletContext;
+ }
}
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ServletContextProxyFactory.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ServletContextProxyFactory.java
new file mode 100644
index 0000000..8a771ab
--- /dev/null
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ServletContextProxyFactory.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2011, IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.equinox.http.servlet.internal;
+
+import java.lang.reflect.*;
+import javax.servlet.ServletContext;
+
+class ServletContextProxyFactory extends Object {
+ private static final String PROXY_METHOD_TRACING_PROPERTY = "org.eclipse.equinox.http.servlet.internal.proxy.method.tracing"; //$NON-NLS-1$
+ private static final boolean PROXY_METHOD_TRACING = Boolean.getBoolean(ServletContextProxyFactory.PROXY_METHOD_TRACING_PROPERTY);
+
+ private MethodAdvisor methodAdvisor;
+
+ static ServletContext create(ServletContextAdaptor adapter) {
+ ServletContextProxyFactory factory = new ServletContextProxyFactory();
+ return factory.createServletContext(adapter);
+ }
+
+ private ServletContextProxyFactory() {
+ super();
+ this.methodAdvisor = new MethodAdvisor(ServletContextAdaptor.class);
+ }
+
+ private ServletContext createServletContext(ServletContextAdaptor adapter) {
+ if (adapter == null)
+ throw new IllegalArgumentException("adapter must not be null"); //$NON-NLS-1$
+ ClassLoader loader = ServletContextAdaptor.class.getClassLoader();
+ InvocationHandler handler = createServletContextInvocationHandler(adapter);
+ Class[] interfaces = new Class[] {ServletContext.class};
+ return (ServletContext) Proxy.newProxyInstance(loader, interfaces, handler);
+ }
+
+ private InvocationHandler createServletContextInvocationHandler(final ServletContextAdaptor adapter) {
+ return new InvocationHandler() {
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ return ServletContextProxyFactory.this.invoke(adapter, proxy, method, args);
+ }
+ };
+ }
+
+ private Object invoke(ServletContextAdaptor adapter, Object proxy, Method method, Object[] args) throws Throwable {
+ if (ServletContextProxyFactory.PROXY_METHOD_TRACING) {
+ System.out.println("TRACE-invoking: " + method.getName()); //$NON-NLS-1$
+ }
+ boolean match = methodAdvisor.isImplemented(method);
+ Object object = match ? adapter : adapter.getSubject();
+ return method.invoke(object, args);
+ }
+}