Package ch.entwine.weblounge.workbench

Source Code of ch.entwine.weblounge.workbench.WorkbenchService$SiteServletTracker

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

import ch.entwine.weblounge.common.content.ResourceURI;
import ch.entwine.weblounge.common.content.page.Composer;
import ch.entwine.weblounge.common.content.page.Page;
import ch.entwine.weblounge.common.content.page.Pagelet;
import ch.entwine.weblounge.common.content.page.PageletRenderer;
import ch.entwine.weblounge.common.impl.content.page.PageReader;
import ch.entwine.weblounge.common.impl.testing.MockHttpServletRequest;
import ch.entwine.weblounge.common.impl.testing.MockHttpServletResponse;
import ch.entwine.weblounge.common.repository.ContentRepository;
import ch.entwine.weblounge.common.repository.ContentRepositoryException;
import ch.entwine.weblounge.common.request.WebloungeRequest;
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.url.UrlUtils;
import ch.entwine.weblounge.workbench.suggest.SimpleSuggestion;

import org.apache.commons.io.IOUtils;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;
import org.osgi.util.tracker.ServiceTracker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response.Status;
import javax.xml.parsers.ParserConfigurationException;

/**
* Implementation of a weblounge workbench. The workbench provides support for
* management applications and the page editor.
*/
public class WorkbenchService {

  /** The logging facility */
  private static Logger logger = LoggerFactory.getLogger(WorkbenchService.class);

  /** The site servlets */
  private static Map<String, Servlet> siteServlets = new HashMap<String, Servlet>();

  /** The cache service tracker */
  private ServiceTracker siteServletTracker = null;

  /** Filter expression used to look up site servlets */
  private static final String serviceFilter = "(&(objectclass=" + Servlet.class.getName() + ")(" + Site.class.getName().toLowerCase() + "=*))";

  /**
   * Callback from OSGi declarative services on component startup.
   *
   * @param ctx
   *          the component context
   */
  void activate(ComponentContext ctx) {
    try {
      Filter filter = ctx.getBundleContext().createFilter(serviceFilter);
      siteServletTracker = new SiteServletTracker(ctx.getBundleContext(), filter);
      siteServletTracker.open();
    } catch (InvalidSyntaxException e) {
      throw new IllegalStateException(e);
    }
  }

  /**
   * Callback from OSGi declarative services on component shutdown.
   */
  void deactivate() {
    if (siteServletTracker != null) {
      siteServletTracker.close();
    }
  }

  /**
   * Returns a list of tags from the given site that are suggested based on what
   * is passed in as <code>text</code>. If <code>limit</code> is larger than
   * <code>0</code>, then this is the maximum number of facet values returned.
   *
   * @param site
   *          the site
   * @param text
   *          the starting test
   * @param limit
   *          the maximum number of tags to return
   * @return the list of suggested tags
   * @throws IllegalStateException
   *           if the content repository is not available
   * @throws ContentRepositoryException
   *           if querying fails
   */
  public List<SimpleSuggestion> suggestTags(Site site, String text, int limit)
      throws IllegalStateException {
    List<SimpleSuggestion> tags = new ArrayList<SimpleSuggestion>();
    List<String> suggestions;
    try {
      suggestions = site.getContentRepository().suggest("subject", text, limit);
      for (String s : suggestions) {
        tags.add(new SimpleSuggestion("subject", s));
      }
    } catch (ContentRepositoryException e) {
      logger.warn("Error loading subject suggestions for '" + text + "'", e);
      return null;
    }
    return tags;
  }

  /**
   * Returns the pagelet editor or <code>null</code> if either one of the page,
   * the composer or the is not available.
   *
   * @param site
   *          the site
   * @param pageURI
   *          the page uri
   * @param composerId
   *          the composer id
   * @param pageletIndex
   *          the pagelet index
   * @param language
   *          the environment
   * @param environment
   *          the execution environment
   * @return the pagelet editor
   * @throws IOException
   *           if reading the pagelet fails
   */
  public PageletEditor getEditor(Site site, ResourceURI pageURI,
      String composerId, int pageletIndex, String language,
      Environment environment) throws IOException {
    if (site == null)
      throw new IllegalArgumentException("Site must not be null");
    if (composerId == null)
      throw new IllegalArgumentException("Composer must not be null");
    if (pageletIndex < 0)
      throw new IllegalArgumentException("Pagelet index must be a positive integer");

    Page page = getPage(site, pageURI);
    if (page == null) {
      logger.warn("Client requested pagelet editor for non existing page {}", pageURI);
      return null;
    }

    // Load the composer
    Composer composer = page.getComposer(composerId);
    if (composer == null) {
      logger.warn("Client requested pagelet editor for non existing composer '{}' on page {}", composerId, pageURI);
      return null;
    }

    // Get the pagelet
    if (composer.getPagelets().length <= pageletIndex || composer.size() <= pageletIndex) {
      logger.warn("Client requested pagelet editor for non existing pagelet on page {}", pageURI);
      return null;
    }

    Pagelet pagelet = composer.getPagelet(pageletIndex);
    pagelet = new TrimpathPageletWrapper(pagelet);
    PageletEditor pageletEditor = new PageletEditor(pagelet, pageURI, composerId, pageletIndex, environment);

    // Load the contents of the editor url
    URL editorURL = pageletEditor.getEditorURL();
    if (editorURL != null) {
      String rendererContent = null;
      try {
        rendererContent = loadContents(editorURL, site, page, composer, pagelet, environment, language);
        pageletEditor.setEditor(rendererContent);
      } catch (ServletException e) {
        logger.warn("Error processing the pagelet renderer at {}: {}", editorURL, e.getMessage());
      }
    }

    return pageletEditor;
  }

  /**
   * Returns the page or <code>null</code> if the page is not found.
   *
   * @param site
   *          the site
   * @param pageURI
   *          the pareURI
   * @return the page
   */
  private Page getPage(Site site, ResourceURI pageURI) {
    // Get hold of the site's content repository
    ContentRepository contentRepository = site.getContentRepository();
    if (contentRepository == null) {
      logger.warn("No content repository found for site '{}'", site);
      throw new WebApplicationException(Status.INTERNAL_SERVER_ERROR);
    }

    // Load the page
    Page page = null;
    try {
      page = (Page) contentRepository.get(pageURI);
    } catch (ContentRepositoryException e) {
      logger.error("Error trying to access content repository {}: {}", contentRepository, e);
      throw new WebApplicationException(Status.INTERNAL_SERVER_ERROR);
    }
    return page;
  }

  /**
   * Returns the pagelet renderer or <code>null</code> if either one of the
   * page, the composer or the is not available.
   *
   * @param site
   *          the site
   * @param pageURI
   *          the page uri
   * @param composerId
   *          the composer id
   * @param pageletIndex
   *          the pagelet index
   * @param language
   *          the language
   * @param environment
   *          the environment
   * @return the pagelet renderer
   * @throws IOException
   *           if reading the pagelet fails
   */
  public String getRenderer(Site site, ResourceURI pageURI, String composerId,
      int pageletIndex, String language, Environment environment)
          throws IOException {

    Page page = getPage(site, pageURI);
    if (page == null) {
      logger.warn("Client requested pagelet renderer for non existing page {}", pageURI);
      return null;
    }

    // Load the composer
    Composer composer = page.getComposer(composerId);
    if (composer == null) {
      logger.warn("Client requested pagelet renderer for non existing composer {} on page {}", composerId, pageURI);
      return null;
    }

    // Get the pagelet
    if (composer.getPagelets().length <= pageletIndex || composer.size() <= pageletIndex) {
      logger.warn("Client requested pagelet renderer for non existing pagelet on page {}", pageURI);
      return null;
    }

    Pagelet pagelet = composer.getPagelet(pageletIndex);
    Module module = site.getModule(pagelet.getModule());
    if (module == null) {
      logger.warn("Client requested pagelet renderer for non existing module {}", pagelet.getModule());
      return null;
    }

    PageletRenderer renderer = module.getRenderer(pagelet.getIdentifier());
    if (renderer == null) {
      logger.warn("Client requested pagelet renderer for non existing renderer on pagelet {}", pagelet.getIdentifier());
      return null;
    }

    // Load the contents of the renderer url
    renderer.setEnvironment(environment);
    URL rendererURL = renderer.getRenderer();
    String rendererContent = null;
    if (rendererURL != null) {
      try {
        rendererContent = loadContents(rendererURL, site, page, composer, pagelet, environment, language);
      } catch (ServletException e) {
        logger.warn("Error processing the pagelet renderer at {}: {}", rendererURL, e.getMessage());
        throw new WebApplicationException(Status.INTERNAL_SERVER_ERROR);
      }
    }

    return rendererContent;
  }

  public String getRenderer(Site site, ResourceURI pageURI, String composerId,
      int pageletIndex, String pageXml, String language, Environment environment)
          throws IOException, ParserConfigurationException, SAXException {

    InputStream is = null;
    Page page = null;
    try {
      PageReader pageReader = new PageReader();
      is = IOUtils.toInputStream(pageXml, "utf-8");
      page = pageReader.read(is, site);
    } finally {
      IOUtils.closeQuietly(is);
    }

    // Load the composer
    Composer composer = page.getComposer(composerId);
    if (composer == null) {
      logger.warn("Client requested pagelet renderer for non existing composer {} on page {}", composerId, pageURI);
      return null;
    }

    // Get the pagelet
    if (composer.getPagelets().length <= pageletIndex || composer.size() <= pageletIndex) {
      logger.warn("Client requested pagelet renderer for non existing pagelet on page {}", pageURI);
      return null;
    }

    Pagelet pagelet = composer.getPagelet(pageletIndex);
    Module module = site.getModule(pagelet.getModule());
    if (module == null) {
      logger.warn("Client requested pagelet renderer for non existing module {}", pagelet.getModule());
      return null;
    }

    PageletRenderer renderer = module.getRenderer(pagelet.getIdentifier());
    if (renderer == null) {
      logger.warn("Client requested pagelet renderer for non existing renderer on pagelet {}", pagelet.getIdentifier());
      return null;
    }

    // Load the contents of the renderer url
    renderer.setEnvironment(environment);
    URL rendererURL = renderer.getRenderer();
    String rendererContent = null;
    if (rendererURL != null) {
      try {
        rendererContent = loadContents(rendererURL, site, page, composer, pagelet, environment, language);
      } catch (ServletException e) {
        logger.warn("Error processing the pagelet renderer at {}: {}", rendererURL, e.getMessage());
        throw new WebApplicationException(Status.INTERNAL_SERVER_ERROR);
      }
    }

    return rendererContent;
  }

  /**
   * Asks the site servlet to render the given url using the page, composer and
   * pagelet as the rendering environment. If the no servlet is available for
   * the given site, the contents are loaded from the url directly.
   *
   * @param rendererURL
   *          the renderer url
   * @param site
   *          the site
   * @param page
   *          the page
   * @param composer
   *          the composer
   * @param pagelet
   *          the pagelet
   * @param environment
   *          the environment
   * @param language
   *          the language
   * @return the servlet response, serialized to a string
   * @throws IOException
   *           if the servlet fails to create the response
   * @throws ServletException
   *           if an exception occurs while processing
   */
  private String loadContents(URL rendererURL, Site site, Page page,
      Composer composer, Pagelet pagelet, Environment environment,
      String language) throws IOException, ServletException {

    Servlet servlet = siteServlets.get(site.getIdentifier());

    String httpContextURI = UrlUtils.concat("/weblounge-sites", site.getIdentifier());
    int httpContextURILength = httpContextURI.length();
    String url = rendererURL.toExternalForm();
    int uriInPath = url.indexOf(httpContextURI);

    if (uriInPath > 0) {
      String pathInfo = url.substring(uriInPath + httpContextURILength);

      // Prepare the mock request
      MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
      request.setServerName(site.getHostname(environment).getURL().getHost());
      request.setServerPort(site.getHostname(environment).getURL().getPort());
      request.setMethod(site.getHostname(environment).getURL().getProtocol());
      if (language != null)
        request.addPreferredLocale(new Locale(language));
      request.setAttribute(WebloungeRequest.PAGE, page);
      request.setAttribute(WebloungeRequest.COMPOSER, composer);
      request.setAttribute(WebloungeRequest.PAGELET, pagelet);
      request.setPathInfo(pathInfo);
      request.setRequestURI(UrlUtils.concat(httpContextURI, pathInfo));

      MockHttpServletResponse response = new MockHttpServletResponse();
      servlet.service(request, response);
      return response.getContentAsString();
    } else {
      InputStream is = null;
      try {
        is = rendererURL.openStream();
        return IOUtils.toString(is, "utf-8");
      } finally {
        IOUtils.closeQuietly(is);
      }
    }
  }

  /**
   * Adds the site servlet to the list of servlets.
   *
   * @param id
   *          the site identifier
   * @param servlet
   *          the site servlet
   */
  void addSiteServlet(String id, Servlet servlet) {
    logger.debug("Site servlet attached to {} workbench", id);
    siteServlets.put(id, servlet);
  }

  /**
   * Removes the site servlet from the list of servlets
   *
   * @param site
   *          the site identifier
   */
  void removeSiteServlet(String id) {
    logger.debug("Site servlet detached from {} workbench", id);
    siteServlets.remove(id);
  }

  /**
   * Implementation of a <code>ServiceTracker</code> that is tracking instances
   * of type {@link Servlet} with an associated <code>site</code> attribute.
   */
  private class SiteServletTracker extends ServiceTracker {

    /**
     * Creates a new servlet tracker that is using the given bundle context to
     * look up service instances.
     *
     * @param ctx
     *          the bundle context
     * @param filter
     *          the service filter
     */
    SiteServletTracker(BundleContext ctx, Filter filter) {
      super(ctx, filter, null);
    }

    /**
     * {@inheritDoc}
     *
     * @see org.osgi.util.tracker.ServiceTracker#addingService(org.osgi.framework.ServiceReference)
     */
    @Override
    public Object addingService(ServiceReference reference) {
      Servlet servlet = (Servlet) super.addingService(reference);
      String site = (String) reference.getProperty(Site.class.getName().toLowerCase());
      addSiteServlet(site, servlet);
      return servlet;
    }

    /**
     * {@inheritDoc}
     *
     * @see org.osgi.util.tracker.ServiceTracker#removedService(org.osgi.framework.ServiceReference,
     *      java.lang.Object)
     */
    @Override
    public void removedService(ServiceReference reference, Object service) {
      String site = (String) reference.getProperty("site");
      removeSiteServlet(site);
    }

  }

}
TOP

Related Classes of ch.entwine.weblounge.workbench.WorkbenchService$SiteServletTracker

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.