001/*
002 * Copyright (C) 2012 eXo Platform SAS.
003 *
004 * This is free software; you can redistribute it and/or modify it
005 * under the terms of the GNU Lesser General Public License as
006 * published by the Free Software Foundation; either version 2.1 of
007 * the License, or (at your option) any later version.
008 *
009 * This software is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * You should have received a copy of the GNU Lesser General Public
015 * License along with this software; if not, write to the Free
016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018 */
019
020package org.crsh.standalone;
021
022import org.crsh.plugin.PluginContext;
023import org.crsh.plugin.PluginLifeCycle;
024import org.crsh.plugin.ServiceLoaderDiscovery;
025import org.crsh.vfs.FS;
026import org.crsh.vfs.Path;
027import org.crsh.vfs.spi.FSDriver;
028
029import java.io.File;
030import java.io.IOException;
031import java.net.URISyntaxException;
032import java.net.URL;
033import java.net.URLClassLoader;
034import java.util.Collections;
035import java.util.Map;
036import java.util.logging.Logger;
037
038/**
039 * A boostrap for starting a standalone CRaSH.
040 */
041public class Bootstrap extends PluginLifeCycle {
042
043  /** . */
044  protected final Logger log = Logger.getLogger(getClass().getName());
045
046  /** The configuration file system. */
047  private final FS confFS = new FS();
048
049  /** The command file system. */
050  private final FS cmdFS = new FS();
051
052  /** The base classloader. */
053  private final ClassLoader loader;
054
055  /** The attributes. */
056  private Map<String, Object> attributes;
057
058  /**
059   * Create a bootstrap instance with the base classloader and an empty and unmodifiable attribute map.
060   *
061   * @param baseLoader the base classloader crash will use
062   * @throws NullPointerException if the loader argument is null
063   */
064  public Bootstrap(ClassLoader baseLoader) throws NullPointerException {
065    if (baseLoader == null) {
066      throw new NullPointerException("No null base loader accepted");
067    }
068    this.attributes = Collections.emptyMap();
069    this.loader = new URLClassLoader(new URL[]{}, baseLoader);
070  }
071
072  /**
073   * Replaces the attributes to use, the new attributes map will be used as is and not copied.
074   *
075   * @param attributes the attribute map
076   */
077  public void setAttributes(Map<String, Object> attributes) {
078    this.attributes = attributes;
079  }
080
081  /**
082   * Add a configuration path driver.
083   *
084   * @param driver the configuration driver
085   * @return this bootstrap
086   * @throws NullPointerException when the driver is null
087   */
088  public Bootstrap addToConfPath(FSDriver<?> driver) throws NullPointerException {
089    if (driver == null) {
090      throw new NullPointerException("No null conf driver");
091    }
092    log.info("Added " + driver + " driver to conf path");
093    confFS.mount(driver);
094    return this;
095  }
096
097  /**
098   * Add a configuration path directory.
099   *
100   * @param path the configuration path
101   * @return this bootstrap
102   * @throws NullPointerException when the path argument is null
103   * @throws IOException any io exception
104   */
105  public Bootstrap addToConfPath(File path) throws NullPointerException, IOException {
106    if (path == null) {
107      throw new NullPointerException("No null conf path");
108    }
109    log.info("Added " + path.getCanonicalPath() + " file to conf path");
110    confFS.mount(path);
111    return this;
112  }
113
114  /**
115   * Add a configuration path.
116   *
117   * @param path the configuration path
118   * @return this bootstrap
119   * @throws NullPointerException when the path argument is null
120   * @throws IOException any io exception
121   * @throws URISyntaxException any uri syntax exception
122   */
123  public Bootstrap addToConfPath(Path path) throws NullPointerException, IOException, URISyntaxException {
124    if (path == null) {
125      throw new NullPointerException("No null conf path");
126    }
127    log.info("Added " + path.getValue() + " path to conf path");
128    confFS.mount(loader, path);
129    return this;
130  }
131
132  /**
133   * Add a command path driver.
134   *
135   * @param driver the command driver
136   * @return this bootstrap
137   * @throws NullPointerException when the driver is null
138   */
139  public Bootstrap addToCmdPath(FSDriver<?> driver) throws NullPointerException {
140    if (driver == null) {
141      throw new NullPointerException("No null conf driver");
142    }
143    log.info("Added " + driver + " driver to command path");
144    cmdFS.mount(driver);
145    return this;
146  }
147
148  /**
149   * Add a command path directory.
150   *
151   * @param path the command path
152   * @return this bootstrap
153   * @throws NullPointerException when the path argument is null
154   * @throws IOException any io exception
155   */
156  public Bootstrap addToCmdPath(File path) throws NullPointerException, IOException {
157    if (path == null) {
158      throw new NullPointerException("No null command path");
159    }
160    log.info("Added " + path.getAbsolutePath() + " file to command path");
161    cmdFS.mount(path);
162    return this;
163  }
164
165  /**
166   * Add a command path directory.
167   *
168   * @param path the command path
169   * @return this bootstrap
170   * @throws NullPointerException when the path argument is null
171   * @throws IOException any io exception
172   * @throws URISyntaxException any uri syntax exception
173   */
174  public Bootstrap addToCmdPath(Path path) throws NullPointerException, IOException, URISyntaxException {
175    if (path == null) {
176      throw new NullPointerException("No null command path");
177    }
178    log.info("Added " + path.getValue() + " path to command path");
179    cmdFS.mount(loader, path);
180    return this;
181  }
182
183  /**
184   * Trigger the boostrap.
185   *
186   * @throws Exception any exception that would prevent the bootstrap
187   */
188  public void bootstrap() throws Exception {
189
190    // The service loader discovery
191    ServiceLoaderDiscovery discovery = new ServiceLoaderDiscovery(loader);
192
193    //
194    PluginContext context = new PluginContext(
195      discovery,
196      attributes,
197      cmdFS,
198      confFS,
199      loader);
200
201    //
202    context.refresh();
203
204    //
205    start(context);
206  }
207
208  public void shutdown() {
209    stop();
210  }
211}