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.vfs;
021    
022    import org.crsh.vfs.spi.FSDriver;
023    import org.crsh.vfs.spi.FSMountFactory;
024    import org.crsh.vfs.spi.Mount;
025    import org.crsh.vfs.spi.file.FileDriver;
026    import org.crsh.vfs.spi.url.ClassPathMountFactory;
027    import org.crsh.vfs.spi.url.URLDriver;
028    
029    import java.io.IOException;
030    import java.net.URISyntaxException;
031    import java.net.URL;
032    import java.util.ArrayList;
033    import java.util.HashMap;
034    import java.util.Iterator;
035    import java.util.List;
036    
037    /**
038     * The file system provides a federated view of {@link org.crsh.vfs.spi.FSDriver} mounts.
039     */
040    public class FS {
041    
042      public static class Builder {
043    
044        /** . */
045        private HashMap<String, FSMountFactory<?>> resolvers;
046    
047        /** . */
048        private ArrayList<Mount<?>> mounts = new ArrayList<Mount<?>>();
049    
050        public Builder() {
051          this.resolvers = new HashMap<String, FSMountFactory<?>>();
052        }
053    
054        /**
055         * Register a resolver.
056         *
057         * @param name the registration name
058         * @param resolver the resolver implementation
059         */
060        public Builder register(String name, FSMountFactory<?> resolver) {
061          resolvers.put(name, resolver);
062          return this;
063        }
064    
065        public Builder mount(String name, Path path) throws IOException, IllegalArgumentException {
066          FSMountFactory<?> resolver = resolvers.get(name);
067          if (resolver == null) {
068            throw new IllegalArgumentException("Unknown driver " + name);
069          } else {
070            Mount<?> mount = resolver.create(path);
071            mounts.add(mount);
072            return this;
073          }
074        }
075    
076        public Builder mount(String mountPointConfig) throws IOException {
077          int prev = 0;
078          while (true) {
079            int next = mountPointConfig.indexOf(';', prev);
080            if (next == -1) {
081              next = mountPointConfig.length();
082            }
083            if (next > prev) {
084              String mount = mountPointConfig.substring(prev, next);
085              int index = mount.indexOf(':');
086              String name;
087              String path;
088              if (index == -1) {
089                name = "classpath";
090                path = mount;
091              } else {
092                name = mount.substring(0, index);
093                path = mount.substring(index + 1);
094              }
095              mount(name, Path.get(path));
096              prev = next + 1;
097            } else {
098              break;
099            }
100          }
101          return this;
102        }
103    
104        public List<Mount<?>> getMounts() {
105          return mounts;
106        }
107    
108        public FS build() throws IOException {
109          FS fs = new FS();
110          for (Mount<?> mount : mounts) {
111            fs.mount(mount.getDriver());
112          }
113          return fs;
114        }
115    
116        @Override
117        public String toString() {
118          StringBuilder sb = new StringBuilder();
119          for (Iterator<Mount<?>> i = mounts.iterator();i.hasNext();) {
120            Mount<?> mount = i.next();
121            sb.append(mount.getValue());
122            if (i.hasNext()) {
123              sb.append(';');
124            }
125          }
126          return sb.toString();
127        }
128      }
129    
130      /** . */
131      final List<FSDriver<?>> drivers;
132    
133      public FS() {
134        this.drivers = new ArrayList<FSDriver<?>>();
135      }
136    
137      public File get(Path path) throws IOException {
138        return new File(this, path);
139      }
140    
141      public FS mount(FSDriver<?> driver) throws IOException {
142        if (driver == null) {
143          throw new NullPointerException();
144        }
145        drivers.add(driver);
146        return this;
147      }
148    
149      public FS mount(java.io.File root) throws IOException {
150        return mount(new FileDriver(root));
151      }
152    
153      public FS mount(ClassLoader cl, Path path) throws IOException, URISyntaxException {
154        if (cl == null) {
155          throw new NullPointerException();
156        } else {
157          return mount(new ClassPathMountFactory(cl).create(path).getDriver());
158        }
159      }
160    
161      public FS mount(Class<?> clazz) throws IOException, URISyntaxException {
162        if (clazz == null) {
163          throw new NullPointerException();
164        }
165        URL url = clazz.getProtectionDomain().getCodeSource().getLocation();
166        URLDriver driver = new URLDriver();
167        driver.merge(url);
168        return mount(driver);
169      }
170    }