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    
020    package org.crsh.standalone;
021    
022    import org.crsh.plugin.PluginContext;
023    import org.crsh.plugin.PluginLifeCycle;
024    import org.crsh.plugin.ServiceLoaderDiscovery;
025    import org.crsh.vfs.FS;
026    import org.crsh.vfs.Path;
027    
028    import java.io.File;
029    import java.io.IOException;
030    import java.net.URISyntaxException;
031    import java.net.URL;
032    import java.net.URLClassLoader;
033    import java.util.Collections;
034    import java.util.Map;
035    import java.util.logging.Logger;
036    
037    /**
038     * A boostrap for starting a standalone CRaSH.
039     */
040    public class Bootstrap extends PluginLifeCycle {
041    
042      /** . */
043      protected final Logger log = Logger.getLogger(getClass().getName());
044    
045      /** The configuration file system. */
046      private final FS confFS = new FS();
047    
048      /** The command file system. */
049      private final FS cmdFS = new FS();
050    
051      /** The base classloader. */
052      private final ClassLoader loader;
053    
054      /** The attributes. */
055      private Map<String, Object> attributes;
056    
057      /**
058       * Create a bootstrap instance with the base classloader and an empty and unmodifiable attribute map.
059       *
060       * @param baseLoader the base classloader crash will use
061       * @throws NullPointerException if the loader argument is null
062       */
063      public Bootstrap(ClassLoader baseLoader) throws NullPointerException {
064        if (baseLoader == null) {
065          throw new NullPointerException("No null base loader accepted");
066        }
067        this.attributes = Collections.emptyMap();
068        this.loader = new URLClassLoader(new URL[]{}, baseLoader);
069      }
070    
071      /**
072       * Replaces the attributes to use, the new attributes map will be used as is and not copied.
073       *
074       * @param attributes the attribute map
075       */
076      public void setAttributes(Map<String, Object> attributes) {
077        this.attributes = attributes;
078      }
079    
080      /**
081       * Add a configuration path directory.
082       *
083       * @param path the configuration path
084       * @return this bootstrap
085       * @throws NullPointerException when the path argument is null
086       * @throws IOException any io exception
087       */
088      public Bootstrap addToConfPath(File path) throws NullPointerException, IOException {
089        if (path == null) {
090          throw new NullPointerException("No null conf path");
091        }
092        log.info("Added " + path.getCanonicalPath() + " command to conf path");
093        confFS.mount(path);
094        return this;
095      }
096    
097      /**
098       * Add a configuration path.
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       * @throws URISyntaxException any uri syntax exception
105       */
106      public Bootstrap addToConfPath(Path path) throws NullPointerException, IOException, URISyntaxException {
107        if (path == null) {
108          throw new NullPointerException("No null conf path");
109        }
110        log.info("Added " + path.getValue() + " command to conf path");
111        confFS.mount(loader, path);
112        return this;
113      }
114    
115      /**
116       * Add a command path directory.
117       *
118       * @param path the command path
119       * @return this bootstrap
120       * @throws NullPointerException when the path argument is null
121       * @throws IOException any io exception
122       */
123      public Bootstrap addToCmdPath(File path) throws NullPointerException, IOException {
124        if (path == null) {
125          throw new NullPointerException("No null command path");
126        }
127        log.info("Added " + path.getAbsolutePath() + " command to command path");
128        cmdFS.mount(path);
129        return this;
130      }
131    
132      /**
133       * Add a command path directory.
134       *
135       * @param path the command path
136       * @return this bootstrap
137       * @throws NullPointerException when the path argument is null
138       * @throws IOException any io exception
139       * @throws URISyntaxException any uri syntax exception
140       */
141      public Bootstrap addToCmdPath(Path path) throws NullPointerException, IOException, URISyntaxException {
142        if (path == null) {
143          throw new NullPointerException("No null command path");
144        }
145        log.info("Added " + path.getValue() + " command to command path");
146        cmdFS.mount(loader, path);
147        return this;
148      }
149    
150      /**
151       * Trigger the boostrap.
152       *
153       * @throws Exception any exception that would prevent the bootstrap
154       */
155      public void bootstrap() throws Exception {
156    
157        // The service loader discovery
158        ServiceLoaderDiscovery discovery = new ServiceLoaderDiscovery(loader);
159    
160        //
161        PluginContext context = new PluginContext(
162          discovery,
163          attributes,
164          cmdFS,
165          confFS,
166          loader);
167    
168        //
169        context.refresh();
170    
171        //
172        start(context);
173      }
174    
175      public void shutdown() {
176        stop();
177      }
178    }