Java tutorial
/* * 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 <id> start</code></li> * <li><code>site <id> stop</code></li> * <li><code>site <id> restart</code></li> * <li><code>site <id> enable</code></li> * <li><code>site <id> disable</code></li> * <li><code>site <id> index</code></li> * <li><code>site <id> status</code></li> * <li><code>site <id> inspect <url></code></li> * <li><code>site <id> search <terms></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); } } }