FELIX-4860 : Revisit HandlerRegistry implementation. Improve error page registration.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1681027 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/RequestDispatcherProvider.java b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/RequestDispatcherProvider.java
index e2a4e9a..abbc165 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/RequestDispatcherProvider.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/RequestDispatcherProvider.java
@@ -22,9 +22,6 @@
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
-/**
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
public interface RequestDispatcherProvider
{
/**
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/ServletContextWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/ServletContextWrapper.java
index c4f009b..b47ece9 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/ServletContextWrapper.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/ServletContextWrapper.java
@@ -24,9 +24,6 @@
import org.apache.felix.http.base.internal.context.ExtServletContext;
import org.apache.felix.http.base.internal.context.ExtServletContextWrapper;
-/**
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
class ServletContextWrapper extends ExtServletContextWrapper
{
private final RequestDispatcherProvider provider;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java
index f896f0e..2fcdae4 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java
@@ -169,4 +169,25 @@
this.useCount = 1;
return this.destroy();
}
+
+ @Override
+ public int hashCode()
+ {
+ return 31 + filterInfo.hashCode();
+ }
+
+ @Override
+ public boolean equals(final Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass() )
+ {
+ return false;
+ }
+ final FilterHandler other = (FilterHandler) obj;
+ return filterInfo.equals(other.filterInfo);
+ }
}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpSessionWrapper.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpSessionWrapper.java
index 106526d..bb76122 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpSessionWrapper.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpSessionWrapper.java
@@ -40,8 +40,6 @@
/**
* The session wrapper keeps track of the internal session, manages their attributes
* separately and also handles session timeout.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class HttpSessionWrapper implements HttpSession
{
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java
index 1ea14dd..0185852 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java
@@ -167,4 +167,26 @@
this.useCount = 1;
return this.destroy();
}
+
+ @Override
+ public int hashCode()
+ {
+ return 31 + servletInfo.hashCode();
+ }
+
+ @Override
+ public boolean equals(final Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass() )
+ {
+ return false;
+ }
+ final ServletHandler other = (ServletHandler) obj;
+ return servletInfo.equals(other.servletInfo);
+ }
+
}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ErrorPageRegistry.java b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ErrorPageRegistry.java
index d4a9b6c..dfcf458 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ErrorPageRegistry.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ErrorPageRegistry.java
@@ -28,10 +28,12 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
+import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import org.apache.felix.http.base.internal.handler.ServletHandler;
import org.apache.felix.http.base.internal.runtime.ServletInfo;
+import org.apache.felix.http.base.internal.runtime.dto.BuilderConstants;
import org.apache.felix.http.base.internal.runtime.dto.ErrorPageDTOBuilder;
import org.osgi.service.http.runtime.dto.DTOConstants;
import org.osgi.service.http.runtime.dto.ErrorPageDTO;
@@ -52,6 +54,43 @@
private static final List<Long> CLIENT_ERROR_CODES = hundredOf(400);
private static final List<Long> SERVER_ERROR_CODES = hundredOf(500);
+ private final Map<String, List<ServletHandler>> errorMapping = new ConcurrentHashMap<String, List<ServletHandler>>();
+
+ private volatile List<ErrorRegistrationStatus> status = Collections.emptyList();
+
+ public static final class ErrorRegistration {
+ public final long[] errorCodes;
+ public final String[] exceptions;
+
+ public ErrorRegistration(final long[] errorCodes, final String[] exceptions)
+ {
+ this.errorCodes = errorCodes;
+ this.exceptions = exceptions;
+ }
+ }
+
+ static final class ErrorRegistrationStatus implements Comparable<ErrorRegistrationStatus> {
+
+ private final ServletHandler handler;
+ public final Map<Integer, ErrorRegistration> reasonMapping = new HashMap<Integer, ErrorRegistration>();
+
+ public ErrorRegistrationStatus(final ServletHandler handler)
+ {
+ this.handler = handler;
+ }
+
+ public ServletHandler getHandler()
+ {
+ return this.handler;
+ }
+
+ @Override
+ public int compareTo(final ErrorRegistrationStatus o)
+ {
+ return this.handler.compareTo(o.getHandler());
+ }
+ }
+
private static List<Long> hundredOf(final int start)
{
List<Long> result = new ArrayList<Long>();
@@ -62,6 +101,51 @@
return Collections.unmodifiableList(result);
}
+ private static long[] toLongArray(final Set<Long> set)
+ {
+ long[] codes = BuilderConstants.EMPTY_LONG_ARRAY;
+ if ( !set.isEmpty() )
+ {
+ codes = new long[set.size()];
+ int index = 0;
+ for(final Long code : set)
+ {
+ codes[index++] = code;
+ }
+ }
+ return codes;
+ }
+
+ private static Set<Long> toLongSet(final long[] codes)
+ {
+ final Set<Long> set = new TreeSet<Long>();
+ for(final long c : codes)
+ {
+ set.add(c);
+ }
+ return set;
+ }
+
+ private static String[] toStringArray(final Set<String> set)
+ {
+ String[] array = BuilderConstants.EMPTY_STRING_ARRAY;
+ if ( !set.isEmpty() )
+ {
+ array = set.toArray(new String[set.size()]);
+ }
+ return array;
+ }
+
+ private static Set<String> toStringSet(final String[] array)
+ {
+ final Set<String> set = new TreeSet<String>();
+ for(final String s : array)
+ {
+ set.add(s);
+ }
+ return set;
+ }
+
private static String parseErrorCodes(final Set<Long> codes, final String string)
{
if (CLIENT_ERROR.equalsIgnoreCase(string))
@@ -83,41 +167,30 @@
return null;
}
- private final Map<Long, List<ServletHandler>> errorCodesMap = new ConcurrentHashMap<Long, List<ServletHandler>>();
- private final Map<String, List<ServletHandler>> exceptionsMap = new ConcurrentHashMap<String, List<ServletHandler>>();
-
- private final Map<ServletInfo, ErrorRegistrationStatus> statusMapping = new ConcurrentHashMap<ServletInfo, ErrorRegistrationStatus>();
-
- public static final class ErrorRegistration {
- public final Set<Long> errorCodes = new TreeSet<Long>();
- public final Set<String> exceptions = new TreeSet<String>();
- }
-
- static final class ErrorRegistrationStatus {
- ServletHandler handler;
- final Map<Long, Integer> errorCodeMapping = new ConcurrentHashMap<Long, Integer>();
- final Map<String, Integer> exceptionMapping = new ConcurrentHashMap<String, Integer>();
- }
-
- Map<ServletInfo, ErrorRegistrationStatus> getStatusMapping()
- {
- return this.statusMapping;
- }
-
- public static ErrorRegistration getErrorRegistration(@Nonnull final ServletInfo info)
+ /**
+ * Parse the registration properties of the servlet for error handling
+ * @param info The servlet info
+ * @return An error registration object if the servlet handles errors
+ */
+ public static @CheckForNull ErrorRegistration getErrorRegistration(@Nonnull final ServletInfo info)
{
if ( info.getErrorPage() != null )
{
- final ErrorRegistration reg = new ErrorRegistration();
+ final Set<Long> errorCodes = new TreeSet<Long>();
+ final Set<String> exceptions = new TreeSet<String>();
+
for(final String val : info.getErrorPage())
{
- final String exception = parseErrorCodes(reg.errorCodes, val);
+ final String exception = parseErrorCodes(errorCodes, val);
if ( exception != null )
{
- reg.exceptions.add(exception);
+ exceptions.add(exception);
}
}
- return reg;
+ final long[] codes = toLongArray(errorCodes);
+ final String[] exceptionsArray = toStringArray(exceptions);
+
+ return new ErrorRegistration(codes, exceptionsArray);
}
return null;
}
@@ -131,87 +204,19 @@
final ErrorRegistration reg = getErrorRegistration(handler.getServletInfo());
if ( reg != null )
{
- final ErrorRegistrationStatus status = new ErrorRegistrationStatus();
- status.handler = handler;
+ final ErrorRegistrationStatus status = new ErrorRegistrationStatus(handler);
for(final long code : reg.errorCodes)
{
- List<ServletHandler> list = errorCodesMap.get(code);
- if ( list == null )
- {
- // activate
- if ( tryToActivate(code, handler, status) )
- {
- final List<ServletHandler> newList = new ArrayList<ServletHandler>(1);
- newList.add(handler);
- errorCodesMap.put(code, newList);
- }
- }
- else
- {
- final List<ServletHandler> newList = new ArrayList<ServletHandler>(list);
- newList.add(handler);
- Collections.sort(newList);
-
- if ( newList.get(0) == handler )
- {
- // activate and reactive
- if ( tryToActivate(code, handler, status) )
- {
- final ServletHandler old = list.get(0);
- old.destroy();
- errorCodesMap.put(code, newList);
- final ErrorRegistrationStatus oldStatus = statusMapping.get(old.getServletInfo());
- oldStatus.errorCodeMapping.put(code, DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE);
- }
- }
- else
- {
- // failure
- status.errorCodeMapping.put(code, DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE);
- errorCodesMap.put(code, newList);
- }
- }
+ addErrorHandling(handler, status, code, null);
}
for(final String exception : reg.exceptions)
{
- List<ServletHandler> list = exceptionsMap.get(exception);
- if ( list == null )
- {
- // activate
- if ( tryToActivate(exception, handler, status) )
- {
- final List<ServletHandler> newList = new ArrayList<ServletHandler>(1);
- newList.add(handler);
- exceptionsMap.put(exception, newList);
- }
- }
- else
- {
- final List<ServletHandler> newList = new ArrayList<ServletHandler>(list);
- newList.add(handler);
- Collections.sort(newList);
-
- if ( newList.get(0) == handler )
- {
- // activate and reactive
- if ( tryToActivate(exception, handler, status) )
- {
- final ServletHandler old = list.get(0);
- old.destroy();
- exceptionsMap.put(exception, newList);
- final ErrorRegistrationStatus oldStatus = statusMapping.get(old.getServletInfo());
- oldStatus.exceptionMapping.put(exception, DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE);
- }
- }
- else
- {
- // failure
- status.exceptionMapping.put(exception, DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE);
- exceptionsMap.put(exception, newList);
- }
- }
+ addErrorHandling(handler, status, 0, exception);
}
- this.statusMapping.put(handler.getServletInfo(), status);
+ final List<ErrorRegistrationStatus> newList = new ArrayList<ErrorPageRegistry.ErrorRegistrationStatus>(this.status);
+ newList.add(status);
+ Collections.sort(newList);
+ this.status = newList;
}
}
@@ -224,102 +229,213 @@
final ErrorRegistration reg = getErrorRegistration(info);
if ( reg != null )
{
- this.statusMapping.remove(info);
+ final List<ErrorRegistrationStatus> newList = new ArrayList<ErrorPageRegistry.ErrorRegistrationStatus>(this.status);
+ final Iterator<ErrorRegistrationStatus> i = newList.iterator();
+ while ( i.hasNext() )
+ {
+ final ErrorRegistrationStatus status = i.next();
+ if ( status.handler.getServletInfo().equals(info) )
+ {
+ i.remove();
+ break;
+ }
+ }
+ this.status = newList;
+
for(final long code : reg.errorCodes)
{
- final List<ServletHandler> list = errorCodesMap.get(code);
- if ( list != null )
- {
- int index = 0;
- final Iterator<ServletHandler> i = list.iterator();
- while ( i.hasNext() )
- {
- final ServletHandler handler = i.next();
- if ( handler.getServletInfo().equals(info) )
- {
- handler.destroy();
-
- final List<ServletHandler> newList = new ArrayList<ServletHandler>(list);
- newList.remove(handler);
-
- if ( index == 0 )
- {
- index++;
- while ( index < list.size() )
- {
- final ServletHandler next = list.get(index);
- if ( tryToActivate(code, next, statusMapping.get(next.getServletInfo())) )
- {
- break;
- }
- else
- {
- newList.remove(next);
- }
- }
- }
- if ( newList.isEmpty() )
- {
- errorCodesMap.remove(code);
- }
- else
- {
- errorCodesMap.put(code, newList);
- }
-
- break;
- }
- index++;
- }
- }
+ removeErrorHandling(info, code, null);
}
for(final String exception : reg.exceptions)
{
- final List<ServletHandler> list = exceptionsMap.get(exception);
+ removeErrorHandling(info, 0, exception);
+ }
+ }
+ }
+
+ private void addErrorHandling(final ServletHandler handler, final ErrorRegistrationStatus status, final long code, final String exception)
+ {
+ final String key = (exception != null ? exception : String.valueOf(code));
+
+ final List<ServletHandler> newList;
+ final List<ServletHandler> list = errorMapping.get(key);
+ if ( list == null )
+ {
+ newList = Collections.singletonList(handler);
+ }
+ else
+ {
+ newList = new ArrayList<ServletHandler>(list);
+ newList.add(handler);
+ Collections.sort(newList);
+ }
+ if ( newList.get(0) == handler )
+ {
+ // try to activate (and deactivate old handler)
+ final int result = handler.init();
+ addReason(status, code, exception, result);
+ if ( result == -1 )
+ {
if ( list != null )
{
- int index = 0;
- final Iterator<ServletHandler> i = list.iterator();
- while ( i.hasNext() )
+ final ServletHandler old = list.get(0);
+ old.destroy();
+ errorMapping.put(key, newList);
+ ErrorRegistrationStatus oldStatus = null;
+ final Iterator<ErrorRegistrationStatus> i = this.status.iterator();
+ while ( oldStatus == null && i.hasNext() )
{
- final ServletHandler handler = i.next();
- if ( handler.getServletInfo().equals(info) )
+ final ErrorRegistrationStatus current = i.next();
+ if ( current.handler.getServletInfo().equals(old.getServletInfo()) )
{
- handler.destroy();
+ oldStatus = current;
+ }
+ }
+ if ( oldStatus != null )
+ {
+ removeReason(oldStatus, code, exception, -1);
+ addReason(oldStatus, code, exception, DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE);
+ }
+ }
+ else
+ {
+ errorMapping.put(key, newList);
+ }
+ }
+ }
+ else
+ {
+ // failure
+ addReason(status, code, exception, DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE);
+ errorMapping.put(key, newList);
+ }
+ }
- final List<ServletHandler> newList = new ArrayList<ServletHandler>(list);
- newList.remove(handler);
+ private void addReason(final ErrorRegistrationStatus status, final long code, final String exception, final int reason)
+ {
+ ErrorRegistration reg = status.reasonMapping.get(reason);
+ if ( reg == null )
+ {
+ if ( exception != null )
+ {
+ reg = new ErrorRegistration(BuilderConstants.EMPTY_LONG_ARRAY, new String[] {exception});
+ }
+ else
+ {
+ reg = new ErrorRegistration(new long[] {code}, BuilderConstants.EMPTY_STRING_ARRAY);
+ }
+ }
+ else
+ {
+ long[] codes = reg.errorCodes;
+ String[] exceptions = reg.exceptions;
+ if ( exception != null )
+ {
+ final Set<String> set = toStringSet(exceptions);
+ set.add(exception);
+ exceptions = toStringArray(set);
+ }
+ else
+ {
+ final Set<Long> set = toLongSet(codes);
+ set.add(code);
+ codes = toLongArray(set);
+ }
- if ( index == 0 )
+ reg = new ErrorRegistration(codes, exceptions);
+ }
+ status.reasonMapping.put(reason, reg);
+ }
+
+ private void removeReason(final ErrorRegistrationStatus status, final long code, final String exception, final int reason)
+ {
+ ErrorRegistration reg = status.reasonMapping.get(reason);
+ if ( reg != null )
+ {
+ long[] codes = reg.errorCodes;
+ String[] exceptions = reg.exceptions;
+ if ( exception != null )
+ {
+ final Set<String> set = toStringSet(exceptions);
+ set.remove(exception);
+ exceptions = toStringArray(set);
+ }
+ else
+ {
+ final Set<Long> set = toLongSet(codes);
+ set.remove(code);
+ codes = toLongArray(set);
+ }
+ if ( codes.length == 0 && exceptions.length == 0 )
+ {
+ status.reasonMapping.remove(reason);
+ }
+ else
+ {
+ status.reasonMapping.put(reason, new ErrorRegistration(codes, exceptions));
+ }
+ }
+ }
+
+ private void removeErrorHandling(final ServletInfo info, final long code, final String exception)
+ {
+ final String key = (exception != null ? exception : String.valueOf(code));
+
+ final List<ServletHandler> list = errorMapping.get(key);
+ if ( list != null )
+ {
+ int index = 0;
+ final Iterator<ServletHandler> i = list.iterator();
+ while ( i.hasNext() )
+ {
+ final ServletHandler handler = i.next();
+ if ( handler.getServletInfo().equals(info) )
+ {
+ final List<ServletHandler> newList = new ArrayList<ServletHandler>(list);
+ newList.remove(handler);
+
+ if ( index == 0 )
+ {
+ handler.destroy();
+
+ index++;
+ while ( index < list.size() )
+ {
+ final ServletHandler next = list.get(index);
+ ErrorRegistrationStatus nextStatus = null;
+ for(final ErrorRegistrationStatus s : this.status)
{
- index++;
- while ( index < list.size() )
+ if ( s.handler.getServletInfo().equals(next.getServletInfo()) )
{
- final ServletHandler next = list.get(index);
- if ( tryToActivate(exception, next, statusMapping.get(next.getServletInfo())) )
- {
- break;
- }
- else
- {
- newList.remove(next);
- }
+ nextStatus = s;
+ break;
}
}
- if ( newList.isEmpty() )
+ this.removeReason(nextStatus, code, exception, DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE);
+ final int reason = next.init();
+ this.addReason(nextStatus, code, exception, reason);
+ if ( reason == -1 )
{
- exceptionsMap.remove(exception);
+ break;
}
else
{
- exceptionsMap.put(exception, newList);
+ newList.remove(next);
}
-
- break;
}
- index++;
}
+ if ( newList.isEmpty() )
+ {
+ errorMapping.remove(key);
+ }
+ else
+ {
+ errorMapping.put(key, newList);
+ }
+
+ break;
}
+ index++;
}
}
}
@@ -351,7 +467,7 @@
*/
private ServletHandler get(final long errorCode)
{
- final List<ServletHandler> list = this.errorCodesMap.get(errorCode);
+ final List<ServletHandler> list = this.errorMapping.get(String.valueOf(errorCode));
if ( list != null )
{
return list.get(0);
@@ -375,7 +491,7 @@
Class<?> throwableClass = exception.getClass();
while ( servletHandler == null && throwableClass != null )
{
- final List<ServletHandler> list = this.exceptionsMap.get(throwableClass.getName());
+ final List<ServletHandler> list = this.errorMapping.get(throwableClass.getName());
if ( list != null )
{
servletHandler = list.get(0);
@@ -394,122 +510,32 @@
}
/**
- * Try to activate a servlet for an error code
- * @param code The error code
- * @param handler The servlet handler
- * @param status The status to keep track of activation
- * @return {@code -1} if activation was successful, failure code otherwise
+ * Get DTOs for error pages.
+ * @param dto The servlet context DTO
+ * @param failedErrorPageDTOs The failed error page DTOs
*/
- private boolean tryToActivate(final Long code, final ServletHandler handler, final ErrorRegistrationStatus status)
- {
- // add to active
- final int result = handler.init();
- status.errorCodeMapping.put(code, result);
-
- return result == -1;
- }
-
- /**
- * Try to activate a servlet for an exception
- * @param exception The exception
- * @param handler The servlet handler
- * @param status The status to keep track of activation
- * @return {@code -1} if activation was successful, failure code otherwise
- */
- private boolean tryToActivate(final String exception, final ServletHandler handler, final ErrorRegistrationStatus status)
- {
- // add to active
- final int result = handler.init();
- status.exceptionMapping.put(exception, result);
-
- return result == -1;
- }
-
public void getRuntimeInfo(final ServletContextDTO dto,
final Collection<FailedErrorPageDTO> failedErrorPageDTOs)
{
- final Collection<ErrorPageDTO> errorPageDTOs = new ArrayList<ErrorPageDTO>();
-
- for(final ErrorRegistrationStatus status : this.statusMapping.values())
+ final List<ErrorPageDTO> errorPageDTOs = new ArrayList<ErrorPageDTO>();
+ final List<ErrorRegistrationStatus> statusList = this.status;
+ for(final ErrorRegistrationStatus status : statusList)
{
- // TODO - we could do this calculation already when generating the status object
- final ErrorRegistration active = new ErrorRegistration();
- final Map<Integer, ErrorRegistration> inactive = new HashMap<Integer, ErrorRegistration>();
-
- for(Map.Entry<Long, Integer> codeEntry : status.errorCodeMapping.entrySet() )
+ for(final Map.Entry<Integer, ErrorRegistration> entry : status.reasonMapping.entrySet())
{
- if ( codeEntry.getValue() == -1 )
+ final ErrorPageDTO state = ErrorPageDTOBuilder.build(status.getHandler(), entry.getKey());
+ state.errorCodes = entry.getValue().errorCodes;
+ state.exceptions = entry.getValue().exceptions;
+
+ if ( entry.getKey() == -1 )
{
- active.errorCodes.add(codeEntry.getKey());
+ errorPageDTOs.add(state);
}
else
{
- ErrorRegistration set = inactive.get(codeEntry.getValue());
- if ( set == null )
- {
- set = new ErrorRegistration();
- inactive.put(codeEntry.getValue(), set);
- }
- set.errorCodes.add(codeEntry.getKey());
+ failedErrorPageDTOs.add((FailedErrorPageDTO)state);
}
}
- for(Map.Entry<String, Integer> codeEntry : status.exceptionMapping.entrySet() )
- {
- if ( codeEntry.getValue() == -1 )
- {
- active.exceptions.add(codeEntry.getKey());
- }
- else
- {
- ErrorRegistration set = inactive.get(codeEntry.getValue());
- if ( set == null )
- {
- set = new ErrorRegistration();
- inactive.put(codeEntry.getValue(), set);
- }
- set.exceptions.add(codeEntry.getKey());
- }
- }
-
- // create DTOs
- if ( !active.errorCodes.isEmpty() || !active.exceptions.isEmpty() )
- {
- final ErrorPageDTO state = ErrorPageDTOBuilder.build(status.handler, -1);
- if ( !active.errorCodes.isEmpty() )
- {
- final long[] codes = new long[active.errorCodes.size()];
- final Iterator<Long> iter = active.errorCodes.iterator();
- for(int i=0; i<codes.length; i++)
- {
- codes[i] = iter.next();
- }
- state.errorCodes = codes;
- }
- if ( !active.exceptions.isEmpty() )
- {
- state.exceptions = active.exceptions.toArray(new String[active.exceptions.size()]);
- }
- errorPageDTOs.add(state);
- }
- for(final Map.Entry<Integer, ErrorRegistration> entry : inactive.entrySet())
- {
- final FailedErrorPageDTO state = (FailedErrorPageDTO)ErrorPageDTOBuilder.build(status.handler, entry.getKey());
- if ( !entry.getValue().errorCodes.isEmpty() )
- {
- final long[] codes = new long[entry.getValue().errorCodes.size()];
- final Iterator<Long> iter = entry.getValue().errorCodes.iterator();
- for(int i=0; i<codes.length; i++)
- {
- codes[i] = iter.next();
- }
- state.errorCodes = codes;
- }
- if ( !entry.getValue().exceptions.isEmpty() )
- {
- state.exceptions = entry.getValue().exceptions.toArray(new String[entry.getValue().exceptions.size()]);
- }
- failedErrorPageDTOs.add(state);
- }
}
if ( !errorPageDTOs.isEmpty() )
{
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/FilterRegistry.java b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/FilterRegistry.java
index a3cde22..560c0b1 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/FilterRegistry.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/FilterRegistry.java
@@ -193,8 +193,8 @@
break;
}
}
- // check for servlet name
- final String servletName = (handler != null) ? handler.getName() : null;
+ // check for servlet name if it's not a resource
+ final String servletName = (handler != null && !handler.getServletInfo().isResource()) ? handler.getName() : null;
if ( !added && servletName != null && status.getHandler().getFilterInfo().getServletNames() != null )
{
for(final String name : status.getHandler().getFilterInfo().getServletNames())
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ServletRegistry.java b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ServletRegistry.java
index 4a3e6d8..373a494 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ServletRegistry.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ServletRegistry.java
@@ -20,9 +20,11 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.Nonnull;
@@ -100,8 +102,15 @@
status.handler = handler;
boolean isActive = false;
+ // used for detecting duplicates
+ final Set<String> patterns = new HashSet<String>();
for(final String pattern : handler.getServletInfo().getPatterns())
{
+ if ( patterns.contains(pattern) )
+ {
+ continue;
+ }
+ patterns.add(pattern);
final PathResolver regHandler = this.activeServletMappings.get(pattern);
if ( regHandler != null )
{
@@ -207,8 +216,15 @@
this.statusMapping.remove(info);
ServletHandler cleanupHandler = null;
+ // used for detecting duplicates
+ final Set<String> patterns = new HashSet<String>();
for(final String pattern : info.getPatterns())
{
+ if ( patterns.contains(pattern) )
+ {
+ continue;
+ }
+ patterns.add(pattern);
final PathResolver regHandler = this.activeServletMappings.get(pattern);
if ( regHandler != null && regHandler.getServletHandler().getServletInfo().equals(info) )
{
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/AbstractInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/AbstractInfo.java
index 008f179..fa9e829 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/AbstractInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/AbstractInfo.java
@@ -204,28 +204,21 @@
@Override
public int hashCode()
{
- final int prime = 31;
- int result = 1;
- result = prime * result + ranking;
- result = prime * result + (int) (serviceId ^ (serviceId >>> 32));
- return result;
+ return 31 + (int) (serviceId ^ (serviceId >>> 32));
}
@Override
public boolean equals(final Object obj)
{
if (this == obj)
+ {
return true;
- if (obj == null)
+ }
+ if (obj == null || getClass() != obj.getClass())
+ {
return false;
- if (getClass() != obj.getClass())
- return false;
- @SuppressWarnings("unchecked")
- final AbstractInfo<T> other = (AbstractInfo<T>) obj;
- if (ranking != other.ranking)
- return false;
- if (serviceId != other.serviceId)
- return false;
- return true;
+ }
+ final AbstractInfo<?> other = (AbstractInfo<?>) obj;
+ return serviceId == other.serviceId;
}
}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/FilterInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/FilterInfo.java
index 4e35a69..0acea5e 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/FilterInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/FilterInfo.java
@@ -20,10 +20,13 @@
import java.util.Collections;
import java.util.Map;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
+import org.apache.felix.http.base.internal.util.PatternUtil;
import org.osgi.dto.DTO;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.runtime.dto.FilterDTO;
@@ -34,8 +37,6 @@
* <p>
* This class only provides information used at registration time, and as such differs slightly from {@link DTO}s like, {@link FilterDTO}.
* </p>
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public final class FilterInfo extends WhiteboardServiceInfo<Filter>
{
@@ -110,7 +111,15 @@
DispatcherType[] dispatchers = new DispatcherType[dispatcherNames.length];
for (int i = 0; i < dispatchers.length; i++)
{
- dispatchers[i] = DispatcherType.valueOf(dispatcherNames[i].toUpperCase());
+ try
+ {
+ dispatchers[i] = DispatcherType.valueOf(dispatcherNames[i].toUpperCase());
+ }
+ catch ( final IllegalArgumentException iae)
+ {
+ dispatchers = null;
+ break;
+ }
}
this.dispatcher = dispatchers;
}
@@ -141,7 +150,44 @@
@Override
public boolean isValid()
{
- return super.isValid() && (!isEmpty(this.patterns) || !isEmpty(this.regexs) || !isEmpty(this.servletNames));
+ boolean valid = super.isValid() && (!isEmpty(this.patterns) || !isEmpty(this.regexs) || !isEmpty(this.servletNames));
+ if ( valid )
+ {
+ if ( this.patterns != null )
+ {
+ for(final String p : this.patterns)
+ {
+ if ( !PatternUtil.isValidPattern(p) )
+ {
+ valid = false;
+ break;
+ }
+ }
+ }
+ if ( valid && this.regexs != null )
+ {
+ for(final String p : this.regexs)
+ {
+ try
+ {
+ Pattern.compile(p);
+ }
+ catch ( final PatternSyntaxException pse)
+ {
+ valid = false;
+ break;
+ }
+ }
+ }
+ }
+ if ( valid )
+ {
+ if ( this.dispatcher == null || this.dispatcher.length == 0 )
+ {
+ valid = false;
+ }
+ }
+ return valid;
}
public String getName()
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/HttpSessionAttributeListenerInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/HttpSessionAttributeListenerInfo.java
index c336026..f751140 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/HttpSessionAttributeListenerInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/HttpSessionAttributeListenerInfo.java
@@ -24,8 +24,6 @@
/**
* Info object for registered servlet context listeners
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public final class HttpSessionAttributeListenerInfo extends ListenerInfo<HttpSessionAttributeListener>
{
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/HttpSessionIdListenerInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/HttpSessionIdListenerInfo.java
index eeb671a..b0eedc0 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/HttpSessionIdListenerInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/HttpSessionIdListenerInfo.java
@@ -24,8 +24,6 @@
/**
* Info object for registered http session id listeners
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public final class HttpSessionIdListenerInfo extends ListenerInfo<HttpSessionIdListener>
{
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/HttpSessionListenerInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/HttpSessionListenerInfo.java
index 17f4727..aa2f1de 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/HttpSessionListenerInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/HttpSessionListenerInfo.java
@@ -24,8 +24,6 @@
/**
* Info object for registered servlet context listeners
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public final class HttpSessionListenerInfo extends ListenerInfo<HttpSessionListener>
{
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ListenerInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ListenerInfo.java
index 33647ab..15eda56 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ListenerInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ListenerInfo.java
@@ -19,14 +19,13 @@
package org.apache.felix.http.base.internal.runtime;
import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceObjects;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
/**
* Info object for registered listeners.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public abstract class ListenerInfo<T> extends WhiteboardServiceInfo<T>
{
@@ -50,10 +49,14 @@
{
if (this.getServiceReference() != null)
{
- final ServiceObjects<T> so = bundle.getBundleContext().getServiceObjects(this.getServiceReference());
- if (so != null)
+ final BundleContext bctx = bundle.getBundleContext();
+ if ( bctx != null )
{
- return so.getService();
+ final ServiceObjects<T> so = bctx.getServiceObjects(this.getServiceReference());
+ if (so != null)
+ {
+ return so.getService();
+ }
}
}
return null;
@@ -63,10 +66,14 @@
{
if (this.getServiceReference() != null)
{
- final ServiceObjects<T> so = bundle.getBundleContext().getServiceObjects(this.getServiceReference());
- if (so != null)
+ final BundleContext bctx = bundle.getBundleContext();
+ if ( bctx != null )
{
- so.ungetService(service);
+ final ServiceObjects<T> so = bctx.getServiceObjects(this.getServiceReference());
+ if (so != null)
+ {
+ so.ungetService(service);
+ }
}
}
}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ResourceInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ResourceInfo.java
index 746cc9f..3b2e283 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ResourceInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ResourceInfo.java
@@ -22,9 +22,7 @@
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
/**
- *
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ * Info object for a resource registration
*/
public final class ResourceInfo extends WhiteboardServiceInfo<Object>
{
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextAttributeListenerInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextAttributeListenerInfo.java
index 341d201..c41901c 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextAttributeListenerInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextAttributeListenerInfo.java
@@ -24,8 +24,6 @@
/**
* Info object for registered servlet context attribute listeners
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public final class ServletContextAttributeListenerInfo extends ListenerInfo<ServletContextAttributeListener>
{
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextListenerInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextListenerInfo.java
index f1c609f..1a11329 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextListenerInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextListenerInfo.java
@@ -24,8 +24,6 @@
/**
* Info object for registered servlet context listeners
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public final class ServletContextListenerInfo extends ListenerInfo<ServletContextListener>
{
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletInfo.java
index 88a3880..d78fedb 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletInfo.java
@@ -23,6 +23,7 @@
import javax.servlet.Servlet;
+import org.apache.felix.http.base.internal.util.PatternUtil;
import org.osgi.dto.DTO;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.runtime.dto.ServletDTO;
@@ -33,8 +34,6 @@
* <p>
* This class only provides information used at registration time, and as such differs slightly from {@link DTO}s like, {@link ServletDTO}.
* </p>
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class ServletInfo extends WhiteboardServiceInfo<Servlet>
{
@@ -128,28 +127,25 @@
this.prefix = null;
}
- ServletInfo(int serviceRanking,
- long serviceId,
- String name,
- String[] patterns,
- String[] errorPage,
- boolean asyncSupported,
- Map<String, String> initParams)
- {
- super(serviceRanking, serviceId);
- this.name = name;
- this.patterns = patterns;
- this.errorPage = errorPage;
- this.asyncSupported = asyncSupported;
- this.initParams = Collections.unmodifiableMap(initParams);
- this.isResource = false;
- this.prefix = null;
- }
-
@Override
public boolean isValid()
{
- return super.isValid() && !(isEmpty(this.patterns) && isEmpty(this.errorPage));
+ boolean valid = super.isValid() && !(isEmpty(this.patterns) && isEmpty(this.errorPage));
+ if ( valid )
+ {
+ if ( this.patterns != null )
+ {
+ for(final String p : this.patterns)
+ {
+ if ( !PatternUtil.isValidPattern(p) )
+ {
+ valid = false;
+ break;
+ }
+ }
+ }
+ }
+ return valid;
}
public String getName()
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletRequestAttributeListenerInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletRequestAttributeListenerInfo.java
index 52733cf..0898b39 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletRequestAttributeListenerInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletRequestAttributeListenerInfo.java
@@ -24,8 +24,6 @@
/**
* Info object for registered servlet context listeners
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public final class ServletRequestAttributeListenerInfo extends ListenerInfo<ServletRequestAttributeListener>
{
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletRequestListenerInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletRequestListenerInfo.java
index ef0a569..c8eb3ca 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletRequestListenerInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletRequestListenerInfo.java
@@ -24,8 +24,6 @@
/**
* Info object for registered servlet context listeners
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public final class ServletRequestListenerInfo extends ListenerInfo<ServletRequestListener>
{
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/FailedDTOHolder.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/FailedDTOHolder.java
index 6f69af9..a4d0ffc 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/FailedDTOHolder.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/dto/FailedDTOHolder.java
@@ -19,7 +19,6 @@
package org.apache.felix.http.base.internal.runtime.dto;
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -77,21 +76,8 @@
final FailedErrorPageDTO dto = (FailedErrorPageDTO)ErrorPageDTOBuilder.build((ServletInfo)info, true);
dto.failureReason = failureCode;
final ErrorPageRegistry.ErrorRegistration reg = ErrorPageRegistry.getErrorRegistration((ServletInfo)info);
- if ( !reg.errorCodes.isEmpty() )
- {
- final long[] codes = new long[reg.errorCodes.size()];
- int index = 0;
- final Iterator<Long> i = reg.errorCodes.iterator();
- while ( i.hasNext() )
- {
- codes[index++] = i.next();
- }
- dto.errorCodes = codes;
- }
- if ( !reg.exceptions.isEmpty() )
- {
- dto.exceptions = reg.exceptions.toArray(new String[reg.exceptions.size()]);
- }
+ dto.errorCodes = reg.errorCodes;
+ dto.exceptions = reg.exceptions;
this.failedErrorPageDTOs.add(dto);
}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/util/PatternUtil.java b/http/base/src/main/java/org/apache/felix/http/base/internal/util/PatternUtil.java
index c9c3c97..d54f431 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/util/PatternUtil.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/util/PatternUtil.java
@@ -22,12 +22,55 @@
/**
* Some convenience utilities to deal with path patterns.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-public class PatternUtil
+public abstract class PatternUtil
{
+ /**
+ * Check for valid servlet pattern
+ * @param pattern The pattern
+ * @return {@code true} if its valid
+ */
+ public static boolean isValidPattern(final String pattern)
+ {
+ if ( pattern == null )
+ {
+ return false;
+ }
+ if ( pattern.indexOf("?") != -1 )
+ {
+ return false;
+ }
+ // default and root
+ if ( pattern.length() == 0 || pattern.equals("/") )
+ {
+ return true;
+ }
+ // extension
+ if ( pattern.startsWith("*.") )
+ {
+ return pattern.indexOf("/") == -1;
+ }
+ if ( !pattern.startsWith("/") )
+ {
+ return false;
+ }
+ final int pos = pattern.indexOf('*');
+ if ( pos != -1 && pos < pattern.length() - 1 )
+ {
+ return false;
+ }
+ if ( pos != -1 && pattern.charAt(pos - 1) != '/')
+ {
+ return false;
+ }
+ if ( pattern.charAt(pattern.length() - 1) == '/')
+ {
+ return false;
+ }
+ return true;
+ }
+
// check for valid symbolic name
public static boolean isValidSymbolicName(final String name)
{
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/util/UriUtils.java b/http/base/src/main/java/org/apache/felix/http/base/internal/util/UriUtils.java
index cc0a4df..c7704e0 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/util/UriUtils.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/util/UriUtils.java
@@ -28,10 +28,8 @@
/**
* Some convenience methods for handling URI(-parts).
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-public class UriUtils
+public abstract class UriUtils
{
private static final String SLASH_STR = "/";
private static final char DOT = '.';
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java
index 1aadbfc..b92a798 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java
@@ -32,6 +32,7 @@
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
import javax.annotation.Nonnull;
@@ -117,6 +118,9 @@
private final HttpServicePlugin plugin;
+ /** Map containing all info objects reported from the trackers. */
+ private final Map<Long, AbstractInfo<?>> allInfos = new ConcurrentHashMap<Long, AbstractInfo<?>>();
+
/**
* Create a new whiteboard http manager
* @param bundleContext
@@ -229,6 +233,7 @@
this.runtimeServiceReg.unregister();
this.runtimeServiceReg = null;
}
+ this.allInfos.clear();
}
public void setProperties(final Hashtable<String, Object> props)
@@ -360,6 +365,7 @@
// no failure DTO and no logging if not matching
if ( isMatchingService(info) )
{
+ this.allInfos.put(info.getServiceId(), info);
if ( info.isValid() )
{
synchronized ( this.contextMap )
@@ -407,10 +413,10 @@
/**
* Remove a servlet context helper
*/
- public void removeContextHelper(final ServletContextHelperInfo info)
+ public void removeContextHelper(final long serviceId)
{
- // no failure DTO and no logging if not matching
- if ( isMatchingService(info) )
+ final ServletContextHelperInfo info = (ServletContextHelperInfo) this.allInfos.remove(serviceId);
+ if ( info != null )
{
if ( info.isValid() )
{
@@ -500,6 +506,7 @@
// no logging and no DTO if other target service
if ( isMatchingService(info) )
{
+ this.allInfos.put(info.getServiceId(), info);
if ( info.isValid() )
{
synchronized ( this.contextMap )
@@ -537,12 +544,13 @@
/**
* Remove whiteboard service from the registry
- * @param info Whiteboard service info
+ * @param info The service id of the whiteboard service
*/
- public void removeWhiteboardService(@Nonnull final WhiteboardServiceInfo<?> info)
+ public void removeWhiteboardService(final long serviceId)
{
- // no logging and no DTO if other target service
- if ( isMatchingService(info) ) {
+ final WhiteboardServiceInfo<?> info = (WhiteboardServiceInfo<?>) this.allInfos.remove(serviceId);
+ if ( info != null )
+ {
if ( info.isValid() )
{
synchronized ( this.contextMap )
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextHelperTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextHelperTracker.java
index 6b5fe65..dc8569c 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextHelperTracker.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextHelperTracker.java
@@ -21,6 +21,7 @@
import org.apache.felix.http.base.internal.runtime.ServletContextHelperInfo;
import org.apache.felix.http.base.internal.whiteboard.WhiteboardManager;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.context.ServletContextHelper;
@@ -81,7 +82,6 @@
private void removed(@Nonnull final ServiceReference<ServletContextHelper> ref)
{
- final ServletContextHelperInfo info = new ServletContextHelperInfo(ref);
- this.contextManager.removeContextHelper(info);
+ this.contextManager.removeContextHelper((Long)ref.getProperty(Constants.SERVICE_ID));
}
}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/WhiteboardServiceTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/WhiteboardServiceTracker.java
index ba3c72c..57b072c 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/WhiteboardServiceTracker.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/WhiteboardServiceTracker.java
@@ -19,6 +19,7 @@
import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
import org.apache.felix.http.base.internal.whiteboard.WhiteboardManager;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
@@ -105,8 +106,7 @@
private void removed(final ServiceReference<T> ref)
{
- final WhiteboardServiceInfo<T> info = this.getServiceInfo(ref);
- this.contextManager.removeWhiteboardService(info);
+ this.contextManager.removeWhiteboardService((Long)ref.getProperty(Constants.SERVICE_ID));
}
/**
diff --git a/http/base/src/test/java/org/apache/felix/http/base/internal/registry/ErrorPageRegistryTest.java b/http/base/src/test/java/org/apache/felix/http/base/internal/registry/ErrorPageRegistryTest.java
index 0ed605e..fc8c146 100644
--- a/http/base/src/test/java/org/apache/felix/http/base/internal/registry/ErrorPageRegistryTest.java
+++ b/http/base/src/test/java/org/apache/felix/http/base/internal/registry/ErrorPageRegistryTest.java
@@ -28,7 +28,6 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashSet;
-import java.util.Map;
import java.util.Set;
import javax.servlet.Servlet;
@@ -52,8 +51,8 @@
import org.osgi.service.http.runtime.dto.ServletContextDTO;
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
-public class ErrorPageRegistryTest {
-
+public class ErrorPageRegistryTest
+{
private void assertEmpty(final ServletContextDTO dto, final FailedDTOHolder holder)
{
assertNull(dto.servletDTOs);
@@ -77,10 +76,7 @@
final FailedDTOHolder holder = new FailedDTOHolder();
final ServletContextDTO dto = new ServletContextDTO();
- final Map<ServletInfo, ErrorPageRegistry.ErrorRegistrationStatus> status = reg.getStatusMapping();
// empty reg
- assertEquals(0, status.size());
- // check DTO
reg.getRuntimeInfo(dto, holder.failedErrorPageDTOs);
assertEmpty(dto, holder);
@@ -91,22 +87,17 @@
verify(h1.getServlet()).init(Matchers.any(ServletConfig.class));
// one entry in reg
- assertEquals(1, status.size());
- assertNotNull(status.get(h1.getServletInfo()));
- assertEquals(1, status.get(h1.getServletInfo()).exceptionMapping.size());
- assertEquals(-1, (int)status.get(h1.getServletInfo()).exceptionMapping.get("java.io.IOException"));
- assertEquals(1, status.get(h1.getServletInfo()).errorCodeMapping.size());
- assertEquals(-1, (int)status.get(h1.getServletInfo()).errorCodeMapping.get(404L));
-
- // check DTO
clear(dto, holder);
reg.getRuntimeInfo(dto, holder.failedErrorPageDTOs);
assertNull(dto.resourceDTOs);
assertNull(dto.servletDTOs);
assertNotNull(dto.errorPageDTOs);
assertEquals(1, dto.errorPageDTOs.length);
+ assertEquals(1L, dto.errorPageDTOs[0].serviceId);
assertEquals(1, dto.errorPageDTOs[0].errorCodes.length);
assertEquals(404, dto.errorPageDTOs[0].errorCodes[0]);
+ assertEquals(1, dto.errorPageDTOs[0].exceptions.length);
+ assertEquals("java.io.IOException", dto.errorPageDTOs[0].exceptions[0]);
assertTrue(holder.failedErrorPageDTOs.isEmpty());
// test error handling
@@ -122,8 +113,6 @@
verify(s).destroy();
// empty again
- assertEquals(0, status.size());
- // check DTO
clear(dto, holder);
reg.getRuntimeInfo(dto, holder.failedErrorPageDTOs);
assertEmpty(dto, holder);
@@ -136,9 +125,6 @@
final FailedDTOHolder holder = new FailedDTOHolder();
final ServletContextDTO dto = new ServletContextDTO();
- final Map<ServletInfo, ErrorPageRegistry.ErrorRegistrationStatus> status = reg.getStatusMapping();
- // empty reg
- assertEquals(0, status.size());
// check DTO
reg.getRuntimeInfo(dto, holder.failedErrorPageDTOs);
assertEmpty(dto, holder);
@@ -152,53 +138,34 @@
verify(h1.getServlet()).init(Matchers.any(ServletConfig.class));
verify(h2.getServlet()).init(Matchers.any(ServletConfig.class));
- // two entries in reg
- assertEquals(2, status.size());
- assertNotNull(status.get(h1.getServletInfo()));
- assertEquals(1, status.get(h1.getServletInfo()).exceptionMapping.size());
- assertEquals(-1, (int)status.get(h1.getServletInfo()).exceptionMapping.get("java.io.IOException"));
- assertEquals(1, status.get(h1.getServletInfo()).errorCodeMapping.size());
- assertEquals(DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE, (int)status.get(h1.getServletInfo()).errorCodeMapping.get(404L));
- assertNotNull(status.get(h2.getServletInfo()));
- assertEquals(1, status.get(h2.getServletInfo()).exceptionMapping.size());
- assertEquals(-1, (int)status.get(h2.getServletInfo()).exceptionMapping.get("some.other.Exception"));
- assertEquals(1, status.get(h2.getServletInfo()).errorCodeMapping.size());
- assertEquals(-1, (int)status.get(h2.getServletInfo()).errorCodeMapping.get(404L));
-
- // check DTO
+ // two entries in DTO
clear(dto, holder);
reg.getRuntimeInfo(dto, holder.failedErrorPageDTOs);
+
assertNull(dto.resourceDTOs);
assertNull(dto.servletDTOs);
assertNotNull(dto.errorPageDTOs);
assertEquals(2, dto.errorPageDTOs.length);
- assertEquals(0, dto.errorPageDTOs[0].errorCodes.length);
- assertEquals(1, dto.errorPageDTOs[1].errorCodes.length);
- assertEquals(404, dto.errorPageDTOs[1].errorCodes[0]);
- assertEquals(1, dto.errorPageDTOs[0].exceptions.length);
+ assertEquals(0, dto.errorPageDTOs[1].errorCodes.length);
+ assertEquals(1, dto.errorPageDTOs[0].errorCodes.length);
+ assertEquals(404, dto.errorPageDTOs[0].errorCodes[0]);
assertEquals(1, dto.errorPageDTOs[1].exceptions.length);
- assertEquals("java.io.IOException", dto.errorPageDTOs[0].exceptions[0]);
- assertEquals("some.other.Exception", dto.errorPageDTOs[1].exceptions[0]);
+ assertEquals(1, dto.errorPageDTOs[0].exceptions.length);
+ assertEquals("java.io.IOException", dto.errorPageDTOs[1].exceptions[0]);
+ assertEquals("some.other.Exception", dto.errorPageDTOs[0].exceptions[0]);
assertEquals(1, holder.failedErrorPageDTOs.size());
- assertEquals(1L, holder.failedErrorPageDTOs.iterator().next().serviceId);
- assertEquals(1, holder.failedErrorPageDTOs.iterator().next().errorCodes.length);
- assertEquals(404, holder.failedErrorPageDTOs.iterator().next().errorCodes[0]);
- assertEquals(0, holder.failedErrorPageDTOs.iterator().next().exceptions.length);
+ assertEquals(1L, holder.failedErrorPageDTOs.get(0).serviceId);
+ assertEquals(1, holder.failedErrorPageDTOs.get(0).errorCodes.length);
+ assertEquals(404, holder.failedErrorPageDTOs.get(0).errorCodes[0]);
+ assertEquals(0, holder.failedErrorPageDTOs.get(0).exceptions.length);
+ assertEquals(DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE, holder.failedErrorPageDTOs.get(0).failureReason);
// remove second page
final Servlet s2 = h2.getServlet();
reg.removeServlet(h2.getServletInfo(), true);
verify(s2).destroy();
- // one entry in reg
- assertEquals(1, status.size());
- assertNotNull(status.get(h1.getServletInfo()));
- assertEquals(1, status.get(h1.getServletInfo()).exceptionMapping.size());
- assertEquals(-1, (int)status.get(h1.getServletInfo()).exceptionMapping.get("java.io.IOException"));
- assertEquals(1, status.get(h1.getServletInfo()).errorCodeMapping.size());
- assertEquals(-1, (int)status.get(h1.getServletInfo()).errorCodeMapping.get(404L));
-
- // check DTO
+ // one entry in DTO
clear(dto, holder);
reg.getRuntimeInfo(dto, holder.failedErrorPageDTOs);
assertNull(dto.resourceDTOs);
@@ -207,6 +174,8 @@
assertEquals(1, dto.errorPageDTOs.length);
assertEquals(1, dto.errorPageDTOs[0].errorCodes.length);
assertEquals(404, dto.errorPageDTOs[0].errorCodes[0]);
+ assertEquals(1, dto.errorPageDTOs[0].exceptions.length);
+ assertEquals("java.io.IOException", dto.errorPageDTOs[0].exceptions[0]);
assertTrue(holder.failedErrorPageDTOs.isEmpty());
// test error handling
@@ -222,8 +191,6 @@
verify(s1).destroy();
// empty again
- assertEquals(0, status.size());
- // check DTO
clear(dto, holder);
reg.getRuntimeInfo(dto, holder.failedErrorPageDTOs);
assertEmpty(dto, holder);
@@ -281,9 +248,9 @@
assertEquals(1, holder.failedErrorPageDTOs.size());
assertEquals(2, dto.errorPageDTOs.length);
- assertEquals(98, dto.errorPageDTOs[0].errorCodes.length);
+ assertEquals(98, dto.errorPageDTOs[1].errorCodes.length);
final Set<Long> codes4 = new HashSet<Long>();
- for(final long c : dto.errorPageDTOs[0].errorCodes)
+ for(final long c : dto.errorPageDTOs[1].errorCodes)
{
assertTrue(c >= 400 && c < 500);
codes4.add(c);
@@ -291,9 +258,9 @@
assertEquals(98, codes4.size());
assertFalse(codes4.contains(404L));
assertFalse(codes4.contains(403L));
- assertEquals(2, dto.errorPageDTOs[1].errorCodes.length);
+ assertEquals(2, dto.errorPageDTOs[0].errorCodes.length);
final Set<Long> codes = new HashSet<Long>();
- for(final long c : dto.errorPageDTOs[1].errorCodes)
+ for(final long c : dto.errorPageDTOs[0].errorCodes)
{
assertTrue(c >= 403 && c < 405);
codes.add(c);
diff --git a/http/base/src/test/java/org/apache/felix/http/base/internal/util/PatternUtilTest.java b/http/base/src/test/java/org/apache/felix/http/base/internal/util/PatternUtilTest.java
index 690a41c..9b8b12c 100644
--- a/http/base/src/test/java/org/apache/felix/http/base/internal/util/PatternUtilTest.java
+++ b/http/base/src/test/java/org/apache/felix/http/base/internal/util/PatternUtilTest.java
@@ -25,8 +25,6 @@
/**
* Test cases for {@link PatternUtil}.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class PatternUtilTest
{
@@ -40,4 +38,21 @@
assertTrue(PatternUtil.isValidSymbolicName("ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
assertTrue(PatternUtil.isValidSymbolicName("0123456789-_"));
}
+
+ @Test public void testServletPattern()
+ {
+ assertFalse(PatternUtil.isValidPattern(null));
+ assertTrue(PatternUtil.isValidPattern(""));
+ assertTrue(PatternUtil.isValidPattern("*.html"));
+ assertTrue(PatternUtil.isValidPattern("/"));
+ assertTrue(PatternUtil.isValidPattern("/test"));
+ assertTrue(PatternUtil.isValidPattern("/test/*"));
+ assertTrue(PatternUtil.isValidPattern("/foo/bar"));
+ assertTrue(PatternUtil.isValidPattern("/foo/bar/*"));
+ assertFalse(PatternUtil.isValidPattern("/*.html"));
+ assertFalse(PatternUtil.isValidPattern("/*/foo"));
+ assertFalse(PatternUtil.isValidPattern("foo"));
+ assertFalse(PatternUtil.isValidPattern("foo/bla"));
+ assertFalse(PatternUtil.isValidPattern("/test/"));
+ }
}
diff --git a/http/base/src/test/java/org/apache/felix/http/base/internal/util/UriUtilsTest.java b/http/base/src/test/java/org/apache/felix/http/base/internal/util/UriUtilsTest.java
index 2acc7a8..e3923bb 100644
--- a/http/base/src/test/java/org/apache/felix/http/base/internal/util/UriUtilsTest.java
+++ b/http/base/src/test/java/org/apache/felix/http/base/internal/util/UriUtilsTest.java
@@ -18,15 +18,17 @@
*/
package org.apache.felix.http.base.internal.util;
-import static org.apache.felix.http.base.internal.util.UriUtils.*;
-import static org.junit.Assert.*;
+import static org.apache.felix.http.base.internal.util.UriUtils.compactPath;
+import static org.apache.felix.http.base.internal.util.UriUtils.concat;
+import static org.apache.felix.http.base.internal.util.UriUtils.decodePath;
+import static org.apache.felix.http.base.internal.util.UriUtils.relativePath;
+import static org.apache.felix.http.base.internal.util.UriUtils.removeDotSegments;
+import static org.junit.Assert.assertEquals;
import org.junit.Test;
/**
* Test cases for {@link UriUtils}.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class UriUtilsTest
{
@@ -51,7 +53,7 @@
assertEquals(null, relativePath("/foo", null));
assertEquals(null, relativePath("/foo", ""));
assertEquals(null, relativePath("/foo", "/foo"));
- assertEquals(null, relativePath("/foo", "/foo/")); // XXX or "/"?
+ assertEquals(null, relativePath("/foo", "/foo/")); // XXX or "/"?
assertEquals("/foo", relativePath("/", "/foo"));
assertEquals("/foo/", relativePath("/", "/foo/"));
assertEquals("/foo/", relativePath(null, "/foo/"));
@@ -159,7 +161,7 @@
assertEquals("foo..", removeDotSegments("foo.."));
assertEquals("foo.", removeDotSegments("foo."));
assertEquals("/.foo", removeDotSegments("/.foo"));
- assertEquals("/..foo", removeDotSegments("/..foo"));
+ assertEquals("/..foo", removeDotSegments("/..foo"));
// FELIX-4440
assertEquals("foo.bar", removeDotSegments("foo.bar"));