| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.felix.http.base.internal.registry; |
| |
| import javax.servlet.DispatcherType; |
| |
| import org.apache.felix.http.base.internal.HttpConfig; |
| import org.apache.felix.http.base.internal.handler.FilterHandler; |
| import org.apache.felix.http.base.internal.handler.ListenerHandler; |
| import org.apache.felix.http.base.internal.handler.ServletHandler; |
| import org.apache.felix.http.base.internal.runtime.FilterInfo; |
| import org.apache.felix.http.base.internal.runtime.ListenerInfo; |
| import org.apache.felix.http.base.internal.runtime.ServletContextHelperInfo; |
| import org.apache.felix.http.base.internal.runtime.ServletInfo; |
| import org.apache.felix.http.base.internal.runtime.dto.FailedDTOHolder; |
| import org.apache.felix.http.base.internal.service.HttpServiceFactory; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| import org.osgi.service.http.runtime.dto.ServletContextDTO; |
| |
| /** |
| * This registry keeps track of all processing components per context: |
| * - servlets |
| * - filters |
| * - error pages |
| */ |
| public final class PerContextHandlerRegistry implements Comparable<PerContextHandlerRegistry> |
| { |
| /** Service id of the context. */ |
| private final long serviceId; |
| |
| /** Ranking of the context. */ |
| private final int ranking; |
| |
| /** The context path. */ |
| private final String path; |
| |
| /** The context prefix. */ |
| private final String prefix; |
| |
| private final ServletRegistry servletRegistry = new ServletRegistry(); |
| |
| private final FilterRegistry filterRegistry = new FilterRegistry(); |
| |
| private final ErrorPageRegistry errorPageRegistry = new ErrorPageRegistry(); |
| |
| private final EventListenerRegistry eventListenerRegistry = new EventListenerRegistry(); |
| |
| private final HttpConfig config; |
| |
| |
| /** |
| * Default http service registry |
| */ |
| public PerContextHandlerRegistry(@NotNull final HttpConfig config) |
| { |
| this.config = config; |
| this.serviceId = HttpServiceFactory.HTTP_SERVICE_CONTEXT_SERVICE_ID; |
| this.ranking = Integer.MAX_VALUE; |
| this.path = "/"; |
| this.prefix = null; |
| } |
| |
| /** |
| * Registry for a servlet context helper (whiteboard support) |
| * @param info The servlet context helper info |
| */ |
| public PerContextHandlerRegistry(@NotNull final ServletContextHelperInfo info, @NotNull final HttpConfig config) |
| { |
| this.config = config; |
| this.serviceId = info.getServiceId(); |
| this.ranking = info.getRanking(); |
| this.path = info.getPath(); |
| if ( this.path.equals("/") ) |
| { |
| this.prefix = null; |
| } |
| else |
| { |
| this.prefix = this.path + "/"; |
| } |
| } |
| |
| public long getContextServiceId() |
| { |
| return this.serviceId; |
| } |
| |
| public HttpConfig getConfig() |
| { |
| return this.config; |
| } |
| |
| public void removeAll() |
| { |
| this.errorPageRegistry.cleanup(); |
| this.eventListenerRegistry.cleanup(); |
| this.filterRegistry.cleanup(); |
| this.servletRegistry.cleanup(); |
| } |
| |
| @Override |
| public int compareTo(@NotNull final PerContextHandlerRegistry other) |
| { |
| final int result = new Integer(other.path.length()).compareTo(this.path.length()); |
| if ( result == 0 ) { |
| if (this.ranking == other.ranking) |
| { |
| // Service id's can be negative. Negative id's follow the reverse natural ordering of integers. |
| int reverseOrder = ( this.serviceId <= 0 && other.serviceId <= 0 ) ? -1 : 1; |
| return reverseOrder * new Long(this.serviceId).compareTo(other.serviceId); |
| } |
| |
| return new Integer(other.ranking).compareTo(this.ranking); |
| } |
| return result; |
| } |
| |
| public String isMatching(@NotNull final String requestURI) |
| { |
| if (requestURI.equals(this.path)) |
| { |
| return ""; |
| } |
| if (this.prefix == null) |
| { |
| return requestURI; |
| } |
| if (requestURI.startsWith(this.prefix)) |
| { |
| return requestURI.substring(this.prefix.length() - 1); |
| } |
| return null; |
| } |
| |
| public PathResolution resolve(@NotNull final String relativeRequestURI) |
| { |
| return this.servletRegistry.resolve(relativeRequestURI); |
| } |
| |
| public ServletHandler resolveServletByName(final String name) |
| { |
| return this.servletRegistry.resolveByName(name); |
| } |
| |
| /** |
| * Get filter handlers for the request uri |
| * @param servletHandler The servlet handler (might be null) |
| * @param dispatcherType The dispatcher type |
| * @param requestURI The request uri |
| * @return The array of filter handlers, the array might be empty. |
| */ |
| public @NotNull FilterHandler[] getFilterHandlers(@Nullable final ServletHandler servletHandler, |
| @NotNull final DispatcherType dispatcherType, |
| @NotNull final String requestURI) |
| { |
| return this.filterRegistry.getFilterHandlers(servletHandler, dispatcherType, requestURI); |
| } |
| |
| /** |
| * Get the servlet handling the error. |
| * @param code The error code |
| * @param exception The optional exception |
| * @return The servlet handler or {@code null}. |
| */ |
| public @Nullable ServletHandler getErrorHandler(final int code, @Nullable final Throwable exception) |
| { |
| return this.errorPageRegistry.get(exception, code); |
| } |
| |
| public EventListenerRegistry getEventListenerRegistry() |
| { |
| return this.eventListenerRegistry; |
| } |
| |
| /** |
| * Create all DTOs for servlets, filters, resources and error pages |
| * @param dto The servlet context DTO |
| * @param failedDTOHolder The container for all failed DTOs |
| */ |
| public void getRuntime(final ServletContextDTO dto, |
| final FailedDTOHolder failedDTOHolder) |
| { |
| // collect filters |
| this.filterRegistry.getRuntimeInfo(dto, failedDTOHolder.failedFilterDTOs); |
| |
| // collect error pages |
| this.errorPageRegistry.getRuntimeInfo(dto, failedDTOHolder.failedErrorPageDTOs); |
| |
| // collect servlets and resources |
| this.servletRegistry.getRuntimeInfo(dto, failedDTOHolder.failedServletDTOs, failedDTOHolder.failedResourceDTOs); |
| |
| // collect listeners |
| this.eventListenerRegistry.getRuntimeInfo(dto, failedDTOHolder.failedListenerDTOs); |
| } |
| |
| /** |
| * Add a servlet |
| * @param handler The servlet handler |
| */ |
| public void registerServlet(@NotNull final ServletHandler handler) |
| { |
| this.servletRegistry.addServlet(handler); |
| this.errorPageRegistry.addServlet(handler); |
| } |
| |
| /** |
| * Remove a servlet |
| * @param servletInfo The servlet info |
| * @param destroy Destroy the servlet |
| */ |
| public void unregisterServlet(@NotNull final ServletInfo servletInfo, final boolean destroy) |
| { |
| this.servletRegistry.removeServlet(servletInfo, destroy); |
| this.errorPageRegistry.removeServlet(servletInfo, destroy); |
| } |
| |
| /** |
| * Add a filter |
| * @param handler The filter handler |
| */ |
| public void registerFilter(@NotNull final FilterHandler handler) |
| { |
| this.filterRegistry.addFilter(handler); |
| } |
| |
| /** |
| * Remove a filter |
| * @param info The filter info |
| * @param destroy Destroy the filter |
| */ |
| public void unregisterFilter(@NotNull final FilterInfo info, final boolean destroy) |
| { |
| this.filterRegistry.removeFilter(info, destroy); |
| } |
| |
| /** |
| * Register listeners |
| * @param listenerHandler |
| */ |
| public void registerListeners(@NotNull final ListenerHandler listenerHandler) |
| { |
| this.eventListenerRegistry.addListeners(listenerHandler); |
| } |
| |
| /** |
| * Unregister listeners |
| * |
| * @param info The listener info |
| */ |
| public void unregisterListeners(@NotNull final ListenerInfo info) |
| { |
| this.eventListenerRegistry.removeListeners(info); |
| } |
| |
| } |