package com.buglabs.bug.ws;
import java.util.Hashtable;
import java.util.Map;
import javax.servlet.http.HttpServlet;
import org.knapsack.init.pub.KnapsackInitService;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.http.HttpService;
import org.osgi.service.log.LogService;
import org.osgi.util.tracker.ServiceTracker;
import org.sprinkles.Applier;
import com.buglabs.bug.dragonfly.module.IModuleControl;
import com.buglabs.bug.ws.module.ModuleServlet;
import com.buglabs.bug.ws.module.PackageServlet;
import com.buglabs.bug.ws.program.ConfigAdminServlet;
import com.buglabs.bug.ws.program.ProgramServlet;
import com.buglabs.bug.ws.service.WSHtmlServlet;
import com.buglabs.bug.ws.service.WSServlet;
import com.buglabs.services.ws.PublicWSProvider;
import com.buglabs.util.osgi.BUGBundleConstants;
import com.buglabs.util.osgi.FilterUtil;
import com.buglabs.util.osgi.LogServiceUtil;
import com.buglabs.util.osgi.OSGiServiceLoader;
import com.buglabs.util.osgi.ServiceTrackerUtil;
import com.buglabs.util.osgi.ServiceTrackerUtil.ManagedInlineRunnable;
/**
* Bundle activator for BUG web services functionality.
*
* @author kgilmer
*
*/
public class Activator implements BundleActivator, ManagedInlineRunnable {
public static final String APP_BUNDLE_PATH = "app.bundle.path";
public static final String PROGRAM_WS_PATH = "/program";
public static final String CONFIG_WS_PATH = "/configuration";
public static final String MODULE_WS_PATH = "/module";
private static final String SERVICE_WS_PATH = "/service";
private static final String SERVICE_HTML_PATH = SERVICE_WS_PATH + ".html";
private static final String PACKAGE_WS_PATH = "/package";
private static BundleContext context;
/**
* @return BundleContext
*/
public static BundleContext getContext() {
return context;
}
private static LogService log;
private Map<String, HttpServlet> servlets;
/**
* @return Log Service
*/
public static LogService getLog() {
return log;
}
private ServiceTracker st;
/**
* Services required before bundle's functionality will be active.
*/
private String[] services = {
HttpService.class.getName(),
ConfigurationAdmin.class.getName(),
KnapsackInitService.class.getName()
};
private HttpService httpService;
private ConfigurationAdmin configAdmin;
private ModuleServlet moduleServlet;
private Map<String, PublicWSProvider> serviceMap;
/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
*/
public void start(BundleContext bundleContext) throws Exception {
Activator.context = bundleContext;
log = LogServiceUtil.getLogService(bundleContext);
serviceMap = new Hashtable<String, PublicWSProvider>();
st = ServiceTrackerUtil.openServiceTracker(bundleContext, this , services);
}
/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext bundleContext) throws Exception {
st.close();
Activator.context = null;
}
@Override
public void run(Map<String, Object> services) {
// Determine if object state is valid
if (servlets != null) {
log.log(LogService.LOG_ERROR
, "Servlets have already been registered but the ServiceTracker was called to register again.");
return;
}
// Get a reference to the HTTP service
httpService = (HttpService) services.get(HttpService.class.getName());
KnapsackInitService initService = (KnapsackInitService) services.get(KnapsackInitService.class.getName());
configAdmin = (ConfigurationAdmin) services.get(ConfigurationAdmin.class.getName());
// Create servlet instances to be hosted by HTTP service
servlets = new Hashtable<String, HttpServlet>();
try {
moduleServlet = new ModuleServlet(getExistingModules());
context.addServiceListener(moduleServlet, FilterUtil.generateServiceFilter(IModuleControl.class.getName()));
servlets.put(MODULE_WS_PATH, moduleServlet);
} catch (InvalidSyntaxException e) {
log.log(LogService.LOG_ERROR, "Failed to construct a valid service filter.", e);
return;
}
servlets.put(PACKAGE_WS_PATH, new PackageServlet(context));
servlets.put(PROGRAM_WS_PATH, new ProgramServlet(context, initService));
servlets.put(CONFIG_WS_PATH, new ConfigAdminServlet(context, configAdmin));
servlets.put(SERVICE_WS_PATH, new WSServlet(context, serviceMap, configAdmin));
servlets.put(SERVICE_HTML_PATH, new WSHtmlServlet(context, serviceMap, configAdmin));
// Register servlets
for (Map.Entry<String, HttpServlet> e : servlets.entrySet())
try {
httpService.registerServlet(e.getKey(), e.getValue(), null, null);
} catch (Exception e1) {
log.log(LogService.LOG_ERROR, "Failed to register servlet " + e.getKey(), e1);
}
}
/**
* @return an array of IModuleControls that reflect currently attached modules to BUG device.
*
* @throws InvalidSyntaxException on OSGi filter syntax exception.
*/
private IModuleControl[] getExistingModules() throws InvalidSyntaxException {
final IModuleControl[] modules = new IModuleControl[BUGBundleConstants.BUG_TOTAL_BMI_SLOTS];
Applier.map(context.getServiceReferences(IModuleControl.class.getName(), null), new Applier.Fn<ServiceReference, IModuleControl>() {
@Override
public IModuleControl apply(ServiceReference element) {
IModuleControl imc = (IModuleControl) context.getService(element);
modules[imc.getSlotId()] = imc;
return imc;
}
});
return modules;
}
@Override
public void shutdown() {
if (moduleServlet != null) {
context.removeServiceListener(moduleServlet);
moduleServlet = null;
}
// Unregister all servlets
if (httpService != null && servlets != null && servlets.size() > 0) {
for (String alias : servlets.keySet())
httpService.unregister(alias);
httpService = null;
}
servlets = null;
}
}