blob: 3931e722a9f9e06566cf25779c9c8fdaf7036e60 [file] [log] [blame]
/*
* 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.whiteboard;
import static org.osgi.service.http.runtime.dto.DTOConstants.FAILURE_REASON_NO_SERVLET_CONTEXT_MATCHING;
import static org.osgi.service.http.runtime.dto.DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE;
import static org.osgi.service.http.runtime.dto.DTOConstants.FAILURE_REASON_UNKNOWN;
import static org.osgi.service.http.runtime.dto.DTOConstants.FAILURE_REASON_VALIDATION_FAILED;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import org.apache.felix.http.base.internal.console.HttpServicePlugin;
import org.apache.felix.http.base.internal.context.ExtServletContext;
import org.apache.felix.http.base.internal.handler.FilterHandler;
import org.apache.felix.http.base.internal.handler.HttpServiceServletHandler;
import org.apache.felix.http.base.internal.handler.HttpSessionWrapper;
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.handler.WhiteboardFilterHandler;
import org.apache.felix.http.base.internal.handler.WhiteboardListenerHandler;
import org.apache.felix.http.base.internal.handler.WhiteboardServletHandler;
import org.apache.felix.http.base.internal.logger.SystemLogger;
import org.apache.felix.http.base.internal.registry.EventListenerRegistry;
import org.apache.felix.http.base.internal.registry.HandlerRegistry;
import org.apache.felix.http.base.internal.runtime.AbstractInfo;
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.ResourceInfo;
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.WhiteboardServiceInfo;
import org.apache.felix.http.base.internal.runtime.dto.FailedDTOHolder;
import org.apache.felix.http.base.internal.runtime.dto.RegistryRuntime;
import org.apache.felix.http.base.internal.runtime.dto.ServletContextDTOBuilder;
import org.apache.felix.http.base.internal.service.HttpServiceFactory;
import org.apache.felix.http.base.internal.service.HttpServiceRuntimeImpl;
import org.apache.felix.http.base.internal.service.ResourceServlet;
import org.apache.felix.http.base.internal.whiteboard.tracker.FilterTracker;
import org.apache.felix.http.base.internal.whiteboard.tracker.ListenersTracker;
import org.apache.felix.http.base.internal.whiteboard.tracker.ResourceTracker;
import org.apache.felix.http.base.internal.whiteboard.tracker.ServletContextHelperTracker;
import org.apache.felix.http.base.internal.whiteboard.tracker.ServletTracker;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.http.context.ServletContextHelper;
import org.osgi.service.http.runtime.HttpServiceRuntime;
import org.osgi.service.http.runtime.HttpServiceRuntimeConstants;
import org.osgi.service.http.runtime.dto.DTOConstants;
import org.osgi.service.http.runtime.dto.ServletContextDTO;
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
import org.osgi.util.tracker.ServiceTracker;
public final class WhiteboardManager
{
/** The bundle context of the http bundle. */
private final BundleContext httpBundleContext;
/** The http service factory. */
private final HttpServiceFactory httpServiceFactory;
private final HttpServiceRuntimeImpl serviceRuntime;
private final List<ServiceTracker<?, ?>> trackers = new ArrayList<ServiceTracker<?, ?>>();
private final HttpServicePlugin plugin;
/** A map containing all servlet context registrations. Mapped by context name */
private final Map<String, List<WhiteboardContextHandler>> contextMap = new HashMap<String, List<WhiteboardContextHandler>>();
/** A map with all servlet/filter registrations, mapped by abstract info. */
private final Map<WhiteboardServiceInfo<?>, List<WhiteboardContextHandler>> servicesMap = new HashMap<WhiteboardServiceInfo<?>, List<WhiteboardContextHandler>>();
private final HandlerRegistry registry;
private final FailureStateHandler failureStateHandler = new FailureStateHandler();
private volatile ServletContext webContext;
private volatile ServiceRegistration<ServletContextHelper> defaultContextRegistration;
private volatile ServiceRegistration<HttpServiceRuntime> runtimeServiceReg;
/**
* Create a new whiteboard http manager
*
* @param bundleContext The bundle context of the http bundle
* @param httpServiceFactory The http service factory
* @param registry The handler registry
*/
public WhiteboardManager(final BundleContext bundleContext,
final HttpServiceFactory httpServiceFactory,
final HandlerRegistry registry)
{
this.httpBundleContext = bundleContext;
this.httpServiceFactory = httpServiceFactory;
this.registry = registry;
this.serviceRuntime = new HttpServiceRuntimeImpl(registry, this);
this.plugin = new HttpServicePlugin(bundleContext, this.serviceRuntime);
}
/**
* Start the whiteboard manager
* @param containerContext The servlet context
*/
public void start(final ServletContext containerContext, @Nonnull final Dictionary<String, Object> httpServiceProps)
{
// runtime service gets the same props for now
this.serviceRuntime.setAllAttributes(httpServiceProps);
this.serviceRuntime.setAttribute(HttpServiceRuntimeConstants.HTTP_SERVICE_ID,
Collections.singletonList(this.httpServiceFactory.getHttpServiceServiceId()));
this.runtimeServiceReg = this.httpBundleContext.registerService(HttpServiceRuntime.class,
serviceRuntime,
this.serviceRuntime.getAttributes());
this.serviceRuntime.setServiceReference(this.runtimeServiceReg.getReference());
this.webContext = containerContext;
final Dictionary<String, Object> props = new Hashtable<String, Object>();
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, HttpWhiteboardConstants.HTTP_WHITEBOARD_DEFAULT_CONTEXT_NAME);
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, "/");
props.put(Constants.SERVICE_RANKING, Integer.MIN_VALUE);
// add context for http service
final List<WhiteboardContextHandler> list = new ArrayList<WhiteboardContextHandler>();
final ServletContextHelperInfo info = new ServletContextHelperInfo(Integer.MAX_VALUE,
HttpServiceFactory.HTTP_SERVICE_CONTEXT_SERVICE_ID,
HttpServiceFactory.HTTP_SERVICE_CONTEXT_NAME, "/", null);
list.add(new HttpServiceContextHandler(info, registry.getRegistry(HttpServiceFactory.HTTP_SERVICE_CONTEXT_SERVICE_ID),
httpServiceFactory, webContext, this.httpBundleContext.getBundle()));
this.contextMap.put(HttpServiceFactory.HTTP_SERVICE_CONTEXT_NAME, list);
this.defaultContextRegistration = httpBundleContext.registerService(
ServletContextHelper.class,
new ServiceFactory<ServletContextHelper>()
{
@Override
public ServletContextHelper getService(
final Bundle bundle,
final ServiceRegistration<ServletContextHelper> registration)
{
return new ServletContextHelper(bundle)
{
// nothing to override
};
}
@Override
public void ungetService(
final Bundle bundle,
final ServiceRegistration<ServletContextHelper> registration,
final ServletContextHelper service)
{
// nothing to do
}
}, props);
addTracker(new FilterTracker(this.httpBundleContext, this));
addTracker(new ListenersTracker(this.httpBundleContext, this));
addTracker(new ResourceTracker(this.httpBundleContext, this));
addTracker(new ServletContextHelperTracker(this.httpBundleContext, this));
addTracker(new ServletTracker(this.httpBundleContext, this));
this.plugin.register();
}
/**
* Add a tracker and start it
* @param tracker The tracker instance
*/
private void addTracker(ServiceTracker<?, ?> tracker)
{
this.trackers.add(tracker);
tracker.open();
}
/**
* Stop the instance
*/
public void stop()
{
this.plugin.unregister();
for(final ServiceTracker<?, ?> t : this.trackers)
{
t.close();
}
this.trackers.clear();
this.serviceRuntime.setServiceReference(null);
this.contextMap.clear();
this.servicesMap.clear();
this.failureStateHandler.clear();
this.registry.reset();
if (this.defaultContextRegistration != null)
{
this.defaultContextRegistration.unregister();
this.defaultContextRegistration = null;
}
if ( this.runtimeServiceReg != null )
{
this.runtimeServiceReg.unregister();
this.runtimeServiceReg = null;
}
this.webContext = null;
}
public void sessionDestroyed(@Nonnull final HttpSession session, final Set<Long> contextIds)
{
for(final Long contextId : contextIds)
{
final WhiteboardContextHandler handler = this.getContextHandler(contextId);
if ( handler != null )
{
final ExtServletContext context = handler.getServletContext(this.httpBundleContext.getBundle());
new HttpSessionWrapper(contextId, session, context, true).invalidate();
handler.ungetServletContext(this.httpBundleContext.getBundle());
}
}
}
/**
* Handle session id changes
* @param session The session where the id changed
* @param oldSessionId The old session id
* @param contextIds The context ids using that session
*/
public void sessionIdChanged(@Nonnull final HttpSessionEvent event, String oldSessionId, final Set<Long> contextIds)
{
for(final Long contextId : contextIds)
{
final WhiteboardContextHandler handler = this.getContextHandler(contextId);
if ( handler != null )
{
handler.getRegistry().getEventListenerRegistry().sessionIdChanged(event, oldSessionId);
}
}
}
/**
* Activate a servlet context helper.
*
* @param handler The context handler
* @return {@code true} if activation succeeded.
*/
private boolean activate(final WhiteboardContextHandler handler)
{
if ( !handler.activate(this.registry) )
{
return false;
}
final List<WhiteboardServiceInfo<?>> services = new ArrayList<WhiteboardServiceInfo<?>>();
for(final Map.Entry<WhiteboardServiceInfo<?>, List<WhiteboardContextHandler>> entry : this.servicesMap.entrySet())
{
if ( entry.getKey().getContextSelectionFilter().match(handler.getContextInfo().getServiceReference()) )
{
entry.getValue().add(handler);
if ( entry.getValue().size() == 1 )
{
this.failureStateHandler.remove(entry.getKey());
}
if ( entry.getKey() instanceof ListenerInfo && ((ListenerInfo)entry.getKey()).isListenerType(ServletContextListener.class.getName()) )
{
// servlet context listeners will be registered directly
this.registerWhiteboardService(handler, entry.getKey());
}
else
{
// registration of other services will be delayed
services.add(entry.getKey());
}
}
}
// notify context listeners first
handler.getRegistry().getEventListenerRegistry().contextInitialized();
// register services
for(final WhiteboardServiceInfo<?> info : services)
{
this.registerWhiteboardService(handler, info);
}
return true;
}
/**
* Deactivate a servlet context.
*
* @param handler A context handler
*/
private void deactivate(final WhiteboardContextHandler handler)
{
// services except context listeners first
final List<WhiteboardServiceInfo<?>> listeners = new ArrayList<WhiteboardServiceInfo<?>>();
final Iterator<Map.Entry<WhiteboardServiceInfo<?>, List<WhiteboardContextHandler>>> i = this.servicesMap.entrySet().iterator();
while ( i.hasNext() )
{
final Map.Entry<WhiteboardServiceInfo<?>, List<WhiteboardContextHandler>> entry = i.next();
if ( entry.getValue().remove(handler) )
{
if ( !this.failureStateHandler.remove(entry.getKey(), handler.getContextInfo().getServiceId()) )
{
if ( entry.getKey() instanceof ListenerInfo && ((ListenerInfo)entry.getKey()).isListenerType(ServletContextListener.class.getName()) )
{
listeners.add(entry.getKey());
}
else
{
this.unregisterWhiteboardService(handler, entry.getKey());
}
}
if ( entry.getValue().isEmpty() )
{
final String type = entry.getKey().getClass().getSimpleName().substring(0, entry.getKey().getClass().getSimpleName().length() - 4);
SystemLogger.debug("Ignoring unmatching " + type + " service " + entry.getKey().getServiceReference());
this.failureStateHandler.add(entry.getKey(), FAILURE_REASON_NO_SERVLET_CONTEXT_MATCHING);
}
}
}
// context listeners last
handler.getRegistry().getEventListenerRegistry().contextDestroyed();
for(final WhiteboardServiceInfo<?> info : listeners)
{
this.unregisterWhiteboardService(handler, info);
}
handler.deactivate(this.registry);
}
/**
* Add a servlet context helper.
*
* @param info The servlet context helper info
* @return {@code true} if the service matches this http whiteboard service
*/
public boolean addContextHelper(final ServletContextHelperInfo info)
{
// no failure DTO and no logging if not matching
if ( isMatchingService(info) )
{
if ( info.isValid() )
{
synchronized ( this.contextMap )
{
final WhiteboardContextHandler handler = new WhiteboardContextHandler(info,
this.webContext,
this.httpBundleContext.getBundle());
// check for activate/deactivate
List<WhiteboardContextHandler> handlerList = this.contextMap.get(info.getName());
if ( handlerList == null )
{
handlerList = new ArrayList<WhiteboardContextHandler>();
}
final boolean activate = handlerList.isEmpty() || handlerList.get(0).compareTo(handler) > 0;
if ( activate )
{
// try to activate
if ( this.activate(handler) )
{
handlerList.add(handler);
Collections.sort(handlerList);
this.contextMap.put(info.getName(), handlerList);
// check for deactivate
if ( handlerList.size() > 1 )
{
final WhiteboardContextHandler oldHead = handlerList.get(1);
this.deactivate(oldHead);
final String type = info.getClass().getSimpleName().substring(0, info.getClass().getSimpleName().length() - 4);
SystemLogger.debug("Ignoring shadowed " + type + " service " + info.getServiceReference());
this.failureStateHandler.add(oldHead.getContextInfo(), FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE);
}
}
else
{
final String type = info.getClass().getSimpleName().substring(0, info.getClass().getSimpleName().length() - 4);
SystemLogger.error("Ignoring ungettable " + type + " service " + info.getServiceReference(), null);
this.failureStateHandler.add(handler.getContextInfo(), DTOConstants.FAILURE_REASON_SERVICE_NOT_GETTABLE);
}
}
else
{
handlerList.add(handler);
Collections.sort(handlerList);
this.contextMap.put(info.getName(), handlerList);
final String type = info.getClass().getSimpleName().substring(0, info.getClass().getSimpleName().length() - 4);
SystemLogger.debug("Ignoring shadowed " + type + " service " + info.getServiceReference());
this.failureStateHandler.add(handler.getContextInfo(), FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE);
}
}
}
else
{
final String type = info.getClass().getSimpleName().substring(0, info.getClass().getSimpleName().length() - 4);
SystemLogger.debug("Ignoring invalid " + type + " service " + info.getServiceReference());
this.failureStateHandler.add(info, FAILURE_REASON_VALIDATION_FAILED);
}
return true;
}
return false;
}
/**
* Remove a servlet context helper
*
* @param The servlet context helper info
*/
public void removeContextHelper(final ServletContextHelperInfo info)
{
if ( info.isValid() )
{
synchronized ( this.contextMap )
{
final List<WhiteboardContextHandler> handlerList = this.contextMap.get(info.getName());
if ( handlerList != null )
{
final Iterator<WhiteboardContextHandler> i = handlerList.iterator();
boolean first = true;
boolean activateNext = false;
while ( i.hasNext() )
{
final WhiteboardContextHandler handler = i.next();
if ( handler.getContextInfo().equals(info) )
{
i.remove();
// check for deactivate
if ( first )
{
this.deactivate(handler);
activateNext = true;
}
break;
}
first = false;
}
if ( handlerList.isEmpty() )
{
this.contextMap.remove(info.getName());
}
else if ( activateNext )
{
// Try to activate next
boolean done = false;
while ( !handlerList.isEmpty() && !done)
{
final WhiteboardContextHandler newHead = handlerList.get(0);
this.failureStateHandler.removeAll(newHead.getContextInfo());
if ( this.activate(newHead) )
{
done = true;
}
else
{
handlerList.remove(0);
final String type = info.getClass().getSimpleName().substring(0, info.getClass().getSimpleName().length() - 4);
SystemLogger.error("Ignoring ungettable " + type + " service " + info.getServiceReference(), null);
this.failureStateHandler.add(newHead.getContextInfo(), DTOConstants.FAILURE_REASON_SERVICE_NOT_GETTABLE);
}
}
}
}
}
}
this.failureStateHandler.removeAll(info);
}
/**
* Find the list of matching contexts for the whiteboard service
*/
private List<WhiteboardContextHandler> getMatchingContexts(final WhiteboardServiceInfo<?> info)
{
final List<WhiteboardContextHandler> result = new ArrayList<WhiteboardContextHandler>();
for(final List<WhiteboardContextHandler> handlerList : this.contextMap.values())
{
final WhiteboardContextHandler h = handlerList.get(0);
// check whether the servlet context helper is visible to the whiteboard bundle
// see chapter 140.2
boolean visible = h.getContextInfo().getServiceId() < 0; // internal ones are always visible
if ( !visible )
{
final String filterString = "(" + Constants.SERVICE_ID + "=" + String.valueOf(h.getContextInfo().getServiceId()) + ")";
try
{
final Collection<ServiceReference<ServletContextHelper>> col = info.getServiceReference().getBundle().getBundleContext().getServiceReferences(ServletContextHelper.class, filterString);
if ( !col.isEmpty() )
{
visible = true;
}
}
catch ( final InvalidSyntaxException ise )
{
// we ignore this and treat it as an invisible service
}
}
if ( visible )
{
if ( h.getContextInfo().getServiceReference() != null )
{
if ( info.getContextSelectionFilter().match(h.getContextInfo().getServiceReference()) )
{
result.add(h);
}
}
else
{
final Map<String, String> props = new HashMap<String, String>();
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, h.getContextInfo().getName());
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, h.getContextInfo().getPath());
if ( info.getContextSelectionFilter().matches(props) )
{
result.add(h);
}
}
}
}
return result;
}
/**
* Add new whiteboard service to the registry
*
* @param info Whiteboard service info
* @return {@code true} if it matches this http service runtime
*/
public boolean addWhiteboardService(@Nonnull final WhiteboardServiceInfo<?> info)
{
// no logging and no DTO if other target service
if ( isMatchingService(info) )
{
if ( info.isValid() )
{
synchronized ( this.contextMap )
{
final List<WhiteboardContextHandler> handlerList = this.getMatchingContexts(info);
this.servicesMap.put(info, handlerList);
if (handlerList.isEmpty())
{
final String type = info.getClass().getSimpleName().substring(0, info.getClass().getSimpleName().length() - 4);
SystemLogger.debug("Ignoring unmatched " + type + " service " + info.getServiceReference());
this.failureStateHandler.add(info, FAILURE_REASON_NO_SERVLET_CONTEXT_MATCHING);
}
else
{
for(final WhiteboardContextHandler h : handlerList)
{
this.registerWhiteboardService(h, info);
if ( info instanceof ListenerInfo && ((ListenerInfo)info).isListenerType(ServletContextListener.class.getName()) )
{
final ListenerHandler handler = h.getRegistry().getEventListenerRegistry().getServletContextListener((ListenerInfo)info);
if ( handler != null )
{
final ServletContextListener listener = (ServletContextListener)handler.getListener();
if ( listener != null )
{
EventListenerRegistry.contextInitialized(handler.getListenerInfo(), listener, new ServletContextEvent(handler.getContext()));
}
}
}
}
}
}
}
else
{
final String type = info.getClass().getSimpleName().substring(0, info.getClass().getSimpleName().length() - 4);
SystemLogger.debug("Ignoring invalid " + type + " service " + info.getServiceReference());
this.failureStateHandler.add(info, FAILURE_REASON_VALIDATION_FAILED);
}
return true;
}
return false;
}
/**
* Remove whiteboard service from the registry.
*
* @param info The service id of the whiteboard service
*/
public void removeWhiteboardService(final WhiteboardServiceInfo<?> info )
{
synchronized ( this.contextMap )
{
if ( !failureStateHandler.remove(info) )
{
final List<WhiteboardContextHandler> handlerList = this.servicesMap.remove(info);
if ( handlerList != null )
{
for(final WhiteboardContextHandler h : handlerList)
{
if ( !failureStateHandler.remove(info, h.getContextInfo().getServiceId()) )
{
if ( info instanceof ListenerInfo && ((ListenerInfo)info).isListenerType(ServletContextListener.class.getName()) )
{
final ListenerHandler handler = h.getRegistry().getEventListenerRegistry().getServletContextListener((ListenerInfo)info);
if ( handler != null )
{
final ServletContextListener listener = (ServletContextListener) handler.getListener();
if ( listener != null )
{
EventListenerRegistry.contextDestroyed(handler.getListenerInfo(), listener, new ServletContextEvent(handler.getContext()));
}
}
}
this.unregisterWhiteboardService(h, info);
}
}
}
}
this.failureStateHandler.removeAll(info);
}
}
/**
* Register whiteboard service in the http service
* @param handler Context handler
* @param info Whiteboard service info
*/
private void registerWhiteboardService(final WhiteboardContextHandler handler, final WhiteboardServiceInfo<?> info)
{
try
{
int failureCode = -1;
if ( info instanceof ServletInfo )
{
final ExtServletContext servletContext = handler.getServletContext(info.getServiceReference().getBundle());
if ( servletContext == null )
{
failureCode = DTOConstants.FAILURE_REASON_SERVLET_CONTEXT_FAILURE;
}
else
{
final ServletHandler servletHandler = new WhiteboardServletHandler(
handler.getContextInfo().getServiceId(),
servletContext,
(ServletInfo)info,
handler.getBundleContext());
handler.getRegistry().registerServlet(servletHandler);
}
}
else if ( info instanceof FilterInfo )
{
final ExtServletContext servletContext = handler.getServletContext(info.getServiceReference().getBundle());
if ( servletContext == null )
{
failureCode = DTOConstants.FAILURE_REASON_SERVLET_CONTEXT_FAILURE;
}
else
{
final FilterHandler filterHandler = new WhiteboardFilterHandler(
handler.getContextInfo().getServiceId(),
servletContext,
(FilterInfo)info,
handler.getBundleContext());
handler.getRegistry().registerFilter(filterHandler);
}
}
else if ( info instanceof ResourceInfo )
{
final ServletInfo servletInfo = ((ResourceInfo)info).getServletInfo();
final ExtServletContext servletContext = handler.getServletContext(info.getServiceReference().getBundle());
if ( servletContext == null )
{
failureCode = DTOConstants.FAILURE_REASON_SERVLET_CONTEXT_FAILURE;
}
else
{
final ServletHandler servleHandler = new HttpServiceServletHandler(
handler.getContextInfo().getServiceId(),
servletContext,
servletInfo,
new ResourceServlet(servletInfo.getPrefix()));
handler.getRegistry().registerServlet(servleHandler);
}
}
else if ( info instanceof ListenerInfo )
{
final ExtServletContext servletContext = handler.getServletContext(info.getServiceReference().getBundle());
if ( servletContext == null )
{
failureCode = DTOConstants.FAILURE_REASON_SERVLET_CONTEXT_FAILURE;
}
else
{
final ListenerHandler listenerHandler = new WhiteboardListenerHandler(
handler.getContextInfo().getServiceId(),
servletContext,
(ListenerInfo)info,
handler.getBundleContext());
handler.getRegistry().registerListeners(listenerHandler);
}
}
else
{
// This should never happen, but we log anyway
SystemLogger.error("Unknown whiteboard service " + info.getServiceReference(), null);
}
if ( failureCode != -1 )
{
final String type = info.getClass().getSimpleName().substring(0,info.getClass().getSimpleName().length() - 4);
SystemLogger.debug("Ignoring " + type + " service " + info.getServiceReference());
this.failureStateHandler.add(info, handler.getContextInfo().getServiceId(), failureCode);
}
}
catch (final Exception e)
{
this.failureStateHandler.add(info, handler.getContextInfo().getServiceId(), FAILURE_REASON_UNKNOWN);
SystemLogger.error("Exception while registering whiteboard service " + info.getServiceReference(), e);
}
}
/**
* Unregister whiteboard service from the http service
* @param handler Context handler
* @param info Whiteboard service info
*/
private void unregisterWhiteboardService(final WhiteboardContextHandler handler, final WhiteboardServiceInfo<?> info)
{
try
{
if ( info instanceof ServletInfo )
{
handler.getRegistry().unregisterServlet((ServletInfo)info, true);
handler.ungetServletContext(info.getServiceReference().getBundle());
}
else if ( info instanceof FilterInfo )
{
handler.getRegistry().unregisterFilter((FilterInfo)info, true);
handler.ungetServletContext(info.getServiceReference().getBundle());
}
else if ( info instanceof ResourceInfo )
{
handler.getRegistry().unregisterServlet(((ResourceInfo)info).getServletInfo(), true);
handler.ungetServletContext(info.getServiceReference().getBundle());
}
else if ( info instanceof ListenerInfo )
{
handler.getRegistry().unregisterListeners((ListenerInfo) info);
handler.ungetServletContext(info.getServiceReference().getBundle());
}
}
catch (final Exception e)
{
SystemLogger.error("Exception while unregistering whiteboard service " + info.getServiceReference(), e);
}
}
/**
* Check whether the service is specifying a target http service runtime
* and if so if that is matching this runtime
*/
private boolean isMatchingService(final AbstractInfo<?> info)
{
final String target = info.getTarget();
if ( target != null )
{
try
{
final Filter f = this.httpBundleContext.createFilter(target);
return f.match(this.runtimeServiceReg.getReference());
}
catch ( final InvalidSyntaxException ise)
{
// log and ignore service
SystemLogger.error("Invalid target filter expression for " + info.getServiceReference() + " : " + target, ise);
return false;
}
}
return true;
}
private WhiteboardContextHandler getContextHandler(final Long contextId)
{
synchronized ( this.contextMap )
{
for(final List<WhiteboardContextHandler> handlerList : this.contextMap.values())
{
final WhiteboardContextHandler h = handlerList.get(0);
if ( h.getContextInfo().getServiceId() == contextId )
{
return h;
}
}
}
return null;
}
public RegistryRuntime getRuntimeInfo()
{
final FailedDTOHolder failedDTOHolder = new FailedDTOHolder();
final Collection<ServletContextDTO> contextDTOs = new ArrayList<ServletContextDTO>();
/*
// add the context for the http service
final ServletContextHelperInfo info = new ServletContextHelperInfo(Integer.MAX_VALUE,
HttpServiceFactory.HTTP_SERVICE_CONTEXT_SERVICE_ID,
HttpServiceFactory.HTTP_SERVICE_CONTEXT_NAME, "/", null);
final ServletContextDTO dto = ServletContextDTOBuilder.build(info, webContext, -1);
if ( registry.getRuntimeInfo(dto, failedDTOHolder) )
{
contextDTOs.add(dto);
}
*/
// get sort list of context handlers
final List<WhiteboardContextHandler> contextHandlerList = new ArrayList<WhiteboardContextHandler>();
synchronized ( this.contextMap )
{
for (final List<WhiteboardContextHandler> list : this.contextMap.values())
{
if ( !list.isEmpty() )
{
contextHandlerList.add(list.get(0));
}
}
this.failureStateHandler.getRuntimeInfo(failedDTOHolder);
}
Collections.sort(contextHandlerList);
for (final WhiteboardContextHandler handler : contextHandlerList)
{
final ServletContextDTO scDTO = ServletContextDTOBuilder.build(handler.getContextInfo(), handler.getSharedContext(), -1);
if ( registry.getRuntimeInfo(scDTO, failedDTOHolder) )
{
contextDTOs.add(scDTO);
}
}
return new RegistryRuntime(failedDTOHolder, contextDTOs);
}
}