/******************************************************************************* * Copyright (c) 2014 IBH SYSTEMS GmbH. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBH SYSTEMS GmbH - initial API and implementation *******************************************************************************/ package org.eclipse.packagedrone.web.controller; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.packagedrone.web.Controller; import org.eclipse.packagedrone.web.RequestHandler; import org.eclipse.packagedrone.web.RequestHandlerFactory; import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceEvent; import org.osgi.framework.ServiceListener; import org.osgi.framework.ServiceReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ControllerTracker implements RequestHandlerFactory { private final static Logger logger = LoggerFactory.getLogger ( ControllerTracker.class ); private final BundleContext context; private final ServiceListener listener = new ServiceListener () { @Override public void serviceChanged ( final ServiceEvent event ) { switch ( event.getType () ) { case ServiceEvent.REGISTERED: handleAddingService ( event.getServiceReference () ); break; case ServiceEvent.UNREGISTERING: handleRemovedService ( event.getServiceReference () ); break; } } }; public ControllerTracker ( final BundleContext context ) { this.context = context; this.context.addServiceListener ( this.listener ); try { final ServiceReference<?>[] refs = context.getServiceReferences ( (String)null, (String)null ); if ( refs != null ) { for ( final ServiceReference<?> ref : refs ) { handleAddingService ( ref ); } } } catch ( final InvalidSyntaxException e ) { // this should never happen } } @Override public void close () { this.context.removeServiceListener ( this.listener ); } protected Object handleAddingService ( final ServiceReference<?> ref ) { Object service = this.context.getService ( ref ); if ( service != null && checkAddService ( ref, service ) == null ) { this.context.ungetService ( ref ); service = null; } return service; } protected Object checkAddService ( final ServiceReference<?> ref, final Object service ) { logger.debug ( "Check add service - ref: {}", ref ); final Controller controller = service.getClass ().getAnnotation ( Controller.class ); if ( controller == null ) { return null; } addController ( ref, new ControllerEntry ( service ) ); return controller; } private final Map<ServiceReference<?>, ControllerEntry> controllers = new ConcurrentHashMap<> (); protected void addController ( final ServiceReference<?> ref, final ControllerEntry entry ) { logger.info ( "Added controller - {}", ref ); this.controllers.put ( ref, entry ); } protected void handleRemovedService ( final ServiceReference<?> ref ) { if ( this.controllers.remove ( ref ) != null ) { this.context.ungetService ( ref ); } } @Override public RequestHandler handleRequest ( final HttpServletRequest request, final HttpServletResponse response ) { for ( final ControllerEntry entry : this.controllers.values () ) { final RequestHandler result = entry.findHandler ( request, response ); if ( logger.isTraceEnabled () ) { logger.trace ( "Result from: {} -> {}", entry, result ); } if ( result != null ) { return result; } } return null; } }