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



package org.netbeans.modules.javacvs.commands;

//import org.openide.*;
import org.openide.filesystems.*;
import java.beans.*;
import org.netbeans.modules.javacvs.customizers.AddParamInput;
import org.openide.util.NbBundle;
import java.io.*;
import java.util.*;

import org.netbeans.modules.javacvs.*;
import org.netbeans.modules.javacvs.commands.*;
import org.netbeans.modules.javacvs.events.*;
import org.netbeans.lib.cvsclient.event.*;
import org.netbeans.lib.cvsclient.admin.*;
import org.netbeans.lib.cvsclient.util.IgnoreFileFilter;

import org.netbeans.lib.cvsclient.command.add.*;
import org.netbeans.lib.cvsclient.command.*;
import org.netbeans.modules.javacvs.caching.*;


/** This class implements the cvs add command.
 * @author mkleint
 */
public class CvsAdd extends CacheUpdatingFsCommand {
    
    AddCommand command;
    private boolean recursive;
    private int removedFilesCommandIndex;
    private int currentCommandIndex;
    
    /**
     * Holds value of property message, (add's switch -m).
     */
    private String message;

    /**
     * Holds value of property keywordSubst.
     */
    private KeywordSubstitutionOptions keywordSubst;
    
    private FsAdd addImpl;
    
    private File[] binaryFiles;
    private File[] textFiles;
    
    private List existingResurrectedFiles;
    
    /** Creates new CvsAdd instance.
     */    
    public CvsAdd() {
        super();
        setRecursive(false); // default is cvs-style behaviour.
        addImpl = new AddImpl();
        binaryFiles = null;
    }

    
    public CvsCommand getImpl() {
        return addImpl;
    }    
    
    public FsAdd getAddImpl() {
        return addImpl;
    }      
    
    /**
     * return the library command that is considered main command.
     * that one is used for loading from
     */
    protected Class getMainCvsCommand() {
        return AddCommand.class;
    }
    
    /** Creates new CvsAdd instance.
     */
    public CvsAdd(File[] files, ClientProvider fs) {
        super(fs);
        setFiles(files);
        setRecursive(false); // default is cvs-style behaviour.
        addImpl = new AddImpl();
        binaryFiles = null;
    }
    
    /** if set to recursive, for each directory added, adds everything in that directory as well.
     * Not part of the standard cvs add command.
     */
    
    public void setRecursive(boolean recursive) {
        this.recursive = recursive;
    }
    
    /** see setRecursive()
     * Not part of the standard cvs add command.
     */    
    public boolean isRecursive() {
        return recursive;
    }
    
    /** this method adds sub-files/dirs (when isRecursive()), otherwise does nothing, just returns it's parameter
     * CAUTION: might take quite some time if huge dir structure, to be called from non-AWT thread
     */
    private List processFiles(File[] files) {
            ArrayList list = new ArrayList();
            addFileArrayToList(list, files);
            // now return the array again.
/*            File[] toReturn = new File[list.size()];
            for (int ind = 0; ind < list.size(); ind++) {
                toReturn[ind] = (File)list.get(ind);
            }
 */
            return list;
    }
    /** used in processFiles() method only
     *  will recursively browse through the directories and add all "important files" to the list
     */
    private void addFileArrayToList(ArrayList list, File[] files) {
        for (int index= 0; index < files.length; index++) {
            File current = files[index];
            if (current == null) continue;
            if (current.getName().equalsIgnoreCase("CVS")) continue; // NOI18N
            if (current.isDirectory()) {
                list.add(current);
                addFileArrayToList(list, current.listFiles());
            } else {

                    list.add(current);
            }
        }
    }
    

    public String getName() {
        return NbBundle.getBundle(CvsAdd.class).getString("CvsAdd.name"); // NOI18N
    }
    
    private LinkedList createBinaryAndOtherCommand(File[] normal, File[] binaryFiles, boolean isRunning) {
        LinkedList list = new LinkedList();
        if (binaryFiles != null) {
            command = new AddCommand();
            if (isRunning) {
                String localPath = libClient.getLocalPath();
                for (int i = 0; i < binaryFiles.length; i++) {
                    if (binaryFiles[i].getAbsolutePath().equals(localPath)) {
                        libClient.setLocalPath(binaryFiles[i].getParentFile().getAbsolutePath());
                    }
                }
            }
            command.setFiles(binaryFiles);
            command.setKeywordSubst(KeywordSubstitutionOptions.BINARY);
            command.setMessage(getMessage());
            list.add(command);
        }
        File[] fls = normal;
        if (fls != null) {
            command = new AddCommand();
            if (isRunning) {
                String localPath = libClient.getLocalPath();
                for (int i = 0; i < fls.length; i++) {
                    if (fls[i].getAbsolutePath().equals(localPath)) {
                        libClient.setLocalPath(fls[i].getParentFile().getAbsolutePath());
                    }
                }
            }
            command.setFiles(fls);
            setCommandArguments(command);
            list.add(command);
        }
        return list;
    }
    
    protected void initCommand(boolean commandIsRunning) {
        // here the the commands is initiated just right before running the command
        clearCommandList();
        int dirNum = 0;
        toDoCommands.addAll(createBinaryAndOtherCommand(textFiles, binaryFiles, commandIsRunning));
        currentCommandIndex = 0;
        if (commandIsRunning) {
            existingResurrectedFiles = new LinkedList();
            if (isRecursive()) {
                // adds all the subdirs + subfiles to the add..
                File[] toTransform = textFiles;
                List list = new LinkedList();
                if (textFiles != null) {
                    list.addAll(processFiles(textFiles));
                }
                if (binaryFiles != null) {
                    list.addAll(processFiles(binaryFiles));
                }
                transform(list);
            }
            checkRemovedFiles();
        }
        super.initCommand(commandIsRunning);
    }
    
        
    /** gets executed before the current command in queue gets executed.
     * To access that command use the getCurrentCommand() method
     */
    protected void beforeEachExecute() {
        if (removedFilesCommandIndex >= currentCommandIndex) {
            AddCommand add = (AddCommand)getCurrentCommand();
            File[] fls = add.getFiles();
            if (fls != null && fls.length > 0) {
                libClient.setLocalPath(fls[0].getParentFile().getAbsolutePath());
            }
//            System.out.println("setting path to=" + fls[0].getParentFile().getAbsolutePath());
        }
        currentCommandIndex = currentCommandIndex + 1;
        super.beforeEachExecute();
    }

    /**
     * in case a locally modified file exists in place of a previously cvs removed file,
     * then we've saved the modification and in this method we overwrite the
     * ressurected copy from cvs add by the local modification..
     */
    private void resurrectLocallyModifiedFiles() {
        if (existingResurrectedFiles != null && existingResurrectedFiles.size() > 0) {
            Iterator it = existingResurrectedFiles.iterator();
            while (it.hasNext()) {
                File originalFile = (File)it.next();
                File destDir = new File(originalFile.getParentFile(), "CVS");
                File backupFile = new File(destDir, originalFile.getName());

                if (backupFile.exists()) {
                    if (originalFile.exists()) {
                        originalFile.delete();
                    }
                    backupFile.renameTo(originalFile);
                } 
            }
        }
    }
    
    protected void finishedCommand() {
        resurrectLocallyModifiedFiles();
        // update cache..
        fireUpdateCache();        
        super.finishedCommand();
    }
    
    /** Will run only if any of the commands in the queue failed - for whatever reason.
     * 
* Fires the FailedDisplayerEvent * * @param exc The exception that was thrown by the library. * */ protected void executeFailed(Exception exc) { resurrectLocallyModifiedFiles(); super.executeFailed(exc); } /** * Called when file status information has been received */ public void fileInfoGenerated(FileInfoEvent e) { FileInfoContainer fInfo = e.getInfoContainer(); if (fInfo != null) { if (fInfo instanceof AddInformation) { AddInformation info = (AddInformation)fInfo; if (existingResurrectedFiles.contains(info.getFile())) { info.setType("M"); //NOI18N } updateCache(info); } } super.fileInfoGenerated(e); } /** * Thi smethod performs the tranformation from 1 add command for all files/dirs to * separate adds for dirs definied in the list. * The original add command is moved to the end of the list and sends only files. * All this is done in order to enable recursive add */ public void transform(List list) { int size = toDoCommands.size(); toDoCommands.clear(); Iterator it = list.iterator(); while (it.hasNext()) { File file = (File)it.next(); if (file.isDirectory()) { AddCommand add = new AddCommand(); File[] commFiles = new File[1]; commFiles[0] = file; add.setFiles(commFiles); setCommandArguments(add); toDoCommands.add(add); it.remove(); } } if (list.size() > 0) { // process through the ignoreFileFilter to get rid of the .cvsignore stuff.. IgnoreFileFilter ignoreFilter = this.getClientProvider().getIgnoreFilter(); if (ignoreFilter != null) { Iterator it2 = list.iterator(); while (it2.hasNext()) { File ignoreFile = (File)it2.next(); if (ignoreFilter.shouldBeIgnored(ignoreFile.getParentFile(), ignoreFile.getName())) { it2.remove(); } } } LinkedList binaryFiles = new LinkedList(); LinkedList normalFiles = new LinkedList(); Iterator it2 = list.iterator(); while (it2.hasNext()) { File file = (File)it2.next(); boolean binary = isBinary(file); if (binary) { binaryFiles.add(file); } else { normalFiles.add(file); } } File[] normal = new File[normalFiles.size()]; File[] binary = new File[binaryFiles.size()]; binary = (File[])binaryFiles.toArray(binary); if (binary.length == 0) { binary = null; } normal = (File[])normalFiles.toArray(normal); if (normal.length == 0) { normal = null; } toDoCommands.addAll(createBinaryAndOtherCommand(normal, binary, true)); } } private void checkRemovedFiles() { Iterator it = toDoCommands.iterator(); LinkedList toDoRemovedCommands = new LinkedList(); StandardAdminHandler adminHandler = new StandardAdminHandler(); // 1. identify removed files and get them off regular commands. while (it.hasNext()) { HashMap removedList = new HashMap(); AddCommand addCom = (AddCommand)it.next(); File[] fls = addCom.getFiles(); List notRemovedList = new LinkedList(); for (int ind = 0; ind < fls.length; ind++) { Entry entry = null; try { entry = adminHandler.getEntry(fls[ind]); } catch (IOException exc) { entry = null; } if (entry != null && entry.getRevision().startsWith("-")) { // add the removed file into the list.. // sort them by directory they belong to. // System.out.println("doing change for rmoved file=" + fls[ind].getAbsolutePath()); if (fls[ind].exists()) { // we need to copy the locally existing file, since add will ressurect the repository version. // and we want the locally present one to be there.. File destDir = new File(fls[ind].getParentFile(), "CVS"); File destFile = new File(destDir, fls[ind].getName()); if (destDir.exists() && (!destFile.exists())) { if (fls[ind].renameTo(destFile)) { existingResurrectedFiles.add(fls[ind]); } } } Vector vecFiles = (Vector)removedList.get(fls[ind].getParentFile().getAbsolutePath()); if (vecFiles == null) { vecFiles = new Vector(); removedList.put(fls[ind].getParentFile().getAbsolutePath(), vecFiles); } vecFiles.add(fls[ind]); } else { // System.out.println("ok existing file=" + fls[ind].getAbsolutePath()); notRemovedList.add(fls[ind]); } } if (notRemovedList.size() == 0) { // System.out.println("removing old add.."); it.remove(); // continue; } if (notRemovedList.size() != fls.length) { // System.out.println("adding removed add.."); File[] newFls = new File[notRemovedList.size()]; newFls = (File[])notRemovedList.toArray(newFls); addCom.setFiles(newFls); // now create add commands for the grouped files.. Iterator it2 = removedList.values().iterator(); while (it2.hasNext()) { Vector vecFiles = (Vector)it2.next(); AddCommand add = new AddCommand(); File[] remFiles = new File[vecFiles.size()]; remFiles = (File[])vecFiles.toArray(remFiles); add.setFiles(remFiles); setCommandArguments(add); add.setKeywordSubst(addCom.getKeywordSubst()); toDoRemovedCommands.add(add); } } } // if (toDoRemovedCommands.size() > 0) { removedFilesCommandIndex = toDoCommands.size(); // System.out.println("are removed=" + removedFilesCommandIndex); toDoCommands.addAll(toDoRemovedCommands); } else { // System.out.println("no removed.."); removedFilesCommandIndex = -1; } } /** * Getter for property message. * @return Value of property message. */ public String getMessage() { return message; } /** * Setter for property message. * @param message New value of property message. */ public void setMessage(String message) { this.message = message; } /** * Getter for property keywordSubst. * @return Value of property keywordSubst. */ public KeywordSubstitutionOptions getKeywordSubst() { return keywordSubst; } /** * Setter for property keywordSubst. * @param keywordSubst New value of property keywordSubst. */ public void setKeywordSubst(KeywordSubstitutionOptions keywordSubst) { this.keywordSubst = keywordSubst; } public String getCvsrcEntry() { String retValue; String message = getMessage(); setMessage(null); retValue = super.getCvsrcEntry(); setMessage(message); return retValue; } /** Sets the cvs switches from the FileSystemCommand to the undelying library command. *
* The algorithm is following:

* For the FileSystem subclass, it reads the BeanDesriptor and gets all the properties.

* It considers these to be the cvs switches.

* It iterates through the properties and tries to find a setter in the library command, * that equals the setter/getter in the FileSystemCommand. If such match is found, it sets * the value to the library command. * * @param command the library command to be set. * @return true if everything succeeded. * */ public boolean setCommandArguments(Command command) { super.setCommandArguments(command); return true; // overriden because of recursive property } /** Sets the cvs switches from the library command to the FIleSystemCommand. *
* For the algorithm, see setCommandArguments(Command). * @param command the library command that is used to set the cvs switches to the FileSystemCommand. * @return true if everything succeeded. */ public boolean getCommandArguments(Command command) { super.getCommandArguments(command); // overriden because of recursive property return true; } public boolean copySwitchesFrom(FileSystemCommand com) { boolean retValue = super.copySwitchesFrom(com); if (com instanceof CvsAdd) { CvsAdd addCom = (CvsAdd)com; this.setRecursive(addCom.isRecursive()); } // overriden because of recursive property return retValue; } private boolean isBinary(File file) { String mime; FileObject[] fos = FileUtil.fromFile(file); if (fos.length > 0) { mime = FileUtil.getMIMEType(fos[0]); } else { String ext = FileUtil.getExtension(file.getName()); mime = FileUtil.getMIMEType(ext); } if (mime != null) { boolean text = mime.startsWith("content/unknown") || mime.startsWith("text/"); // NOI18N return !text; } return false; } public void setFiles(File[] files) { super.setFiles(files); if (files != null) { LinkedList binaryFiles = new LinkedList(); LinkedList normalFiles = new LinkedList(); for (int i = 0; i < files.length; i++) { File file = files[i]; boolean binary = isBinary(file); if (binary) { binaryFiles.add(files[i]); } else { normalFiles.add(files[i]); } } Collections.sort(binaryFiles); Collections.sort(normalFiles); File[] normal = new File[normalFiles.size()]; File[] binary = new File[binaryFiles.size()]; binary = (File[])binaryFiles.toArray(binary); normal = (File[])normalFiles.toArray(normal); setTextFiles(normal); setBinaryFiles(binary); } } public void setBinaryFiles(File[] files) { binaryFiles = files; } public void setTextFiles(File[] files) { textFiles = files; } public class AddImpl extends FsAdd implements FileSystemCommandImpl { public AddImpl() { } public FileSystemCommand getOuterClassInstance() { return CvsAdd.this; } public void setFileObjects(FileObject[] fileObjects) { CvsAdd.this.setFileObjects(fileObjects); } /** * Getter for property keywordSubst. * @return Value of property keywordSubst. */ public KeywordSubstitutionOptions getKeywordSubst() { return CvsAdd.this.getKeywordSubst(); } /** if set to recursive, for each directory added, adds everything in that directory as well. * Not part of the standard cvs add command. */ public void setRecursive(boolean recursive) { CvsAdd.this.setRecursive(recursive); } public void addCommandErrorListener(org.netbeans.modules.javacvs.events.CommandErrorListener commErrListener) { CvsAdd.this.addCommandErrorListener(commErrListener); } /** see setRecursive() * Not part of the standard cvs add command. */ public boolean isRecursive() { return CvsAdd.this.isRecursive(); } /** * Setter for property keywordSubst. * @param keywordSubst New value of property keywordSubst. */ public void setKeywordSubst(KeywordSubstitutionOptions keywordSubst) { CvsAdd.this.setKeywordSubst(keywordSubst); } /** * Getter for property message. * @return Value of property message. */ public String getMessage() { return CvsAdd.this.getMessage(); } /** Add a CommandDisplayerListener to the FilesystemCommand. *
All UI communication and display of output should be handled via the CommandDisplayerListeners. * * @param listener The listener to add. * */ public void addDisplayerListener(CommandDisplayerListener listener) { CvsAdd.this.addDisplayerListener(listener); } /** Removes a CommandDisplayerListener from the FilesystemCommand. * All the listeners are removed once the command ends. * * @param listener the listener to remove */ public void removeDisplayerListener(CommandDisplayerListener listener) { CvsAdd.this.removeDisplayerListener(listener); } public void removeCommandErrorListener(org.netbeans.modules.javacvs.events.CommandErrorListener commErrListener) { CvsAdd.this.removeCommandErrorListener(commErrListener); } /** * Setter for property message. * @param message New value of property message. */ public void setMessage(String message) { CvsAdd.this.setMessage(message); } /** Starts the thread with the command - executes the run() method. */ public void startCommand() { CvsAdd.this.startCommand(); } public FsGlobalOptions getGlobalOptions() { FsGlobalOptions retValue; retValue = new FsGlobalOptionsImpl(CvsAdd.this.getGlobalOptions()); return retValue; } } }

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