1 19 20 package org.netbeans.core.startup.layers; 21 22 import java.beans.PropertyVetoException ; 23 import java.io.File ; 24 import java.io.IOException ; 25 import java.lang.ref.Reference ; 26 import java.lang.ref.SoftReference ; 27 import java.net.URI ; 28 import java.net.URISyntaxException ; 29 import java.net.URL ; 30 import java.net.URLDecoder ; 31 import java.util.Enumeration ; 32 import java.util.HashMap ; 33 import java.util.Map ; 34 import java.util.logging.Level ; 35 import org.openide.filesystems.FileChangeAdapter; 36 import org.openide.filesystems.FileChangeListener; 37 import org.openide.filesystems.FileEvent; 38 import org.openide.filesystems.FileObject; 39 import org.openide.filesystems.FileRenameEvent; 40 import org.openide.filesystems.FileSystem; 41 import org.openide.filesystems.FileUtil; 42 import org.openide.filesystems.JarFileSystem; 43 import org.openide.filesystems.Repository; 44 import org.openide.filesystems.URLMapper; 45 import org.openide.util.Exceptions; 46 47 public class ArchiveURLMapper extends URLMapper { 48 49 private static final String JAR_PROTOCOL = "jar"; 51 private static Map <File ,SoftReference <JarFileSystem>> mountRoots = new HashMap <File ,SoftReference <JarFileSystem>>(); 52 53 public URL getURL(FileObject fo, int type) { 54 assert fo != null; 55 if (type == URLMapper.EXTERNAL || type == URLMapper.INTERNAL) { 56 if (fo.isValid()) { 57 try { 58 FileSystem fs = fo.getFileSystem(); 59 if (fs instanceof JarFileSystem) { 60 JarFileSystem jfs = (JarFileSystem) fs; 61 File archiveFile = jfs.getJarFile(); 62 if (isRoot(archiveFile)) { 63 return new URL ("jar:"+archiveFile.toURI()+"!/"+fo.getPath()+ 78 ((fo.isFolder() && !fo.isRoot()) ? "/" : "")); } 80 } 81 } catch (IOException e) { 82 Exceptions.printStackTrace(e); 83 } 84 } 85 } 86 return null; 87 } 88 89 public FileObject[] getFileObjects(URL url) { 90 assert url != null; 91 String protocol = url.getProtocol (); 92 if (JAR_PROTOCOL.equals (protocol)) { 93 String path = url.getPath(); 94 int index = path.lastIndexOf ('!'); 95 if (index>=0) { 96 try { 97 URI archiveFileURI = new URI (path.substring(0,index)); 98 if (!archiveFileURI.isAbsolute() || archiveFileURI.isOpaque()) { 99 return null; } 101 FileObject fo = URLMapper.findFileObject (archiveFileURI.toURL()); 102 if (fo == null || fo.isVirtual()) { 103 return null; 104 } 105 File archiveFile = FileUtil.toFile (fo); 106 if (archiveFile == null) { 107 return null; 108 } 109 String offset = path.length()>index+2 ? URLDecoder.decode(path.substring(index+2),"UTF-8"): ""; JarFileSystem fs = getFileSystem(archiveFile); 111 FileObject resource = fs.findResource(offset); 112 if (resource != null) { 113 return new FileObject[] {resource}; 114 } 115 } catch (IOException e) { 116 ModuleLayeredFileSystem.err.log(Level.WARNING, null, e); 119 } 120 catch (URISyntaxException e) { 121 Exceptions.printStackTrace(e); 122 } 123 } 124 } 125 return null; 126 } 127 128 private static synchronized boolean isRoot (File file) { 129 return mountRoots.containsKey(file); 130 } 131 132 private static synchronized JarFileSystem getFileSystem (File file) throws IOException { 133 Reference <JarFileSystem> reference = mountRoots.get(file); 134 JarFileSystem jfs = null; 135 if (reference == null || (jfs = reference.get()) == null) { 136 jfs = findJarFileSystemInRepository(file); 137 if (jfs == null) { 138 try { 139 jfs = new JarFileSystem(); 140 File aRoot = FileUtil.normalizeFile(file); 141 jfs.setJarFile(aRoot); 142 } catch (PropertyVetoException pve) { 143 throw new AssertionError (pve); 144 } 145 } 146 mountRoots.put(file, new JFSReference(jfs)); 147 } 148 return jfs; 149 } 150 151 private static JarFileSystem findJarFileSystemInRepository(File jarFile) { 153 @SuppressWarnings ("deprecation") Enumeration <? extends FileSystem> en = Repository.getDefault().getFileSystems(); 155 while (en.hasMoreElements()) { 156 FileSystem fs = en.nextElement(); 157 if (fs instanceof JarFileSystem) { 158 JarFileSystem jfs = (JarFileSystem)fs; 159 if (jarFile.equals(jfs.getJarFile())) { 160 return jfs; 161 } 162 } 163 } 164 return null; 165 } 166 167 171 private static class JFSReference extends SoftReference <JarFileSystem> { 172 private FileChangeListener fcl; 173 public JFSReference(JarFileSystem jfs) { 174 super(jfs); 175 final File root = jfs.getJarFile(); 176 FileObject rootFo = FileUtil.toFileObject(root); 177 if (rootFo != null) { 178 fcl = new FileChangeAdapter() { 179 public void fileDeleted(FileEvent fe) { 180 releaseMe(root); 181 } 182 183 public void fileRenamed(FileRenameEvent fe) { 184 releaseMe(root); 185 } 186 187 188 189 }; 190 rootFo.addFileChangeListener(FileUtil.weakFileChangeListener(fcl, rootFo)); 191 192 } 193 } 194 195 void releaseMe (final File root) { 196 JarFileSystem jfs = get(); 197 if (jfs != null) { 198 synchronized (ArchiveURLMapper.class) { 199 File keyToRemove = (root != null) ? root : jfs.getJarFile(); 200 mountRoots.remove(keyToRemove); 201 } 202 } 203 } 204 } 205 206 } 207 | Popular Tags |