001    /*
002     * Copyright (C) 2010 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.spi.jarurl;
021    
022    import org.crsh.vfs.spi.AbstractFSDriver;
023    
024    import java.io.IOException;
025    import java.net.JarURLConnection;
026    import java.net.URL;
027    import java.util.Collections;
028    import java.util.HashMap;
029    import java.util.Map;
030    import java.util.jar.JarEntry;
031    import java.util.jar.JarFile;
032    
033    /**
034     * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
035     * @version $Revision$
036     */
037    public class JarURLDriver extends AbstractFSDriver<Handle> {
038    
039      /** . */
040      final Handle root;
041    
042      /** . */
043      final URL jarURL;
044    
045      private static Handle get(JarURLDriver driver, Map<String, Handle> handles, String path) {
046        Handle handle = handles.get(path);
047        if (handle == null) {
048          handle = new Handle(driver, path);
049          int to = path.length();
050          if (path.charAt(to - 1) == '/') {
051            to--;
052          }
053          int from = -1;
054          for (int i = to - 1;i >= 0;i--) {
055            if (path.charAt(i) == '/') {
056              from = i;
057              break;
058            }
059          }
060          String name;
061          Handle parent;
062          if (from == -1) {
063            parent = handles.get("");
064            name = path.substring(0, to);
065          } else {
066            parent = get(driver, handles, path.substring(0, from));
067            name = path.substring(from + 1, to);
068          }
069          parent.children.put(name, handle);
070          handles.put(path.substring(0, to), handle);
071        }
072        return handle;
073      }
074    
075      public JarURLDriver(JarURLConnection conn) throws IOException {
076        JarFile file = conn.getJarFile();
077        Map<String, Handle> handles = new HashMap<String, Handle>();
078        handles.put("", root = new Handle(this, ""));
079        for (JarEntry entry : Collections.list(file.entries())) {
080          Handle handle = get(this, handles, entry.getName());
081          handle.entry = entry;
082        }
083    
084        //
085        this.jarURL = conn.getJarFileURL();
086      }
087    
088      public Handle root() throws IOException {
089        return root;
090      }
091    
092      public String name(Handle handle) throws IOException {
093        return handle.path.getName();
094      }
095    
096      public boolean isDir(Handle handle) throws IOException {
097        return handle.path.isDir();
098      }
099    
100      public Iterable<Handle> children(Handle handle) throws IOException {
101        return handle.children.values();
102      }
103    
104      public URL toURL(Handle handle) throws IOException {
105        return handle.toURL();
106      }
107    }