Package ch.entwine.weblounge.kernel.command

Source Code of ch.entwine.weblounge.kernel.command.SiteCommand

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

import ch.entwine.weblounge.common.content.Resource;
import ch.entwine.weblounge.common.content.SearchQuery;
import ch.entwine.weblounge.common.content.SearchResult;
import ch.entwine.weblounge.common.content.SearchResultItem;
import ch.entwine.weblounge.common.content.page.Composer;
import ch.entwine.weblounge.common.content.page.Page;
import ch.entwine.weblounge.common.impl.content.SearchQueryImpl;
import ch.entwine.weblounge.common.impl.content.page.PageURIImpl;
import ch.entwine.weblounge.common.language.Language;
import ch.entwine.weblounge.common.repository.ContentRepository;
import ch.entwine.weblounge.common.repository.ContentRepositoryException;
import ch.entwine.weblounge.common.repository.WritableContentRepository;
import ch.entwine.weblounge.common.site.Site;
import ch.entwine.weblounge.common.site.SiteURL;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.DateFormat;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.Formatter;
import java.util.Hashtable;
import java.util.List;

/**
* OSGi shell command implementation for sites.
*/
public class SiteCommand {

  /** Logger */
  private static final Logger logger = LoggerFactory.getLogger(SiteCommand.class);

  /** The list of registered sites */
  private final List<Site> sites = new ArrayList<Site>();

  /**
   * Command signature that allows to do
   * <ul>
   * <li><code>site list</code></li>
   * <li><code>site &lt;id&gt; start</code></li>
   * <li><code>site &lt;id&gt; stop</code></li>
   * <li><code>site &lt;id&gt; restart</code></li>
   * <li><code>site &lt;id&gt; enable</code></li>
   * <li><code>site &lt;id&gt; disable</code></li>
   * <li><code>site &lt;id&gt; index</code></li>
   * <li><code>site &lt;id&gt; status</code></li>
   * <li><code>site &lt;id&gt; inspect &lt;url&gt;</code></li>
   * <li><code>site &lt;id&gt; search &lt;terms&gt;</code></li>
   * </ul>
   *
   * @param args
   *          the list of arguments to this command
   */
  public void site(String[] args) {
    if (args.length == 0) {
      list();
      return;
    } else if (args.length == 1) {
      if ("list".equals(args[0])) {
        list();
      } else {
        printUsage();
      }
    } else if (args.length > 1) {
      String id = args[0];

      // Look up the site
      Site site = getSite(id);
      if (site == null) {
        try {
          site = getSite(Integer.parseInt(id));
          if (site == null) {
            System.out.println("Unknown site: " + id);
            return;
          }
        } catch (NumberFormatException e) {
          System.out.println("Unknown site: " + id);
          return;
        }
      }

      // Process the command
      if ("start".equals(args[1]))
        start(site);
      else if ("stop".equals(args[1]))
        stop(site);
      else if ("restart".equals(args[1]))
        restart(site);
      else if ("index".equals(args[1]))
        index(site);
      else if ("status".equals(args[1]))
        status(site);
      else if ("inspect".equals(args[1]))
        inspect(site, Arrays.copyOfRange(args, 2, args.length));
      else if ("search".equals(args[1])) {
        search(site, Arrays.copyOfRange(args, 2, args.length));
      } else {
        System.out.println("Unknown command: " + args[1]);
        return;
      }
    } else {
      printUsage();
    }
  }

  /**
   * Lists the registered sites.
   */
  public void sites() {
    list();
  }

  /**
   * Prints a list of currently registered sites.
   */
  private void list() {
    synchronized (sites) {

      // Are there any sites?
      if (sites.size() == 0) {
        System.out.println("No sites found");
        return;
      }

      // Setup the number formatter
      int digits = 1 + (int) (Math.log(sites.size() + 1) / Math.log(10));
      StringBuffer format = new StringBuffer();
      for (int i = 0; i < digits; i++)
        format.append("#");
      DecimalFormat formatter = new DecimalFormat(format.toString());

      // Display the site list
      for (int i = 0; i < sites.size(); i++) {
        Site site = sites.get(i);
        StringBuffer buf = new StringBuffer();
        buf.append("[ ").append(formatter.format(i + 1)).append(" ] ");
        while (buf.length() < 8)
          buf.append(" ");
        buf.append(site.getName() != null ? site.getName() : site.getIdentifier());
        buf.append(" ");
        int descriptionLength = buf.length();
        for (int j = 0; j < 64 - descriptionLength; j++)
          buf.append(".");
        buf.append(site.isOnline() ? " STARTED " : " STOPPED");
        while (buf.length() < 22)
          buf.append(" ");
        System.out.println(buf.toString());
      }
    }
  }

  /**
   * Prints out information about the site.
   *
   * @param site
   *          the site
   */
  private void status(Site site) {
    pad("identifier", site.getIdentifier());
    if (site.getName() != null)
      pad("description", site.getName());

    // Enabled
    pad("autostart", (site.isStartedAutomatically() ? "yes" : "no"));

    // Started / Stopped
    pad("running", (site.isOnline() ? "yes" : "no"));

    // Hostnames
    if (site.getHostnames().length > 0)
      pad("hosts", site.getHostnames());

    // Languages
    if (site.getLanguages().length > 0) {
      StringBuffer buf = new StringBuffer();
      if (site.getDefaultLanguage() != null) {
        buf.append(site.getDefaultLanguage());
        buf.append(" (default)");
      }
      for (Language language : site.getLanguages()) {
        if (language.equals(site.getDefaultLanguage()))
          continue;
        if (buf.length() > 0)
          buf.append(", ");
        buf.append(language);
      }
      pad("languages", buf.toString());
    }

    // Pages and revisions
    try {
      ContentRepository repository = site.getContentRepository();
      long pages = repository != null ? repository.getResourceCount() : -1;
      pad("pages", (pages >= 0 ? Long.toString(pages) : "n/a"));
      long revisions = repository != null ? repository.getVersionCount() : -1;
      pad("revisions", (revisions >= 0 ? Long.toString(revisions) : "n/a"));
    } catch (ContentRepositoryException e) {
      System.err.println("Error trying to access the content repository");
      e.printStackTrace(System.err);
    }
  }

  /**
   * Prints out information about the given url or page identifier.
   *
   * @param site
   *          the site
   * @param args
   *          arguments to this function
   */
  private void inspect(Site site, String[] args) {
    if (args.length == 0) {
      System.err.println("Please specify what to inspect");
      System.err.println("Usage: site <id> inspect <url>|<id>");
      return;
    }

    // What are we looking at?
    ContentRepository repository = site.getContentRepository();
    Page page = null;

    // Is it a page?
    try {
      String objectId = args[0];
      // TODO: What if we hit a file or an image?
      if (objectId.startsWith("/"))
        page = (Page) repository.get(new PageURIImpl(site, args[0]));
      else
        page = (Page) repository.get(new PageURIImpl(site, null, args[0]));
      if (page != null) {
        title("page");
        pad("id", page.getURI().getIdentifier().toString());
        pad("path", page.getURI().getPath());

        section("lifecycle");

        DateFormat df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG);

        // Created
        if (page.getCreationDate() != null) {
          StringBuffer buf = new StringBuffer();
          buf.append(df.format(page.getCreationDate()));
          if (page.getCreator() != null) {
            buf.append(" by ").append(page.getCreator().toString());
          }
          pad("created", buf.toString());
        }

        // Modified
        if (page.getModificationDate() != null) {
          StringBuffer buf = new StringBuffer();
          buf.append(df.format(page.getModificationDate()));
          if (page.getModifier() != null) {
            buf.append(" by ").append(page.getModifier().toString());
          }
          pad("modified", buf.toString());
        }

        // Published
        if (page.getPublishFrom() != null) {
          StringBuffer buf = new StringBuffer();
          buf.append(df.format(page.getPublishFrom()));
          if (page.getPublisher() != null) {
            buf.append(" by ").append(page.getPublisher().toString());
          }
          pad("published", buf.toString());
          if (page.getPublishTo() != null)
            pad("published until", df.format(page.getPublishTo()));
        }

        section("header");

        if (page.getTitle() != null)
          pad("title", page.getTitle());

        // subjects
        StringBuffer subjectList = new StringBuffer();
        for (String c : page.getSubjects()) {
          if (subjectList.length() > 0)
            subjectList.append(", ");
          subjectList.append(c);
        }
        pad("subjects", subjectList.toString());

        section("content");

        // composers
        StringBuffer composerList = new StringBuffer();
        for (Composer c : page.getComposers()) {
          if (composerList.length() > 0)
            composerList.append(", ");
          composerList.append(c.getIdentifier());
          composerList.append(" (").append(c.getPagelets().length).append(")");
        }
        pad("composers", composerList.toString());

      }
    } catch (ContentRepositoryException e) {
      System.err.println("Error trying to access the content repository");
      e.printStackTrace(System.err);
    }
  }

  /**
   * Does a search using the terms from the arguments and displays the search
   * hits on the console.
   *
   * @param site
   *          the site
   * @param args
   *          search terms
   */
  private void search(Site site, String[] args) {
    if (args.length == 0) {
      System.out.println("Please specify a search term");
      System.err.println("Usage: site <id> search <terms>");
      return;
    }

    // Build the search expression
    // TODO: Use AND?
    String text = StringUtils.join(args, " ");

    // Get hold of the content repository
    ContentRepository repository = site.getContentRepository();
    SearchQuery query = new SearchQueryImpl(site);
    query.withVersion(Resource.LIVE);
    query.withFulltext(text.toString());

    // Is it a page?
    Formatter formatter = null;
    try {
      SearchResult result = repository.find(query);

      // Format the output
      formatter = new Formatter(System.out);
      StringBuffer format = new StringBuffer();
      int padding = Long.toString(result.getDocumentCount()).length();
      format.append("%1$#").append(padding).append("s. %2$s\n");

      // List results
      int i = 1;
      for (SearchResultItem item : result.getItems()) {
        formatter.format(format.toString(), i++, item.getUrl());
      }

      System.out.println("Found " + result.getDocumentCount() + " results (" + result.getSearchTime() + " ms)");
    } catch (ContentRepositoryException e) {
      System.err.println("Error trying to access the content repository");
      e.printStackTrace(System.err);
    } finally {
      IOUtils.closeQuietly(formatter);
    }
  }

  /**
   * Triggers a rebuilding of the site index.
   *
   * @param site
   *          the site
   */
  private void index(Site site) {
    // boolean restart = site.isOnline();

    // Make sure we are in good shape before we index
    ContentRepository repository = site.getContentRepository();
    if (repository == null) {
      System.out.println("Site " + site + " has no content repository");
      return;
    } else if (repository.isReadOnly()) {
      System.out.println("Site " + site + " is read only");
      return;
      // } else if (site.isOnline()) {
      // while (true) {
      // String answer =
      // System.console().readLine("Can't index a running site! Stop now? [y/n] ");
      // if ("y".equalsIgnoreCase(answer)) {
      // stop(site);
      // System.out.println();
      // break;
      // } else if ("n".equalsIgnoreCase(answer)) {
      // return;
      // } else {
      // answer = null;
      // }
      // }
    }

    // Finally! Let's do the work
    System.out.println("Indexing site " + site);
    try {
      ((WritableContentRepository) repository).index();
    } catch (ContentRepositoryException e) {
      e.printStackTrace();
    }

    // Restart the site if we shut it down previously
    System.out.println("Site " + site + " indexed");
    // if (restart) {
    // System.out.println();
    // start(site);
    // }
  }

  /**
   * Returns a padded version of the text.
   *
   * @param caption
   *          the caption
   * @param info
   *          the information
   */
  private void pad(String caption, SiteURL[] info) {
    for (int i = 0; i < info.length; i++) {
      if (i == 0)
        pad(caption, info[i].toExternalForm());
      else
        pad(null, info[i].toExternalForm());
    }
  }

  /**
   * Returns a padded version of the title.
   *
   * @param title
   *          the title
   */
  private void title(String title) {
    for (int i = 0; i < (15 - title.length()); i++)
      System.out.print(" ");
    System.out.println(title);
  }

  /**
   * Returns a padded version of the section title.
   *
   * @param title
   *          the title
   */
  private void section(String title) {
    System.out.println();
    for (int i = 0; i < (15 - title.length()); i++)
      System.out.print(" ");
    System.out.println(title.toUpperCase());
  }

  /**
   * Returns a padded version of the text.
   *
   * @param caption
   *          the caption
   * @param info
   *          the information
   */
  private void pad(String caption, String info) {
    if (caption == null)
      caption = "";
    for (int i = 0; i < (15 - caption.length()); i++)
      System.out.print(" ");
    if (!"".equals(caption)) {
      System.out.print(caption);
      System.out.print(": ");
    } else {
      System.out.print("  ");
    }
    System.out.print(info);
    System.out.println();
  }

  /**
   * Starts the site.
   *
   * @param site
   *          the site to start
   */
  private void start(Site site) {
    if (site.isOnline()) {
      System.out.println("Site " + site + " is already running");
      return;
    }

    System.out.println("Starting site " + site);
    try {
      site.start();
    } catch (Throwable t) {
      t.printStackTrace();
    }
  }

  /**
   * Stops the site.
   *
   * @param site
   *          the site to stop
   */
  private void stop(Site site) {
    if (!site.isOnline()) {
      System.out.println("Site " + site + " is already stopped");
      return;
    }
    System.out.println("Stopping site " + site);
    site.stop();
  }

  /**
   * Restarts the site.
   *
   * @param site
   *          the site to restart
   */
  private void restart(Site site) {
    try {
      if (site.isOnline()) {
        site.stop();
        site.start();
      } else if (site.isStartedAutomatically()) {
        site.start();
      }
    } catch (Throwable t) {
      t.printStackTrace();
    }
  }

  /**
   * Prints the command usage to the commandline.
   */
  private void printUsage() {
    System.out.println("  Usage:");
    System.out.println("    site list");
    System.out.println("    site <id> start|stop|restart");
    System.out.println("    site <id> index");
    System.out.println("    site <id> status");
    System.out.println("    site <id> inspect <url|id>");
    System.out.println("    site <id> search <terms>");
  }

  /**
   * Returns the site with the given identifier or <code>null</code> if no such
   * site was registered.
   *
   * @param id
   *          the site identifier
   * @return the site
   */
  private Site getSite(String id) {
    synchronized (sites) {
      for (Site site : sites) {
        if (site.getIdentifier().equals(id))
          return site;
      }
    }
    return null;
  }

  /**
   * Returns the site with the given index or <code>null</code> if a wrong index
   * is given.
   *
   * @param index
   *          the site number
   * @return the site
   */
  private Site getSite(int index) {
    synchronized (sites) {
      index--;
      return (index < sites.size()) ? sites.get(index) : null;
    }
  }

  /**
   * Callback for OSGi's declarative services component activation.
   *
   * @param context
   *          the component context
   * @throws Exception
   *           if component inactivation fails
   */
  void activate(ComponentContext context) throws Exception {
    BundleContext bundleContext = context.getBundleContext();
    logger.debug("Registering site commands");
    Dictionary<String, Object> commands = new Hashtable<String, Object>();
    commands.put("osgi.command.scope", "weblounge");
    commands.put("osgi.command.function", new String[] { "site", "sites" });
    bundleContext.registerService(getClass().getName(), this, commands);
  }

  /**
   * Adds a site to the list of registered sites.
   *
   * @param site
   *          the site to add
   */
  void addSite(Site site) {
    synchronized (sites) {
      sites.add(site);
    }
  }

  /**
   * Removes a site from the list of registered sites.
   *
   * @param site
   *          the site to remove
   */
  void removeSite(Site site) {
    synchronized (sites) {
      sites.remove(site);
    }
  }

}
TOP

Related Classes of ch.entwine.weblounge.kernel.command.SiteCommand

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.