Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Auge2016-07-07 02:31:02 +0000
committerThomas Watson2016-08-18 18:24:31 +0000
commit6bfd9bef40482dd0e0766758bbdd1f29e562b99e (patch)
treec20f10ca1c72a572787214c735dd8e9967749840
parent51197e523ee8f565d365d81e056001e989d9cfe2 (diff)
downloadrt.equinox.bundles-6bfd9bef40482dd0e0766758bbdd1f29e562b99e.tar.gz
rt.equinox.bundles-6bfd9bef40482dd0e0766758bbdd1f29e562b99e.tar.xz
rt.equinox.bundles-6bfd9bef40482dd0e0766758bbdd1f29e562b99e.zip
Bug 497435 - [http servlet] performance optimizations, CPU and memoryY20160825-1000I20160824-1429I20160823-1359I20160823-0759
https://issues.liferay.com/browse/LPS-66801 https://issues.liferay.com/browse/LPS-66813 https://issues.liferay.com/browse/LPS-66827 https://issues.liferay.com/browse/LPS-66847 https://issues.liferay.com/browse/LPS-66881 https://issues.liferay.com/browse/LPS-66903 https://issues.liferay.com/browse/LPS-66904 https://issues.liferay.com/browse/LPS-66908 https://issues.liferay.com/browse/LPS-66911 https://issues.liferay.com/browse/LPS-66959 Change-Id: I0374bfa5d566c2f01d34af57a64fd982b92ba4b8 Signed-off-by: shuyangzhou <shuyang.zhou@liferay.com> Signed-off-by: Matthew Tambara <matthew.tambara@liferay.com> Signed-off-by: Raymond Auge <raymond.auge@liferay.com> Signed-off-by: Thomas Watson <tjwatson@us.ibm.com>
-rw-r--r--bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/ContextController.java75
-rw-r--r--bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/DispatchTargets.java14
-rw-r--r--bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/EndpointRegistration.java14
-rw-r--r--bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/Registration.java77
-rw-r--r--bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpServletRequestWrapperImpl.java152
-rw-r--r--bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpSessionAdaptor.java75
-rw-r--r--bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/RequestDispatcherAdaptor.java4
-rw-r--r--bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/ServletContextAdaptor.java20
8 files changed, 276 insertions, 155 deletions
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/ContextController.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/ContextController.java
index 9af775c60..2a15d8a4a 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/ContextController.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/ContextController.java
@@ -15,6 +15,8 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.security.AccessController;
import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Pattern;
@@ -142,7 +144,7 @@ public class ContextController {
this.trackingContext = trackingContextParam;
this.consumingContext = consumingContext;
- this.string = getClass().getSimpleName() + '[' + serviceId + "][" + contextName + ", " + consumingContext.getBundle() + ']'; //$NON-NLS-1$
+ this.string = SIMPLE_NAME + '[' + serviceId + "][" + contextName + ", " + trackingContextParam.getBundle() + ']'; //$NON-NLS-1$
listenerServiceTracker = new ServiceTracker<EventListener, AtomicReference<ListenerRegistration>>(
trackingContext, httpServiceRuntime.getListenerFilter(),
@@ -1180,20 +1182,22 @@ public class ContextController {
}
private void flushActiveSessions() {
- Collection<HttpSessionAdaptor> currentActiveSessions;
- synchronized (activeSessions) {
- currentActiveSessions = new ArrayList<HttpSessionAdaptor>(activeSessions.values());
- activeSessions.clear();
- }
- for (HttpSessionAdaptor httpSessionAdaptor : currentActiveSessions) {
+ Collection<HttpSessionAdaptor> httpSessionAdaptors =
+ activeSessions.values();
+
+ Iterator<HttpSessionAdaptor> iterator = httpSessionAdaptors.iterator();
+
+ while (iterator.hasNext()) {
+ HttpSessionAdaptor httpSessionAdaptor = iterator.next();
+
httpSessionAdaptor.invalidate();
+
+ iterator.remove();
}
}
public void removeActiveSession(HttpSession session) {
- synchronized (activeSessions) {
- activeSessions.remove(session);
- }
+ activeSessions.remove(session.getId());
}
public void fireSessionIdChanged(String oldSessionId) {
@@ -1208,11 +1212,7 @@ public class ContextController {
return;
}
- Collection<HttpSessionAdaptor> currentActiveSessions;
- synchronized (activeSessions) {
- currentActiveSessions = new ArrayList<HttpSessionAdaptor>(activeSessions.values());
- }
- for (HttpSessionAdaptor httpSessionAdaptor : currentActiveSessions) {
+ for (HttpSessionAdaptor httpSessionAdaptor : activeSessions.values()) {
HttpSessionEvent httpSessionEvent = new HttpSessionEvent(httpSessionAdaptor);
for (javax.servlet.http.HttpSessionIdListener listener : listeners) {
listener.sessionIdChanged(httpSessionEvent, oldSessionId);
@@ -1222,22 +1222,35 @@ public class ContextController {
public HttpSessionAdaptor getSessionAdaptor(
HttpSession session, ServletContext servletContext) {
- boolean created = false;
- HttpSessionAdaptor sessionAdaptor;
- synchronized (activeSessions) {
- sessionAdaptor = activeSessions.get(session);
- if (sessionAdaptor == null) {
- created = true;
- sessionAdaptor = HttpSessionAdaptor.createHttpSessionAdaptor(session, servletContext, this);
- activeSessions.put(session, sessionAdaptor);
- }
+
+ String sessionId = session.getId();
+
+ HttpSessionAdaptor httpSessionAdaptor = activeSessions.get(sessionId);
+
+ if (httpSessionAdaptor != null) {
+ return httpSessionAdaptor;
}
- if (created) {
- for (HttpSessionListener listener : eventListeners.get(HttpSessionListener.class)) {
- listener.sessionCreated(new HttpSessionEvent(sessionAdaptor));
- }
+
+ httpSessionAdaptor = HttpSessionAdaptor.createHttpSessionAdaptor(
+ session, servletContext, this);
+
+ HttpSessionAdaptor previousHttpSessionAdaptor =
+ activeSessions.putIfAbsent(sessionId, httpSessionAdaptor);
+
+ if (previousHttpSessionAdaptor != null) {
+ return previousHttpSessionAdaptor;
+ }
+
+ HttpSessionEvent httpSessionEvent = new HttpSessionEvent(
+ httpSessionAdaptor);
+
+ for (HttpSessionListener listener : eventListeners.get(
+ HttpSessionListener.class)) {
+
+ listener.sessionCreated(httpSessionEvent);
}
- return sessionAdaptor;
+
+ return httpSessionAdaptor;
}
private void validate(String preValidationContextName, String preValidationContextPath) {
@@ -1261,6 +1274,8 @@ public class ContextController {
private static final String[] DISPATCHER =
new String[] {DispatcherType.REQUEST.toString()};
+ private static final String SIMPLE_NAME = ContextController.class.getSimpleName();
+
private static final Pattern contextNamePattern = Pattern.compile("^([a-zA-Z_0-9\\-]+\\.)*[a-zA-Z_0-9\\-]+$"); //$NON-NLS-1$
private final Map<String, String> initParams;
@@ -1272,7 +1287,7 @@ public class ContextController {
private final Set<EndpointRegistration<?>> endpointRegistrations = new ConcurrentSkipListSet<EndpointRegistration<?>>();
private final EventListeners eventListeners = new EventListeners();
private final Set<FilterRegistration> filterRegistrations = new ConcurrentSkipListSet<FilterRegistration>();
- private final Map<HttpSession, HttpSessionAdaptor> activeSessions = new HashMap<HttpSession, HttpSessionAdaptor>();
+ private final ConcurrentMap<String, HttpSessionAdaptor> activeSessions = new ConcurrentHashMap<String, HttpSessionAdaptor>();
private final HttpServiceRuntimeImpl httpServiceRuntime;
private final Set<ListenerRegistration> listenerRegistrations = new HashSet<ListenerRegistration>();
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/DispatchTargets.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/DispatchTargets.java
index 903166f77..6e30ca04a 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/DispatchTargets.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/DispatchTargets.java
@@ -54,8 +54,6 @@ public class DispatchTargets {
this.servletPath = (servletPath == null) ? Const.BLANK : servletPath;
this.pathInfo = pathInfo;
this.queryString = queryString;
-
- this.string = SIMPLE_NAME + '[' + contextController.getFullContextPath() + requestURI + (queryString != null ? '?' + queryString : "") + ", " + endpointRegistration.toString() + ']'; //$NON-NLS-1$ //$NON-NLS-2$
}
public void addRequestParameters(HttpServletRequest request) {
@@ -197,7 +195,15 @@ public class DispatchTargets {
@Override
public String toString() {
- return string;
+ String value = string;
+
+ if (value == null) {
+ value = SIMPLE_NAME + '[' + contextController.getFullContextPath() + requestURI + (queryString != null ? '?' + queryString : "") + ", " + endpointRegistration.toString() + ']'; //$NON-NLS-1$
+
+ string = value;
+ }
+
+ return value;
}
private static Map<String, String[]> queryStringToParameterMap(String queryString) {
@@ -266,6 +272,6 @@ public class DispatchTargets {
private final String servletPath;
private final String servletName;
private final Map<String, Object> specialOverides = new ConcurrentHashMap<String, Object>();
- private final String string;
+ private String string;
} \ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/EndpointRegistration.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/EndpointRegistration.java
index 067a04fc8..2c8e87d80 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/EndpointRegistration.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/EndpointRegistration.java
@@ -168,7 +168,19 @@ public abstract class EndpointRegistration<D extends DTO>
@Override
public String toString() {
- return getClass().getSimpleName() + '[' + getD().toString() + ']';
+ String toString = _toString;
+
+ if (toString == null) {
+ toString = SIMPLE_NAME + '[' + getD().toString() + ']';
+
+ _toString = toString;
+ }
+
+ return toString;
}
+ private static final String SIMPLE_NAME =
+ EndpointRegistration.class.getSimpleName();
+
+ private String _toString;
}
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/Registration.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/Registration.java
index 0df5d73a0..4e3e612f8 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/Registration.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/Registration.java
@@ -12,6 +12,11 @@
*******************************************************************************/
package org.eclipse.equinox.http.servlet.internal.registration;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.osgi.dto.DTO;
public abstract class Registration<T, D extends DTO> {
@@ -19,42 +24,82 @@ public abstract class Registration<T, D extends DTO> {
private final D d;
private final T t;
- protected int referenceCount;
+ protected final AtomicInteger referenceCount = new AtomicInteger();
public Registration(T t, D d) {
this.t = t;
this.d = d;
}
- public synchronized void addReference() {
- ++referenceCount;
+ public void addReference() {
+ readLock.lock();
+
+ try {
+ referenceCount.incrementAndGet();
+ }
+ finally {
+ readLock.unlock();
+ }
}
- public synchronized void removeReference() {
- --referenceCount;
- if (referenceCount == 0) {
- notifyAll();
+ public void removeReference() {
+ readLock.lock();
+
+ try {
+ if (referenceCount.decrementAndGet() == 0 && destroyed) {
+ readLock.unlock();
+
+ writeLock.lock();
+
+ try {
+ condition.signalAll();
+ }
+ finally {
+ writeLock.unlock();
+
+ readLock.lock();
+ }
+ }
+ }
+ finally {
+ readLock.unlock();
}
}
- public synchronized void destroy() {
+ public void destroy() {
boolean interrupted = false;
+
+ writeLock.lock();
+
+ destroyed = true;
+
try {
- while (referenceCount != 0) {
+ while (referenceCount.get() != 0) {
try {
- (new Exception()).printStackTrace();
- wait();
- } catch (InterruptedException e) {
- // wait until the servlet is inactive but save the interrupted status
+ condition.await();
+ }
+ catch (InterruptedException ie) {
interrupted = true;
}
}
- } finally {
- if (interrupted)
- Thread.currentThread().interrupt(); //restore the interrupted state
+ }
+ finally {
+ writeLock.unlock();
+
+ if (interrupted) {
+ Thread.currentThread().interrupt();
+ }
}
}
+ private volatile boolean destroyed;
+
+ private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
+
+ private final Lock readLock = readWriteLock.readLock();
+ private final Lock writeLock = readWriteLock.writeLock();
+ private final Condition condition = writeLock.newCondition();
+
public D getD() {
return d;
}
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpServletRequestWrapperImpl.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpServletRequestWrapperImpl.java
index 30f03be2e..6472681f1 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpServletRequestWrapperImpl.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpServletRequestWrapperImpl.java
@@ -32,24 +32,26 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {
private Map<String, Part> parts;
private final Lock lock = new ReentrantLock();
- private static final String[] dispatcherAttributes = new String[] {
- RequestDispatcher.ERROR_EXCEPTION,
- RequestDispatcher.ERROR_EXCEPTION_TYPE,
- RequestDispatcher.ERROR_MESSAGE,
- RequestDispatcher.ERROR_REQUEST_URI,
- RequestDispatcher.ERROR_SERVLET_NAME,
- RequestDispatcher.ERROR_STATUS_CODE,
- RequestDispatcher.FORWARD_CONTEXT_PATH,
- RequestDispatcher.FORWARD_PATH_INFO,
- RequestDispatcher.FORWARD_QUERY_STRING,
- RequestDispatcher.FORWARD_REQUEST_URI,
- RequestDispatcher.FORWARD_SERVLET_PATH,
- RequestDispatcher.INCLUDE_CONTEXT_PATH,
- RequestDispatcher.INCLUDE_PATH_INFO,
- RequestDispatcher.INCLUDE_QUERY_STRING,
- RequestDispatcher.INCLUDE_REQUEST_URI,
- RequestDispatcher.INCLUDE_SERVLET_PATH
- };
+ private static final Set<String> dispatcherAttributes = new HashSet<String>();
+
+ static {
+ dispatcherAttributes.add(RequestDispatcher.ERROR_EXCEPTION);
+ dispatcherAttributes.add(RequestDispatcher.ERROR_EXCEPTION_TYPE);
+ dispatcherAttributes.add(RequestDispatcher.ERROR_MESSAGE);
+ dispatcherAttributes.add(RequestDispatcher.ERROR_REQUEST_URI);
+ dispatcherAttributes.add(RequestDispatcher.ERROR_SERVLET_NAME);
+ dispatcherAttributes.add(RequestDispatcher.ERROR_STATUS_CODE);
+ dispatcherAttributes.add(RequestDispatcher.FORWARD_CONTEXT_PATH);
+ dispatcherAttributes.add(RequestDispatcher.FORWARD_PATH_INFO);
+ dispatcherAttributes.add(RequestDispatcher.FORWARD_QUERY_STRING);
+ dispatcherAttributes.add(RequestDispatcher.FORWARD_REQUEST_URI);
+ dispatcherAttributes.add(RequestDispatcher.FORWARD_SERVLET_PATH);
+ dispatcherAttributes.add(RequestDispatcher.INCLUDE_CONTEXT_PATH);
+ dispatcherAttributes.add(RequestDispatcher.INCLUDE_PATH_INFO);
+ dispatcherAttributes.add(RequestDispatcher.INCLUDE_QUERY_STRING);
+ dispatcherAttributes.add(RequestDispatcher.INCLUDE_REQUEST_URI);
+ dispatcherAttributes.add(RequestDispatcher.INCLUDE_SERVLET_PATH);
+ }
public static HttpServletRequestWrapperImpl findHttpRuntimeRequest(
HttpServletRequest request) {
@@ -87,11 +89,13 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {
}
public String getPathInfo() {
- if ((dispatchTargets.peek().getServletName() != null) ||
- (dispatchTargets.peek().getDispatcherType() == DispatcherType.INCLUDE)) {
+ DispatchTargets currentDispatchTargets = dispatchTargets.peek();
+
+ if ((currentDispatchTargets.getServletName() != null) ||
+ (currentDispatchTargets.getDispatcherType() == DispatcherType.INCLUDE)) {
return this.dispatchTargets.get(0).getPathInfo();
}
- return this.dispatchTargets.peek().getPathInfo();
+ return currentDispatchTargets.getPathInfo();
}
public DispatcherType getDispatcherType() {
@@ -120,20 +124,24 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {
@Override
public String getQueryString() {
- if ((dispatchTargets.peek().getServletName() != null) ||
- (dispatchTargets.peek().getDispatcherType() == DispatcherType.INCLUDE)) {
+ DispatchTargets currentDispatchTargets = dispatchTargets.peek();
+
+ if ((currentDispatchTargets.getServletName() != null) ||
+ (currentDispatchTargets.getDispatcherType() == DispatcherType.INCLUDE)) {
return request.getQueryString();
}
- return this.dispatchTargets.peek().getQueryString();
+ return currentDispatchTargets.getQueryString();
}
@Override
public String getRequestURI() {
- if ((dispatchTargets.peek().getServletName() != null) ||
- (dispatchTargets.peek().getDispatcherType() == DispatcherType.INCLUDE)) {
+ DispatchTargets currentDispatchTargets = dispatchTargets.peek();
+
+ if ((currentDispatchTargets.getServletName() != null) ||
+ (currentDispatchTargets.getDispatcherType() == DispatcherType.INCLUDE)) {
return request.getRequestURI();
}
- return this.dispatchTargets.peek().getRequestURI();
+ return currentDispatchTargets.getRequestURI();
}
public ServletContext getServletContext() {
@@ -141,14 +149,16 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {
}
public String getServletPath() {
- if ((dispatchTargets.peek().getServletName() != null) ||
- (dispatchTargets.peek().getDispatcherType() == DispatcherType.INCLUDE)) {
+ DispatchTargets currentDispatchTargets = dispatchTargets.peek();
+
+ if ((currentDispatchTargets.getServletName() != null) ||
+ (currentDispatchTargets.getDispatcherType() == DispatcherType.INCLUDE)) {
return this.dispatchTargets.get(0).getServletPath();
}
- if (dispatchTargets.peek().getServletPath().equals(Const.SLASH)) {
+ if (currentDispatchTargets.getServletPath().equals(Const.SLASH)) {
return Const.BLANK;
}
- return this.dispatchTargets.peek().getServletPath();
+ return currentDispatchTargets.getServletPath();
}
public String getContextPath() {
@@ -157,19 +167,20 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {
public Object getAttribute(String attributeName) {
DispatchTargets current = dispatchTargets.peek();
-
+ DispatcherType dispatcherType = current.getDispatcherType();
+ boolean hasServletName = (current.getServletName() != null);
Map<String, Object> specialOverides = current.getSpecialOverides();
- if (current.getDispatcherType() == DispatcherType.ERROR) {
- if ((Arrays.binarySearch(dispatcherAttributes, attributeName) > -1) &&
+ if (dispatcherType == DispatcherType.ERROR) {
+ if (dispatcherAttributes.contains(attributeName) &&
!attributeName.startsWith("javax.servlet.error.")) { //$NON-NLS-1$
return null;
}
}
- else if (current.getDispatcherType() == DispatcherType.INCLUDE) {
+ else if (dispatcherType == DispatcherType.INCLUDE) {
if (attributeName.equals(RequestDispatcher.INCLUDE_CONTEXT_PATH)) {
- if (current.getServletName() != null) {
+ if (hasServletName) {
return null;
}
if (specialOverides.containsKey(RequestDispatcher.INCLUDE_CONTEXT_PATH)) {
@@ -178,7 +189,7 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {
return current.getContextController().getContextPath();
}
else if (attributeName.equals(RequestDispatcher.INCLUDE_PATH_INFO)) {
- if (current.getServletName() != null) {
+ if (hasServletName) {
return null;
}
if (specialOverides.containsKey(RequestDispatcher.INCLUDE_PATH_INFO)) {
@@ -187,7 +198,7 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {
return current.getPathInfo();
}
else if (attributeName.equals(RequestDispatcher.INCLUDE_QUERY_STRING)) {
- if (current.getServletName() != null) {
+ if (hasServletName) {
return null;
}
if (specialOverides.containsKey(RequestDispatcher.INCLUDE_QUERY_STRING)) {
@@ -196,7 +207,7 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {
return current.getQueryString();
}
else if (attributeName.equals(RequestDispatcher.INCLUDE_REQUEST_URI)) {
- if (current.getServletName() != null) {
+ if (hasServletName) {
return null;
}
if (specialOverides.containsKey(RequestDispatcher.INCLUDE_REQUEST_URI)) {
@@ -205,7 +216,7 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {
return current.getRequestURI();
}
else if (attributeName.equals(RequestDispatcher.INCLUDE_SERVLET_PATH)) {
- if (current.getServletName() != null) {
+ if (hasServletName) {
return null;
}
if (specialOverides.containsKey(RequestDispatcher.INCLUDE_SERVLET_PATH)) {
@@ -214,60 +225,49 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {
return current.getServletPath();
}
- if (Arrays.binarySearch(dispatcherAttributes, attributeName) > -1) {
+ if (dispatcherAttributes.contains(attributeName)) {
return null;
}
}
- else if (current.getDispatcherType() == DispatcherType.FORWARD) {
+ else if (dispatcherType == DispatcherType.FORWARD) {
+ if (hasServletName && attributeName.startsWith("javax.servlet.forward")) {
+ return null;
+ }
+
DispatchTargets original = dispatchTargets.get(0);
if (attributeName.equals(RequestDispatcher.FORWARD_CONTEXT_PATH)) {
- if (current.getServletName() != null) {
- return null;
- }
if (specialOverides.containsKey(RequestDispatcher.FORWARD_CONTEXT_PATH)) {
return specialOverides.get(RequestDispatcher.FORWARD_CONTEXT_PATH);
}
return original.getContextController().getContextPath();
}
else if (attributeName.equals(RequestDispatcher.FORWARD_PATH_INFO)) {
- if (current.getServletName() != null) {
- return null;
- }
if (specialOverides.containsKey(RequestDispatcher.FORWARD_PATH_INFO)) {
return specialOverides.get(RequestDispatcher.FORWARD_PATH_INFO);
}
return original.getPathInfo();
}
else if (attributeName.equals(RequestDispatcher.FORWARD_QUERY_STRING)) {
- if (current.getServletName() != null) {
- return null;
- }
if (specialOverides.containsKey(RequestDispatcher.FORWARD_QUERY_STRING)) {
return specialOverides.get(RequestDispatcher.FORWARD_QUERY_STRING);
}
return original.getQueryString();
}
else if (attributeName.equals(RequestDispatcher.FORWARD_REQUEST_URI)) {
- if (current.getServletName() != null) {
- return null;
- }
if (specialOverides.containsKey(RequestDispatcher.FORWARD_REQUEST_URI)) {
return specialOverides.get(RequestDispatcher.FORWARD_REQUEST_URI);
}
return original.getRequestURI();
}
else if (attributeName.equals(RequestDispatcher.FORWARD_SERVLET_PATH)) {
- if (current.getServletName() != null) {
- return null;
- }
if (specialOverides.containsKey(RequestDispatcher.FORWARD_SERVLET_PATH)) {
return specialOverides.get(RequestDispatcher.FORWARD_SERVLET_PATH);
}
return original.getServletPath();
}
- if (Arrays.binarySearch(dispatcherAttributes, attributeName) > -1) {
+ if (dispatcherAttributes.contains(attributeName)) {
return null;
}
}
@@ -276,12 +276,14 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {
}
public RequestDispatcher getRequestDispatcher(String path) {
+ DispatchTargets currentDispatchTarget = dispatchTargets.peek();
+
ContextController contextController =
- this.dispatchTargets.peek().getContextController();
+ currentDispatchTarget.getContextController();
// support relative paths
if (!path.startsWith(Const.SLASH)) {
- path = this.dispatchTargets.peek().getServletPath() + Const.SLASH + path;
+ path = currentDispatchTarget.getServletPath() + Const.SLASH + path;
}
// if the path starts with the full context path strip it
else if (path.startsWith(contextController.getFullContextPath())) {
@@ -305,20 +307,16 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {
}
public HttpSession getSession() {
- HttpSession session = request.getSession();
- if (session != null) {
- return dispatchTargets.peek().getContextController().getSessionAdaptor(
- session, dispatchTargets.peek().getServletRegistration().getT().getServletConfig().getServletContext());
- }
-
- return null;
+ return getSession(true);
}
public HttpSession getSession(boolean create) {
HttpSession session = request.getSession(create);
if (session != null) {
- return dispatchTargets.peek().getContextController().getSessionAdaptor(
- session, dispatchTargets.peek().getServletRegistration().getT().getServletConfig().getServletContext());
+ DispatchTargets currentDispatchTarget = dispatchTargets.peek();
+
+ return currentDispatchTarget.getContextController().getSessionAdaptor(
+ session, currentDispatchTarget.getServletRegistration().getT().getServletConfig().getServletContext());
}
return null;
@@ -336,7 +334,7 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {
}
public void removeAttribute(String name) {
- if (Arrays.binarySearch(dispatcherAttributes, name) > -1) {
+ if (dispatcherAttributes.contains(name)) {
DispatchTargets current = dispatchTargets.peek();
current.getSpecialOverides().remove(name);
@@ -345,7 +343,9 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {
request.removeAttribute(name);
}
- EventListeners eventListeners = dispatchTargets.peek().getContextController().getEventListeners();
+ DispatchTargets currentDispatchTarget = dispatchTargets.peek();
+
+ EventListeners eventListeners = currentDispatchTarget.getContextController().getEventListeners();
List<ServletRequestAttributeListener> listeners = eventListeners.get(
ServletRequestAttributeListener.class);
@@ -356,7 +356,7 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {
ServletRequestAttributeEvent servletRequestAttributeEvent =
new ServletRequestAttributeEvent(
- dispatchTargets.peek().getServletRegistration().getServletContext(), this, name, null);
+ currentDispatchTarget.getServletRegistration().getServletContext(), this, name, null);
for (ServletRequestAttributeListener servletRequestAttributeListener : listeners) {
servletRequestAttributeListener.attributeRemoved(
@@ -367,7 +367,7 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {
public void setAttribute(String name, Object value) {
boolean added = (request.getAttribute(name) == null);
- if (Arrays.binarySearch(dispatcherAttributes, name) > -1) {
+ if (dispatcherAttributes.contains(name)) {
DispatchTargets current = dispatchTargets.peek();
if (value == null) {
@@ -381,7 +381,9 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {
request.setAttribute(name, value);
}
- EventListeners eventListeners = dispatchTargets.peek().getContextController().getEventListeners();
+ DispatchTargets currentDispatchTarget = dispatchTargets.peek();
+
+ EventListeners eventListeners = currentDispatchTarget.getContextController().getEventListeners();
List<ServletRequestAttributeListener> listeners = eventListeners.get(
ServletRequestAttributeListener.class);
@@ -392,7 +394,7 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {
ServletRequestAttributeEvent servletRequestAttributeEvent =
new ServletRequestAttributeEvent(
- dispatchTargets.peek().getServletRegistration().getServletContext(), this, name, value);
+ currentDispatchTarget.getServletRegistration().getServletContext(), this, name, value);
for (ServletRequestAttributeListener servletRequestAttributeListener : listeners) {
if (added) {
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpSessionAdaptor.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpSessionAdaptor.java
index 14212dd67..58ca6e53e 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpSessionAdaptor.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpSessionAdaptor.java
@@ -14,6 +14,7 @@ package org.eclipse.equinox.http.servlet.internal.servlet;
import java.io.Serializable;
import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.ServletContext;
import javax.servlet.http.*;
import org.eclipse.equinox.http.servlet.internal.context.ContextController;
@@ -27,7 +28,7 @@ public class HttpSessionAdaptor implements HttpSession, Serializable {
private static final long serialVersionUID = 4626167646903550760L;
private static final String PARENT_SESSION_LISTENER_KEY = "org.eclipse.equinox.http.parent.session.listener"; //$NON-NLS-1$
- transient final Set<HttpSessionAdaptor> innerSessions = new HashSet<HttpSessionAdaptor>();
+ transient final Set<HttpSessionAdaptor> innerSessions = Collections.newSetFromMap(new ConcurrentHashMap<HttpSessionAdaptor, Boolean>());
@Override
public void valueBound(HttpSessionBindingEvent event) {
// do nothing
@@ -37,42 +38,64 @@ public class HttpSessionAdaptor implements HttpSession, Serializable {
public void valueUnbound(HttpSessionBindingEvent event) {
// Here we assume the unbound event is signifying the session is being invalidated.
// Must invalidate the inner sessions
- Set<HttpSessionAdaptor> innerSessionsToInvalidate;
- synchronized (innerSessions) {
- // copy the sessions to invalidate and clear the set
- innerSessionsToInvalidate = new HashSet<HttpSessionAdaptor>(innerSessions);
- innerSessions.clear();
- }
- for (HttpSessionAdaptor innerSession : innerSessionsToInvalidate) {
- innerSession.invalidate();
+ Iterator<HttpSessionAdaptor> iterator = innerSessions.iterator();
+
+ while (iterator.hasNext()) {
+ HttpSessionAdaptor innerSession = iterator.next();
+
+ iterator.remove();
+
+ ContextController contextController =
+ innerSession.getController();
+
+ EventListeners eventListeners =
+ contextController.getEventListeners();
+
+ List<HttpSessionListener> httpSessionListeners =
+ eventListeners.get(HttpSessionListener.class);
+
+ if (!httpSessionListeners.isEmpty()) {
+ HttpSessionEvent httpSessionEvent = new HttpSessionEvent(
+ innerSession);
+
+ for (HttpSessionListener listener : httpSessionListeners) {
+ try {
+ listener.sessionDestroyed(httpSessionEvent);
+ }
+ catch (IllegalStateException ise) {
+ // outer session is already invalidated
+ }
+ }
+ }
+
+ contextController.removeActiveSession(
+ innerSession.getSession());
}
}
static void addHttpSessionAdaptor(HttpSessionAdaptor innerSession) {
+ HttpSession httpSession = innerSession.getSession();
+
ParentSessionListener parentListener;
// need to have a global lock here because we must ensure that this is added only once
- synchronized (ParentSessionListener.class) {
- parentListener = (ParentSessionListener) innerSession.getSession().getAttribute(PARENT_SESSION_LISTENER_KEY);
+ synchronized (httpSession) {
+ parentListener = (ParentSessionListener) httpSession.getAttribute(PARENT_SESSION_LISTENER_KEY);
if (parentListener == null) {
parentListener = new ParentSessionListener();
- innerSession.getSession().setAttribute(PARENT_SESSION_LISTENER_KEY, parentListener);
+ httpSession.setAttribute(PARENT_SESSION_LISTENER_KEY, parentListener);
}
}
- synchronized (parentListener.innerSessions) {
- parentListener.innerSessions.add(innerSession);
- }
+
+ parentListener.innerSessions.add(innerSession);
}
static void removeHttpSessionAdaptor(HttpSessionAdaptor innerSession) {
- ParentSessionListener parentListener;
- // need to have a global lock here because we must ensure that this is added only once
- synchronized (ParentSessionListener.class) {
- parentListener = (ParentSessionListener) innerSession.getSession().getAttribute(PARENT_SESSION_LISTENER_KEY);
- }
+ HttpSession httpSession = innerSession.getSession();
+
+ ParentSessionListener parentListener = (ParentSessionListener) httpSession.getAttribute(PARENT_SESSION_LISTENER_KEY);
+
if (parentListener != null) {
- synchronized (parentListener.innerSessions) {
- parentListener.innerSessions.remove(innerSession);
- }
+ parentListener.innerSessions.remove(innerSession);
}
}
}
@@ -172,7 +195,7 @@ public class HttpSessionAdaptor implements HttpSession, Serializable {
this.controller = controller;
this.attributePrefix = "equinox.http." + controller.getContextName(); //$NON-NLS-1$
- this.string = getClass().getSimpleName() + '[' + session.getId() + ", " + attributePrefix + ']'; //$NON-NLS-1$
+ this.string = SIMPLE_NAME + '[' + session.getId() + ", " + attributePrefix + ']'; //$NON-NLS-1$
}
public ContextController getController() {
@@ -317,4 +340,8 @@ public class HttpSessionAdaptor implements HttpSession, Serializable {
public String toString() {
return string;
}
+
+ private static final String SIMPLE_NAME =
+ HttpSessionAdaptor.class.getSimpleName();
+
}
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/RequestDispatcherAdaptor.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/RequestDispatcherAdaptor.java
index c3791adfd..c07d8189e 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/RequestDispatcherAdaptor.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/RequestDispatcherAdaptor.java
@@ -21,6 +21,8 @@ import org.eclipse.equinox.http.servlet.internal.context.DispatchTargets;
//This class unwraps the request so it can be processed by the underlying servlet container.
public class RequestDispatcherAdaptor implements RequestDispatcher {
+ private static final String SIMPLE_NAME = RequestDispatcherAdaptor.class.getSimpleName();
+
private final DispatchTargets dispatchTargets;
private final String path;
private final String string;
@@ -31,7 +33,7 @@ public class RequestDispatcherAdaptor implements RequestDispatcher {
this.dispatchTargets = dispatchTargets;
this.path = path;
- this.string = getClass().getSimpleName() + '[' + path + ", " + dispatchTargets + ']'; //$NON-NLS-1$
+ this.string = SIMPLE_NAME + '[' + path + ", " + dispatchTargets + ']'; //$NON-NLS-1$
}
public void forward(ServletRequest request, ServletResponse response)
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/ServletContextAdaptor.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/ServletContextAdaptor.java
index 9eb656646..35a87d47a 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/ServletContextAdaptor.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/ServletContextAdaptor.java
@@ -88,7 +88,7 @@ public class ServletContextAdaptor {
this.classLoader = bundleWiring.getClassLoader();
- this.string = getClass().getSimpleName() + '[' + contextController + ']';
+ this.string = SIMPLE_NAME + '[' + contextController + ']';
}
public ServletContext createServletContext() {
@@ -385,7 +385,13 @@ public class ServletContextAdaptor {
}
Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- servletContextTL.set((ServletContext)proxy);
+ boolean useThreadLocal =
+ "removeAttribute".equals(method.getName()) ||
+ "setAttribute".equals(method.getName());
+
+ if (useThreadLocal) {
+ servletContextTL.set((ServletContext)proxy);
+ }
try {
Method m = contextToHandlerMethods.get(method);
@@ -399,7 +405,9 @@ public class ServletContextAdaptor {
}
}
finally {
- servletContextTL.remove();
+ if (useThreadLocal) {
+ servletContextTL.remove();
+ }
}
}
@@ -422,6 +430,11 @@ public class ServletContextAdaptor {
}
+ private final static String SIMPLE_NAME =
+ ServletContextAdaptor.class.getSimpleName();
+
+ private final static ThreadLocal<ServletContext> servletContextTL = new ThreadLocal<ServletContext>();
+
private final AccessControlContext acc;
private final Bundle bundle;
private final ClassLoader classLoader;
@@ -430,7 +443,6 @@ public class ServletContextAdaptor {
private final ProxyContext proxyContext;
private final ServletContext servletContext;
final ServletContextHelper servletContextHelper;
- private final ThreadLocal<ServletContext> servletContextTL = new ThreadLocal<ServletContext>();
private final String string;
}

Back to the top