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-2003 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.masterfs;

import org.netbeans.modules.masterfs.providers.MountSupport;
import org.openide.filesystems.*;

import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * Encapsulates access to mount table, which can be considered as set
 * of pairs . Method mount adds new pair and
 * method unmount removes one. Every MasterFileObject delegates its functionality
 * and  FileSystems, that are held in mout table, provide such delgates.
 * Method resolveBestDelegate is responsible for finding the best delegate to
 * requested resource path. There may be possible to find more than one delagate to
 * requested path. So, there also exist method resolveSecondDelegate.
 *
 *
 * @author Radek Matous
 */
final class MountTable implements InternalMountSupport {
    /** maps */
    final private static Map res2fsMap = Collections.synchronizedMap(new HashMap());
    final private static MountTable instance = new MountTable();
    final static MountSupport mountSupport = APIAccess.DEFAULT.createMountSupport(instance);

    /***
     * @return one shared instance of MountTable
     */
    static MountTable getDefault() {
        return instance;
    }

    private MountTable() {
    }

    /**
     * Mounts new pair .
     * @param mountPointPath resource path associated with mounted filesystem mount
     * @param mount mounted filesystem
     * @throws IOException is thrown if mount can't be mounted (e.g.: if already mounted)
     */
    public void mount(final String mountPointPath, final FileSystem mount) throws IOException {
        /*if (!(mount instanceof LocalFileSystem || mount instanceof JarFileSystem))
            return;*/
        final boolean syncNeeded = !(mount instanceof  ExLocalFileSystem);
        
        final String normName = ResourcePath.getNormalizedPath(mountPointPath);

        MasterFileSystem.getDefault().runAtomicAction(new FileSystem.AtomicAction() {
            public void run() throws IOException {
                if (syncNeeded) {
                    SyncSection.getDefault().enterExclusiveSection();
                    try {
                        mountIt(normName, mount, mountPointPath);
                    } finally {
                        SyncSection.getDefault().finishExclusiveSection();
                    }
                } else {
                    mountIt(normName, mount, mountPointPath);                    
                }
            }
        });

        mount.addFileStatusListener(MasterFileSystem.getDefault());
        mount.addNotify();
    }

    private void mountIt(final String normName, final FileSystem mount, final String mountPointPath) throws IOException {
        FileSystem oldFs = (FileSystem) res2fsMap.put(normName, mount);
        if (oldFs != null) handleAlreadyMounted(oldFs, mount, normName);
        else refreshAfterMount(getMountEnumeration(mountPointPath));
    }

    /**
     * Unmounts already mounted filesystem mount.
     * @param mount filesystem requested to unmount
     * @throws IOException is thrown if fs2Mount can't be unmounted
     * (e.g.: haven't been mounted yet)
     */
    public void unmount(final FileSystem mount) throws IOException {
        MasterFileSystem.getDefault().runAtomicAction(new FileSystem.AtomicAction() {
            public void run() throws IOException {
                SyncSection.getDefault().enterExclusiveSection();
                try {
                    if (!removeFileSystem(mount)) {
                        String errMsg = Utils.formatString("EXC_CannotUnMount",
                                new Object[]{mount.getDisplayName()});
                        throw new IOException(errMsg);
                    }
                } finally {
                    SyncSection.getDefault().finishExclusiveSection();
                }
            }
        });

        mount.removeFileStatusListener(MasterFileSystem.getDefault());
        mount.removeNotify();
    }

    /**
     * Tries to find the best delegate to requested resourcePath.
     * @param resourcePath
     * @return the best delegate or null if delegate doesn't exist
     */
    FileObject resolveBestDelegate(final String resourcePath) {
        return resolveDelegate(resourcePath, Delegate.BEST_DELEGATE);
    }

    /**
     * Tries to find the second possible delegate to requested resourcePath.
     * There may be  possible to find more than one delagate to requested path.
     * If the second one is not found, then the best one is returned.
     * @param resourcePath
     * @return the second possible delegate if found or best delegate or null
     * (in mentioned order)
     */
    FileObject resolveSecondDelegate(final String resourcePath) {
        return resolveDelegate(resourcePath, Delegate.SECOND_DELEGATE);
    }

    void unmount(final String mountPointPath) throws IOException {
        final FileSystem fs = getMountedFileSystem(mountPointPath);
        if (fs != null)
            MountTable.getDefault().unmount(fs);
    }

    /**
     * Gets all mounted filesystems
     * @return enumeration of mounted filesystems
     */
    Enumeration geAllFileSystems() {
        final ArrayList qE = new ArrayList ();
        final Collection values = res2fsMap.values();
        //SyncSection.getDefault().enterExclusiveSection();
        SyncSection.getDefault().enterSection();
        try {
            synchronized (res2fsMap) {
                for (Iterator it = values.iterator(); it.hasNext();) {
                    FileSystem fs = (FileSystem) it.next();
                    if (fs != null)
                        qE.add (fs);
                }
            }
        } finally {
            //SyncSection.getDefault().finishExclusiveSection();
            SyncSection.getDefault().finishSection();
        }
        return Collections.enumeration (qE);
    }

    /**
     * Gets mount point, if mount is mounted. Else null is returned.
     *
     * @param mount filesystem of which mount point is looked for
     * @return mount point or null */
    boolean isMounted(final FileSystem mount) {
        ResourcePath resource = findResourcePath(mount);
        FileSystem fsTest = (FileSystem) res2fsMap.get(resource.getNormalizedPath());
        return (mount == fsTest) ? true : false;
    }

    private ResourcePath findResourcePath(final FileSystem fs) {
        final File f = FileUtil.toFile(fs.getRoot());
        return Utils.getResource(f);
    }

    private FileObject resolveDelegate(String resourcePath, final int delegateLevel) {
        FileSystem fs;
        String bestMountPoint = "";

        final LinkedList retValList = new LinkedList();
        resourcePath = ResourcePath.getNormalizedPath(resourcePath);
        synchronized (res2fsMap) {
            final List sortedList = new ArrayList(res2fsMap.keySet());
            Collections.sort(sortedList);

            for (Iterator it = sortedList.iterator(); it.hasNext();) {
                String mountPoint = (String) it.next();
                if (resourcePath.startsWith(mountPoint) &&
                        mountPoint.length() > bestMountPoint.length()) {
                    boolean isMountPoint = mountPoint.length() == resourcePath.length() || 
                            resourcePath.charAt(mountPoint.length()) == '/';
                    if (isMountPoint || new ResourcePath (mountPoint).isRoot()) {
                        bestMountPoint = mountPoint;
                        retValList.addLast(bestMountPoint);                        
                    }
                }
            }
            if (retValList.size() == 0) return null;

            int idx = retValList.size() - (delegateLevel + 1);
            if (idx < 0) idx = 0;

            bestMountPoint = (String) retValList.get(idx);
            fs = (FileSystem) res2fsMap.get(bestMountPoint);
        }
        FileObject retVal = fs.findResource(resourcePath.substring(bestMountPoint.length()));

        return retVal;
    }

    private static void refreshAfterMount(final Enumeration changeList) {
        final Set toReset = new LinkedHashSet();
        while (changeList.hasMoreElements()) {
            MasterFileObject hfo = (MasterFileObject) changeList.nextElement();
            refreshAfterMount(hfo);
            toReset.add(hfo);
        }
        resetAfterMount(toReset);
        MasterFileSystem masterFs = MasterFileSystem.getDefault();
        masterFs.fireFileStatus(new FileStatusEvent(masterFs,toReset, true, true ));  
    }

    static void refreshAfterMount(MasterFileObject hfo) {
        //if (true) return;
        FileObject oldDelegate = hfo.getDelegate().get();
        if (oldDelegate == null) return;
        FileObject newDelegate = MountTable.getDefault().resolveBestDelegate(hfo.getResource().getNormalizedPath());
        if (oldDelegate == newDelegate) return;
        MasterFileObject.refreshAfterMount(newDelegate, oldDelegate, hfo);
    }

    private static void resetAfterMount(final Set toReset) {
        Iterator it = toReset.iterator();
        while (it.hasNext()) {
            MasterFileObject hfo = (MasterFileObject) it.next();
            hfo.getDelegate().reset(hfo.getResource());
        }
    }

    static void renameCachedFileObjects(final String oldName, final String newName) {
        final Enumeration en = Cache.getDefault().getAll();
        while (en.hasMoreElements()) {
            MasterFileObject fo = (MasterFileObject) en.nextElement();
            String oldResPath = fo.getResource().getNormalizedPath();
            if (oldResPath.startsWith(newName)) {
                continue;
            }
            if (oldResPath.startsWith(oldName)) {
                ResourcePath newResPath = new ResourcePath(newName + oldResPath.substring(oldName.length()));
                fo.setResource(newResPath);
                Cache.getDefault().replace(oldResPath, fo);
            }
        }
    }

    private Enumeration getMountEnumeration(final String mountPointPath) {
        class Mnt implements org.openide.util.Enumerations.Processor {
            public Object process (Object o, Collection ignore) {
                final MasterFileObject hfo = (MasterFileObject) o;
                String normalizedMountPoint = ResourcePath.getNormalizedPath(mountPointPath);                
                String normalizedResourcePath = hfo.getResource().getNormalizedPath();
                
                if (normalizedResourcePath.startsWith(normalizedMountPoint) && hfo.isValid()) {
                    return o;
                }
                return null;
            }
        }
        return org.openide.util.Enumerations.filter (
            Cache.getDefault().getAll(), 
            new Mnt ()
        );
    }

    private static Enumeration getUnMountEnumeration(final FileSystem fs2Umount) {
        class UnMnt implements org.openide.util.Enumerations.Processor {
            public Object process (Object o, Collection ignore) {
                final MasterFileObject hfo = (MasterFileObject) o;
                if (hfo != null && hfo.isValid()) {
                    FileSystem delgFs = hfo.getDelegateFileSystem();
                    if (delgFs == fs2Umount)
                        return o;

                }
                return null;
            }
        }
        return org.openide.util.Enumerations.filter (
            Cache.getDefault().getAll(), 
            new UnMnt ()
        );
    }

    FileSystem getMountedFileSystem(String resName) {
        resName = ResourcePath.getNormalizedPath(resName);
        final FileSystem fsTest = (FileSystem) res2fsMap.get(resName);
        return fsTest;
    }

    private void handleAlreadyMounted(FileSystem originalFs, final FileSystem newFs, final String name) throws IOException {
        /** already registered another filesystem. First must be unregistered*/
        res2fsMap.put(name, originalFs);
/*
        Object[] params = new Object[]{newFs.getDisplayName(), name, originalFs.getDisplayName()};
        IOException iex = new IOException(Utils.formatString("EXC_AlreadyMounted", params));
        iex.printStackTrace();
        throw iex;
*/
    }

    private boolean removeFileSystem(final FileSystem fs) {
        Iterator it = res2fsMap.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            FileSystem fsValue = (FileSystem) entry.getValue();
            if (fsValue == fs) {
                it.remove();
                refreshAfterMount(getUnMountEnumeration(fs));
                return true;
            }
        }
        return false;
    }

}
... 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.