Package ch.entwine.weblounge.kernel.site

Source Code of ch.entwine.weblounge.kernel.site.SiteDispatcherServiceImpl

/*
*  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.site;

import ch.entwine.weblounge.common.impl.util.WebloungeDateFormat;
import ch.entwine.weblounge.common.impl.util.config.ConfigurationUtils;
import ch.entwine.weblounge.common.repository.ContentRepository;
import ch.entwine.weblounge.common.security.SecurityService;
import ch.entwine.weblounge.common.site.Action;
import ch.entwine.weblounge.common.site.Environment;
import ch.entwine.weblounge.common.site.Module;
import ch.entwine.weblounge.common.site.Site;
import ch.entwine.weblounge.common.site.SiteListener;
import ch.entwine.weblounge.common.url.PathUtils;
import ch.entwine.weblounge.common.url.UrlUtils;
import ch.entwine.weblounge.dispatcher.ActionRequestHandler;
import ch.entwine.weblounge.dispatcher.DispatcherConfiguration;
import ch.entwine.weblounge.dispatcher.SharedHttpContext;
import ch.entwine.weblounge.dispatcher.SiteDispatcherService;
import ch.entwine.weblounge.kernel.http.WebXml;

import org.apache.commons.io.FileUtils;
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.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;
import org.osgi.service.prefs.PreferencesService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Date;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;
import java.util.WeakHashMap;

import javax.servlet.Servlet;
import javax.servlet.http.HttpServletRequest;

/**
* The site dispatcher watches sites coming and going and registers them with
* the weblounge dispatcher.
*/
public class SiteDispatcherServiceImpl implements SiteDispatcherService, SiteListener, SiteServiceListener, ManagedService {

  /** Logging facility */
  private static final Logger logger = LoggerFactory.getLogger(SiteDispatcherServiceImpl.class);

  /** Default value for the <code>WEBAPP_CONTEXT_ROOT</code> property */
  public static final String DEFAULT_WEBAPP_CONTEXT_ROOT = "/";

  /** Default value for the <code>BUNDLE_ROOT_URI</code> property */
  public static final String DEFAULT_BUNDLE_CONTEXT_ROOT_URI = "/weblounge-sites";

  /** Service pid, used to look up the service configuration */
  public static final String SERVICE_PID = "ch.entwine.weblounge.sitedispatcher";

  /** Configuration key prefix for jsp precompilation */
  public static final String OPT_PRECOMPILE = "precompile";

  /** Configuration key prefix for jsp precompilation logging */
  public static final String OPT_PRECOMPILE_LOGGING = "precompile.logerrors";

  /** Configuration key prefix for jasper configuration values */
  public static final String OPT_JASPER_PREFIX = "jasper.";

  /** Configuration option for jasper's scratch directory */
  public static final String OPT_JASPER_SCRATCHDIR = "scratchdir";

  /** Default value for jasper's <code>scratchDir</code> compiler context */
  public static final String DEFAULT_JASPER_SCRATCH_DIR = "jasper";

  /** Prefix for the precompilation date */
  public static final String X_COMPILE_PREFIX = "X-COMPILE-";

  /** Path to the scratch directory */
  private String jasperScratchDir = null;

  /** The action request handler */
  private ActionRequestHandler actionRequestHandler = null;

  /** The site manager */
  private SiteManager siteManager = null;

  /** The default environment */
  private Environment environment = Environment.Production;

  /** Init parameters for jetty */
  private final TreeMap<String, String> jasperConfig = new TreeMap<String, String>();

  /** Maps sites to site servlets */
  private final Map<Site, SiteServlet> siteServlets = new HashMap<Site, SiteServlet>();

  /** The site servlet registrations */
  private Map<Site, ServiceRegistration> servletRegistrations = null;

  /** The security service */
  private SecurityService securityService = null;

  /** The preferences service */
  private PreferencesService preferencesService = null;

  /** The precompiler for java server pages */
  private boolean precompile = true;

  /** Shutdown flag for running threads */
  private boolean shutdown = false;

  /** List of precompilers */
  private final WeakHashMap<Site, Precompiler> precompilers = new WeakHashMap<Site, Precompiler>();

  /** True to log errors that appear during precompilation */
  private boolean logCompileErrors = false;

  /**
   * Callback for OSGi's declarative services component activation.
   *
   * @param context
   *          the component context
   * @throws IOException
   *           if reading from the configuration admin service fails
   * @throws ConfigurationException
   *           if service configuration fails
   */
  void activate(ComponentContext context) throws IOException,
  ConfigurationException {

    BundleContext bundleContext = context.getBundleContext();
    logger.info("Starting site dispatcher");

    // Configure the jasper work directory where compiled java classes go
    String tmpDir = System.getProperty("java.io.tmpdir");
    jasperScratchDir = PathUtils.concat(tmpDir, DEFAULT_JASPER_SCRATCH_DIR);
    jasperConfig.put(OPT_JASPER_SCRATCHDIR, jasperScratchDir);

    // 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) {
        configure(config);
      } else {
        logger.debug("No customized configuration for site dispatcher found");
      }
    } else {
      logger.debug("No configuration admin service found while looking for site dispatcher configuration");
    }

    servletRegistrations = new HashMap<Site, ServiceRegistration>();

    logger.debug("Site dispatcher activated");

    // Register for changing sites
    siteManager.addSiteListener(this);

    // Process sites that have already been registered
    Thread t = new Thread(new Runnable() {
      @Override
      public void run() {
        for (Iterator<Site> si = siteManager.sites(); si.hasNext();) {
          addSite(si.next());
        }
      }
    });
    t.setDaemon(true);
    t.start();
  }

  /**
   * Callback for OSGi's declarative services component dactivation.
   *
   * @param context
   *          the component context
   * @throws Exception
   *           if component inactivation fails
   */
  void deactivate(ComponentContext context) {
    logger.debug("Deactivating site dispatcher");

    // Don't listen to new sites anymore
    siteManager.removeSiteListener(this);

    // Tell everyone to finish their work
    shutdown = true;
    synchronized (servletRegistrations) {
      servletRegistrations.notifyAll();
    }

    // Stop precompilers
    for (Precompiler compiler : precompilers.values()) {
      if (compiler.isRunning()) {
        compiler.stop();
      } else if (preferencesService != null) {
        Preferences preferences = preferencesService.getSystemPreferences();
        String date = WebloungeDateFormat.formatStatic(new Date());
        preferences.put(compiler.getCompilerKey(), date);
        try {
          preferences.flush();
        } catch (BackingStoreException e) {
          logger.warn("Failed to store precompiler results: {}", e.getMessage());
        }
      } else if (preferencesService == null) {
        logger.warn("Unable to store precompiler results: preference service unavailable");
      }
    }

    logger.info("Site dispatcher stopped");
  }

  /**
   * {@inheritDoc}
   *
   * @see org.osgi.service.cm.ManagedService#updated(java.util.Dictionary)
   */
  public void updated(Dictionary properties) throws ConfigurationException {
    if (properties == null)
      return;
    configure(properties);
  }

  /**
   * Configures this service using the given configuration properties.
   *
   * @param config
   *          the service configuration
   * @throws ConfigurationException
   *           if configuration fails
   */
  private boolean configure(Dictionary<?, ?> config)
      throws ConfigurationException {

    logger.debug("Configuring the site registration service");
    boolean configurationChanged = true;

    // Activate precompilation?
    String precompileSetting = StringUtils.trimToNull((String) config.get(OPT_PRECOMPILE));
    precompile = precompileSetting == null || ConfigurationUtils.isTrue(precompileSetting);
    logger.debug("Jsp precompilation {}", precompile ? "activated" : "deactivated");

    // Log compilation errors?
    String logPrecompileErrors = StringUtils.trimToNull((String) config.get(OPT_PRECOMPILE_LOGGING));
    logCompileErrors = logPrecompileErrors != null && ConfigurationUtils.isTrue(logPrecompileErrors);
    logger.debug("Precompilation errors will {} logged", logCompileErrors ? "be" : "not be");

    // Store the jasper configuration keys
    Enumeration<?> keys = config.keys();
    while (keys.hasMoreElements()) {
      String key = (String) keys.nextElement();
      if (key.startsWith(OPT_JASPER_PREFIX) && key.length() > OPT_JASPER_PREFIX.length()) {
        String value = (String) config.get(key);
        if (StringUtils.trimToNull(value) == null)
          continue;
        value = ConfigurationUtils.processTemplate(value);
        key = key.substring(OPT_JASPER_PREFIX.length());

        boolean optionChanged = value.equalsIgnoreCase(jasperConfig.get(key));
        configurationChanged |= !optionChanged;
        if (optionChanged)
          logger.debug("Jetty jsp parameter '{}' configured to '{}'", key, value);

        jasperConfig.put(key, value);
        // This is a work around for jasper's horrible implementation of the
        // compiler context configuration. Some keys are camel case, others are
        // lower case.
        jasperConfig.put(key.toLowerCase(), value);
      }
    }

    return configurationChanged;
  }

  /**
   * Callback from the OSGi environment which registers the request handler with
   * the site observer.
   *
   * @param handler
   *          the action request handler
   */
  void setActionRequestHandler(ActionRequestHandler handler) {
    logger.debug("Registering {}", handler);
    this.actionRequestHandler = handler;
    if (siteManager == null)
      return;
    for (Iterator<Site> si = siteManager.sites(); si.hasNext();) {
      for (Module module : si.next().getModules()) {
        for (Action action : module.getActions()) {
          actionRequestHandler.register(action);
        }
      }
    }
  }

  /**
   * Callback from the OSGi environment which removes the action request handler
   * from the site observer.
   *
   * @param handler
   *          the action request handler
   */
  void removeActionRequestHandler(ActionRequestHandler handler) {
    logger.debug("Unregistering {}", handler);
    if (siteManager == null)
      return;
    for (Iterator<Site> si = siteManager.sites(); si.hasNext();) {
      for (Module module : si.next().getModules()) {
        for (Action action : module.getActions()) {
          actionRequestHandler.unregister(action);
        }
      }
    }
    this.actionRequestHandler = null;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.dispatcher.SiteDispatcherService#getSiteServlet(ch.entwine.weblounge.common.site.Site)
   */
  public Servlet getSiteServlet(Site site) {
    return siteServlets.get(site);
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.dispatcher.SiteDispatcherService#findSiteByIdentifier(java.lang.String)
   */
  public Site findSiteByIdentifier(String identifier) {
    return siteManager.findSiteByIdentifier(identifier);
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.dispatcher.SiteDispatcherService#findSiteByURL(java.lang.String)
   */
  public Site findSiteByURL(URL siteURL) {
    return siteManager.findSiteByURL(siteURL);
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.dispatcher.SiteDispatcherService#findSiteByRequest(javax.servlet.http.HttpServletRequest)
   */
  public Site findSiteByRequest(HttpServletRequest request) {
    if (request == null)
      throw new IllegalArgumentException("Request must not be null");
    return findSiteByURL(UrlUtils.toURL(request, false, false));
  }

  /**
   * Adds a new site.
   *
   * This method may be long-running and therefore is executed in its own
   * thread.
   *
   * @param site
   *          the site
   */
  private void addSite(final Site site) {
    Thread t = new Thread(new Runnable() {

      public void run() {

        Bundle siteBundle = siteManager.getSiteBundle(site);
        WebXml webXml = createWebXml(site, siteBundle);
        Properties initParameters = new Properties();

        // Prepare the init parameters
        // initParameters.put("load-on-startup", Integer.toString(1));
        initParameters.putAll(webXml.getContextParams());
        initParameters.putAll(jasperConfig);

        // Create the site URI
        String contextRoot = webXml.getContextParam(DispatcherConfiguration.WEBAPP_CONTEXT_ROOT, DEFAULT_WEBAPP_CONTEXT_ROOT);
        String bundleURI = webXml.getContextParam(DispatcherConfiguration.BUNDLE_URI, site.getIdentifier());
        String siteContextURI = webXml.getContextParam(DispatcherConfiguration.BUNDLE_CONTEXT_ROOT_URI, DEFAULT_BUNDLE_CONTEXT_ROOT_URI);
        String siteRoot = UrlUtils.concat(contextRoot, siteContextURI, bundleURI);

        // Prepare the Jasper work directory
        String scratchDirPath = PathUtils.concat(jasperConfig.get(OPT_JASPER_SCRATCHDIR), site.getIdentifier());
        File scratchDir = new File(scratchDirPath);
        boolean jasperArtifactsExist = scratchDir.isDirectory() && scratchDir.list().length > 0;
        try {
          FileUtils.forceMkdir(scratchDir);
          logger.debug("Temporary jsp source files and classes go to {}", scratchDirPath);
        } catch (IOException e) {
          logger.warn("Unable to create jasper scratch directory at {}: {}", scratchDirPath, e.getMessage());
        }

        try {
          // Create and register the site servlet
          SiteServlet siteServlet = new SiteServlet(site, siteBundle, environment);
          siteServlet.setSecurityService(securityService);
          Dictionary<String, String> servletRegistrationProperties = new Hashtable<String, String>();
          servletRegistrationProperties.put(Site.class.getName().toLowerCase(), site.getIdentifier());
          servletRegistrationProperties.put(SharedHttpContext.ALIAS, siteRoot);
          servletRegistrationProperties.put(SharedHttpContext.SERVLET_NAME, site.getIdentifier());
          servletRegistrationProperties.put(SharedHttpContext.CONTEXT_ID, SharedHttpContext.WEBLOUNGE_CONTEXT_ID);
          servletRegistrationProperties.put(SharedHttpContext.INIT_PREFIX + OPT_JASPER_SCRATCHDIR, scratchDirPath);
          ServiceRegistration servletRegistration = siteBundle.getBundleContext().registerService(Servlet.class.getName(), siteServlet, servletRegistrationProperties);
          servletRegistrations.put(site, servletRegistration);

          // We are using the Whiteboard pattern to register servlets. Wait for
          // the http service to pick up the servlet and initialize it
          synchronized (servletRegistrations) {
            boolean warnedOnce = false;
            while (!siteServlet.isInitialized()) {

              if (!warnedOnce) {
                logger.info("Waiting for site '{}' to be online", site.getIdentifier());
                warnedOnce = true;
              }

              logger.debug("Waiting for http service to pick up {}", siteServlet);
              servletRegistrations.wait(500);
              if (shutdown) {
                logger.info("Giving up waiting for registration of site '{}'");
                servletRegistrations.remove(site);
                return;
              }
            }
          }

          siteServlets.put(site, siteServlet);

          logger.info("Site '{}' is online and registered under site://{}", site, siteRoot);

          // Did we already miss the "siteStarted()" event? If so, we trigger it
          // for ourselves, so the modules are being started.
          site.addSiteListener(SiteDispatcherServiceImpl.this);
          if (site.isOnline()) {
            siteStarted(site);
          }

          // Start the precompiler if requested
          if (precompile) {
            String compilationKey = X_COMPILE_PREFIX + siteBundle.getBundleId();
            Date compileDate = null;

            boolean needsCompilation = true;

            // Check if this site has been precompiled already
            if (preferencesService != null) {
              Preferences preferences = preferencesService.getSystemPreferences();
              String compileDateString = preferences.get(compilationKey, null);
              if (compileDateString != null) {
                compileDate = WebloungeDateFormat.parseStatic(compileDateString);
                needsCompilation = false;
                logger.info("Site '{}' has already been precompiled on {}", site.getIdentifier(), compileDate);
              }
            } else {
              logger.info("Precompilation status cannot be determined, consider deploying a preferences service implementation");
            }

            // Does the scratch dir exist?
            if (!jasperArtifactsExist) {
              needsCompilation = true;
              logger.info("Precompiled artifacts for '{}' have been removed", site.getIdentifier());
            }

            // Let's do the work anyways
            if (needsCompilation) {
              Precompiler precompiler = new Precompiler(compilationKey, siteServlet, environment, securityService, logCompileErrors);
              precompilers.put(site, precompiler);
              precompiler.precompile();
            }
          }

          logger.debug("Site '{}' registered under site://{}", site, siteRoot);

        } catch (Throwable t) {
          logger.error("Error setting up site '{}' for http requests: {}", new Object[] {
              site,
              t.getMessage() });
          logger.error(t.getMessage(), t);
        }

      }

    });
    t.setDaemon(true);
    t.start();
  }

  /**
   * Removes a site from the dispatcher.
   *
   * @param site
   *          the site to remove
   */
  private void removeSite(Site site) {
    // Remove site dispatcher servlet
    ServiceRegistration servletRegistration = servletRegistrations.remove(site);

    try {
      servletRegistration.unregister();
    } catch (IllegalStateException e) {
      // Never mind, the service has been unregistered already
    } catch (Throwable t) {
      logger.error("Unregistering site '{}' failed: {}", site.getIdentifier(), t.getMessage());
    }

    // We are no longer interested in site events
    site.removeSiteListener(this);

    // Stop the site's precompiler
    Precompiler compiler = precompilers.get(site);
    if (compiler != null) {
      if (compiler.isRunning()) {
        compiler.stop();
      } else if (preferencesService != null) {
        Preferences preferences = preferencesService.getSystemPreferences();
        String date = WebloungeDateFormat.formatStatic(new Date());
        preferences.put(compiler.getCompilerKey(), date);
        try {
          preferences.flush();
        } catch (BackingStoreException e) {
          logger.warn("Failed to store precompiler results: {}", e.getMessage());
        }
      } else if (preferencesService == null) {
        logger.warn("Unable to store precompiler results: preference service unavailable");
      }
    }

    siteServlets.remove(site);

    // TODO: unregister site dispatcher

    logger.debug("Site {} unregistered", site);
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.site.SiteListener#siteStarted(ch.entwine.weblounge.common.site.Site)
   */
  public void siteStarted(Site site) {
    if (actionRequestHandler != null) {
      for (Module module : site.getModules()) {
        for (Action action : module.getActions()) {
          actionRequestHandler.register(action);
        }
      }
    }
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.site.SiteListener#siteStopped(ch.entwine.weblounge.common.site.Site)
   */
  public void siteStopped(Site site) {
    if (actionRequestHandler != null) {
      for (Module module : site.getModules()) {
        for (Action action : module.getActions()) {
          actionRequestHandler.unregister(action);
        }
      }
    }
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.site.SiteListener#repositoryConnected(ch.entwine.weblounge.common.site.Site,
   *      ch.entwine.weblounge.common.repository.ContentRepository)
   */
  public void repositoryConnected(Site site, ContentRepository repository) {
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.site.SiteListener#repositoryDisconnected(ch.entwine.weblounge.common.site.Site,
   *      ch.entwine.weblounge.common.repository.ContentRepository)
   */
  public void repositoryDisconnected(Site site, ContentRepository repository) {
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.kernel.site.SiteServiceListener#siteAppeared(ch.entwine.weblounge.common.site.Site,
   *      org.osgi.framework.ServiceReference)
   */
  public void siteAppeared(Site site, ServiceReference reference) {
    addSite(site);
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.kernel.site.SiteServiceListener#siteDisappeared(ch.entwine.weblounge.common.site.Site)
   */
  public void siteDisappeared(Site site) {
    removeSite(site);
  }

  /**
   * Returns the <code>web.xml</code> representation that is used to register
   * the site dispatcher servlets with the <code>HttpService</code>.
   * <p>
   * The method registers the following init parameters in the
   * <code>web.xml</code> with appropriate default values:
   * <ul>
   * <li>weblounge.http.WEBAPP_CONTEXT_ROOT</li>
   * <li>weblounge.http.BUNDLE_CONTEXT_ROOT</li>
   * <li>weblounge.http.BUNDLE_CONTEXT_ROOT_URI</li>
   * <li>weblounge.http.BUNDLE_NAME</li>
   * <li>weblounge.http.BUNDLE_ROOT</li>
   * <li>weblounge.http.BUNDLE_URI</li>
   * <li>weblounge.http.BUNDLE_ENTRY</li>
   * </ul>
   * <p>
   * <b>Note:</b> almost all of these properties can be overwritten using either
   * the system properties or the service properties.
   */
  public WebXml createWebXml(Site site, Bundle siteBundle) {
    ServiceReference reference = null;
    ServiceReference[] references = siteBundle.getRegisteredServices();
    for (ServiceReference ref : references) {
      if (site.equals(siteBundle.getBundleContext().getService(ref))) {
        reference = ref;
        break;
      }
    }

    WebXml webXml = new WebXml();
    webXml.addContextParam(DispatcherConfiguration.BUNDLE_NAME, siteBundle.getSymbolicName());
    webXml.addContextParam(DispatcherConfiguration.BUNDLE_ENTRY, Site.BUNDLE_PATH);

    // Webapp context root
    String webappRoot = null;
    if (reference != null && reference.getProperty(DispatcherConfiguration.WEBAPP_CONTEXT_ROOT) != null)
      webappRoot = (String) reference.getProperty(DispatcherConfiguration.WEBAPP_CONTEXT_ROOT);
    else if (System.getProperty(DispatcherConfiguration.WEBAPP_CONTEXT_ROOT) != null)
      webappRoot = System.getProperty(DispatcherConfiguration.WEBAPP_CONTEXT_ROOT);
    if (webappRoot == null)
      webappRoot = DEFAULT_WEBAPP_CONTEXT_ROOT;
    if (!webappRoot.startsWith("/"))
      webappRoot = "/" + webappRoot;
    webXml.addContextParam(DispatcherConfiguration.WEBAPP_CONTEXT_ROOT, webappRoot);

    // Bundle name
    webXml.addContextParam(DispatcherConfiguration.BUNDLE_NAME, siteBundle.getSymbolicName().toLowerCase());

    // Bundle context root uri
    String sitesRoot = null;
    if (reference != null && reference.getProperty(DispatcherConfiguration.BUNDLE_CONTEXT_ROOT_URI) != null)
      sitesRoot = (String) reference.getProperty(DispatcherConfiguration.BUNDLE_CONTEXT_ROOT_URI);
    else if (System.getProperty(DispatcherConfiguration.BUNDLE_CONTEXT_ROOT_URI) != null)
      sitesRoot = System.getProperty(DispatcherConfiguration.BUNDLE_CONTEXT_ROOT_URI);
    if (sitesRoot == null)
      sitesRoot = DEFAULT_BUNDLE_CONTEXT_ROOT_URI;
    if (!sitesRoot.startsWith("/"))
      sitesRoot = "/" + sitesRoot;
    webXml.addContextParam(DispatcherConfiguration.BUNDLE_CONTEXT_ROOT_URI, sitesRoot);

    // Bundle context root
    sitesRoot = UrlUtils.concat(webappRoot, sitesRoot);
    webXml.addContextParam(DispatcherConfiguration.BUNDLE_CONTEXT_ROOT, sitesRoot);

    // Bundle uri
    webXml.addContextParam(DispatcherConfiguration.BUNDLE_URI, site.getIdentifier());

    // Bundle root
    String bundleRoot = UrlUtils.concat(sitesRoot, site.getIdentifier());
    webXml.addContextParam(DispatcherConfiguration.BUNDLE_ROOT, bundleRoot);

    // Bundle entry
    String bundleEntry = null;
    if (reference != null && reference.getProperty(DispatcherConfiguration.BUNDLE_ENTRY) != null)
      bundleEntry = (String) reference.getProperty(DispatcherConfiguration.BUNDLE_ENTRY);
    else if (System.getProperty(DispatcherConfiguration.BUNDLE_ENTRY) != null)
      bundleEntry = System.getProperty(DispatcherConfiguration.BUNDLE_ENTRY);
    if (bundleEntry == null)
      bundleEntry = Site.BUNDLE_PATH;
    if (!bundleEntry.startsWith("/"))
      bundleEntry = "/" + bundleEntry;
    webXml.addContextParam(DispatcherConfiguration.BUNDLE_ENTRY, bundleEntry);

    return webXml;
  }

  /**
   * OSGi callback that will set the site manager.
   *
   * @param siteManager
   *          the site manager
   */
  void setSiteManager(SiteManager siteManager) {
    this.siteManager = siteManager;
  }

  /**
   * OSGi callback that will unset the site manager.
   *
   * @param siteManager
   *          the site manager
   */
  void removeSiteManager(SiteManager siteManager) {
    this.siteManager = null;
  }

  /**
   * Sets the default environment;
   *
   * @param environment
   *          the environment
   */
  void setEnvironment(Environment environment) {
    this.environment = environment;
    for (SiteServlet servlet : siteServlets.values()) {
      servlet.setEnvironment(environment);
    }
  }

  /**
   * Sets the security service.
   *
   * @param securityService
   *          the security service
   */
  void setSecurityService(SecurityService securityService) {
    this.securityService = securityService;
  }

  /**
   * Sets the preferences service.
   *
   * @param preferencesService
   *          the OSGi preferences service
   */
  void setPreferencesService(PreferencesService preferencesService) {
    this.preferencesService = preferencesService;
  }

}
TOP

Related Classes of ch.entwine.weblounge.kernel.site.SiteDispatcherServiceImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.