alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 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-2004 Sun
 * Microsystems, Inc. All Rights Reserved.
 */
package org.openide.filesystems;

import java.net.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.*;
import java.lang.StringBuffer;

import org.openide.util.Lookup;
import org.openide.util.LookupEvent;
import org.openide.util.LookupListener;
import org.openide.util.Utilities;

/** Mapper from FileObject -> URL.
 * Should be registered in default lookup. For details see {@link Lookup#getDefault()}.
 * 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;
    
    static {
        result = Lookup.getDefault().lookup(new Lookup.Template (URLMapper.class));
        result.addLookupListener(new LookupListener() {
            public void resultChanged (LookupEvent ev) {
                synchronized (URLMapper.class) {
                    cache = null;
                }
            }});
    }

    
    /** Basic impl. for JarFileSystem, LocalFileSystem, MultiFileSystem */    
    private static URLMapper defMapper;
    /** Cache of all available URLMapper instances. */
    private static List/**/ cache;

    /** 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 = getInstances().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
     * The implementation can't use neither {@link FileUtil#toFile} nor {@link FileUtil#toFileObject}
     * otherwise StackOverflowError maybe thrown.  
     * @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
     *  findURL(FileObject fo, int type) .
     * @param url to wanted FileObjects
     * @return a suitable arry of FileObjects, or empty array if not successful
     * @since  2.22
     * @deprecated Use {@link #findFileObject} instead.
     */
    public static FileObject[] findFileObjects (URL url) {
        /** first basic implementation */
        Set retSet = new LinkedHashSet ();
        FileObject[] retVal = null;
        
        Iterator instances = getInstances().iterator();
        while (instances.hasNext()) {
            URLMapper mapper = (URLMapper) instances.next();
            if (mapper == getDefault ()) continue;                        
            retVal = mapper.getFileObjects(url);
            if (retVal != null) {
                retSet.addAll(Arrays.asList(retVal));
            }
        }

        retVal = getDefault ().getFileObjects (url);
        if (retVal != null) {
            retSet.addAll(Arrays.asList(retVal));            
        }
        
        retVal = new FileObject [retSet.size()];
        retSet.toArray(retVal);
        return retVal;
    }

    /** Find an appropiate instance of FileObject that addresses this url
     *
     * @param url url to be converted to file object
     * @return file object corresponding to url or null if no one was found
     * @since  4.29
     */
    public static FileObject findFileObject(URL url) {
        if (url == null) {
            throw new NullPointerException("Cannot pass null URL to URLMapper.findFileObject"); // NOI18N
        }
        /** first basic implementation */
        FileObject[] results = null;

        Iterator instances = getInstances().iterator();
        while (instances.hasNext() && (results == null || results.length == 0)) {
            URLMapper mapper = (URLMapper) instances.next();
            if (mapper == getDefault()) continue;
            results = mapper.getFileObjects(url);
        }
        /** first basic implementation */
        if (results == null || results.length == 0) {
            results = getDefault().getFileObjects(url);
        }

        return (results != null && results.length > 0) ? results[0] : null;
    }


    /** Get an array of FileObjects for this url. There is no reason to return array
     * with size greater than one because method {@link #findFileObject findFileObject}
     * uses just first element (next elements won't be accepted anyway).
     * The implementation can't use neither {@link FileUtil#toFile} nor {@link FileUtil#toFileObject}
     * otherwise StackOverflowError maybe thrown.  
     * 

There isn't necessary to return array here. * The only one reason is just backward compatibility.

* @param url to wanted FileObjects * @return an array of FileObjects with size no greater than one, 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; } } /** Returns all available instances of URLMapper. * @return list of URLMapper instances */ private static List getInstances() { synchronized (URLMapper.class) { if (cache != null) { return cache; } // Set cache to empty array here to prevent infinite loop. // See issue #41358, #43359 cache = new ArrayList(); } ArrayList res = null; try { res = new ArrayList(result.allInstances()); } finally { synchronized (URLMapper.class) { cache = res; } } // Just in case cahe == null: // return empty array to prevent NPE // but let cache null to be able to recover from undeclared exception // caused by lookup (see #45546) return (cache == null) ? new ArrayList() : cache; } /*** Basic impl. for JarFileSystem, LocalFileSystem, MultiFileSystem */ private static class DefaultURLMapper extends URLMapper { DefaultURLMapper() {} // implements URLMapper.getFileObjects(URL url) public FileObject[] getFileObjects(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 return getFileObjectsForJarProtocol(url); } if (prot.equals("file")) { //// NOI18N File f = toFile(url); if (f != null) { FileObject[] foRes = findFileObjectsInRepository(f); if (foRes != null && foRes.length > 0) { return foRes; } } } return null; } private FileObject[] findFileObjectsInRepository(File f) { if (!f.equals(FileUtil.normalizeFile(f))) { throw new IllegalArgumentException("Parameter file was not "+ // NOI18N "normalized. Was "+f+" instead of "+FileUtil.normalizeFile(f)); // NOI18N } Enumeration en = Repository.getDefault().getFileSystems(); LinkedList list = new LinkedList (); String fileName = f.getAbsolutePath(); while (en.hasMoreElements()) { FileSystem fs = (FileSystem)en.nextElement(); String rootName = null; FileObject fsRoot = fs.getRoot (); File root = findFileInRepository (fsRoot); if (root == null) { Object rootPath = fsRoot.getAttribute("FileSystem.rootPath");//NOI18N if (rootPath != null && (rootPath instanceof String)) rootName = (String)rootPath; else continue; } if (rootName == null) rootName = root.getAbsolutePath(); /**root is parent of file*/ if (fileName.indexOf(rootName) == 0) { String res = fileName.substring(rootName.length()).replace(File.separatorChar, '/'); FileObject fo = fs.findResource(res); File file2Fo = (fo != null)? findFileInRepository(fo) : null; if (fo != null && file2Fo != null && f.equals(file2Fo)) { if (fo.getClass().toString().indexOf ("org.netbeans.modules.masterfs.MasterFileObject") != -1) {//NOI18N list.addFirst(fo); } else { list.addLast(fo); } } } } FileObject[] results = new FileObject[list.size()]; list.toArray(results); return results; } // 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; if (fo instanceof MultiFileObject && type == INTERNAL) { // Stick to nbfs protocol, otherwise URL calculations // get messed up. See #39613. return null; } File fFile = findFileInRepository(fo); if (fFile != null) { try { return fFile.toURI().toURL(); } catch (MalformedURLException mfx) { assert false : mfx; return null; } } URL retURL = null; FileSystem fs = null; try { fs = fo.getFileSystem(); } catch (FileStateInvalidException fsex) { return null; } if (fs instanceof JarFileSystem) { JarFileSystem jfs = (JarFileSystem) fs; File f = jfs.getJarFile(); if (f == null) return null; try { // XXX fo.getPath() needs to be escaped retURL = new URL("jar:" + f.toURI() + "!/" + fo.getPath() + // NOI18N ((fo.isFolder() && !fo.isRoot()) ? "/" : "")); // NOI18N } catch (MalformedURLException mfx) { mfx.printStackTrace(); 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; } } return retURL; } private static File findFileInRepository(FileObject fo) { File f = (File)fo.getAttribute("java.io.File"); // NOI18N return (f != null) ? FileUtil.normalizeFile(f) : null ; } private static FileObject[] getFileObjectsForJarProtocol(URL url) { FileObject retVal = null; JarURLParser jarUrlParser = new JarURLParser(url); File file = jarUrlParser.getJarFile(); String entryName = jarUrlParser.getEntryName(); if (file != null ) { JarFileSystem fs = findJarFileSystem(file); if (fs != null) { if (entryName == null) entryName = ""; // #39190: root of JAR retVal = fs.findResource(entryName); } } return (retVal == null) ? null : new FileObject[] {retVal}; } private static JarFileSystem findJarFileSystem(File jarFile) { JarFileSystem retVal = null; Enumeration en = Repository.getDefault().getFileSystems(); while (en.hasMoreElements()) { FileSystem fs = (FileSystem)en.nextElement(); if (fs instanceof JarFileSystem) { File fsJarFile = ((JarFileSystem)fs).getJarFile(); if (fsJarFile.equals(jarFile)) { retVal = (JarFileSystem)fs; break; } } } return retVal; } private static class JarURLParser { private File jarFile; private String entryName; JarURLParser (URL originalURL) { parse (originalURL); } /** copy & pasted from JarURLConnection.parse*/ void parse (URL originalURL) { String spec = originalURL.getFile(); int separator = spec.indexOf('!'); if (separator != -1) { try { jarFile = toFile(new URL(spec.substring(0, separator++))); entryName = null; } catch (MalformedURLException e) { return; } /* if ! is the last letter of the innerURL, entryName is null */ if (++separator != spec.length()) { entryName = spec.substring(separator, spec.length()); } } } File getJarFile() { return jarFile; } String getEntryName() { return entryName; } } private static File toFile(URL u) { if (u == null) throw new NullPointerException(); try { URI uri = new URI(u.toExternalForm()); return new File(uri); } catch (URISyntaxException use) { // malformed URL return null; } catch (IllegalArgumentException iae) { // not a file: URL return null; } } } }
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.