/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun * Microsystems, Inc. All Rights Reserved. */ package org.openide.filesystems; import java.net.*; import java.io.File; import java.util.Iterator; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import org.openide.util.Lookup; import org.openide.util.Utilities; /** Mapper from FileObject -> URL. * Should be registered in lookup. * For all methods, if the passed-in file object is the root folder * of some filesystem, then it is assumed that any valid file object * in that filesystem may also have a URL constructed for it by means * of appending the file object's resource path to the URL of the root * folder. If this cannot work for all file objects on the filesystem, * the root folder must not be assigned a URL of that type. nbfs: URLs * of course always work correctly in this regard. * @since 2.16 */ public abstract class URLMapper { /** URL which works inside this VM.*/ public static final int INTERNAL = 0; /** URL which works inside this machine.*/ public static final int EXTERNAL = 1; /** URL which works from networked machines.*/ public static final int NETWORK = 2; /** results with URLMapper instances*/ private static Lookup.Result result; /** Basic impl. for JarFileSystem, LocalFileSystem, MultiFileSystem */ private static URLMapper defMapper; static { result = Lookup.getDefault().lookup(new Lookup.Template (URLMapper.class)); } /** Find a good URL for this file object which works according to type: * -inside this VM * - inside this machine * - from networked machines * @return a suitable URL, or null */ public static URL findURL(FileObject fo, int type) { URL retVal; /** secondly registered URLMappers are asked to resolve URL */ Iterator instances = result.allInstances ().iterator(); while (instances.hasNext()) { URLMapper mapper = (URLMapper) instances.next(); if (mapper == getDefault ()) continue; retVal = mapper.getURL (fo, type); if (retVal != null) return retVal; } /** first basic implementation */ retVal = getDefault ().getURL (fo, type); if (retVal != null) return retVal; /** if not resolved yet then internal URL with nbfs protocol is returned */ if (type == INTERNAL) { try { retVal = FileURL.encodeFileObject (fo); } catch (FileStateInvalidException iex) { return null;} } return retVal; } /** Get a good URL for this file object which works according to type: * -inside this VM * - inside this machine * - from networked machines * @return a suitable URL, or null */ public abstract URL getURL(FileObject fo, int type); /** Find an array of FileObjects for this url * Zero or more FOs may be returned. * * For each returned FO, it must be true that FO -> URL gives the * exact URL which was passed in, but depends on appripriate type * <code> findURL(FileObject fo, int type) </code>. * @param url to wanted FileObjects * @return a suitable arry of FileObjects, or empty array if not successful * @since 2.22*/ public static FileObject[] findFileObjects (URL url) { /** first basic implementation */ Set retSet = new HashSet (); FileObject[] retVal = getDefault ().getFileObjects (url); if (retVal != null) retSet.addAll(Arrays.asList(retVal)); /** secondly registered URLMappers are asked to resolve URL */ Iterator instances = result.allInstances().iterator(); while (instances.hasNext()) { URLMapper mapper = (URLMapper) instances.next(); retVal = mapper.getFileObjects(url); if (retVal != null) retSet.addAll(Arrays.asList(retVal)); } retVal = new FileObject [retSet.size()]; retSet.toArray(retVal); return retVal; } /** Get an array of FileObjects for this url * @param url to wanted FileObjects * @return a suitable arry of FileObjects, or null * @since 2.22*/ public abstract FileObject[] getFileObjects (URL url); /** this method is expeceted to be invoked to create instance of URLMapper, * because of method invocation (attr name="instanceCreate" * methodvalue="org.openide.filesystems.URLMapper.getDefault")*/ private static URLMapper getDefault () { synchronized (URLMapper.class) { if (defMapper == null) defMapper = new DefaultURLMapper (); return defMapper; } } /*** Basic impl. for JarFileSystem, LocalFileSystem, MultiFileSystem */ private static class DefaultURLMapper extends URLMapper { DefaultURLMapper() {} // implements URLMapper.getFileObjects(URL url) public FileObject[] getFileObjects(URL url) { return geFileObjectBasicImpl(url); } // implements URLMapper.getURL(FileObject fo, int type) public URL getURL(FileObject fo, int type) { return getURLBasicImpl(fo, type); } private static URL getURLBasicImpl(FileObject fo, int type) { if (fo == null) return null; if (type == NETWORK) return null; URL retURL = null; FileSystem fs = null; try { fs = fo.getFileSystem(); } catch (FileStateInvalidException fsex) { return null; } if (fs instanceof LocalFileSystem ) { if (type != EXTERNAL) return null; LocalFileSystem lfs = (LocalFileSystem) fs; File f = lfs.getRootDirectory(); if (f == null) return null; try { retURL = new URL(Utilities.toURL(f), fo.getPath()); } catch (MalformedURLException mfx) { return null; } } else if (fs instanceof JarFileSystem ) { if (type != EXTERNAL) return null; /** JarFile doesn`t contain folders as resources*/ if (fo.isFolder()) return null; JarFileSystem jfs = (JarFileSystem) fs; File f = jfs.getJarFile(); if (f == null) return null; try { retURL = new URL("jar:"+Utilities.toURL(f).toExternalForm()+"!/" + fo.getPath());//NOI18N } catch (MalformedURLException mfx) { return null; } } else if (fs instanceof MultiFileSystem ) { if (fo instanceof MultiFileObject) { FileObject leader = ((MultiFileObject)fo).getLeader(); return getURLBasicImpl(leader, type); } else return null; } else if (fs instanceof XMLFileSystem ) { URL retVal = null; try { retVal = ((XMLFileSystem)fs).getURL(fo.getPath()); if (retVal == null) return null; if (type == INTERNAL) return retVal; boolean isInternal = retVal.getProtocol().startsWith("nbres");//NOI18N if (type == EXTERNAL && !isInternal) return retVal; return null; } catch (FileNotFoundException fnx) { return null; } } if (retURL == null) { File fFile = FileUtil.toFile(fo); if (fFile != null) { try { return Utilities.toURL(fFile); } catch (MalformedURLException mfx) { return null; } } } return retURL; } private static FileObject[] geFileObjectBasicImpl(URL url) { String prot = url.getProtocol(); if (prot.equals("nbfs")) { //// NOI18N FileObject retVal = FileURL.decodeURL(url); return (retVal == null) ? null : new FileObject[] {retVal}; } if (prot.equals("jar")) { //// NOI18N try { URLConnection ucon = url.openConnection(); if (ucon != null && ucon instanceof JarURLConnection) { URL jarURL = ((JarURLConnection) ucon).getJarFileURL(); String systemName = Utilities.toFile(jarURL).getCanonicalPath(); FileSystem fs = Repository.getDefault().findFileSystem(systemName); if (fs != null && fs instanceof JarFileSystem) { FileObject retVal = fs.findResource(((JarURLConnection) ucon).getEntryName()); return (retVal == null) ? null : new FileObject[] {retVal}; } } } catch (IOException iox) { return null; } return null; } if (prot.equals("file")) { //// NOI18N File f = Utilities.toFile(url); FileObject[] foRes = FileUtil.fromFile(f); if (foRes != null && foRes.length > 0) { return foRes; } } return null; } } }