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.javacvs;

import java.beans.*;
import java.io.*;
import java.util.*;
import java.util.Date;
import java.lang.ref.*;
import java.text.MessageFormat;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.*;
import java.awt.*;
import java.util.HashMap;
import org.apache.regexp.RE;
import org.apache.regexp.RESyntaxException;

import org.openide.util.*;
//import org.openide.*;
import org.openide.ErrorManager;
import org.openide.util.actions.SystemAction;

import org.openide.filesystems.*;
import org.openide.filesystems.FileSystem; // override java.io.FileSystem
//import org.openide.windows.*;
//import org.openide.loaders.DataObject;

import org.netbeans.modules.javacvs.caching.*;
import org.netbeans.modules.vcscore.cache.*;

import org.netbeans.modules.javacvs.passwd.*;
import org.netbeans.modules.javacvs.util.*;
import org.netbeans.modules.javacvs.commands.*;
import org.netbeans.modules.javacvs.events.*;


import org.netbeans.lib.cvsclient.Client;
import org.netbeans.lib.cvsclient.connection.*;
import org.netbeans.lib.cvsclient.admin.*;
import org.netbeans.lib.cvsclient.file.*;
import org.netbeans.lib.cvsclient.util.DefaultIgnoreFileFilter;
import org.netbeans.lib.cvsclient.util.IgnoreFileFilter;
import org.netbeans.lib.cvsclient.command.GlobalOptions;

/** A filesystem that is capable of running cvs commands.
 * It has a cache mechanism build-in that enables it to store status information about the files.
 *
 *
 * @author mkleint
 */
public class JavaCvsFileSystem extends AbstractFileSystem    {
    static final long serialVersionUID = -5990750897426301780L;
    
    /** Identifier of the property relative mountpoint
     */    
    public static final String PROP_REL_MOUNT = "relMount"; //NOI18N
    /** Identifier of the property working directory
     */    
    public static final String PROP_WORKING_DIR = "workingDir"; //NOI18N
    /** Identifier of the property off-line
     */    
    public static final String PROP_OFF_LINE = "offLine"; //NOI18N
    /** Identifier of the property auto-refresh
     */    
    public static final String PROP_AUTO_REFRESH = "autoRefresh"; //NOI18N
    /** Identifier of the property zipped transfer
     */    
    public static final String PROP_ZIPPED_TRANSFER = "ZippedTransfer"; //NOI18N
    /** Identifier of the property hide shadow files.
     */    
    public static final String PROP_HIDE_SHADOW_FILES  = "hideShadowFiles"; // NOI18N
    /** Identifier of the property cvs ignore list.
     */    
    public static final String PROP_CVS_IGNORE_LIST = "cvsIgnoreList"; //NOI18N

    public static final String PROP_FS_INGORED_FILES = "fsIgnoredFiles"; //NOI18N
    
    public static final String PROP_CREATE_BACKUPS = "createBackups"; //NOI18N
    
    public static final String PROP_CVS_SERVER_TYPE = "cvsServerType"; //NOI18N
    public static final String PROP_CVS_SERVER_NAME = "cvsServerName"; //NOI18N
    public static final String PROP_CVS_USER_NAME   = "cvsUserName"; //NOI18N
    public static final String PROP_CVS_REPOSITORY  = "cvsRepository"; //NOI18N
    
    
    /** Identifier of the property CvsPort.
     *
     */    
    public static final String PROP_CVS_PORT = "cvsPort"; //NOI18N

    public static final int STANDARD_PORT = 2401;    
    /** autoRefresh property's constant - never do auto refresh.
     */    
    public static final int AUTO_NONE = 0;
    /** autoRefresh property's constant - do refresh on newly opened directories.
     */    
    public static final int AUTO_SIMPLE = 1;
    /** autoRefresh property's constant - run recursive refresh upon mounting the fs.
     */    
    public static final int AUTO_RECURS_ONCE = 2;
    /** autoRefresh property's constant - on each start, run recursive refresh for the filesystem.
     */    
    public static final int AUTO_RECURS_EVERYTIME = 3;
    /**
     *combines AUTO_RECURS_ONCE and AUTO_RECURS_EVERYTIME
     */
    public static final int AUTO_MOUNT_AND_RESTART = 4;
    
    /** Server type constant - :server: access method
     */    
    public static final int TYPE_SERVER = 0;
    /** Server type constant - :pserver: access method
     */    
    public static final int TYPE_PSERVER = 1;
    
    private static final String[] TYPE_NAMES = { "server", "pserver"}; //NOI18N
    
    protected static final int REFRESH_TIME = 0; // Disabled by default (see #28352).

    private static final int BADGE_ICON_SHIFT_X = 16;
    private static final int BADGE_ICON_SHIFT_Y = 8;
    
    protected int refreshTimeToSet = REFRESH_TIME;
    
    private File rootFile = null;
    private boolean readOnly;
    
    protected transient CvsFsCache cache=null;
    private boolean isRootSet;
    private long cacheId=0;
    
    // properties
    private java.io.File workingDir = null;
    private String relMount = ""; //NOI18N
    private boolean offLine = false;
    private int autoRefresh = 0;
    private boolean zippedTransfer = true;
    private boolean hideShadowFiles = false;
    /** regexp of ignorable children*/
    protected String fsIgnoredFiles = "~$|^\\.#"; //NOI18N
    
    /** regexp matcher for ignoredFiles, null if not needed */
    protected transient RE ignoredRE = null;
    
    
    
//    private transient boolean runningRefreshSemaphore = false;
    private String repository = ""; //NOI18N
    private String serverName = ""; //NOI18N 
    private int serverType = 1;
    private String userName = ""; //NOI18N
    protected Status status;
    
    private File homeDirectory = new File(System.getProperty("user.home")); //NOI18N
    
    private org.openide.ErrorManager errorManager;
    
//    protected transient GlobalOptions globalOptions;
    
    /** Holds value of property cvsPort. */
    private int cvsPort = STANDARD_PORT;    

    /** Holds value of property createBackups. */
    private boolean createBackups = true;
    
    
    private transient CacheHandlerListener cacheListener;
    
    private transient RepositoryListener addRemoveFSListener;
    
    /**
     * Denotes that the filesystem instance was just created and is not deserialized.
     * is used for different refresh modes.
     */
    private transient boolean freshlyMounted = false;
    
    protected transient WeakReference ignoreListReference;
    
    /** 
     * Creates a new instance of JavaCvsFileSystem.
     */
    
    public JavaCvsFileSystem() {
        // Create and use implementations of file system functionality:
        // Handle filesystem.attributes files normally:
        initImpls();
        DefaultAttributes defattr = new DefaultAttributes (info, change, new ListImpl ());
        // (Otherwise set attr to a special implementation, and use ListImpl for list.)
        attr = defattr;
        list = defattr;
        // See below:
        // transfer = new TransferImpl ();
        isRootSet = false;
        setRefreshTime (0);
        setWorkingDir(new File(System.getProperty("user.home"))); //NOI18N
        setOffLine(false);
        setAutoRefresh(JavaCvsFileSystem.AUTO_NONE);
        setHideShadowFiles(false);
        try {
            ignoredRE = new RE(fsIgnoredFiles);
        } catch (RESyntaxException rese) {
            ignoredRE = null;
        }
        freshlyMounted = true;
        
        //        cache = new CvsFsCache(this);
//        init();
        initCache();
        independantInit();
        addRemoveFSListener = new JavaCvsFileSystem.FSRepositoryListener();
        Repository.getDefault().addRepositoryListener(WeakListener.repository(addRemoveFSListener, this));
    }
    
    protected void initImpls() {
        info = new InfoImpl ();
        change = new ChangeImpl ();
        status = new MyStatus();
    }

    /** 
     * Creates a new instance of JavaCvsFileSystem.
     */
    
    public JavaCvsFileSystem(FileSystemCapability cap) {
        this ();
        setCapability (cap);
        
    }
    
    protected void initCache() {
        CacheHandler handler = CacheHandler.getInstance();
        JavaCvsCache cache = (JavaCvsCache)handler.getCache(JavaCvsCache.JAVA_CACHE_NAME);
        if (cache == null) {
            cache = new JavaCvsCache();
            handler.registerCacheType(JavaCvsCache.JAVA_CACHE_NAME, cache);
        }
        cache.registerFileSystem(this);
        cacheListener = new CacheHandlerListenerImpl();
        cache.addCacheHandlerListener(
           (CacheHandlerListener) WeakListener.create(CacheHandlerListener.class, cacheListener, cache));
    }
    
    protected void independantInit() {
//        runningRefreshSemaphore = false;
        if (this.getClass().equals(JavaCvsFileSystem.class)) {
            Lookup l = Lookup.getDefault();
            errorManager = (org.openide.ErrorManager)l.lookup(org.openide.ErrorManager.class);
            //        initCache();
            
            cache = new CvsFsCache(this, getHomeDirectory());
            // init of cache..
            cache.setAutoRefresh(getAutoRefresh());
            cache.setOffLine(isOffLine());
            cache.setHideShadowFiles(isHideShadowFiles());
            cache.setFsRootFile(new File(constructRootDirectory()));
            //        globalOptions = new GlobalOptions();
            //        globalOptions.setCVSRoot(getCvsRootString());
        }
    }
    
    // --------- NAMING AND PROPERTIES ---------
    
    // This should be something unique based on the filesystem's config:
    protected String computeSystemName (File rootFile, int seed) {
        if (seed == 0) {
            return "org.netbeans.modules.javacvs.JavaCvsFileSystem " + rootFile.toString(); //NOI18N
        } else {
            return "org.netbeans.modules.javacvs.JavaCvsFileSystem " + rootFile.toString() + seed; //NOI18N
        }
    }

    /**
     * Returns what should be displayed to the user as the filesystem name.
     * Overrides AbstractFileSystem method.
     * @return name of the filesystem.
     */
    public String getDisplayName () {
/*        if (! isValid ()) {
            return NbBundle.getMessage (JavaCvsFileSystem.class, "JavaCvsFileSystem.invalidFilesystemLabel"); //NOI18N
        }
        else {
 */
            return NbBundle.getMessage (JavaCvsFileSystem.class, "JavaCvsFileSystem.validFilesystemLabel", rootFile.toString ()); //NOI18N
//        }
//DEBUG            return getSystemName();
    }
    
    /** Sets cvs home directory for the filesystem. The filesystem will then use this directory for lookup of
     * files .cvsrc, .cvspass, .cvsignore etc.
     * @param homeDir The home directory.
     */    
    public void setHomeDirectory(File homeDir) {
        homeDirectory = homeDir;
//        if (cache != null) {
//            cache.getCacheObject().setHomeDirectory(homeDir);
//        }
    }
    
    /** Gets cvs home directory for the filesystem. The filesystem uses this directory for lookup of
     * files .cvsrc, .cvspass, .cvsignore etc.
     * @return home directory
     */    
    public File getHomeDirectory() {
        return homeDirectory;
    }
    
    // Bean getter.
    public File getRootDirectory () {
        return rootFile;
    }
    
    
    
/*    public void setupGlobalOptions(Client client) {
        if (isZippedTransfer()) {
            client.setFileHandler(new GzippedFileHandler());
        } else {
            client.setFileHandler(new UncompressedFileHandler());
        }
        globalOptions.setCVSRoot(getCvsRootString());
    }
*/
    
/*    public GlobalOptions getGlobalOptions() {
        return globalOptions;
    }
 */
    
    public JavaCvsCommandFactory getCommandFactory() {
        return JavaCvsCommandFactory.getInstance();
    }
    
    // Bean setter. Changing the root directory (or in general, the identity
    // of the root file object) should cause everything using this filesystem
    // to refresh. The system name must change and refreshRoot should be used
    // to ensure that everything is correctly updated.
    private synchronized void setRootDirectory (File r) throws PropertyVetoException, IOException {
        
        if (! r.exists () || r.isFile ())
            throw new JavaCvsFileSystemException
            (r.toString () + " does not exist", //NOI18N
            NbBundle.getMessage (JavaCvsFileSystem.class, "JavaCvsFileSystem.EXC_root_dir_does_not_exist", //NOI18N
            r.toString ()));
        boolean ok = false;
        int seed = 0;
        while (!ok) {
            try {
                setSystemName(computeSystemName(r, seed));
                ok = true;
            } catch (PropertyVetoException exc) {
                ok = false;
                seed = seed + 1;
            }
        }
        rootFile = r;
//        System.out.println("rootFile=" + rootFile.getAbsolutePath());
        FileObject fo = refreshRoot();
        firePropertyChange (PROP_ROOT, null, fo);
        firePropertyChange("name", null, getDisplayName()); //NOI18N
        fo = findResource("");
//        globalOptions.setCVSRoot(getCvsRootString());
        isRootSet = true;
    }
    
    public String constructRootDirectory() {
        StringBuffer root = new StringBuffer();
        if (workingDir != null) {
            root.append(workingDir.getAbsolutePath());
        } 
        if (root.charAt(root.length() - 1) != File.separatorChar) {
            root.append(File.separatorChar);
        }
        if (relMount.startsWith(File.separator)) {
            root.append(relMount.substring(1));
        }
        else root.append(relMount);
        if (root.length() > 1 && root.charAt(root.length() - 1) == File.separatorChar) {
            root = root.deleteCharAt(root.length() - 1);
        }
        String toReturn = root.toString().replace('/', File.separatorChar);
        toReturn = toReturn.replace('\\', File.separatorChar);
        return toReturn;
    }
    
    // Bean getter.
    /** Returns the read-only property.
     */    
    public boolean isReadOnly () {
        return readOnly;
    }
    
    // Bean setter.
    /** Sets the read-only property.
     */    
    public void setReadOnly (boolean flag) {
        if (flag != readOnly) {
            readOnly = flag;
            firePropertyChange (PROP_READ_ONLY, ! flag ? Boolean.TRUE : Boolean.FALSE, flag ? Boolean.TRUE : Boolean.FALSE);
        }
    }
    
    // Bean setter.
    /** Sets the working directory property. Equals the root of the checked out sources.
     */    
    public void setWorkingDir(java.io.File newWorking) {
        if (!newWorking.equals(workingDir)) {
            File oldWorking = workingDir;
            workingDir = newWorking;
            String oldRelMount = relMount;
            firePropertyChange (PROP_WORKING_DIR, oldWorking, newWorking);
            setRelMount(""); //NOI18N
            try {
                this.setRootDirectory(new File(constructRootDirectory()));
            } catch (PropertyVetoException prop) {
                //should not happen at all..
                workingDir = oldWorking;
                firePropertyChange(PROP_WORKING_DIR, newWorking, oldWorking);
                firePropertyChange(PROP_REL_MOUNT, "", oldRelMount);
                return;
            } catch (IOException io) {
                //TODO
                workingDir = oldWorking;
                firePropertyChange(PROP_WORKING_DIR, newWorking, oldWorking);
                firePropertyChange(PROP_REL_MOUNT, "", oldRelMount);
                return;
            }
            
//            D.deb("setWorkingDir", "new Working=" + newWorking);
            //            this.cache.refreshDir("");
        }
    }
    
    // Bean getter.
    /** Returns the working directory property.
     */    
    public java.io.File getWorkingDir() {
        return workingDir;
    }
    
    // Bean setter.
    /** Sets the relative mountpoint. It is a relative part to the filesystem root from the working directory.
     * Eg.
     * 
* If I want to mount the cvs library that is stored under c:\src\netbeans\javacvs\srclib * I need to set the working directory to c:\src\netbeans * and the relative mountpoint to javacvs/srclib *
Warning: If not set correctly, some commands can have strange effects (mostly the checkout command) * * */ public void setRelMount (String newMount) { if (!newMount.equals(relMount)) { String oldMount = relMount; relMount = newMount; try { this.setRootDirectory(new File(constructRootDirectory())); } catch (PropertyVetoException prop) { //TODO relMount = oldMount; return; } catch (IOException io) { //TODO relMount = oldMount; return; } firePropertyChange (PROP_REL_MOUNT, oldMount, newMount); // D.deb("setRelMount", "new relMount=" + newMount); // this.cache.refreshDir(""); } } // Bean getter. /** Returns the relative mountpoint. It is a relative part to the filesystem root from the working directory. */ public String getRelMount () { if (relMount == null) return ""; //NOI18N return relMount; } //Bean getter public boolean isOffLine() { return offLine; } //bean setter public void setOffLine(boolean off) { if (off != offLine) { offLine = off; firePropertyChange (PROP_OFF_LINE, !offLine ? Boolean.TRUE : Boolean.FALSE, off ? Boolean.TRUE : Boolean.FALSE); } } /** * equals to the isOffLine() method, but lets the subclasses override this method, if User * interaction is required (user can reset the value in the dialog.) */ public boolean checkOffLine() { return isOffLine(); } //Bean getter public int getAutoRefresh() { return autoRefresh; } //bean setter public void setAutoRefresh(int newAuto) { if (newAuto != autoRefresh) { int oldAuto = autoRefresh; autoRefresh = newAuto; firePropertyChange (PROP_AUTO_REFRESH, new Integer(oldAuto), new Integer(autoRefresh)); // D.deb("setAutoRefresh", "new refresh=" + autoRefresh); } } //Bean getter /** * @deprecated use the global options's useGZip property.. */ public boolean isZippedTransfer() { return zippedTransfer; } /** * @deprecated use the global options's useGZip property.. */ public void setZippedTransfer(boolean zipped) { if (zippedTransfer != zipped) { firePropertyChange (PROP_ZIPPED_TRANSFER, !zipped ? Boolean.TRUE : Boolean.FALSE, zipped ? Boolean.TRUE : Boolean.FALSE); zippedTransfer = zipped; // TODO.. set global options somehow?? } } public String getFsIgnoredFiles () { return fsIgnoredFiles; } public synchronized void setFsIgnoredFiles (String nue) throws IllegalArgumentException { if (! nue.equals (fsIgnoredFiles)) { if (nue.length () > 0) { try { ignoredRE = new RE (nue); } catch (RESyntaxException rese) { IllegalArgumentException iae = new IllegalArgumentException (); throw iae; } } else { ignoredRE = null; } fsIgnoredFiles = nue; firePropertyChange (PROP_FS_INGORED_FILES, null, null); // NOI18N java.util.Enumeration en = existingFileObjects(findResource("")); //NOI18N while (en.hasMoreElements()) { FileObject fo2 = (FileObject)en.nextElement(); if (fo2 != null && fo2.isFolder()) { fo2.refresh(true); // System.out.println("refreshing=" + fo2.getPackageName('/')); } } } } /** * if true, hides all shadow files in the filesystems. * "Shadow" means files that don't exist in working directory. * Usually these are Locally-Removed, Needs-Checkout files * @param hide do hide shadow files? * @deprecated - since the appearance of VirtualDataObject, it's obsolete.. */ public void setHideShadowFiles(boolean hide) { /* if (hideShadowFiles != hide) { boolean oldHide = hideShadowFiles; hideShadowFiles = hide; FileObject fo = findResource(""); //NOI18N fo.refresh(true); fireRecursiveFileStatus(fo); firePropertyChange (PROP_HIDE_SHADOW_FILES, oldHide ? Boolean.TRUE : Boolean.FALSE, hideShadowFiles ? Boolean.TRUE : Boolean.FALSE); } */ } /** * if true, hides all shadow files in the filesystems. * "Shadow" means files that don't exist in working directory. * Usually these are Locally-Removed, Needs-Checkout files * @return should hide? * @deprecated - since the appearance of VirtualDataObject, it's obsolete.. */ public boolean isHideShadowFiles() { return false; // return hideShadowFiles; } // ------------------------------------------------------------------------- public void setCvsRepository(String repos) { if (!repos.equals(repository)) { String oldRepos = repository; repository = repos; firePropertyChange (PROP_CVS_REPOSITORY, oldRepos, repos); } } public String getCvsRepository() { return repository; } //--- public void setCvsServerType(int type) { if (serverType != type) { int old =serverType; serverType = type; firePropertyChange (PROP_CVS_SERVER_TYPE, new Integer(old), new Integer(type)); } } public int getCvsServerType() { return serverType; } public int getCvsServerType(String typeName) { for (int index = 0; index < TYPE_NAMES.length; index++) { if (TYPE_NAMES[index].equalsIgnoreCase(typeName)) return index; } return -1; } public String[] getCvsServerTypes() { return TYPE_NAMES; } public String getCvsServerTypeName() { if ((serverType >= 0) && (serverType < TYPE_NAMES.length)) { return TYPE_NAMES[serverType]; } return ""; //NOI18N } public String getCvsServerTypeName(int type) { if ((type >= 0) && (type < TYPE_NAMES.length)) { return TYPE_NAMES[type]; } return ""; //NOI18N } //--- public void setCvsServerName(String name) { if (!name.equals(serverName)) { String oldName = serverName; serverName = name; firePropertyChange (PROP_CVS_SERVER_NAME, oldName, name); } } public String getCvsServerName() { return serverName; } //-- public void setCvsUserName(String name) { if (!name.equals(userName)) { String oldName = userName; userName = name; firePropertyChange (PROP_CVS_USER_NAME, oldName, name); } } public String getCvsUserName() { return userName; } /** Returns a port that the pserver access method uses for connection. * * @return Value of property cvsPort. */ public int getCvsPort() { return cvsPort; } /** Sets a port for the pserver access method to connect to. * @param cvsPort New value of property cvsPort. */ public void setCvsPort(int cvsPort) { if (cvsPort != this.cvsPort) { int old = this.cvsPort; this.cvsPort = cvsPort; firePropertyChange (PROP_CVS_PORT, new Integer(old), new Integer(cvsPort)); } } //-- cvs root string is stored in each CVS directory, also used for authentification public String getCvsRootString() { StringBuffer toReturn = new StringBuffer(":"); //NOI18N toReturn.append(getCvsServerTypeName()); toReturn.append(':'); toReturn.append(getCvsUserName()); toReturn.append('@'); toReturn.append(getCvsServerName()); toReturn.append(':'); if (getCvsPort() != PServerConnection.DEFAULT_PORT) { toReturn.append(""+getCvsPort()); } toReturn.append(getCvsRepository()); return toReturn.toString(); } protected JavaCvsStatusManager getStatusManager() { return JavaCvsStatusManager.getInstance(); } // ----------- SPECIAL CAPABILITIES -------------- private Map lockedFilesToBeModified = new HashMap(); /** * Lock the files so that they can not be modified in the IDE. * This is necessary for commands, that make changes to the processed files. * It's crutial, that the file does not get modified twice - externally via * the update command and internally (e.g. through the Editor). * One MUST call {@link #unlockFilesToBeModified} after the command * finish. * @param path The path of the file to be locked or directory in which all * files will be locked. * @param recursively Whether the files in directories should be locked recursively. */ public void lockFilesToBeModified(String path, boolean recursively) { synchronized (lockedFilesToBeModified) { // Multiple locks are not considered. It's locked just once. lockedFilesToBeModified.put(path, recursively ? Boolean.TRUE : Boolean.FALSE); } } /** * Unlock the files that were previously locked by {@link #lockFilesToBeModified} * method. It's necessary to call this method with appropriate arguments after * the command finish so that the user can edit the files. */ public void unlockFilesToBeModified(String path, boolean recursively) { synchronized (lockedFilesToBeModified) { lockedFilesToBeModified.remove(path); } } /** Check whether the provided name is locked for modification. * If yes, IOException is thrown. */ private void checkModificationLock(String name) throws IOException { boolean isLocked; synchronized (lockedFilesToBeModified) { isLocked = lockedFilesToBeModified.get(name) != null; if (!isLocked) { for (Iterator it = lockedFilesToBeModified.keySet().iterator(); it.hasNext(); ) { String path = (String) it.next(); if (name.startsWith(path) && name.charAt(path.length()) == '/') { boolean recursively = ((Boolean) lockedFilesToBeModified.get(path)).booleanValue(); // either we lock it recursively or there are no more path separators '/': isLocked = (recursively || name.indexOf('/', path.length() + 1) < 0); } } } } if (isLocked) { throw new JavaCvsFileSystemException( "File " + name + " can be altered by a running CVS command, it's modification in the IDE is remporarily disabled.", //NOI18N NbBundle.getMessage (JavaCvsFileSystem.class, "EXC_file_is_being_modified", name)); //NOI18N } } // This is how you can affect the classpath for execution, compilation, etc.: public void prepareEnvironment (FileSystem.Environment environment) { environment.addClassPath (rootFile.toString ()); } // Affect the name and icon of files on this filesystem according to their // "status", e.g. version-control modification-commit state: public class MyStatus implements Status, Serializable { static final long serialVersionUID = 7525827069203814770L; public Image annotateIcon(Image icon, int iconType, Set files) { Object[] oo = files.toArray(); int len = oo.length; if (len == 0/* || name.indexOf(getRootDirectory().toString()) >= 0*/) { return icon; } String status = null; Vector important; if( len==1 ) { /* FileObject ff=(FileObject)oo[0]; String fullName=ff.getPackageNameExt('/','.'); important = new Vector(); important.add(fullName); */ important=getImportantFiles(oo); } else { important=getImportantFiles(oo); } if (important.size() == 0) { important = new Vector(); for (int i = 0; i < oo.length; i++) { FileObject ff=(FileObject)oo[i]; important.add(ff.getPackageNameExt('/', '.')); } } status = cache.getFileStatusOnly(important); if (status != null) { Image img = getStatusManager().getIcon(status); if (img != null) { icon = org.openide.util.Utilities.mergeImages(icon, img, BADGE_ICON_SHIFT_X, BADGE_ICON_SHIFT_Y); } } return icon; } public String annotateName (String name, Set files) { // D.deb("----------------------------------------------------------------------------"); String result=name; String fullName=""; // NOI18N Object[] oo=files.toArray(); Vector important; int len=oo.length; if( len==0 || name.indexOf(getRootDirectory().toString())>=0){ return result; } Vector importantFiles; if( len==1 ) { /* FileObject ff=(FileObject)oo[0]; fullName=ff.getPackageNameExt('/','.'); important = new Vector(); important.add(fullName); */ important=getImportantFiles(oo); } else { important=getImportantFiles(oo); } /* if (autoRefresh == JavaCvsFileSystem.AUTO_SIMPLE) { runningRefreshSemaphore = true; } */ if (important.size() == 0) { important = new Vector(); for (int i = 0; i < oo.length; i++) { FileObject ff=(FileObject)oo[i]; important.add(ff.getPackageNameExt('/', '.')); } } String status = cache.getStatus(name, important).trim(); // D.deb("name = "+name+": status = "+status); result = status; return result; } } public Status getStatus () { return status; } // And use fireFileStatusChanged whenever you know something has changed. // Filesystem-specific actions, such as version-control operations. // The actions should typically be CookieActions looking for DataObject // cookies, where the object's primary file is on this type of file system. public SystemAction[] getActions () { return null; } /** * Get the VCS actions on a collection of FileObjects. * @param fos the collection of FileObjects to act on. * @return the actions retrieved from VcsFactory.getActions(fos) */ public SystemAction[] getActions(Set fos) { return null; } protected void handleDelete(String name) { } protected void handleRename(String oldName, String newName) { } /** * Utility method that find the fileobject reference and if it exists, retypes it to CacheReference. * @param name pathname of the resource. * @returns the cacheReference instance if one exists or null */ protected CacheReference getCacheReference(String name) { Reference ref = findReference(name); if (ref != null && ref instanceof CacheReference) { CacheReference cref = (CacheReference)ref; return cref; } return null; } // ----------- IMPLEMENTATIONS OF ABSTRACT FUNCTIONALITY ---------- // Utility method only: protected File getFile (String name) { if (name.length() > 0) { return new File (rootFile, name); } else { return new File(rootFile.getAbsolutePath()); } } /** Converst from String fs-related representation of a file (path+name) * to absolute representation in File objects. */ protected File[] getFiles(FileObject[] fos) { // D.deb("getFiles() START"); File[] files = new File[fos.length]; for (int index = 0; index < fos.length; index++) { if (fos[index] != null) { String name = fos[index].getPackageNameExt('/','.'); files[index] = getFile(name); } } return files; } public FileObject getFileObjectForFile(File file) { String root = this.constructRootDirectory(); String absPath = file.getAbsolutePath(); if (absPath.startsWith(root)) { // it belongs to this FS -> do something // D.deb("-------- it is in this filesystem"); String path; if (absPath.equals(root)) { path = ""; //NOI18N } else { path = absPath.substring(root.length() + 1,absPath.length()); if (path.length() > 0 && path.charAt(0) == File.separatorChar) { //another sanity check. path = path.substring(1); } } path = path.replace('\\', '/'); FileObject fo = findResource(path); return fo; } return null; } private Set getRecursFileObjectSet(File file) { FileObject fo = getFileObjectForFile(file); if (fo != null) { Set toReturn = new HashSet(); Enumeration enum = fo.getChildren(true); while (enum.hasMoreElements()) { toReturn.add(enum.nextElement()); } return toReturn; } return null; } // Information about files and operations on the contents which do // not affect the file's presence or name. // MK: no changes needed for javacvs in order the interface to be functional.. protected class InfoImpl implements AbstractFileSystem.Info { public InfoImpl () {} static final long serialVersionUID = -627867218820299311L; public boolean folder (String name) { return getFile (name).isDirectory (); } public Date lastModified (String name) { File file = getFile(name); if (!file.exists()) return new Date(System.currentTimeMillis()); return new Date (file.lastModified ()); } public boolean readOnly (String name) { File f = getFile (name); return f.exists () && ! f.canWrite (); } // Some filesystems, e.g. based on HTTP, could have better heuristics for this: public String mimeType (String name) { FileObject fo = findResource(name); String mimeType = (fo != null) ? FileUtil.getMIMEType(fo) : "content/unknown"; // NOI18N return mimeType; } public long size (String name) { return getFile (name).length (); } public InputStream inputStream (String name) throws FileNotFoundException { //D.deb("inputStream("+name+")"); // NOI18N InputStream in = null; try { in = new FileInputStream(getFile(name)); } catch (java.io.FileNotFoundException exc) { final String fname = name; if (errorManager != null) { throw (java.io.FileNotFoundException) errorManager.annotate( new java.io.FileNotFoundException() { public String getLocalizedMessage() { return MessageFormat.format(NbBundle.getBundle(JavaCvsFileSystem.class).getString("MSG_FileNotExist"), new Object[] { fname }); //NOI18N } }, MessageFormat.format(NbBundle.getBundle(JavaCvsFileSystem.class).getString("MSG_FileNotExist"), new Object[] { fname })); //NOI18N } else { throw new java.io.FileNotFoundException() { public String getLocalizedMessage() { return MessageFormat.format(NbBundle.getBundle(JavaCvsFileSystem.class).getString("MSG_FileNotExist"), new Object[] { fname }); //NOI18N } }; } } return in; } public OutputStream outputStream (String name) throws IOException { // JavaCvsFOStream enables us to be notified when an outputstream is closed // -> when file is locally modified if (isCreateBackups() && isImportant(name)) { // FileObject file = findResource(name); File file = getFile(name); if (file != null && (!checkVirtual(name)) && (!name.endsWith("~")) && file.length() > 0) { //NOI18N File back = getFile(name + "~"); //NOI18N if (!back.exists()) { back.createNewFile(); } OutputStream stream = new BufferedOutputStream(new FileOutputStream(back)); InputStream input = new BufferedInputStream(new FileInputStream(file)); try { FileUtil.copy(input, stream); stream.flush(); } finally { try { stream.close(); } finally { input.close(); } } // file.getParent().refresh(); } } return new JavaCvsFOStream (getFile (name)); } // AbstractFileSystem handles locking the file to the rest of the IDE. // This only means that you should define how the file should be locked // to the outside world--perhaps it does not need to be. public void lock (String name) throws IOException { checkModificationLock(name); File file = getFile (name); if (file.exists () && ! file.canWrite ()) throw new JavaCvsFileSystemException ("file " + file + " could not be locked", //NOI18N NbBundle.getMessage (JavaCvsFileSystem.class, "EXC_file_could_not_be_locked", //NOI18N file.getName ())); } public void unlock (String name) { // Nothing special needed to unlock a file to the outside world. } public void markUnimportant (String name) { CacheReference ref = getCacheReference(name); if (ref != null) { ref.markUnimportant(); } } } // Operations that change the available files. public class ChangeImpl implements AbstractFileSystem.Change { static final long serialVersionUID = 1647280700071658302L; public void createFolder (String name) throws IOException { File f = getFile (name); Object[] errorParams = new Object[] { f.getName (), getDisplayName (), f.getPath () }; if (name.equals ("")) throw new JavaCvsFileSystemException ("cannot create empty name", //NOI18N NbBundle.getMessage (JavaCvsFileSystem.class, "EXC_create_empty_name", errorParams)); //NOI18N if (f.exists()) throw new JavaCvsFileSystemException ("folder " + f + " already exists", //NOI18N NbBundle.getMessage (JavaCvsFileSystem.class, "EXC_folder_already_exists", errorParams)); //NOI18N boolean b = createRecursiveFolder (f); if (! b) { throw new JavaCvsFileSystemException ("folder " + f + " could not be created", //NOI18N NbBundle.getMessage (JavaCvsFileSystem.class, "EXC_folder_could_not_be_created", errorParams)); //NOI18N } else { name = name.replace('\\', '/'); /* FileObject fo = findResource(name); if (fo != null && fo.getParent() != null) { fo.getParent().refresh(); } */ } } private boolean createRecursiveFolder (File f) { if (f.exists ()) return true; if (! f.isAbsolute ()) f = f.getAbsoluteFile (); String par = f.getParent (); if (par == null) return false; if (! createRecursiveFolder (new File (par))) return false; f.mkdir (); // TODO here comes the cvscaching stuff.. if (f.exists()) { cache.addToCache(f); return true; } return false; } public void createData (String name) throws IOException { File f = getFile (name); if (! f.createNewFile ()) throw new JavaCvsFileSystemException ("file " + f + " could not be created", //NOI18N NbBundle.getMessage (JavaCvsFileSystem.class, "EXC_file_could_not_be_created", //NOI18N f.getName (), getDisplayName (), f.getPath ())); if (f.exists()) { name = name.replace('\\', '/'); /* FileObject fo = findResource(name); if (fo != null && fo.getParent() != null) { fo.getParent().refresh(); } */ } File folder = f.getParentFile();//new File(constructRootDirectory(), name); CacheFile cfolder = CacheHandler.getInstance().getCacheFile(folder, CacheHandler.STRAT_DISK, cache); if (cfolder instanceof CacheDir) { String fileName = f.getName(); ((CacheDir) cfolder).addFile(new CvsCacheFile(JavaCvsCache.JAVA_CACHE_NAME, fileName), true); } } public void rename (String oldName, String newName) throws IOException { File of = getFile (oldName); File nf = getFile (newName); String name = oldName.replace('\\', '/'); /* FileObject oldFo = findResource(name); Set foSet = new HashSet(); FileObject oldFoParent = null; if (oldFo != null) { oldFoParent = oldFo.getParent(); // foSet.add(oldFoParent); // foSet.add(oldFo); } */ boolean fails = nf.exists() && !nf.equals(of); boolean renamed = false; if (!fails) { // cache.removeFromCache(of, of.isDirectory()); renamed = of.renameTo(nf); handleRename(oldName, newName); /* if (renamed) { if (foParent != null) { foParent.refresh(true); System.out.println("oldparentrefresh=" + foParent.getName()); } name = newName.replace('\\', '/'); FileObject fo = findResource(name); if (fo != null && fo.getParent() != null) { fo.getParent().refresh(true); fo.refresh(true); foSet.add(fo); foSet.add(fo.getParent()); // System.out.println("newParentRefresh=" + fo.getParent().getName()); } name = oldName.replace('\\', '/'); FileObject oldFo2 = findResource(name); if (oldFo2 != null) { foSet.add(oldFo2); oldFo2.refresh(true); // System.out.println("oldFoAdded"); } // fireFileStatusChanged(new FileStatusEvent(JavaCvsFileSystem.this, foSet, true, true)); } */ } if (! renamed || fails) throw new JavaCvsFileSystemException ("file " + of + " could not be renamed to " + nf, //NOI18N NbBundle.getMessage (JavaCvsFileSystem.class, "EXC_file_could_not_be_renamed", //NOI18N new Object[] { of.getName (), nf.getName (), getDisplayName (), of.getPath (), nf.getPath () })); } /** The last folder in which a file was deleted */ private transient File lastFolderWhoseFileWasDeleted = null; /** The map of file names and corresponding Entry objects of files * in the last folder in which a file was deleted. It's likely, that * next deleted file will be in the same folder (e.g. clean all) * and thus it's good to cache the entries so that they need not to be * read and parsed again and again from the CVS/Entries file. */ private transient Map entriesByFilesOfLastFolderWhoseFileWasDeleted = null; /** The time when the last file was processed. * When a long time elapses, it's likely that CVS/Entries file change * in the mean time and we want to read it again. */ private transient long lastTimeFileWasDeletedInLastFolder = 0; /** The expiration time of cached CVS/Entries. It's likely that after * this time elapses the entries could change. */ private static final long ENTRIES_EXPIRE_TIME = 200L; // [ms] /** The lock which we use to access the above variables. */ private transient Object lastFolderLock = new Object(); public void delete (String name) throws IOException { File file = getFile (name); name = name.replace('\\', '/'); // FileObject fo = findResource(name); boolean deleted = deleteFile(file); if (deleted) { File folder = file.getParentFile(); if (folder != null) { Map entriesMap; synchronized (lastFolderLock) { if (!folder.equals(lastFolderWhoseFileWasDeleted) || System.currentTimeMillis() - lastTimeFileWasDeletedInLastFolder > ENTRIES_EXPIRE_TIME) { Entry[] entries = null; try { entries = new StandardAdminHandler().getEntriesAsArray(folder); } catch (IOException ioex) {} entriesByFilesOfLastFolderWhoseFileWasDeleted = new HashMap(); if (entries != null) { for (int i = 0; i < entries.length; i++) { entriesByFilesOfLastFolderWhoseFileWasDeleted.put(entries[i].getName(), entries[i]); } } lastFolderWhoseFileWasDeleted = folder; lastTimeFileWasDeletedInLastFolder = System.currentTimeMillis(); } entriesMap = entriesByFilesOfLastFolderWhoseFileWasDeleted; } Entry ent = (Entry) entriesMap.get(file.getName()); if (ent != null && ent.getRevision() != null && ent.getRevision().equals("0")) { new StandardAdminHandler().removeEntry(file); } } handleDelete(name); } /* if (deleted && fo != null && fo.getParent() != null) { // fo.getParent().refresh(); // fireFileStatusChanged(new FileStatusEvent(JavaCvsFileSystem.this, fo.getParent(), true, true)); } */ if (file.exists () && !deleted) throw new JavaCvsFileSystemException ("file " + file + " could not be deleted", //NOI18N NbBundle.getMessage (JavaCvsFileSystem.class, "EXC_file_could_not_be_deleted", //NOI18N file.getName (), getDisplayName (), file.getPath ())); } private boolean deleteFile (File file) { if (file.isDirectory ()) { File[] arr = file.listFiles (); for (int i = 0; i < arr.length; i++) if (! deleteFile (arr[i])) return false; } //update cache.. // String flName = file.getName(); // boolean wasDirectory = file.isDirectory(); // that info gets lost when delete() is performed boolean isDone = file.delete(); /* if (isDone) { cache.removeFromCache(file, wasDirectory); } */ return isDone; } private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException { in.defaultReadObject(); lastFolderLock = new Object(); } } // Operation which provides the directory structure. public class ListImpl implements AbstractFileSystem.List { static final long serialVersionUID = -102893327017356802L; public String[] children (String name) { // D.deb("Children()","name=" + name + " ----------------------------------------------------------------------------"); if (!isRootSet) return null; File f = getFile (name); String[] toReturn = null; // System.out.println("children for=" +name); if (f != null && f.isDirectory ()) { if (cache != null) { toReturn = cache.getDirContent(f); /* if (toReturn != null) { for (int i = 0; i < toReturn.length; i++) { System.out.print(toReturn[i] + " "); } System.out.println(""); } */ } } if (toReturn == null) { toReturn = new String[0]; } for (int i = 0; i < toReturn.length; i++) { if (ignoredRE != null && ignoredRE.match(toReturn[i])) { // System.out.println("ignoring.." + toReturn[i]); toReturn[i] = null; } } /* System.out.println("dir=" + f.getAbsolutePath()); System.out.println("children of : " + name); for (int i = 0; i < toReturn.length; i++) { System.out.print(toReturn[i] + " "); } System.out.println(""); */ return toReturn; } } public void setRefreshTimeToSet() { setRefreshTime(refreshTimeToSet); } public boolean isImportant(String name) { CacheReference rf = getCacheReference(name); if (rf != null) { return rf.isImportant(); } // D.deb("isImportant("+name+")"+unimportantNames.contains(name)); return true; } /** * Get the important files. * @return the Vector of important files as Strings (package + name + extension) */ protected Vector getImportantFiles(Object[] oo){ // D.deb("getImportantFiles()"); // NOI18N Vector result=new Vector(3); int len=oo.length; for(int i=0;i 0) { try { ignoredRE = new RE (fsIgnoredFiles); } catch (RESyntaxException rese) { } } freshlyMounted = false; // System.out.println("readobject for fs=" + getDisplayName()); // init(); // D.deb("Reading bean done"); addRemoveFSListener = new JavaCvsFileSystem.FSRepositoryListener(); Repository.getDefault().addRepositoryListener(WeakListener.repository(addRemoveFSListener, this)); } //------------------------------------------- private void writeObject(ObjectOutputStream out) throws IOException { // D.deb("writeObject() - now save cache"); // NOI18N /* moved to module install if (cache != null) { cache.saveToDisk(); } */ // D.deb("writeObject() - saving bean"); // NOI18N out.defaultWriteObject(); // D.deb("writeObject() - saving bean2"); // NOI18N } //------------------------------------------------------------------------ // do commands /** Creates a class implementing the ClientProvider interface that needs to be passed to the cvs commands. * This method makes sure the client provider is properly setup. * */ protected ClientProvider createClientProvider() { StandardClientProvider client = new StandardClientProvider(getHomeDirectory()); client.setCvsRootString(getCvsRootString()); client.setCvsPort(getCvsPort()); client.setLocalPath(getRootDirectory().getAbsolutePath()); java.util.List ignoreList = JavaCvsFileSystem.constructIgnoreList(getHomeDirectory(), new File(getWorkingDir(), "CVSROOT")); //NOI18N IgnoreFileFilter ignoreFilter = new DefaultIgnoreFileFilter(ignoreList); client.setIgnoreFilter(ignoreFilter); FsGlobalOptionsImpl glOptions = (FsGlobalOptionsImpl)getCommandFactory().getGlobalOptions(); client.setGlobalOptions(glOptions.getLibraryGlobalOptions()); return client; } public String[] getCvsIgnoreList() { String[] array; Object obj = null; if (ignoreListReference == null || ((obj = ignoreListReference.get()) == null)) { // obj = ignoreListReference.get(); java.util.List ignoreList = JavaCvsFileSystem.constructIgnoreList(getHomeDirectory(), new File(getWorkingDir(), "CVSROOT")); //NOI18N array = new String[ignoreList.size()]; array = (String[])ignoreList.toArray(array); ignoreListReference = new WeakReference(array); } else { array = (String[])obj; } return array; } public static java.util.List constructIgnoreList(File home, File cvsRootDir) { java.util.List ignoreList = null; java.io.File ignoreFile = new File(cvsRootDir, "cvsignore"); //NOI18N // first parse the CVSROOT/cvsignore file try { ignoreList = DefaultIgnoreFileFilter.parseCvsIgnoreFile(ignoreFile); } catch (IOException exc) {/* ignore */} // now parse the $home/.cvsignore file if (ignoreList == null) { ignoreList = new LinkedList(); } ignoreFile = new File(home, ".cvsignore"); //NOI18N try { ignoreList = DefaultIgnoreFileFilter.parseCvsIgnoreFile(ignoreFile); } catch (IOException exc) {/* ignore */ } // now parse the Enviroment variable String envIgnore = System.getProperty("env-cvsignore"); //NOI18N if (envIgnore != null) { StringTokenizer token = new StringTokenizer(envIgnore, " ", false); //NOI18N while (token.hasMoreTokens()) { String tok = token.nextToken(); ignoreList.add(tok); } } return ignoreList; } /** Performs a status refresh on the filesystem. * @param fileNames Array of FileObjects that should be refreshed. * @param recursive boolean parameter - if true, do recursive refresh for all the directories. */ public void doRefresh(FileObject[] fileNames, boolean recursive) { // this method is just directing the processing to the cache // before that it sorts out the directories and files.. // it's needed because of the CacheUpdateingCommand.setRefreshing() method if (isOffLine()) return; File[] files = getFiles(fileNames); LinkedList dirs = new LinkedList(); LinkedList fls = new LinkedList(); for (int i = 0; i < files.length; i++) { if (files[i].isDirectory()) { dirs.add(files[i]); } else { fls.add(files[i]); } } if (dirs.size() > 0) { File[] fos = new File[dirs.size()]; fos = (File[])dirs.toArray(fos); cache.doRefresh(fos, recursive); } if (fls.size() > 0) { File[] fos = new File[fls.size()]; fos = (File[])fls.toArray(fos); cache.doRefresh(fos, recursive); } } /* public boolean isRunningRefreshSemaphore() { return runningRefreshSemaphore; } */ /* public void clearRunningRefreshSemaphore() { runningRefreshSemaphore = false; } */ /** * Notifies this file system that it has been added to the repository. * Since we can not rely on the addNotify() method (see issue #30763), * this method was introduced to be notified when this FS is really added. * Call super.notifyFSAdded() when you're extending this method. Do not * call directly. */ protected void notifyFSAdded() { cache.addNotify(this); initCache(); FileObject[] root = new FileObject[1]; root[0] = findResource(""); //NOI18N if ((getAutoRefresh() == JavaCvsFileSystem.AUTO_RECURS_ONCE && freshlyMounted) || (getAutoRefresh() == JavaCvsFileSystem.AUTO_RECURS_EVERYTIME && !freshlyMounted) || getAutoRefresh() == JavaCvsFileSystem.AUTO_MOUNT_AND_RESTART) { doRefresh(root, true); } } /** * Notifies this file system that it has been removed from the repository. * Since we can not rely on the removeNotify() method (see issue #30763), * this method was introduced to be notified when this FS is really removed. * Call super.notifyFSRemoved() when you're extending this method. Do not * call directly. */ protected void notifyFSRemoved() { if (cache != null) { cache.removeNotify(); } } /** * Deprecated. use the fireFileStatusForExisting method instead * together with the refreshExisting method. * @deprecated use the fireFileStatusForExisting method instead. */ protected void fireRecursiveFileStatus(FileObject fo) { Set foSet = new HashSet(); Enumeration enum = fo.getChildren(true); while (enum.hasMoreElements()) { FileObject suFO = (FileObject)enum.nextElement(); foSet.add(suFO); suFO.refresh(true); // System.out.println("refreshing child=" + suFO.getName()); } fireFileStatusChanged(new FileStatusEvent(this, foSet, true, true)); } protected void fireFileStatusForExisting(FileObject fo) { Set foSet = new HashSet(); // Set reloadFoSet = new HashSet(); Enumeration enum = existingFileObjects(fo); while (enum.hasMoreElements()) { FileObject exFo = (FileObject)enum.nextElement(); setVirtualDataLoader(exFo); foSet.add(exFo); // System.out.println("status=" + exFo.getNameExt()); } fireFileStatusChanged(new FileStatusEvent(this, foSet, true, true)); } /** * takes existing fileobjects and refreshes the folders among them. * should be called before any fileFileStatusForExisting method calls. */ protected void refreshExisting(FileObject fo) { Enumeration enum = existingFileObjects(fo); while (enum.hasMoreElements()) { FileObject exFo = (FileObject)enum.nextElement(); if (exFo.isFolder()) { // System.out.println("refrshing=" + exFo.getNameExt()); exFo.refresh(); } else { exFo.refresh(true); } } } /** * Utility method here, just for use/to be overridden in NbJavaCvsFilesystem. * It's empty here because we don't know anything about Dataobjects here. * it's used in the various refreshing methods to check if the file exists locally. (wheather it's virtual) * if so, it's assigned a special dataloader/dataobject, so that it doesn't get mixed up with existing fileobjects.. * @returns return true if the data object should be reloaded. */ protected void setVirtualDataLoader(FileObject fo) { } // ------ inner class for extending FileOutputStream that signals that a file was modified to the filesystem. private class JavaCvsFOStream extends FileOutputStream { private File changingFile; private boolean closed = false; public JavaCvsFOStream(File file) throws IOException { super(file); this.changingFile = file; } public void close() throws IOException { super.close(); // assure, that we mark the file as modified only once. // FileOutputStream will call close() on finalization even when close() was called before. if (!closed) { cache.fileModified(this.changingFile, true); closed = true; } } } /** Creates weakReference to FileObject. In FileSystem, which subclasses AbstractFileSystem, you can overload method * createReference(FileObject fo) to achieve another type of Reference (weak, strong etc.) * @param fo is FileObject. It`s reference yourequire to get. * @return Reference to FileObject */ protected Reference createReference(FileObject fo) { return cache.createReference(fo); } /** Creates an implementation of the cvs status command. * @return Status command. */ public FsStatus createStatus() { CvsStatus stat = (CvsStatus)getCommandFactory().getCommand(CvsStatus.class, false); ClientProvider prov = createClientProvider(); stat.setClientProvider(prov); return stat.getStatusImpl(); } /** Creates an implementation of the cvs refresh command. * @return Status command. */ public FsStatus createRefresh() { CvsStatus stat = new RefreshCommand(); ClientProvider prov = createClientProvider(); stat.setClientProvider(prov); return stat.getStatusImpl(); } /** Creates an implementation of the cvs log command. * @return Log commands. */ public FsLog createLog() { CvsLog stat = (CvsLog)getCommandFactory().getCommand(CvsLog.class, false); ClientProvider prov = createClientProvider(); stat.setClientProvider(prov); return stat.getLogImpl(); } /** Creates an implementation of the cvs update command. * @return Update command. */ public FsUpdate createUpdate() { CvsUpdate stat = (CvsUpdate)getCommandFactory().getCommand(CvsUpdate.class, false); ClientProvider prov = createClientProvider(); stat.setClientProvider(prov); return stat.getUpdateImpl(); } /** Creates an implementation of the cvs tag command. * @return Tag command. */ public FsTag createTag() { CvsTag stat = (CvsTag)getCommandFactory().getCommand(CvsTag.class, false); ClientProvider prov = createClientProvider(); stat.setClientProvider(prov); return stat.getTagImpl(); } /** Creates an implementation of the cvs remove command. * @return remove command. */ public FsRemove createRemove() { CvsRemove stat = (CvsRemove)getCommandFactory().getCommand(CvsRemove.class, false); ClientProvider prov = createClientProvider(); stat.setClientProvider(prov); return stat.getRemoveImpl(); } /** Creates an implementation of the cvs diff command. * @return Diff Command. */ public FsDiff createDiff() { CvsDiff stat = (CvsDiff)getCommandFactory().getCommand(CvsDiff.class, false); ClientProvider prov = createClientProvider(); stat.setClientProvider(prov); return stat.getDiffImpl(); } /** Creates an implementation of the cvs commit command. * @return Commit command. */ public FsCommit createCommit() { CvsCommit stat = (CvsCommit)getCommandFactory().getCommand(CvsCommit.class, false); ClientProvider prov = createClientProvider(); stat.setClientProvider(prov); return stat.getCommitImpl(); } /** Creates an implementation of the cvs checkout command. * @return Checkout command. */ public FsCheckout createCheckout() { CvsCheckout stat = (CvsCheckout)getCommandFactory().getCommand(CvsCheckout.class, false); ClientProvider prov = createClientProvider(); stat.setLocalPath(getWorkingDir().getAbsolutePath()); stat.setClientProvider(prov); return stat.getCheckoutImpl(); } /** Creates an implementation of the cvs add command. * @return Add command. */ public FsAdd createAdd() { CvsAdd stat = (CvsAdd)getCommandFactory().getCommand(CvsAdd.class, false); ClientProvider prov = createClientProvider(); stat.setClientProvider(prov); return stat.getAddImpl(); } /** Creates an implementation of the cvs annotate command. * @return Annotate command. */ public FsAnnotate createAnnotate() { CvsAnnotate stat = (CvsAnnotate)getCommandFactory().getCommand(CvsAnnotate.class, false); ClientProvider prov = createClientProvider(); stat.setClientProvider(prov); return stat.getAnnotateImpl(); } /** Creates an implementation of the cvs import command. * @return Import command. */ public FsImport createImport() { CvsImport stat = (CvsImport)getCommandFactory().getCommand(CvsImport.class, false); ClientProvider prov = createClientProvider(); stat.setClientProvider(prov); return stat.getImportImpl(); } /** Creates an implementation of the cvs export command. * @return Export command. */ public FsExport createExport() { CvsExport stat = (CvsExport)getCommandFactory().getCommand(CvsExport.class, false); ClientProvider prov = createClientProvider(); stat.setClientProvider(prov); return stat.getExportImpl(); } /** Creates an implementation of the cvs history command. * @return History command. */ public FsHistory createHistory() { CvsHistory stat = (CvsHistory)getCommandFactory().getCommand(CvsHistory.class, false); ClientProvider prov = createClientProvider(); stat.setClientProvider(prov); return stat.getHistoryImpl(); } /** Creates an implementation of the cvs watchers command. * @return watchers command. */ public FsWatchers createWatchers() { CvsWatchers stat = (CvsWatchers)getCommandFactory().getCommand(CvsWatchers.class, false); ClientProvider prov = createClientProvider(); stat.setClientProvider(prov); return stat.getWatchersImpl(); } /** * Returns an istance of global options for the specified command. * it's properties should be set before running the command. * */ public FsGlobalOptions getGlobalOptionsFor(CvsCommand command) { FileSystemCommandImpl impl = (FileSystemCommandImpl)command; FileSystemCommand comm = impl.getOuterClassInstance(); return new FsGlobalOptionsImpl(comm.getGlobalOptions()); } /** * This method is called from AbstractFileObject.isVirtual. Tests if file * really exists or is missing. Some operation on it may be restricted if returns true. * @param name of the file * @return true indicates that the file is missing. */ protected boolean checkVirtual(String name) { File file = getFile(name); return !file.exists(); } /** Getter for property createBackups. * @return Value of property createBackups. */ public boolean isCreateBackups() { return this.createBackups; } /** Setter for property createBackups. * @param createBackups New value of property createBackups. */ public void setCreateBackups(boolean createBacks) { if (createBackups != createBacks) { this.createBackups = createBacks; firePropertyChange (PROP_CREATE_BACKUPS, !createBacks ? Boolean.TRUE : Boolean.FALSE, createBacks ? Boolean.TRUE : Boolean.FALSE); } } /** Mark the file as being important or unimportant. * @param name the file to mark * @param important true indicates that file is important, false conversely * file is unimportant. * @since 1.9 */ protected void markImportant(String name, boolean important) { super.markImportant(name, important); if (important) { CacheReference ref = getCacheReference(name); if (ref != null) { ref.markImportant(); } } } private class CacheHandlerListenerImpl implements CacheHandlerListener { public void cacheRemoved(CacheHandlerEvent event) { // D.deb("cacheRemoved called for:" + event.getCvsCacheFile().getName()); /* CacheFile file = event.getCacheFile(); if (file == null || file.getParent() == null) return; String fileString = file.getParent().getAbsolutePath(); String root = constructRootDirectory(); if (fileString.startsWith(root)) { if (fileString.length() > root.length()) { fileString = fileString.substring(root.length() + 1 , fileString.length()); } fileString = fileString.replace('\\', '/'); FileObject fo = findResource(""); //NOI18N StringTokenizer tok = new StringTokenizer(fileString, "/", false); //NOI18N Set foSet = new HashSet(); while (fo != null) { fo.refresh(true); Enumeration enum = fo.getChildren(false); while (enum.hasMoreElements()) {foSet.add(enum.nextElement());} if (tok.hasMoreTokens()) { fo = findResource(fo.getPackageName('/') + "/" + tok.nextToken()); //NOI18N } else { fo = null; } } fireFileStatusChanged(new FileStatusEvent(JavaCvsFileSystem.this, foSet, false, true)); } */ cacheAdded(event); } public void statusChanged(CacheHandlerEvent event) { FileObject fo = getFileObjectForFile(new File(event.getCacheFile().getAbsolutePath())); if (fo == null) { // E.err("statusChanged().. could not find FileObject.. name=" + event.getCacheFile().getAbsolutePath()); return; } if (!event.isRecursive()) { if (fo.isFolder()) { Set foSet = new HashSet(); Enumeration enum = fo.getChildren(false); while (enum.hasMoreElements()) {foSet.add(enum.nextElement());} fireFileStatusChanged(new FileStatusEvent(JavaCvsFileSystem.this, foSet, true, true)); } else { fireFileStatusChanged(new FileStatusEvent(JavaCvsFileSystem.this, fo, true, true)); } } else { cacheAdded(event); } } //----------------------------------------------------------------------------- //-------------------- method from CacheHandlerListener------------------------ public void cacheAdded(CacheHandlerEvent event) { // System.out.println("cacheAdded called for:" + event.getCacheFile().getName()); CacheFile file = event.getCacheFile(); String fileString = file.getAbsolutePath(); // System.out.println("in fs=" + fileString); String root = constructRootDirectory(); // System.out.println("root=" + root); if (fileString.startsWith(root)) { if (fileString.length() > root.length()) { fileString = fileString.substring(root.length() + 1 , fileString.length()); } fileString = fileString.replace('\\', '/'); FileObject fo = findResource(fileString); //NOI18N if (fo == null) { fo = findResource(""); //NOI18N } /* System.out.println("refreshing dir =" + fileString); System.out.println("fs=" + JavaCvsFileSystem.this.getDisplayName()); fo.refresh(); // Enumeration en = JavaCvsFileSystem.this.existingFileObjects(fo); Enumeration en = fo.getChildren(false); Set foSet = new HashSet(); while (en.hasMoreElements()) { FileObject fo2 = (FileObject)en.nextElement(); /* if (fo2.isFolder()) { fo2.refresh(); // System.out.println("refreshing=" + fo2.getPackageName('/')); } */ JavaCvsFileSystem.this.refreshExisting(fo); JavaCvsFileSystem.this.fireFileStatusForExisting(fo); /* Enumeration en = JavaCvsFileSystem.this.existingFileObjects(fo); Set foSet = new HashSet(); while (en.hasMoreElements()) { FileObject fo2 = (FileObject)en.nextElement(); if (fo2.isFolder()) { fo2.refresh(); // System.out.println("refreshing=" + fo2.getPackageName('/')); } foSet.add(fo2); // System.out.println("adding to set=" + fo2.getPackageNameExt('/', '.')); } fireFileStatusChanged(new FileStatusEvent(JavaCvsFileSystem.this, foSet, false, true)); */ } else if (root.startsWith(fileString)) { //special case for checkout command. FileObject fo = findResource(""); //NOI18N JavaCvsFileSystem.this.refreshExisting(fo); JavaCvsFileSystem.this.fireFileStatusForExisting(fo); } } /* CacheFile file = event.getCacheFile(); String fileString = file.getAbsolutePath(); String root = constructRootDirectory(); if (fileString.startsWith(root)) { if (fileString.length() > root.length()) { fileString = fileString.substring(root.length() + 1 , fileString.length()); } fileString = fileString.replace('\\', '/'); FileObject fo = findResource(""); StringTokenizer tok = new StringTokenizer(fileString, "/", false); Set foSet = new HashSet(); while (fo != null) { fo.refresh(true); // System.out.println("refreshing parent=" + fo.getName()); Enumeration enum = fo.getChildren(false); while (enum.hasMoreElements()) {foSet.add(enum.nextElement());} if (tok.hasMoreTokens()) { // System.out.println("next token"); FileObject newFo = findResource(fo.getPackageName('/') + "/" + tok.nextToken()); if (newFo == null) { fireRecursiveFileStatus(fo); } fo = newFo; } else { fireRecursiveFileStatus(fo); fo = null; } } fireFileStatusChanged(new FileStatusEvent(JavaCvsFileSystem.this, foSet, false, true)); } } */ } /** * The listener on Repository to be informed when this filesystem was mounted * and unmounted. addNotify() and removeNotify() are not reliable methods. * They can be called even when this filesystem is added into or removed from * a multifilesystem. */ private class FSRepositoryListener extends Object implements RepositoryListener { public void fileSystemAdded(RepositoryEvent repositoryEvent) { if (JavaCvsFileSystem.this.equals(repositoryEvent.getFileSystem())) { notifyFSAdded(); } } public void fileSystemPoolReordered(RepositoryReorderedEvent repositoryReorderedEvent) { } public void fileSystemRemoved(RepositoryEvent repositoryEvent) { if (JavaCvsFileSystem.this.equals(repositoryEvent.getFileSystem())) { notifyFSRemoved(); } } } }
... 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.