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