/* * Weblounge: Web Content Management System * Copyright (c) 2003 - 2011 The Weblounge Team * http://entwinemedia.com/weblounge * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package ch.entwine.weblounge.kernel.shared; import ch.entwine.weblounge.dispatcher.SharedHttpContext; import org.apache.commons.lang.StringUtils; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.cm.ConfigurationException; import org.osgi.service.cm.ManagedService; import org.osgi.service.component.ComponentContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.util.Dictionary; import java.util.Hashtable; import javax.servlet.Servlet; /** * This component registers this bundle's <code>/html</code> resource directory * with the http service under <code>/system/shared/</code> so that images, * cascading stylesheets and javascripts are available locally. */ public class WebloungeSharedResources implements ManagedService { /** Logger */ private static final Logger logger = LoggerFactory.getLogger(WebloungeSharedResources.class); /** Service pid, used to look up the service configuration */ public static final String SERVICE_PID = "ch.entwine.weblounge.resources"; /** Bundle directory containing the shared resources */ public static final String RESOURCES_BUNDLE_DIR = "/html"; /** Mountpoint to use when registering the shared resources */ public static final String DEFAULT_RESOURCES_MOUNTPOINT = "/weblounge-shared"; /** Option name for the shared resources mountpoint */ public static final String OPT_RESOURCES_MOUNTPOINT = "resources.path"; /** Option name for the external location of shared resources */ public static final String OPT_EXT_RESOURCES = "resources.external.dir"; /** Name of the current jQuery version */ public static final String JQUERY_VERSION = "1.6.4"; /** Name of the current jQuery Tools version */ public static final String JQUERY_TOOLS_VERSION = "1.2.5"; /** Directory with external resources */ private File externalResourcesDir = null; /** Actual mountpoint for the shared resources */ private String resourcesMountpoint = null; /** The http servlet registration */ private ServiceRegistration servletRegistration = null; /** Bundle context */ private BundleContext bundleContext = null; /** * Callback for OSGi's declarative services component inactivation. * * @param context * the component context * @throws Exception * if component inactivation fails */ void activate(ComponentContext context) throws Exception { bundleContext = context.getBundleContext(); // Try to get hold of the service configuration ServiceReference configAdminRef = bundleContext.getServiceReference(ConfigurationAdmin.class.getName()); if (configAdminRef != null) { ConfigurationAdmin configAdmin = (ConfigurationAdmin) bundleContext.getService(configAdminRef); Dictionary<?, ?> config = configAdmin.getConfiguration(SERVICE_PID).getProperties(); if (config != null) { updated(config); } else { logger.debug("No customized configuration for content repository found"); resourcesMountpoint = DEFAULT_RESOURCES_MOUNTPOINT; } } else { logger.debug("No configuration admin service found while looking for content repository configuration"); } if (servletRegistration == null) { register(resourcesMountpoint, externalResourcesDir, bundleContext.getBundle()); } } /** * Callback for OSGi's declarative services component inactivation. * * @param context * the component context * @throws Exception * if component inactivation fails */ void deactivate(ComponentContext context) throws Exception { logger.info("Stopping serving of shared resources", this); if (servletRegistration != null) { try { servletRegistration.unregister(); } catch (IllegalStateException e) { // Never mind, the service has been unregistered already } catch (Throwable t) { logger.error("Unregistering shared resource servlet failed: {}", t.getMessage()); } servletRegistration = null; } } /** * {@inheritDoc} * * @see org.osgi.service.cm.ManagedService#updated(java.util.Dictionary) */ @SuppressWarnings("rawtypes") public void updated(Dictionary properties) throws ConfigurationException { if (properties == null) return; // Mountpoint String mountpoint = (String) properties.get(OPT_RESOURCES_MOUNTPOINT); if (StringUtils.isNotBlank(mountpoint)) { resourcesMountpoint = mountpoint; logger.debug("Configured value for the shared resource mountpoint is '{}'", mountpoint); } else { resourcesMountpoint = DEFAULT_RESOURCES_MOUNTPOINT; logger.debug("Using default mountpoint {} for shared resources", resourcesMountpoint); } // Optional external resources directory String externalResources = (String) properties.get(OPT_EXT_RESOURCES); if (StringUtils.isNotBlank(externalResources)) { externalResourcesDir = new File(externalResources); logger.debug("Configured external shared resources directory at '{}'", externalResources); } else { logger.debug("Shared resources will be served from bundle '{}'", bundleContext.getBundle().getSymbolicName()); } // Register the new servlet if (servletRegistration != null) { try { servletRegistration.unregister(); } catch (IllegalStateException e) { // Never mind, the service has been unregistered already } catch (Throwable t) { logger.error("Unregistering shared resources servlet failed: {}", t.getMessage()); } } servletRegistration = register(resourcesMountpoint, externalResourcesDir, bundleContext.getBundle()); logger.info("Serving shared resources at {}", resourcesMountpoint); } /** * Returns the path to the root of the shared resources. * * @return the shared resources mountpoint */ public String getResourcesMountpoint() { return resourcesMountpoint; } /** * Registers the shared resources directory under the given context. * * @param context * the context path * @param resourcesDir * directory containing the resources to serve * @param the * contextual bundle */ private ServiceRegistration register(String context, File resourcesDir, Bundle bundle) { Dictionary<String, String> registrationProperties = new Hashtable<String, String>(); registrationProperties.put(SharedHttpContext.CONTEXT_ID, SharedHttpContext.WEBLOUNGE_CONTEXT_ID); registrationProperties.put(SharedHttpContext.ALIAS, context); registrationProperties.put(SharedHttpContext.SERVLET_NAME, "weblounge.sharedresources"); Servlet servlet = new WebloungeResourcesServlet(resourcesDir, bundle, RESOURCES_BUNDLE_DIR); return bundleContext.registerService(Servlet.class.getName(), servlet, registrationProperties); } }