| /******************************************************************************* |
| * Copyright (c) 2016, 2019 Raymond Augé and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Raymond Augé <raymond.auge@liferay.com> - Bug 436698 |
| ******************************************************************************/ |
| |
| package org.eclipse.equinox.http.servlet.internal.context; |
| |
| import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.*; |
| |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.security.AccessController; |
| import java.util.*; |
| import java.util.concurrent.*; |
| import java.util.concurrent.atomic.AtomicReference; |
| import java.util.regex.Pattern; |
| import java.util.regex.PatternSyntaxException; |
| import javax.servlet.*; |
| import javax.servlet.Filter; |
| import javax.servlet.http.*; |
| import org.eclipse.equinox.http.servlet.internal.HttpServiceRuntimeImpl; |
| import org.eclipse.equinox.http.servlet.internal.customizer.*; |
| import org.eclipse.equinox.http.servlet.internal.dto.ExtendedErrorPageDTO; |
| import org.eclipse.equinox.http.servlet.internal.dto.ExtendedErrorPageDTO.ErrorCodeType; |
| import org.eclipse.equinox.http.servlet.internal.error.*; |
| import org.eclipse.equinox.http.servlet.internal.registration.*; |
| import org.eclipse.equinox.http.servlet.internal.registration.FilterRegistration; |
| import org.eclipse.equinox.http.servlet.internal.registration.ServletRegistration; |
| import org.eclipse.equinox.http.servlet.internal.servlet.*; |
| import org.eclipse.equinox.http.servlet.internal.util.*; |
| import org.osgi.framework.*; |
| import org.osgi.service.http.context.ServletContextHelper; |
| import org.osgi.service.http.runtime.dto.*; |
| import org.osgi.util.tracker.ServiceTracker; |
| |
| /** |
| * @author Raymond Augé |
| */ |
| public class ContextController { |
| |
| public ContextController( |
| BundleContext trackingContextParam, BundleContext consumingContext, |
| ServiceReference<ServletContextHelper> serviceReference, |
| ServletContext parentServletContext, HttpServiceRuntimeImpl httpServiceRuntime) { |
| |
| this.trackingContext = trackingContextParam; |
| this.consumingContext = consumingContext; |
| this.serviceReference = serviceReference; |
| this.httpServiceRuntime = httpServiceRuntime; |
| this.contextName = validateName(); |
| this.contextPath = validatePath(); |
| this.proxyContext = new ProxyContext(contextName, parentServletContext); |
| this.contextServiceId = (Long)serviceReference.getProperty(Constants.SERVICE_ID); |
| this.servletContextHelperRefFilter = createFilter(contextServiceId); |
| |
| this.initParams = ServiceProperties.parseInitParams( |
| serviceReference, HTTP_WHITEBOARD_CONTEXT_INIT_PARAM_PREFIX, parentServletContext); |
| |
| listenerServiceTracker = new ServiceTracker<EventListener, AtomicReference<ListenerRegistration>>( |
| trackingContext, httpServiceRuntime.getListenerFilter(), |
| new ContextListenerTrackerCustomizer( |
| trackingContext, httpServiceRuntime, this)); |
| |
| listenerServiceTracker.open(); |
| |
| filterServiceTracker = new ServiceTracker<Filter, AtomicReference<FilterRegistration>>( |
| trackingContext, httpServiceRuntime.getFilterFilter(), |
| new ContextFilterTrackerCustomizer( |
| trackingContext, httpServiceRuntime, this)); |
| |
| filterServiceTracker.open(); |
| |
| errorPageServiceTracker = new ServiceTracker<Servlet, AtomicReference<ErrorPageRegistration>>( |
| trackingContext, httpServiceRuntime.getErrorPageFilter(), |
| new ContextErrorPageTrackerCustomizer( |
| trackingContext, httpServiceRuntime, this)); |
| |
| errorPageServiceTracker.open(); |
| |
| servletServiceTracker = new ServiceTracker<Servlet, AtomicReference<ServletRegistration>>( |
| trackingContext, httpServiceRuntime.getServletFilter(), |
| new ContextServletTrackerCustomizer( |
| trackingContext, httpServiceRuntime, this)); |
| |
| servletServiceTracker.open(); |
| |
| resourceServiceTracker = new ServiceTracker<Object, AtomicReference<ResourceRegistration>>( |
| trackingContext, httpServiceRuntime.getResourceFilter(), |
| new ContextResourceTrackerCustomizer( |
| trackingContext, httpServiceRuntime, this)); |
| |
| resourceServiceTracker.open(); |
| } |
| |
| public ErrorPageRegistration addErrorPageRegistration(ServiceReference<Servlet> servletRef) { |
| ServiceHolder<Servlet> servletHolder = new ServiceHolder<Servlet>(consumingContext.getServiceObjects(servletRef)); |
| Servlet servlet = servletHolder.get(); |
| ErrorPageRegistration registration = null; |
| //boolean addedRegisteredObject = false; |
| try { |
| if (servlet == null) { |
| throw new IllegalArgumentException("Servlet cannot be null"); //$NON-NLS-1$ |
| } |
| //addedRegisteredObject = httpServiceRuntime.getRegisteredObjects().add(servlet); |
| //if (!addedRegisteredObject) { |
| // throw new HttpWhiteboardFailureException("Multiple registration of instance detected. Prototype scope is recommended: " + servletRef, DTOConstants.FAILURE_REASON_SERVICE_IN_USE); //$NON-NLS-1$ |
| //} |
| registration = doAddErrorPageRegistration(servletHolder, servletRef); |
| } finally { |
| if (registration == null) { |
| // Always attempt to release here; even though destroy() may have been called |
| // on the registration while failing to add. There are cases where no |
| // ServletRegistration may have even been created at all to call destory() on. |
| // Also, addedRegisteredObject may be false which means we never call doAddServletRegistration |
| servletHolder.release(); |
| //if (addedRegisteredObject) { |
| // httpServiceRuntime.getRegisteredObjects().remove(servlet); |
| //} |
| } |
| } |
| return registration; |
| } |
| |
| private ErrorPageRegistration doAddErrorPageRegistration(ServiceHolder<Servlet> servletHolder, ServiceReference<Servlet> servletRef) { |
| ExtendedErrorPageDTO errorPageDTO = DTOUtil.assembleErrorPageDTO(servletRef, getServiceId(), true); |
| errorPageDTO.servletInfo = servletHolder.get().getServletInfo(); |
| errorPageDTO.serviceId = servletHolder.getServiceId(); |
| |
| if (((errorPageDTO.errorCodes == null) || (errorPageDTO.errorCodes.length == 0)) && |
| ((errorPageDTO.exceptions == null) || (errorPageDTO.exceptions.length == 0))) { |
| |
| throw new HttpWhiteboardFailureException("'errorPage' expects String, String[] or Collection<String>.", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$ |
| } |
| |
| if (errorPageDTO.name == null) { |
| errorPageDTO.name = servletHolder.get().getClass().getName(); |
| } |
| |
| ServletContextHelper curServletContextHelper = getServletContextHelper( |
| servletHolder.getBundle()); |
| |
| ServletContext servletContext = createServletContext( |
| servletHolder.getBundle(), curServletContextHelper); |
| ErrorPageRegistration errorPageRegistration = new ErrorPageRegistration( |
| servletHolder, errorPageDTO, curServletContextHelper, this); |
| ServletConfig servletConfig = new ServletConfigImpl( |
| errorPageDTO.name, errorPageDTO.initParams, servletContext); |
| |
| try { |
| errorPageRegistration.init(servletConfig); |
| } |
| catch (Throwable t) { |
| errorPageRegistration.destroy(); |
| |
| return Throw.unchecked(t); |
| } |
| |
| recordErrorPageShadowing(errorPageRegistration); |
| |
| endpointRegistrations.add(errorPageRegistration); |
| |
| return errorPageRegistration; |
| } |
| |
| public FilterRegistration addFilterRegistration(ServiceReference<Filter> filterRef) throws ServletException { |
| ServiceHolder<Filter> filterHolder = new ServiceHolder<Filter>(consumingContext.getServiceObjects(filterRef)); |
| Filter filter = filterHolder.get(); |
| FilterRegistration registration = null; |
| boolean addedRegisteredObject = false; |
| try { |
| if (filter == null) { |
| throw new IllegalArgumentException("Filter cannot be null"); //$NON-NLS-1$ |
| } |
| addedRegisteredObject = httpServiceRuntime.getRegisteredObjects().add(filter); |
| if (!addedRegisteredObject) { |
| throw new HttpWhiteboardFailureException("Multiple registration of instance detected. Prototype scope is recommended: " + filterRef, DTOConstants.FAILURE_REASON_SERVICE_IN_USE); //$NON-NLS-1$ |
| } |
| registration = doAddFilterRegistration(filterHolder, filterRef); |
| } finally { |
| if (registration == null) { |
| filterHolder.release(); |
| if (addedRegisteredObject) { |
| httpServiceRuntime.getRegisteredObjects().remove(filter); |
| } |
| } |
| } |
| return registration; |
| } |
| |
| private FilterRegistration doAddFilterRegistration(ServiceHolder<Filter> filterHolder, ServiceReference<Filter> filterRef) throws ServletException { |
| boolean asyncSupported = ServiceProperties.parseBoolean( |
| filterRef, HTTP_WHITEBOARD_FILTER_ASYNC_SUPPORTED); |
| |
| List<String> dispatcherList = StringPlus.from( |
| filterRef.getProperty( |
| HTTP_WHITEBOARD_FILTER_DISPATCHER)); |
| String[] dispatchers = dispatcherList.toArray(new String[0]); |
| Integer filterPriority = (Integer)filterRef.getProperty( |
| Constants.SERVICE_RANKING); |
| if (filterPriority == null) { |
| filterPriority = Integer.valueOf(0); |
| } |
| Map<String, String> filterInitParams = ServiceProperties.parseInitParams( |
| filterRef, HTTP_WHITEBOARD_FILTER_INIT_PARAM_PREFIX); |
| List<String> patternList = StringPlus.from( |
| filterRef.getProperty( |
| HTTP_WHITEBOARD_FILTER_PATTERN)); |
| String[] patterns = patternList.toArray(new String[0]); |
| List<String> regexList = StringPlus.from( |
| filterRef.getProperty( |
| HTTP_WHITEBOARD_FILTER_REGEX)); |
| String[] regexs = regexList.toArray(new String[0]); |
| List<String> servletList = StringPlus.from( |
| filterRef.getProperty( |
| HTTP_WHITEBOARD_FILTER_SERVLET)); |
| String[] servletNames = servletList.toArray(new String[0]); |
| |
| String name = ServiceProperties.parseName(filterRef.getProperty( |
| HTTP_WHITEBOARD_FILTER_NAME), filterHolder.get()); |
| |
| if (((patterns == null) || (patterns.length == 0)) && |
| ((regexs == null) || (regexs.length == 0)) && |
| ((servletNames == null) || (servletNames.length == 0))) { |
| |
| throw new HttpWhiteboardFailureException( |
| "Patterns, regex or servletNames must contain a value.", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$ |
| } |
| |
| if (patterns != null) { |
| for (String pattern : patterns) { |
| checkPattern(pattern); |
| } |
| } |
| |
| if (regexs != null) { |
| for (String regex : regexs) { |
| checkRegex(regex); |
| } |
| } |
| |
| Filter filter = filterHolder.get(); |
| |
| if (name == null) { |
| name = filter.getClass().getName(); |
| } |
| |
| dispatchers = checkDispatcher(dispatchers); |
| |
| FilterDTO filterDTO = new FilterDTO(); |
| |
| filterDTO.asyncSupported = asyncSupported; |
| filterDTO.dispatcher = sort(dispatchers); |
| filterDTO.initParams = filterInitParams; |
| filterDTO.name = name; |
| filterDTO.patterns = sort(patterns); |
| filterDTO.regexs = regexs; |
| filterDTO.serviceId = filterHolder.getServiceId(); |
| filterDTO.servletContextId = contextServiceId; |
| filterDTO.servletNames = sort(servletNames); |
| |
| ServletContextHelper curServletContextHelper = getServletContextHelper( |
| filterHolder.getBundle()); |
| |
| ServletContext servletContext = createServletContext( |
| filterHolder.getBundle(), curServletContextHelper); |
| FilterRegistration newRegistration = new FilterRegistration( |
| filterHolder, filterDTO, filterPriority, this); |
| FilterConfig filterConfig = new FilterConfigImpl( |
| name, filterInitParams, servletContext); |
| |
| newRegistration.init(filterConfig); |
| |
| filterRegistrations.add(newRegistration); |
| return newRegistration; |
| } |
| |
| public ListenerRegistration addListenerRegistration(ServiceReference<EventListener> listenerRef) throws ServletException { |
| ServiceHolder<EventListener> listenerHolder = new ServiceHolder<EventListener>(consumingContext.getServiceObjects(listenerRef)); |
| EventListener listener = listenerHolder.get(); |
| ListenerRegistration registration = null; |
| try { |
| if (listener == null) { |
| throw new IllegalArgumentException("EventListener cannot be null"); //$NON-NLS-1$ |
| } |
| registration = doAddListenerRegistration(listenerHolder, listenerRef); |
| } finally { |
| if (registration == null) { |
| listenerHolder.release(); |
| } |
| } |
| return registration; |
| } |
| |
| private ListenerRegistration doAddListenerRegistration( |
| ServiceHolder<EventListener> listenerHolder, |
| ServiceReference<EventListener> listenerRef) throws ServletException { |
| |
| EventListener eventListener = listenerHolder.get(); |
| List<Class<? extends EventListener>> classes = getListenerClasses(listenerRef); |
| |
| if (classes.isEmpty()) { |
| throw new IllegalArgumentException( |
| "EventListener does not implement a supported type."); //$NON-NLS-1$ |
| } |
| |
| for (ListenerRegistration listenerRegistration : listenerRegistrations) { |
| if (listenerRegistration.getT().equals(eventListener)) { |
| throw new ServletException( |
| "EventListener has already been registered."); //$NON-NLS-1$ |
| } |
| } |
| |
| ListenerDTO listenerDTO = new ListenerDTO(); |
| |
| listenerDTO.serviceId = listenerHolder.getServiceId(); |
| listenerDTO.servletContextId = contextServiceId; |
| listenerDTO.types = asStringArray(classes); |
| |
| ServletContextHelper curServletContextHelper = getServletContextHelper( |
| listenerHolder.getBundle()); |
| |
| ServletContext servletContext = createServletContext( |
| listenerHolder.getBundle(), curServletContextHelper); |
| ListenerRegistration listenerRegistration = new ListenerRegistration( |
| listenerHolder, classes, listenerDTO, servletContext, this); |
| |
| if (classes.contains(ServletContextListener.class)) { |
| ServletContextListener servletContextListener = |
| (ServletContextListener)listenerRegistration.getT(); |
| |
| servletContextListener.contextInitialized( |
| new ServletContextEvent(servletContext)); |
| } |
| |
| listenerRegistrations.add(listenerRegistration); |
| |
| eventListeners.put(classes, listenerRegistration); |
| |
| return listenerRegistration; |
| } |
| |
| public ResourceRegistration addResourceRegistration(ServiceReference<?> resourceRef) { |
| ClassLoader legacyTCCL = (ClassLoader)resourceRef.getProperty(Const.EQUINOX_LEGACY_TCCL_PROP); |
| Integer rankProp = (Integer) resourceRef.getProperty(Constants.SERVICE_RANKING); |
| int serviceRanking = rankProp == null ? 0 : rankProp.intValue(); |
| Object patternObj = resourceRef.getProperty(HTTP_WHITEBOARD_RESOURCE_PATTERN); |
| if (!(patternObj instanceof String) && |
| !(patternObj instanceof String[]) && |
| !(patternObj instanceof Collection)) { |
| throw new HttpWhiteboardFailureException("Expect pattern to be String+ (String | String[] | Collection<String>)", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$ |
| } |
| List<String> patternList = StringPlus.from(patternObj); |
| String[] patterns = patternList.toArray(new String[0]); |
| Long serviceId = (Long)resourceRef.getProperty( |
| Constants.SERVICE_ID); |
| if (legacyTCCL != null) { |
| // this is a legacy registration; use a negative id for the DTO |
| serviceId = -serviceId; |
| } |
| Object prefixObj = resourceRef.getProperty( |
| HTTP_WHITEBOARD_RESOURCE_PREFIX); |
| |
| checkPrefix(prefixObj); |
| String prefix = (String)prefixObj; |
| |
| if ((patterns == null) || (patterns.length < 1)) { |
| throw new IllegalArgumentException( |
| "Patterns must contain a value."); //$NON-NLS-1$ |
| } |
| |
| for (String pattern : patterns) { |
| checkPattern(pattern); |
| } |
| |
| Bundle bundle = resourceRef.getBundle(); |
| ServletContextHelper curServletContextHelper = getServletContextHelper( |
| bundle); |
| Servlet servlet = new ResourceServlet( |
| prefix, curServletContextHelper, AccessController.getContext()); |
| |
| ResourceDTO resourceDTO = new ResourceDTO(); |
| |
| resourceDTO.patterns = sort(patterns); |
| resourceDTO.prefix = prefix; |
| resourceDTO.serviceId = serviceId; |
| resourceDTO.servletContextId = contextServiceId; |
| |
| ServletContext servletContext = createServletContext( |
| bundle, curServletContextHelper); |
| ResourceRegistration resourceRegistration = new ResourceRegistration( |
| resourceRef, new ServiceHolder<Servlet>(servlet, bundle, serviceId, serviceRanking, legacyTCCL), |
| resourceDTO, curServletContextHelper, this); |
| ServletConfig servletConfig = new ServletConfigImpl( |
| resourceRegistration.getName(), new HashMap<String, String>(), |
| servletContext); |
| |
| try { |
| resourceRegistration.init(servletConfig); |
| } |
| catch (Throwable t) { |
| resourceRegistration.destroy(); |
| |
| return Throw.unchecked(t); |
| } |
| |
| recordEndpointShadowing(resourceRegistration); |
| |
| endpointRegistrations.add(resourceRegistration); |
| |
| return resourceRegistration; |
| } |
| |
| public ServletRegistration addServletRegistration(ServiceReference<Servlet> servletRef) { |
| ServiceHolder<Servlet> servletHolder = new ServiceHolder<Servlet>(consumingContext.getServiceObjects(servletRef)); |
| Servlet servlet = servletHolder.get(); |
| ServletRegistration registration = null; |
| boolean addedRegisteredObject = false; |
| try { |
| if (servlet == null) { |
| throw new IllegalArgumentException("Servlet cannot be null"); //$NON-NLS-1$ |
| } |
| addedRegisteredObject = httpServiceRuntime.getRegisteredObjects().add(servlet); |
| if (!addedRegisteredObject) { |
| throw new HttpWhiteboardFailureException("Multiple registration of instance detected. Prototype scope is recommended: " + servletRef, DTOConstants.FAILURE_REASON_SERVICE_IN_USE); //$NON-NLS-1$ |
| } |
| registration = doAddServletRegistration(servletHolder, servletRef); |
| } finally { |
| if (registration == null) { |
| // Always attempt to release here; even though destroy() may have been called |
| // on the registration while failing to add. There are cases where no |
| // ServletRegistration may have even been created at all to call destory() on. |
| // Also, addedRegisteredObject may be false which means we never call doAddServletRegistration |
| servletHolder.release(); |
| if (addedRegisteredObject) { |
| httpServiceRuntime.getRegisteredObjects().remove(servlet); |
| } |
| } |
| } |
| return registration; |
| } |
| |
| private ServletRegistration doAddServletRegistration(ServiceHolder<Servlet> servletHolder, ServiceReference<Servlet> servletRef) { |
| ServletDTO servletDTO = DTOUtil.assembleServletDTO(servletRef, getServiceId(), true); |
| servletDTO.servletInfo = servletHolder.get().getServletInfo(); |
| servletDTO.serviceId = servletHolder.getServiceId(); |
| |
| if (((servletDTO.patterns == null) || (servletDTO.patterns.length == 0)) && |
| (servletDTO.name == null)) { |
| |
| StringBuilder sb = new StringBuilder(); |
| sb.append("One of the service properties "); //$NON-NLS-1$ |
| sb.append(HTTP_WHITEBOARD_SERVLET_NAME); |
| sb.append(", "); //$NON-NLS-1$ |
| sb.append(HTTP_WHITEBOARD_SERVLET_PATTERN); |
| sb.append(" must contain a value."); //$NON-NLS-1$ |
| |
| throw new HttpWhiteboardFailureException(sb.toString(), DTOConstants.FAILURE_REASON_VALIDATION_FAILED); |
| } |
| |
| if (servletDTO.name == null) { |
| servletDTO.name = servletHolder.get().getClass().getName(); |
| } |
| |
| ServletContextHelper curServletContextHelper = getServletContextHelper( |
| servletHolder.getBundle()); |
| |
| ServletContext servletContext = createServletContext( |
| servletHolder.getBundle(), curServletContextHelper); |
| ServletRegistration servletRegistration = new ServletRegistration( |
| servletHolder, servletDTO, curServletContextHelper, this, |
| servletContext); |
| ServletConfig servletConfig = new ServletConfigImpl( |
| servletDTO.name, servletDTO.initParams, servletContext); |
| |
| try { |
| servletRegistration.init(servletConfig); |
| } |
| catch (Throwable t) { |
| servletRegistration.destroy(); |
| |
| return Throw.unchecked(t); |
| } |
| |
| recordEndpointShadowing(servletRegistration); |
| |
| endpointRegistrations.add(servletRegistration); |
| |
| return servletRegistration; |
| } |
| |
| private void recordEndpointShadowing(EndpointRegistration<?> newRegistration) { |
| Set<EndpointRegistration<?>> shadowedRegs = new HashSet<EndpointRegistration<?>>(); |
| for (EndpointRegistration<?> existingRegistration : endpointRegistrations) { |
| for (String newPattern : newRegistration.getPatterns()) { |
| for (String existingPattern : existingRegistration.getPatterns()) { |
| if (newPattern.equals(existingPattern)) { |
| // the new reg is shadowing an existing reg |
| if (newRegistration.compareTo(existingRegistration) < 0) { |
| shadowedRegs.add(existingRegistration); |
| } |
| // the new reg is shadowed by existing reg |
| else { |
| shadowedRegs.add(newRegistration); |
| } |
| // notice that we keep checking all the existing regs. more than one could be shadowed because reg's multi patterns |
| } |
| } |
| } |
| } |
| for (EndpointRegistration<?> shadowedReg : shadowedRegs) { |
| if (shadowedReg instanceof ServletRegistration) { |
| recordFailedServletDTO(shadowedReg.getServiceReference(), (ServletDTO)shadowedReg.getD(), DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE); |
| } |
| else { |
| recordFailedResourceDTO(shadowedReg.getServiceReference(), (ResourceDTO)shadowedReg.getD(), DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE); |
| } |
| } |
| } |
| |
| private void recordErrorPageShadowing(ErrorPageRegistration newRegistration) { |
| Set<ErrorPageRegistration> shadowedEPs = new HashSet<ErrorPageRegistration>(); |
| for (EndpointRegistration<?> existingRegistration : endpointRegistrations) { |
| if (!(existingRegistration instanceof ErrorPageRegistration)) { |
| continue; |
| } |
| ErrorPageRegistration existingSRegistration = (ErrorPageRegistration)existingRegistration; |
| ExtendedErrorPageDTO existingErrorPageDTO = existingSRegistration.getD(); |
| if ((existingErrorPageDTO == null) || |
| (((existingErrorPageDTO.errorCodeType == ErrorCodeType.RANGE_4XX) || (existingErrorPageDTO.errorCodeType == ErrorCodeType.RANGE_5XX)) && (newRegistration.getD().errorCodeType == ErrorCodeType.SPECIFIC))) { |
| continue; |
| } |
| if (((existingErrorPageDTO.errorCodeType == ErrorCodeType.RANGE_4XX) && (newRegistration.getD().errorCodeType == ErrorCodeType.RANGE_4XX)) || |
| ((existingErrorPageDTO.errorCodeType == ErrorCodeType.RANGE_5XX) && (newRegistration.getD().errorCodeType == ErrorCodeType.RANGE_5XX))) { |
| if (newRegistration.compareTo(existingSRegistration) < 0) { |
| shadowedEPs.add(existingSRegistration); |
| } |
| // the new reg is shadowed by existing reg |
| else { |
| shadowedEPs.add(newRegistration); |
| } |
| continue; |
| } |
| for (long newErrorCode : newRegistration.getD().errorCodes) { |
| for (long existingCode : existingErrorPageDTO.errorCodes) { |
| if (newErrorCode == existingCode) { |
| // the new reg is shadowing an existing reg |
| if (newRegistration.compareTo(existingSRegistration) < 0) { |
| shadowedEPs.add(existingSRegistration); |
| } |
| // the new reg is shadowed by existing reg |
| else { |
| shadowedEPs.add(newRegistration); |
| } |
| // notice that we keep checking all the existing regs. more than one could be shadowed because reg's multi patterns |
| } |
| } |
| } |
| for (String newException : newRegistration.getD().exceptions) { |
| for (String existingException : existingErrorPageDTO.exceptions) { |
| if (newException.equals(existingException)) { |
| // the new reg is shadowing an existing reg |
| if (newRegistration.compareTo(existingSRegistration) < 0) { |
| shadowedEPs.add(existingSRegistration); |
| } |
| // the new reg is shadowed by existing reg |
| else { |
| shadowedEPs.add(newRegistration); |
| } |
| // notice that we keep checking all the existing regs. more than one could be shadowed because reg's multi patterns |
| } |
| } |
| } |
| } |
| for (ErrorPageRegistration shadowedReg : shadowedEPs) { |
| recordFailedErrorPageDTO(shadowedReg.getServiceReference(), shadowedReg.getD(), DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE); |
| } |
| } |
| |
| public synchronized void destroy() { |
| flushActiveSessions(); |
| resourceServiceTracker.close(); |
| servletServiceTracker.close(); |
| errorPageServiceTracker.close(); |
| filterServiceTracker.close(); |
| listenerServiceTracker.close(); |
| |
| endpointRegistrations.clear(); |
| filterRegistrations.clear(); |
| listenerRegistrations.clear(); |
| eventListeners.clear(); |
| proxyContext.destroy(); |
| |
| shutdown = true; |
| } |
| |
| public void createContextAttributes() { |
| getProxyContext().createContextAttributes(this); |
| } |
| |
| public void destroyContextAttributes() { |
| if (shutdown) { |
| return; |
| } |
| |
| proxyContext.destroyContextAttributes(this); |
| } |
| |
| public boolean isLegacyContext() { |
| return serviceReference.getProperty(HTTP_SERVICE_CONTEXT_PROPERTY) != null; |
| } |
| |
| public String getContextName() { |
| return contextName; |
| } |
| |
| public String getContextPath() { |
| return contextPath; |
| } |
| |
| public DispatchTargets getDispatchTargets( |
| String pathString, RequestInfoDTO requestInfoDTO) { |
| |
| Path path = new Path(pathString); |
| |
| String queryString = path.getQueryString(); |
| String requestURI = path.getRequestURI(); |
| |
| // perfect match |
| DispatchTargets dispatchTargets = getDispatchTargets( |
| requestURI, null, queryString, Match.EXACT, requestInfoDTO); |
| |
| if (dispatchTargets == null) { |
| // extension match |
| |
| dispatchTargets = getDispatchTargets( |
| requestURI, path.getExtension(), queryString, Match.EXTENSION, |
| requestInfoDTO); |
| } |
| |
| if (dispatchTargets == null) { |
| // regex match |
| dispatchTargets = getDispatchTargets( |
| requestURI, null, queryString, Match.REGEX, requestInfoDTO); |
| } |
| |
| if (dispatchTargets == null) { |
| // handle '/' aliases |
| dispatchTargets = getDispatchTargets( |
| requestURI, null, queryString, Match.DEFAULT_SERVLET, |
| requestInfoDTO); |
| } |
| |
| return dispatchTargets; |
| } |
| |
| private DispatchTargets getDispatchTargets( |
| String requestURI, String extension, String queryString, Match match, |
| RequestInfoDTO requestInfoDTO) { |
| |
| int pos = requestURI.lastIndexOf('/'); |
| |
| String servletPath = requestURI; |
| String pathInfo = null; |
| |
| if (match == Match.DEFAULT_SERVLET) { |
| pathInfo = servletPath; |
| servletPath = Const.SLASH; |
| } |
| |
| do { |
| DispatchTargets dispatchTargets = getDispatchTargets( |
| null, requestURI, servletPath, pathInfo, |
| extension, queryString, match, requestInfoDTO); |
| |
| if (dispatchTargets != null) { |
| return dispatchTargets; |
| } |
| |
| if (match == Match.EXACT) { |
| break; |
| } |
| |
| if (pos > -1) { |
| String newServletPath = requestURI.substring(0, pos); |
| pathInfo = requestURI.substring(pos); |
| servletPath = newServletPath; |
| pos = servletPath.lastIndexOf('/'); |
| |
| continue; |
| } |
| |
| break; |
| } |
| while (true); |
| |
| return null; |
| } |
| |
| public DispatchTargets getDispatchTargets( |
| String servletName, String requestURI, String servletPath, |
| String pathInfo, String extension, String queryString, Match match, |
| RequestInfoDTO requestInfoDTO) { |
| |
| checkShutdown(); |
| |
| EndpointRegistration<?> endpointRegistration = null; |
| for (EndpointRegistration<?> curEndpointRegistration : endpointRegistrations) { |
| if (curEndpointRegistration.match(servletName, servletPath, pathInfo, extension, match) != null) { |
| endpointRegistration = curEndpointRegistration; |
| |
| break; |
| } |
| } |
| |
| if (endpointRegistration == null) { |
| return null; |
| } |
| |
| if (match == Match.EXTENSION) { |
| servletPath = servletPath + pathInfo; |
| pathInfo = null; |
| } |
| |
| addEnpointRegistrationsToRequestInfo( |
| endpointRegistration, requestInfoDTO); |
| |
| if (filterRegistrations.isEmpty()) { |
| return new DispatchTargets( |
| this, endpointRegistration, servletName, requestURI, servletPath, |
| pathInfo, queryString); |
| } |
| |
| if (requestURI != null) { |
| int x = requestURI.lastIndexOf('.'); |
| |
| if (x != -1) { |
| extension = requestURI.substring(x + 1); |
| } |
| } |
| |
| List<FilterRegistration> matchingFilterRegistrations = |
| new ArrayList<FilterRegistration>(); |
| |
| collectFilters( |
| matchingFilterRegistrations, endpointRegistration.getName(), requestURI, |
| servletPath, pathInfo, extension); |
| |
| addFilterRegistrationsToRequestInfo( |
| matchingFilterRegistrations, requestInfoDTO); |
| |
| return new DispatchTargets( |
| this, endpointRegistration, matchingFilterRegistrations, servletName, |
| requestURI, servletPath, pathInfo, queryString); |
| } |
| |
| private void collectFilters( |
| List<FilterRegistration> matchingFilterRegistrations, |
| String servletName, String requestURI, String servletPath, String pathInfo, String extension) { |
| |
| for (FilterRegistration filterRegistration : filterRegistrations) { |
| if ((filterRegistration.match( |
| servletName, requestURI, extension, null) != null) && |
| !matchingFilterRegistrations.contains(filterRegistration)) { |
| |
| matchingFilterRegistrations.add(filterRegistration); |
| } |
| } |
| } |
| |
| public Map<String, HttpSessionAdaptor> getActiveSessions() { |
| return activeSessions; |
| } |
| |
| public Set<EndpointRegistration<?>> getEndpointRegistrations() { |
| return endpointRegistrations; |
| } |
| |
| public EventListeners getEventListeners() { |
| return eventListeners; |
| } |
| |
| public Set<FilterRegistration> getFilterRegistrations() { |
| return filterRegistrations; |
| } |
| |
| public String getFullContextPath() { |
| if (fullContextPath != null) { |
| return fullContextPath; |
| } |
| |
| return fullContextPath = getFullContextPath0(); |
| } |
| |
| private String getFullContextPath0() { |
| List<String> endpoints = httpServiceRuntime.getHttpServiceEndpoints(); |
| |
| if (endpoints.isEmpty()) { |
| return proxyContext.getServletPath().concat(contextPath); |
| } |
| |
| String defaultEndpoint = endpoints.get(0); |
| |
| if (defaultEndpoint.length() > 0) { |
| int protocol = defaultEndpoint.indexOf(Const.PROTOCOL); |
| if (protocol > -1) { |
| defaultEndpoint = defaultEndpoint.substring(protocol + 3); |
| } |
| int slash = defaultEndpoint.indexOf(Const.SLASH); |
| if (defaultEndpoint.endsWith(Const.SLASH)) { |
| defaultEndpoint = defaultEndpoint.substring(slash, defaultEndpoint.length() - 1); |
| } |
| } |
| |
| return defaultEndpoint + contextPath; |
| } |
| |
| public HttpServiceRuntimeImpl getHttpServiceRuntime() { |
| return httpServiceRuntime; |
| } |
| |
| public Map<String, String> getInitParams() { |
| return initParams; |
| } |
| |
| public Set<ListenerRegistration> getListenerRegistrations() { |
| return listenerRegistrations; |
| } |
| |
| public ProxyContext getProxyContext() { |
| return proxyContext; |
| } |
| |
| public long getServiceId() { |
| return contextServiceId; |
| } |
| |
| public synchronized ServletContextDTO getServletContextDTO(){ |
| ServletContextDTO servletContextDTO = new ServletContextDTO(); |
| |
| ServletContext servletContext = proxyContext.getServletContext(); |
| |
| servletContextDTO.attributes = getDTOAttributes(servletContext); |
| servletContextDTO.contextPath = getContextPath(); |
| servletContextDTO.initParams = new HashMap<String, String>(initParams); |
| servletContextDTO.name = getContextName(); |
| servletContextDTO.serviceId = getServiceId(); |
| |
| collectEndpointDTOs(servletContextDTO); |
| collectFilterDTOs(servletContextDTO); |
| collectListenerDTOs(servletContextDTO); |
| |
| return servletContextDTO; |
| } |
| |
| public boolean matches(ServiceReference<?> whiteBoardService) { |
| // make sure the context helper is either one of the built-in ones registered by this http whiteboard implementation; |
| // or is visible to the whiteboard registering bundle. |
| |
| if (!visibleContextHelper(whiteBoardService)) { |
| return false; |
| } |
| |
| String contextSelector = (String) whiteBoardService.getProperty( |
| HTTP_WHITEBOARD_CONTEXT_SELECT); |
| |
| // custom equinox behaviour |
| if (contextName.equals(contextSelector)) { |
| return true; |
| } |
| |
| if (contextSelector == null) { |
| contextSelector = httpServiceRuntime.getDefaultContextSelectFilter(whiteBoardService); |
| if (contextSelector == null) { |
| contextSelector = "(" + //$NON-NLS-1$ |
| HTTP_WHITEBOARD_CONTEXT_NAME + "=" //$NON-NLS-1$ |
| + HTTP_WHITEBOARD_DEFAULT_CONTEXT_NAME + ")"; //$NON-NLS-1$ |
| } |
| } |
| |
| if (contextSelector.startsWith(Const.OPEN_PAREN)) { |
| org.osgi.framework.Filter targetFilter; |
| |
| try { |
| targetFilter = FrameworkUtil.createFilter(contextSelector); |
| } |
| catch (InvalidSyntaxException ise) { |
| throw new IllegalArgumentException(ise); |
| } |
| |
| if (matches(targetFilter)) { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| private boolean visibleContextHelper(ServiceReference<?> whiteBoardService) { |
| if (consumingContext.getBundle().equals(serviceReference.getBundle())) { |
| Boolean defaultContextHelper = (Boolean) serviceReference.getProperty(Const.EQUINOX_HTTP_WHITEBOARD_CONTEXT_HELPER_DEFAULT); |
| if (defaultContextHelper == null) { |
| return true; |
| } |
| } |
| try { |
| if (whiteBoardService.getBundle().getBundleContext().getAllServiceReferences(ServletContextHelper.class.getName(), servletContextHelperRefFilter) != null) { |
| return true; |
| } |
| } |
| catch (InvalidSyntaxException e) { |
| // ignore |
| } |
| return false; |
| } |
| |
| public boolean matches(org.osgi.framework.Filter targetFilter) { |
| return targetFilter.match(serviceReference); |
| } |
| |
| @Override |
| public String toString() { |
| String value = string; |
| |
| if (value == null) { |
| value = SIMPLE_NAME + '[' + contextName + ", " + trackingContext.getBundle() + ']'; //$NON-NLS-1$ |
| |
| string = value; |
| } |
| |
| return value; |
| } |
| |
| private void addEnpointRegistrationsToRequestInfo( |
| EndpointRegistration<?> endpointRegistration, |
| RequestInfoDTO requestInfoDTO) { |
| |
| if (requestInfoDTO == null) { |
| return; |
| } |
| |
| requestInfoDTO.servletContextId = getServiceId(); |
| |
| if (endpointRegistration instanceof ResourceRegistration) { |
| requestInfoDTO.resourceDTO = |
| (ResourceDTO)endpointRegistration.getD(); |
| } |
| else { |
| requestInfoDTO.servletDTO = |
| (ServletDTO)endpointRegistration.getD(); |
| } |
| } |
| |
| private void addFilterRegistrationsToRequestInfo( |
| List<FilterRegistration> matchedFilterRegistrations, |
| RequestInfoDTO requestInfoDTO) { |
| |
| if (requestInfoDTO == null) { |
| return; |
| } |
| |
| List<FilterDTO> filterDTOs = new ArrayList<FilterDTO>(); |
| |
| for (FilterRegistration filterRegistration : matchedFilterRegistrations) { |
| if (Arrays.binarySearch(filterRegistration.getD().dispatcher, DispatcherType.REQUEST.toString()) > -1) { |
| filterDTOs.add(filterRegistration.getD()); |
| } |
| } |
| |
| requestInfoDTO.filterDTOs = filterDTOs.toArray(new FilterDTO[0]); |
| } |
| |
| private String[] asStringArray( |
| List<Class<? extends EventListener>> clazzes) { |
| |
| String[] classesArray = new String[clazzes.size()]; |
| |
| for (int i = 0; i < classesArray.length; i++) { |
| classesArray[i] = clazzes.get(i).getName(); |
| } |
| |
| Arrays.sort(classesArray); |
| |
| return classesArray; |
| } |
| |
| private String[] checkDispatcher(String[] dispatcher) { |
| if ((dispatcher == null) || (dispatcher.length == 0)) { |
| return DISPATCHER; |
| } |
| |
| for (String type : dispatcher) { |
| try { |
| DispatcherType.valueOf(type); |
| } |
| catch (IllegalArgumentException iae) { |
| throw new HttpWhiteboardFailureException( |
| "Invalid dispatcher '" + type + "'", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| |
| Arrays.sort(dispatcher); |
| |
| return dispatcher; |
| } |
| |
| public static void checkPattern(String pattern) { |
| if (pattern == null) { |
| throw new HttpWhiteboardFailureException("Pattern cannot be null", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$ |
| } |
| |
| if (pattern.indexOf("*.") == 0) { //$NON-NLS-1$ |
| return; |
| } |
| |
| if (Const.BLANK.equals(pattern)) { |
| return; |
| } |
| |
| if (Const.SLASH.equals(pattern)) { |
| return; |
| } |
| |
| if (!pattern.startsWith(Const.SLASH) || |
| (pattern.endsWith(Const.SLASH) && !pattern.equals(Const.SLASH)) || |
| pattern.contains("**")) { //$NON-NLS-1$ |
| |
| throw new HttpWhiteboardFailureException( |
| "Invalid pattern '" + pattern + "'", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| |
| private static void checkPrefix(Object prefixObj) { |
| if (prefixObj == null) { |
| throw new HttpWhiteboardFailureException("Prefix cannot be null.", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$ |
| } |
| |
| if (!(prefixObj instanceof String)) { |
| throw new HttpWhiteboardFailureException("Prefix must be String.", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$ |
| } |
| |
| String prefix = (String)prefixObj; |
| |
| if (prefix.endsWith(Const.SLASH) && !prefix.equals(Const.SLASH)) { |
| throw new HttpWhiteboardFailureException("Invalid prefix '" + prefix + "'", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| |
| private static void checkRegex(String regex) { |
| try { |
| Pattern.compile(regex); |
| } |
| catch (PatternSyntaxException pse) { |
| throw new HttpWhiteboardFailureException( |
| "Invalid regex '" + regex + "'", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| |
| public synchronized void checkShutdown() { |
| if (shutdown) { |
| throw new IllegalStateException( |
| "Context is already shutdown"); //$NON-NLS-1$ |
| } |
| } |
| |
| private static String createFilter(long contextServiceId) { |
| StringBuilder filterBuilder = new StringBuilder(); |
| filterBuilder.append('('); |
| filterBuilder.append(Constants.SERVICE_ID); |
| filterBuilder.append('='); |
| filterBuilder.append(contextServiceId); |
| filterBuilder.append(')'); |
| return filterBuilder.toString(); |
| } |
| |
| private ServletContext createServletContext( |
| Bundle curBundle, ServletContextHelper curServletContextHelper) { |
| |
| ServletContextAdaptor adaptor = new ServletContextAdaptor( |
| this, curBundle, curServletContextHelper, eventListeners, |
| AccessController.getContext()); |
| |
| return adaptor.createServletContext(); |
| } |
| |
| private void collectEndpointDTOs( |
| ServletContextDTO servletContextDTO) { |
| |
| List<ErrorPageDTO> errorPageDTOs = new ArrayList<ErrorPageDTO>(); |
| List<ResourceDTO> resourceDTOs = new ArrayList<ResourceDTO>(); |
| List<ServletDTO> servletDTOs = new ArrayList<ServletDTO>(); |
| |
| for (EndpointRegistration<?> endpointRegistration : endpointRegistrations) { |
| if (endpointRegistration instanceof ResourceRegistration) { |
| if (!httpServiceRuntime.isFailedResourceDTO(endpointRegistration.getServiceReference())) { |
| resourceDTOs.add(DTOUtil.clone((ResourceDTO)endpointRegistration.getD())); |
| } |
| } |
| else if (endpointRegistration instanceof ErrorPageRegistration) { |
| if (!httpServiceRuntime.isFailedErrorPageDTO(endpointRegistration.getServiceReference())) { |
| errorPageDTOs.add(DTOUtil.clone((ExtendedErrorPageDTO)endpointRegistration.getD())); |
| } |
| } |
| else { |
| if (!httpServiceRuntime.isFailedServletDTO(endpointRegistration.getServiceReference())) { |
| servletDTOs.add(DTOUtil.clone((ServletDTO)endpointRegistration.getD())); |
| } |
| } |
| } |
| |
| servletContextDTO.errorPageDTOs = errorPageDTOs.toArray(new ErrorPageDTO[0]); |
| servletContextDTO.resourceDTOs = resourceDTOs.toArray(new ResourceDTO[0]); |
| servletContextDTO.servletDTOs = servletDTOs.toArray(new ServletDTO[0]); |
| } |
| |
| private void collectFilterDTOs( |
| ServletContextDTO servletContextDTO) { |
| |
| List<FilterDTO> filterDTOs = new ArrayList<FilterDTO>(); |
| |
| for (FilterRegistration filterRegistration : filterRegistrations) { |
| filterDTOs.add(DTOUtil.clone(filterRegistration.getD())); |
| } |
| |
| servletContextDTO.filterDTOs = filterDTOs.toArray(new FilterDTO[0]); |
| } |
| |
| private void collectListenerDTOs( |
| ServletContextDTO servletContextDTO) { |
| |
| List<ListenerDTO> listenerDTOs = new ArrayList<ListenerDTO>(); |
| |
| for (ListenerRegistration listenerRegistration : listenerRegistrations) { |
| listenerDTOs.add(DTOUtil.clone(listenerRegistration.getD())); |
| } |
| |
| servletContextDTO.listenerDTOs = listenerDTOs.toArray(new ListenerDTO[0]); |
| } |
| |
| private Map<String, Object> getDTOAttributes(ServletContext servletContext) { |
| Map<String, Object> map = new HashMap<String, Object>(); |
| |
| for (Enumeration<String> names = servletContext.getAttributeNames(); |
| names.hasMoreElements();) { |
| |
| String name = names.nextElement(); |
| |
| map.put(name, DTOUtil.mapValue(servletContext.getAttribute(name))); |
| } |
| |
| return Collections.unmodifiableMap(map); |
| } |
| |
| private List<Class<? extends EventListener>> getListenerClasses( |
| ServiceReference<EventListener> listenerReference) { |
| |
| List<String> objectClassList = StringPlus.from(listenerReference.getProperty(Constants.OBJECTCLASS)); |
| |
| List<Class<? extends EventListener>> classes = |
| new ArrayList<Class<? extends EventListener>>(); |
| |
| if (objectClassList.contains(ServletContextListener.class.getName())) { |
| classes.add(ServletContextListener.class); |
| } |
| if (objectClassList.contains(ServletContextAttributeListener.class.getName())) { |
| classes.add(ServletContextAttributeListener.class); |
| } |
| if (objectClassList.contains(ServletRequestListener.class.getName())) { |
| classes.add(ServletRequestListener.class); |
| } |
| if (objectClassList.contains(ServletRequestAttributeListener.class.getName())) { |
| classes.add(ServletRequestAttributeListener.class); |
| } |
| if (objectClassList.contains(HttpSessionListener.class.getName())) { |
| classes.add(HttpSessionListener.class); |
| } |
| if (objectClassList.contains(HttpSessionAttributeListener.class.getName())) { |
| classes.add(HttpSessionAttributeListener.class); |
| } |
| |
| if (objectClassList.contains(javax.servlet.http.HttpSessionIdListener.class.getName())) { |
| classes.add(javax.servlet.http.HttpSessionIdListener.class); |
| } |
| |
| return classes; |
| } |
| |
| public ServiceReference<ServletContextHelper> getServiceReference() { |
| return serviceReference; |
| } |
| |
| private ServletContextHelper getServletContextHelper(Bundle curBundle) { |
| BundleContext context = curBundle.getBundleContext(); |
| return context.getService(serviceReference); |
| } |
| |
| public void ungetServletContextHelper(Bundle curBundle) { |
| BundleContext context = curBundle.getBundleContext(); |
| try { |
| context.ungetService(serviceReference); |
| } catch (IllegalStateException e) { |
| // this can happen if the whiteboard bundle is in the process of stopping |
| // and the framework is in the middle of auto-unregistering any services |
| // the bundle forgot to unregister on stop |
| } |
| } |
| |
| private String[] sort(String[] values) { |
| if (values == null) { |
| return null; |
| } |
| |
| Arrays.sort(values); |
| |
| return values; |
| } |
| |
| private void flushActiveSessions() { |
| 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) { |
| removeActiveSession(session.getId()); |
| } |
| |
| public void removeActiveSession(String sessionId) { |
| HttpSessionAdaptor httpSessionAdaptor = activeSessions.remove(sessionId); |
| |
| if (httpSessionAdaptor != null) { |
| httpServiceRuntime.getHttpSessionTracker().removeHttpSessionAdaptor(sessionId, httpSessionAdaptor); |
| } |
| } |
| |
| public void fireSessionIdChanged(String oldSessionId) { |
| if (shutdown) { |
| return; |
| } |
| |
| List<javax.servlet.http.HttpSessionIdListener> listeners = eventListeners.get(javax.servlet.http.HttpSessionIdListener.class); |
| |
| if (listeners.isEmpty()) { |
| return; |
| } |
| |
| for (HttpSessionAdaptor httpSessionAdaptor : activeSessions.values()) { |
| HttpSessionEvent httpSessionEvent = new HttpSessionEvent(httpSessionAdaptor); |
| for (javax.servlet.http.HttpSessionIdListener listener : listeners) { |
| listener.sessionIdChanged(httpSessionEvent, oldSessionId); |
| } |
| } |
| } |
| |
| public HttpSessionAdaptor getSessionAdaptor( |
| HttpSession session, ServletContext servletContext) { |
| |
| String sessionId = session.getId(); |
| |
| HttpSessionAdaptor httpSessionAdaptor = activeSessions.get(sessionId); |
| |
| if (httpSessionAdaptor != null) { |
| return httpSessionAdaptor; |
| } |
| |
| httpSessionAdaptor = HttpSessionAdaptor.createHttpSessionAdaptor( |
| session, servletContext, this); |
| |
| HttpSessionAdaptor previousHttpSessionAdaptor = |
| addSessionAdaptor(sessionId, httpSessionAdaptor); |
| |
| if (previousHttpSessionAdaptor != null) { |
| return previousHttpSessionAdaptor; |
| } |
| |
| List<HttpSessionListener> listeners = eventListeners.get(HttpSessionListener.class); |
| |
| if (listeners.isEmpty()) { |
| return httpSessionAdaptor; |
| } |
| |
| HttpSessionEvent httpSessionEvent = new HttpSessionEvent( |
| httpSessionAdaptor); |
| |
| for (HttpSessionListener listener : listeners) { |
| listener.sessionCreated(httpSessionEvent); |
| } |
| |
| return httpSessionAdaptor; |
| } |
| |
| public HttpSessionAdaptor addSessionAdaptor( |
| String sessionId, HttpSessionAdaptor httpSessionAdaptor) { |
| |
| HttpSessionAdaptor previousHttpSessionAdaptor = |
| activeSessions.putIfAbsent(sessionId, httpSessionAdaptor); |
| |
| if (previousHttpSessionAdaptor != null) { |
| return previousHttpSessionAdaptor; |
| } |
| |
| httpServiceRuntime.getHttpSessionTracker().addHttpSessionAdaptor(sessionId, httpSessionAdaptor); |
| |
| return null; |
| } |
| |
| public void recordFailedErrorPageDTO( |
| ServiceReference<?> servletReference, ExtendedErrorPageDTO errorPageDTO, int failureReason) { |
| |
| FailedErrorPageDTO failedErrorPageDTO = new FailedErrorPageDTO(); |
| failedErrorPageDTO.asyncSupported = errorPageDTO.asyncSupported; |
| failedErrorPageDTO.errorCodes = errorPageDTO.errorCodes; |
| failedErrorPageDTO.exceptions = errorPageDTO.exceptions; |
| failedErrorPageDTO.failureReason = failureReason; |
| failedErrorPageDTO.initParams = errorPageDTO.initParams; |
| failedErrorPageDTO.name = errorPageDTO.name; |
| failedErrorPageDTO.serviceId = errorPageDTO.serviceId; |
| failedErrorPageDTO.servletContextId = errorPageDTO.servletContextId; |
| failedErrorPageDTO.servletInfo = errorPageDTO.servletInfo; |
| |
| getHttpServiceRuntime().recordFailedErrorPageDTO(servletReference, failedErrorPageDTO); |
| } |
| |
| public void recordFailedResourceDTO( |
| ServiceReference<?> resourceReference, ResourceDTO resourceDTO, int failureReason) { |
| |
| FailedResourceDTO failedResourceDTO = new FailedResourceDTO(); |
| failedResourceDTO.failureReason = failureReason; |
| failedResourceDTO.patterns = resourceDTO.patterns; |
| failedResourceDTO.prefix = resourceDTO.prefix; |
| failedResourceDTO.serviceId = resourceDTO.serviceId; |
| failedResourceDTO.servletContextId = resourceDTO.servletContextId; |
| |
| getHttpServiceRuntime().recordFailedResourceDTO(resourceReference, failedResourceDTO); |
| } |
| |
| public void recordFailedServletDTO(ServiceReference<?> servletReference, ServletDTO servletDTO, int failureReason) { |
| FailedServletDTO failedServletDTO = new FailedServletDTO(); |
| |
| failedServletDTO.asyncSupported = servletDTO.asyncSupported; |
| failedServletDTO.failureReason = failureReason; |
| failedServletDTO.initParams = servletDTO.initParams; |
| failedServletDTO.multipartEnabled = servletDTO.multipartEnabled; |
| failedServletDTO.multipartFileSizeThreshold = servletDTO.multipartFileSizeThreshold; |
| failedServletDTO.multipartLocation = servletDTO.multipartLocation; |
| failedServletDTO.multipartMaxFileSize = servletDTO.multipartMaxFileSize; |
| failedServletDTO.multipartMaxRequestSize = servletDTO.multipartMaxRequestSize; |
| failedServletDTO.name = servletDTO.name; |
| failedServletDTO.patterns = servletDTO.patterns; |
| failedServletDTO.serviceId = servletDTO.serviceId; |
| failedServletDTO.servletContextId = servletDTO.servletContextId; |
| failedServletDTO.servletInfo = servletDTO.servletInfo; |
| |
| getHttpServiceRuntime().recordFailedServletDTO(servletReference, failedServletDTO); |
| } |
| |
| private String validateName() { |
| Object contextNameObj = serviceReference.getProperty(HTTP_WHITEBOARD_CONTEXT_NAME); |
| |
| if (contextNameObj == null) { |
| throw new IllegalContextNameException( |
| HTTP_WHITEBOARD_CONTEXT_NAME + " is null. Ignoring!", //$NON-NLS-1$ |
| DTOConstants.FAILURE_REASON_VALIDATION_FAILED); |
| } |
| else if (!(contextNameObj instanceof String)) { |
| throw new IllegalContextNameException( |
| HTTP_WHITEBOARD_CONTEXT_NAME + " is not String. Ignoring!", //$NON-NLS-1$ |
| DTOConstants.FAILURE_REASON_VALIDATION_FAILED); |
| } |
| |
| String name = (String)contextNameObj; |
| |
| if (!contextNamePattern.matcher(name).matches()) { |
| throw new IllegalContextNameException( |
| "The context name '" + name + "' does not follow Bundle-SymbolicName syntax.", //$NON-NLS-1$ //$NON-NLS-2$ |
| DTOConstants.FAILURE_REASON_VALIDATION_FAILED); |
| } |
| |
| // Now check for naming conflicts |
| for (ContextController existingContext : httpServiceRuntime.getContextControllers()) { |
| if (name.equals(existingContext.getContextName())) { |
| if (serviceReference.compareTo(existingContext.serviceReference) < 0) { |
| throw new HttpWhiteboardFailureException("Context with same name exists. " + serviceReference, DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$ |
| } |
| |
| httpServiceRuntime.recordFailedServletContextDTO( |
| existingContext.serviceReference, (Long)serviceReference.getProperty(Constants.SERVICE_ID), DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE); |
| } |
| } |
| |
| return name; |
| } |
| |
| private String validatePath() { |
| Object contextPathObj = serviceReference.getProperty(HTTP_WHITEBOARD_CONTEXT_PATH); |
| |
| if (contextPathObj == null) { |
| throw new IllegalContextPathException( |
| HTTP_WHITEBOARD_CONTEXT_PATH + " is null. Ignoring!", //$NON-NLS-1$ |
| DTOConstants.FAILURE_REASON_VALIDATION_FAILED); |
| } |
| else if (!(contextPathObj instanceof String)) { |
| throw new IllegalContextPathException( |
| HTTP_WHITEBOARD_CONTEXT_PATH + " is not String. Ignoring!", //$NON-NLS-1$ |
| DTOConstants.FAILURE_REASON_VALIDATION_FAILED); |
| } |
| |
| String path = (String)contextPathObj; |
| |
| try { |
| @SuppressWarnings("unused") |
| URI uri = new URI(Const.HTTP, Const.LOCALHOST, path, null); |
| } |
| catch (URISyntaxException use) { |
| throw new IllegalContextPathException( |
| "The context path '" + path + "' is not valid URI path syntax.", //$NON-NLS-1$ //$NON-NLS-2$ |
| DTOConstants.FAILURE_REASON_VALIDATION_FAILED); |
| } |
| |
| path = httpServiceRuntime.adaptContextPath(path, serviceReference); |
| if (path.equals(Const.SLASH)) { |
| path = Const.BLANK; |
| } |
| |
| return path; |
| } |
| |
| 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; |
| private final BundleContext trackingContext; |
| private final BundleContext consumingContext; |
| private final String contextName; |
| private final String contextPath; |
| private volatile String fullContextPath; |
| private final long contextServiceId; |
| private final Set<EndpointRegistration<?>> endpointRegistrations = new ConcurrentSkipListSet<EndpointRegistration<?>>(); |
| private final EventListeners eventListeners = new EventListeners(); |
| private final Set<FilterRegistration> filterRegistrations = new ConcurrentSkipListSet<FilterRegistration>(); |
| private final ConcurrentMap<String, HttpSessionAdaptor> activeSessions = new ConcurrentHashMap<String, HttpSessionAdaptor>(); |
| |
| private final HttpServiceRuntimeImpl httpServiceRuntime; |
| private final Set<ListenerRegistration> listenerRegistrations = new HashSet<ListenerRegistration>(); |
| private final ProxyContext proxyContext; |
| private final ServiceReference<ServletContextHelper> serviceReference; |
| private final String servletContextHelperRefFilter; |
| private boolean shutdown; |
| private String string; |
| |
| private final ServiceTracker<Servlet, AtomicReference<ErrorPageRegistration>> errorPageServiceTracker; |
| private final ServiceTracker<Filter, AtomicReference<FilterRegistration>> filterServiceTracker; |
| private final ServiceTracker<EventListener, AtomicReference<ListenerRegistration>> listenerServiceTracker; |
| private final ServiceTracker<Object, AtomicReference<ResourceRegistration>> resourceServiceTracker; |
| private final ServiceTracker<Servlet, AtomicReference<ServletRegistration>> servletServiceTracker; |
| } |