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.vfs;
021
022import org.crsh.vfs.spi.FSDriver;
023import org.crsh.vfs.spi.FSMountFactory;
024import org.crsh.vfs.spi.Mount;
025import org.crsh.vfs.spi.file.FileDriver;
026import org.crsh.vfs.spi.url.ClassPathMountFactory;
027import org.crsh.vfs.spi.url.URLDriver;
028
029import java.io.IOException;
030import java.net.URISyntaxException;
031import java.net.URL;
032import java.util.ArrayList;
033import java.util.HashMap;
034import java.util.Iterator;
035import java.util.List;
036
037/**
038 * The file system provides a federated view of {@link org.crsh.vfs.spi.FSDriver} mounts.
039 */
040public 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}