? projects/tests.jar ? projects/projectuiapi/test/unit/src/org/netbeans/modules ? ant/ant.diff ? ant/copymove.diff ? java/java.diff ? java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/diff Index: projects/projectapi/apichanges.xml =================================================================== RCS file: /cvs/projects/projectapi/apichanges.xml,v retrieving revision 1.4 diff -u -r1.4 apichanges.xml --- projects/projectapi/apichanges.xml 11 Jul 2005 12:18:06 -0000 1.4 +++ projects/projectapi/apichanges.xml 29 Jul 2005 14:58:14 -0000 @@ -76,31 +76,32 @@ - + - Support for project delete - - + Added support for project delete/copy/rename/move + + - -

- As only the ProjectManager is allowed to implement ProjectState interface, - this change should not directly affect any clients. -

+

- The notifyDeleted action is added to the ProjectState, - allowing the project implmentation to let the ProjectManager - know that the project has been deleted. ProjectManager.isValid(Project) added - to detect deleted projects. -

-

- ProjectOperations and ProjectOperationsImplementation added to support - project delete operation. + Introduced: +

    +
  • + New method notifyDeleted added to ProjectState. +
  • +
  • + Interfaces DataFilesProviderImplementation, DeleteOperationImplementation, CopyOperationImplementation, MoveOperationImplementation has + been added to support project delete/copy/rename/move. +
  • +
  • + Support class ProjectOperations has been added to simplify operations on compound projects. +
  • +

- +
Index: projects/projectapi/manifest.mf =================================================================== RCS file: /cvs/projects/projectapi/manifest.mf,v retrieving revision 1.9 diff -u -r1.9 manifest.mf --- projects/projectapi/manifest.mf 11 Jul 2005 12:18:06 -0000 1.9 +++ projects/projectapi/manifest.mf 29 Jul 2005 14:58:14 -0000 @@ -1,5 +1,5 @@ Manifest-Version: 1.0 OpenIDE-Module: org.netbeans.modules.projectapi/1 -OpenIDE-Module-Specification-Version: 1.6 +OpenIDE-Module-Specification-Version: 1.7 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/projectapi/Bundle.properties Index: projects/projectapi/src/org/netbeans/api/project/ProjectOperations.java =================================================================== RCS file: projects/projectapi/src/org/netbeans/api/project/ProjectOperations.java diff -N projects/projectapi/src/org/netbeans/api/project/ProjectOperations.java --- projects/projectapi/src/org/netbeans/api/project/ProjectOperations.java 11 Jul 2005 12:18:07 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,134 +0,0 @@ -/* - * 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-2005 Sun - * Microsystems, Inc. All Rights Reserved. - */ - -package org.netbeans.api.project; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import org.netbeans.spi.project.ProjectOperationsImplementation.DataFilesProviderImplementation; -import org.netbeans.spi.project.ProjectOperationsImplementation.DeleteOperationImplementation; -import org.openide.util.Lookup; - -/**Allows gathering information for vaious project operations (currently only project delete, but will - * be extended in the future). - * - *

Project Delete Operation - * - * Consists of {@link #getMetadataFiles(Project) getMetadataFiles}, - * {@link #getDataFiles(Project) getDataFiles}, {@link #performClean(Project) performClean} - * and {@link #notifyDeleted(Project) notifyDeleted}. - * - * The delete operation should run in two phases: preparation, when - * {@link #getMetadataFiles(Project) getMetadataFiles} and {@link #getDataFiles(Project) getDataFiles} - * (any number of times, - * in any order) are called and performing, when {@link #performClean(Project) performClean} should be called, - * then the files previously returned should be deleted (as required by the user) - * and finally {@link #notifyDeleted(Project) notifyDeleted} should be called. - * - * @since 1.6 - * @author Jan Lahoda - */ -public final class ProjectOperations { - - private static ProjectOperations INSTANCE = null; - - public static synchronized ProjectOperations getDefault() { - if (INSTANCE == null) { - INSTANCE = new ProjectOperations(); - } - - return INSTANCE; - } - - private ProjectOperations() { - } - - /**Return list of files that are considered metadata files and folders for the given project. - * Returns meaningfull values only if some of the is*Supported methods - * return true. - * - * @param prj project to test - * @return list of metadata files/folders - */ - public List/**/ getMetadataFiles(Project prj) { - List/**/ result = new ArrayList(); - - for (Iterator i = getProjectsOperationsImplementation(prj).iterator(); i.hasNext(); ) { - result.addAll(((DataFilesProviderImplementation) i.next()).getMetadataFiles()); - } - - return result; - } - - /**Return list of files that are considered source files and folders for the given project. - * Returns meaningfull values only if some of the is*Supported methods - * return true. - * - * @param prj project to test - * @return list of data files/folders - */ - public List/**/ getDataFiles(Project prj) { - List/**/ result = new ArrayList(); - - for (Iterator i = getProjectsOperationsImplementation(prj).iterator(); i.hasNext(); ) { - result.addAll(((DataFilesProviderImplementation) i.next()).getDataFiles()); - } - - return result; - } - - /**Test whether the delete operation is supported on the given project. - * - * - * @param prj project to test - * @return true if the project supports delete operation, - * false otherwise - */ - public boolean isDeleteOperationSupported(Project prj) { - return !getDeleteOperationImplementation(prj).isEmpty(); - } - - /**Performs pre-delete clean of the project. Should be called immediatelly before - * the project is deleted. - * - * @param prj project to clean - */ - public void performClean(Project prj) throws IOException { - for (Iterator i = getDeleteOperationImplementation(prj).iterator(); i.hasNext(); ) { - ((DeleteOperationImplementation) i.next()).performClean(); - } - } - - /**Post-delete notification that the project has been deleted.. Should be called immediatelly after - * the project is deleted. - * - * @param prj deleted project - */ - public void notifyDeleted(Project prj) throws IOException { - for (Iterator i = getDeleteOperationImplementation(prj).iterator(); i.hasNext(); ) { - ((DeleteOperationImplementation) i.next()).notifyDeleted(); - } - } - - private Collection/**/ getDeleteOperationImplementation(Project prj) { - return prj.getLookup().lookup(new Lookup.Template(DeleteOperationImplementation.class)).allInstances(); - } - - private Collection/**/ getProjectsOperationsImplementation(Project prj) { - return prj.getLookup().lookup(new Lookup.Template(DataFilesProviderImplementation.class)).allInstances(); - } - -} Index: projects/projectapi/src/org/netbeans/spi/project/ActionProvider.java =================================================================== RCS file: /cvs/projects/projectapi/src/org/netbeans/spi/project/ActionProvider.java,v retrieving revision 1.7 diff -u -r1.7 ActionProvider.java --- projects/projectapi/src/org/netbeans/spi/project/ActionProvider.java 11 Jul 2005 12:18:08 -0000 1.7 +++ projects/projectapi/src/org/netbeans/spi/project/ActionProvider.java 29 Jul 2005 14:58:14 -0000 @@ -94,6 +94,27 @@ String COMMAND_DELETE = "delete"; // NOI18N /** + * Standard command for deleting the project. + * + * @since 1.7 + */ + String COMMAND_COPY = "copy"; // NOI18N + + /** + * Standard command for deleting the project. + * + * @since 1.7 + */ + String COMMAND_MOVE = "move"; // NOI18N + + /** + * Standard command for deleting the project. + * + * @since 1.7 + */ + String COMMAND_RENAME = "rename"; // NOI18N + + /** * Get a list of all commands which this project supports. * @return a list of command names suitable for {@link #invokeAction} * @see #COMMAND_BUILD Index: projects/projectapi/src/org/netbeans/spi/project/CopyOperationImplementation.java =================================================================== RCS file: projects/projectapi/src/org/netbeans/spi/project/CopyOperationImplementation.java diff -N projects/projectapi/src/org/netbeans/spi/project/CopyOperationImplementation.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ projects/projectapi/src/org/netbeans/spi/project/CopyOperationImplementation.java 29 Jul 2005 14:58:14 -0000 @@ -0,0 +1,64 @@ +/* + * 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-2005 Sun + * Microsystems, Inc. All Rights Reserved. + */ +package org.netbeans.spi.project; + +import java.io.File; +import java.io.IOException; +import org.netbeans.api.project.Project; + +/** + * Project Copy Operation. Allows to gather information necessary for project + * copy and also provides callbacks to the project type to handle special + * checkpoints during the copy process. + * + * An implementation of this interface may be registered in the project's lookup to support + * copy operation in the following cases: + *

    + *
  • The project type wants to use the {@link org.netbeans.spi.project.ui.support DefaultProjectOperationsImplementation} + * to perform the copy operation. + *
  • + *
  • If this project may be part of of a compound project (like EJB project is a part of a J2EE project), + * and the compound project wants to copy all the sub-projects. + *
  • + *
+ * + * The project type is not required to put an implementation of this interface into the project's + * lookup if the above two cases should not be supported. + * + * @author Jan Lahoda + * @since 1.7 + */ +public interface CopyOperationImplementation extends DataFilesProviderImplementation { + + /**Pre-copy notification. The exact meaning is left on the project implementors, but + * typically this means to undeloy the application and remove all artifacts + * created by the build project. + * + * @throws IOException if an I/O operation fails. + */ + public void notifyCopying() throws IOException; + + /**Notification that the copy operation has finished. Is supposed to fix the + * newly created (copied) project into the correct state (including changing its display name + * to nueName). Should be called on both original and newly created project (in this order). + * + * @param original the original project + * @param originalPath the project folder of the original project (for consistency + * with MoveOperationImplementation.notifyMoved) + * @param nueName new name for the newly created project. + * + * @throws IOException if an I/O operation fails. + */ + public void notifyCopied(Project original, File originalPath, String nueName) throws IOException; + +} Index: projects/projectapi/src/org/netbeans/spi/project/DataFilesProviderImplementation.java =================================================================== RCS file: projects/projectapi/src/org/netbeans/spi/project/DataFilesProviderImplementation.java diff -N projects/projectapi/src/org/netbeans/spi/project/DataFilesProviderImplementation.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ projects/projectapi/src/org/netbeans/spi/project/DataFilesProviderImplementation.java 29 Jul 2005 14:58:14 -0000 @@ -0,0 +1,45 @@ +/* + * 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-2005 Sun + * Microsystems, Inc. All Rights Reserved. + */ +package org.netbeans.spi.project; + +import java.util.List; +import org.openide.filesystems.FileObject; + +/** + * Base for various Project Operations, allows to gather metadata and data files + * for a project. + * + * @author Jan Lahoda + * @since 1.7 + */ +public interface DataFilesProviderImplementation { + + /** + * Returns list of {@link FileObject}s the are considered to be metadata files + * and folders belonging into this project. + * See {@link ProjectOperations#getMetadataFiles()} for more information. + * + * @return list of {@link FileObject}s that are considered metadata files and folders. + */ + public List/**/ getMetadataFiles(); + + /** + * Returns list of {@link FileObject}s the are considered to be data files and folders + * belonging into this project. + * See {@link ProjectOperations#getDataFiles()} for more information. + * + * @return list of {@link FileObject}s that are considered data files and folders. + */ + public List/**/ getDataFiles(); + +} Index: projects/projectapi/src/org/netbeans/spi/project/DeleteOperationImplementation.java =================================================================== RCS file: projects/projectapi/src/org/netbeans/spi/project/DeleteOperationImplementation.java diff -N projects/projectapi/src/org/netbeans/spi/project/DeleteOperationImplementation.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ projects/projectapi/src/org/netbeans/spi/project/DeleteOperationImplementation.java 29 Jul 2005 14:58:14 -0000 @@ -0,0 +1,56 @@ +/* + * 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-2005 Sun + * Microsystems, Inc. All Rights Reserved. + */ +package org.netbeans.spi.project; + +import java.io.IOException; + +/** + * Project Delete Operation. Allows to gather information necessary for project + * delete and also provides callbacks to the project type to handle special + * checkpoints during the delete. + * + * An implementation of this interface may be registered in the project's lookup to support + * delete operation in the following cases: + *
    + *
  • The project type wants to use the {@link org.netbeans.spi.project.ui.support.DefaultProjectOperationsImplementation} + * to perform the delete operation. + *
  • + *
  • If this project may be part of of a compound project (like EJB project is a part of a J2EE project), + * and the compound project wants to delete all the sub-projects. + *
  • + *
+ * + * The project type is not required to put an implementation of this interface into the project's + * lookup if the above two cases should not be supported. + * + * @author Jan Lahoda + * @since 1.7 + */ +public interface DeleteOperationImplementation extends DataFilesProviderImplementation { + + /**Pre-delete notification. The exact meaning is left on the project implementors, but + * typically this means to undeloy the application and remove all artifacts + * created by the build project. + * + * @throws IOException if an I/O operation fails. + */ + public void notifyDeleting() throws IOException; + + /**Notification that the delete operation has finished. Is supposed to perform + * final cleanup and to call {@link ProjectState#notifyDeleted}. + * + * @throws IOException if an I/O operation fails. + */ + public void notifyDeleted() throws IOException; + +} Index: projects/projectapi/src/org/netbeans/spi/project/MoveOperationImplementation.java =================================================================== RCS file: projects/projectapi/src/org/netbeans/spi/project/MoveOperationImplementation.java diff -N projects/projectapi/src/org/netbeans/spi/project/MoveOperationImplementation.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ projects/projectapi/src/org/netbeans/spi/project/MoveOperationImplementation.java 29 Jul 2005 14:58:14 -0000 @@ -0,0 +1,64 @@ +/* + * 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-2005 Sun + * Microsystems, Inc. All Rights Reserved. + */ +package org.netbeans.spi.project; + +import java.io.File; +import java.io.IOException; +import org.netbeans.api.project.Project; + +/** + * Project Rename/Move Operation. Allows to gather information necessary for project + * move and also provides callbacks to the project type to handle special + * checkpoints during the delete. + * + * An implementation of this interface may be registered in the project's lookup to support + * move operation in the following cases: + *
    + *
  • The project type wants to use the {@link org.netbeans.spi.project.ui.support.DefaultProjectOperationsImplementation} + * to perform the rename/move operation. + *
  • + *
  • If this project may be part of of a compound project (like EJB project is a part of a J2EE project), + * and the compound project wants to rename/move all the sub-projects. + *
  • + *
+ * + * The project type is not required to put an implementation of this interface into the project's + * lookup if the above two cases should not be supported. + * + * @author Jan Lahoda + * @since 1.7 + */ +public interface MoveOperationImplementation extends DataFilesProviderImplementation { + + /**Pre-move notification. The exact meaning is left on the project implementors, but + * typically this means to undeloy the application and remove all artifacts + * created by the build project. + * + * @throws IOException if an I/O operation fails. + */ + public void notifyMoving() throws IOException; + + /**Notification that the move operation has finished. Is supposed to fix the + * newly created (moved) project into the correct state (including changing its display name + * to nueName) and call {@link ProjectState#notifyDeleted} on the original project. + * Should be called on both original and newly created project (in this order). + * + * @param original the original project + * @param originalPath the project folder of the original project + * @param nueName new name for the newly created project. + * + * @throws IOException if an I/O operation fails. + */ + public void notifyMoved(Project original, File originalPath, String nueName) throws IOException; + +} Index: projects/projectapi/src/org/netbeans/spi/project/ProjectOperationsImplementation.java =================================================================== RCS file: projects/projectapi/src/org/netbeans/spi/project/ProjectOperationsImplementation.java diff -N projects/projectapi/src/org/netbeans/spi/project/ProjectOperationsImplementation.java --- projects/projectapi/src/org/netbeans/spi/project/ProjectOperationsImplementation.java 11 Jul 2005 12:18:08 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,84 +0,0 @@ -/* - * 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-2005 Sun - * Microsystems, Inc. All Rights Reserved. - */ - -package org.netbeans.spi.project; - -import java.io.IOException; -import java.util.List; -import org.netbeans.api.project.ProjectOperations; - -/**This is only a scope class that holds several project operation interfaces. - * See particular interface for more information: - *
  • - *
      {@link DeleteOperationImplementation DeleteOperationImplementation}
    - *
  • - * - * @since 1.6 - * @author Jan Lahoda - */ -public final class ProjectOperationsImplementation { - - /** - * Base for various Project Operations, allows to gather metadata and data files - * for a project. - */ - public interface DataFilesProviderImplementation { - - /** - * Returns list of {@link FileObject}s the are considered to be metadata files - * and folders belonging into this project. - * See {@link ProjectOperations#getMetadataFiles()} for more information. - * - * @return list of {@link FileObject}s that are considered metadata files and folders. - */ - public List/**/ getMetadataFiles(); - - /** - * Returns list of {@link FileObject}s the are considered to be data files and folders - * belonging into this project. - * See {@link ProjectOperations#getDataFiles()} for more information. - * - * @return list of {@link FileObject}s that are considered data files and folders. - */ - public List/**/ getDataFiles(); - - } - - /** - * Project Delete Operation. Allows to gather information necessary for project - * delete and also provides callbacks to the project type to handle special - * checkpoints during the delete. - * - * An implementation of this interface should be registered in the project to support - * delete operation. - */ - public interface DeleteOperationImplementation extends DataFilesProviderImplementation { - - /**Pre-delete clean. The exact meaning is left on the project implementors, but - * typically this means to undeloy the application and remove all artifacts - * created by the build project. - * - * @throws IOException if an I/O operation fails. - */ - public void performClean() throws IOException; - - /**Notification that the delete operation has finished. Is supposed to perform - * final cleanup and to call {@link ProjectState#notifyDeleted}. - * - * @throws IOException if an I/O operation fails. - */ - public void notifyDeleted() throws IOException; - - } - -} Index: projects/projectapi/src/org/netbeans/spi/project/support/ProjectOperations.java =================================================================== RCS file: projects/projectapi/src/org/netbeans/spi/project/support/ProjectOperations.java diff -N projects/projectapi/src/org/netbeans/spi/project/support/ProjectOperations.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ projects/projectapi/src/org/netbeans/spi/project/support/ProjectOperations.java 29 Jul 2005 14:58:14 -0000 @@ -0,0 +1,220 @@ +/* + * 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-2005 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.spi.project.support; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import org.netbeans.api.project.Project; +import org.netbeans.spi.project.CopyOperationImplementation; +import org.netbeans.spi.project.DataFilesProviderImplementation; +import org.netbeans.spi.project.DeleteOperationImplementation; +import org.netbeans.spi.project.MoveOperationImplementation; +import org.openide.util.Lookup; + +/** + * Allows gathering information for various project operations. + * + * @author Jan Lahoda + * @since 1.7 + */ +public final class ProjectOperations { + + private ProjectOperations() { + } + + /**Return list of files that are considered metadata files and folders for the given project. + * Returns meaningfull values only if some of the is*Supported methods + * return true. + * + * @param prj project to test + * @return list of metadata files/folders + */ + public static List/**/ getMetadataFiles(Project prj) { + List/**/ result = new ArrayList(); + + for (Iterator i = getProjectsOperationsImplementation(prj).iterator(); i.hasNext(); ) { + result.addAll(((DataFilesProviderImplementation) i.next()).getMetadataFiles()); + } + + return result; + } + + /**Return list of files that are considered source files and folders for the given project. + * Returns meaningfull values only if some of the is*Supported methods + * return true. + * + * @param prj project to test + * @return list of data files/folders + */ + public static List/**/ getDataFiles(Project prj) { + List/**/ result = new ArrayList(); + + for (Iterator i = getProjectsOperationsImplementation(prj).iterator(); i.hasNext(); ) { + result.addAll(((DataFilesProviderImplementation) i.next()).getDataFiles()); + } + + return result; + } + + /**Test whether the delete operation is supported on the given project. + * + * @param prj project to test + * @return true if the project supports delete operation, + * false otherwise + */ + public static boolean isDeleteOperationSupported(Project prj) { + return !getDeleteOperationImplementation(prj).isEmpty(); + } + + /**Notification that the project is about to be deleted. + * Should be called immediatelly before the project is deleted. + * + * The project is supposed to do all required cleanup to allow the project to be deleted. + * + * @param prj project to notify + * @throws IOException is some error occurs + */ + public static void notifyDeleting(Project prj) throws IOException { + for (Iterator i = getDeleteOperationImplementation(prj).iterator(); i.hasNext(); ) { + ((DeleteOperationImplementation) i.next()).notifyDeleting(); + } + } + + /**Notification that the project has been deleted. + * Should be called immediatelly after the project is deleted. + * + * @param prj project to notify + * @throws IOException is some error occurs + */ + public static void notifyDeleted(Project prj) throws IOException { + for (Iterator i = getDeleteOperationImplementation(prj).iterator(); i.hasNext(); ) { + ((DeleteOperationImplementation) i.next()).notifyDeleted(); + } + } + + /**Test whether the copy operation is supported on the given project. + * + * @param prj project to test + * @return true if the project supports the copy operation, + * false otherwise + */ + public static boolean isCopyOperationSupported(Project prj) { + return !getCopyOperationImplementation(prj).isEmpty(); + } + + /**Notification that the project is about to be copyied. + * Should be called immediatelly before the project is copied. + * + * The project is supposed to do all required cleanup to allow the project to be copied. + * + * @param prj project to notify + * @throws IOException is some error occurs + */ + public static void notifyCopying(Project prj) throws IOException { + for (Iterator i = getCopyOperationImplementation(prj).iterator(); i.hasNext(); ) { + ((CopyOperationImplementation) i.next()).notifyCopying(); + } + } + + /**Notification that the project has been copied. + * Should be called immediatelly after the project is copied. + * + * The project is supposed to do all necessary fixes to the project's structure to + * form a valid project. + * + * Both original and newly created project (copy) are notified, in this order. + * + * @param original original project + * @param nue new project (copy) + * @param originalPath the project folder of the original project (for consistency with notifyMoved) + * @param name new name of the project + * @throws IOException is some error occurs + */ + public static void notifyCopied(Project original, Project nue, File originalPath, String name) throws IOException { + for (Iterator i = getCopyOperationImplementation(original).iterator(); i.hasNext(); ) { + ((CopyOperationImplementation) i.next()).notifyCopied(original, originalPath, name); + } + for (Iterator i = getCopyOperationImplementation(nue).iterator(); i.hasNext(); ) { + ((CopyOperationImplementation) i.next()).notifyCopied(original, originalPath, name); + } + } + + /**Notification that the project is about to be moved. + * Should be called immediatelly before the project is moved. + * + * The project is supposed to do all required cleanup to allow the project to be moved. + * + * @param prj project to notify + * @throws IOException is some error occurs + */ + public static void notifyMoving(Project prj) throws IOException { + for (Iterator i = getMoveOperationImplementation(prj).iterator(); i.hasNext(); ) { + ((MoveOperationImplementation) i.next()).notifyMoving(); + } + } + + /**Notification that the project has been moved. + * Should be called immediatelly after the project is moved. + * + * The project is supposed to do all necessary fixes to the project's structure to + * form a valid project. + * + * Both original and moved project are notified, in this order. + * + * @param original original project + * @param nue moved project + * @param originalPath the project folder of the original project + * @param name new name of the project + * @throws IOException is some error occurs + */ + public static void notifyMoved(Project original, Project nue, File originalPath, String name) throws IOException { + for (Iterator i = getMoveOperationImplementation(original).iterator(); i.hasNext(); ) { + ((MoveOperationImplementation) i.next()).notifyMoved(original, originalPath, name); + } + for (Iterator i = getMoveOperationImplementation(nue).iterator(); i.hasNext(); ) { + ((MoveOperationImplementation) i.next()).notifyMoved(original, originalPath, name); + } + } + + /**Test whether the move operation is supported on the given project. + * + * @param prj project to test + * @return true if the project supports the move operation, + * false otherwise + */ + public static boolean isMoveOperationSupported(Project prj) { + return true; + } + + private static Collection/**/ getDeleteOperationImplementation(Project prj) { + return prj.getLookup().lookup(new Lookup.Template(DeleteOperationImplementation.class)).allInstances(); + } + + private static Collection/**/ getProjectsOperationsImplementation(Project prj) { + return prj.getLookup().lookup(new Lookup.Template(DataFilesProviderImplementation.class)).allInstances(); + } + + private static Collection/**/ getCopyOperationImplementation(Project prj) { + return prj.getLookup().lookup(new Lookup.Template(CopyOperationImplementation.class)).allInstances(); + } + + private static Collection/**/ getMoveOperationImplementation(Project prj) { + return prj.getLookup().lookup(new Lookup.Template(MoveOperationImplementation.class)).allInstances(); + } + +} Index: projects/projectui/src/org/netbeans/modules/project/ui/actions/Actions.java =================================================================== RCS file: /cvs/projects/projectui/src/org/netbeans/modules/project/ui/actions/Actions.java,v retrieving revision 1.25 diff -u -r1.25 Actions.java --- projects/projectui/src/org/netbeans/modules/project/ui/actions/Actions.java 12 Jul 2005 12:52:34 -0000 1.25 +++ projects/projectui/src/org/netbeans/modules/project/ui/actions/Actions.java 29 Jul 2005 14:58:14 -0000 @@ -51,6 +51,9 @@ private static Action OPEN_SUBPROJECTS; private static Action CLOSE_PROJECT; private static Action NEW_FILE; + private static Action COPY_PROJECT; + private static Action MOVE_PROJECT; + private static Action RENAME_PROJECT; public synchronized Action setAsMainProjectAction() { if ( SET_AS_MAIN_PROJECT == null ) { @@ -91,6 +94,18 @@ return deleteProject(); } + public Action copyProjectAction() { + return copyProject(); + } + + public Action moveProjectAction() { + return moveProject(); + } + + public Action renameProjectAction() { + return renameProject(); + } + public synchronized Action newProjectAction() { return new NewProject(); } @@ -178,6 +193,45 @@ a.putValue(Action.ACCELERATOR_KEY, DeleteAction.get(DeleteAction.class).getValue(Action.ACCELERATOR_KEY)); return a; + } + + public static synchronized Action copyProject() { + if (COPY_PROJECT == null) { + Action a = new ProjectAction( + ActionProvider.COMMAND_COPY, + "Copy Project", // NO18N + null, //NOI18N + null ); + COPY_PROJECT = a; + } + + return COPY_PROJECT; + } + + public static synchronized Action moveProject() { + if (MOVE_PROJECT == null) { + Action a = new ProjectAction( + ActionProvider.COMMAND_MOVE, + "Move Project", // NO18N + null, //NOI18N + null ); + MOVE_PROJECT = a; + } + + return MOVE_PROJECT; + } + + public static synchronized Action renameProject() { + if (RENAME_PROJECT == null) { + Action a = new ProjectAction( + ActionProvider.COMMAND_RENAME, + "Rename Project", // NO18N + null, //NOI18N + null ); + RENAME_PROJECT = a; + } + + return RENAME_PROJECT; } // 1-off actions ----------------------------------------------------------- Index: projects/projectuiapi/apichanges.xml =================================================================== RCS file: /cvs/projects/projectuiapi/apichanges.xml,v retrieving revision 1.17 diff -u -r1.17 apichanges.xml --- projects/projectuiapi/apichanges.xml 29 Jul 2005 00:10:39 -0000 1.17 +++ projects/projectuiapi/apichanges.xml 29 Jul 2005 14:58:15 -0000 @@ -76,6 +76,24 @@ + + + Project Delete/Copy/Rename/Move Support Added, Support for Default Project Delete/Copy/Rename/Move Added + + + + + + Introduced: +
      +
    • CommonProjectActions.deleteProjectAction, CommonProjectActions.copyProjectAction, + CommonProjectActions.moveProjectAction, CommonProjectActions.removeProjectAction methods.
    • +
    • DefaultProjectOperations support to simplify implementation of project delete/copy/rename/move for simple projects.
    • +
    +
    + +
    + Added ability to set an error message for project customizer's categories. @@ -137,22 +155,6 @@ - - - Delete Action Added - - - - - - Introduced: -
      -
    • CommonProjectActions.deleteProjectAction method
    • -
    -
    - -
    - New Project Wizard Action Index: projects/projectuiapi/nbproject/project.properties =================================================================== RCS file: /cvs/projects/projectuiapi/nbproject/project.properties,v retrieving revision 1.11 diff -u -r1.11 project.properties --- projects/projectuiapi/nbproject/project.properties 28 Jul 2005 14:25:17 -0000 1.11 +++ projects/projectuiapi/nbproject/project.properties 29 Jul 2005 14:58:15 -0000 @@ -9,7 +9,7 @@ # Code is Sun Microsystems, Inc. Portions Copyright 1997-2005 Sun # Microsystems, Inc. All Rights Reserved. -spec.version.base=1.9.0 +spec.version.base=1.10.0 is.autoload=true javadoc.title=Project UI API javadoc.arch=${basedir}/arch.xml @@ -17,4 +17,12 @@ # copy paste magic to enable unit tests test.unit.src.dir=${basedir}/test/unit/src test-unit-sys-prop.test.junit.jar=${junit.dir}/modules/ext/junit-3.8.1.jar +test.unit.cp.extra=\ + ${nb_all}/projects/projectapi/build/test/unit/classes +test.unit.run.cp.extra=\ + ${openide/masterfs.dir}/modules/org-netbeans-modules-masterfs.jar:\ + ${openide/options.dir}/modules/org-openide-options.jar:\ + ${projects/projectui.dir}/modules/org-netbeans-modules-projectui.jar +# ${libs/xerces.dir}/modules/ext/xerces-2.6.2.jar:\ +# ${libs/xerces.dir}/modules/ext/xml-commons-dom-ranges-1.0.b2.jar:\ Index: projects/projectuiapi/nbproject/project.xml =================================================================== RCS file: /cvs/projects/projectuiapi/nbproject/project.xml,v retrieving revision 1.10 diff -u -r1.10 project.xml --- projects/projectuiapi/nbproject/project.xml 14 Jul 2005 20:32:52 -0000 1.10 +++ projects/projectuiapi/nbproject/project.xml 29 Jul 2005 14:58:15 -0000 @@ -18,6 +18,15 @@ org.netbeans.modules.projectuiapi + org.netbeans.api.progress + + + + 1 + 1.0 + + + org.netbeans.modules.projectapi @@ -27,15 +36,16 @@ - org.openide.filesystems + org.netbeans.modules.queries - 6.2 + 1 + 1.5 - org.openide.util + org.openide.awt @@ -43,7 +53,7 @@ - org.openide.nodes + org.openide.dialogs @@ -59,7 +69,7 @@ - org.openide.awt + org.openide.filesystems @@ -67,7 +77,13 @@ - org.openide.dialogs + org.openide.loaders + + + + + + org.openide.nodes @@ -75,10 +91,12 @@ - org.openide.loaders + org.openide.util - + + 6.2 + Index: projects/projectuiapi/src/org/netbeans/modules/project/uiapi/ActionsFactory.java =================================================================== RCS file: /cvs/projects/projectuiapi/src/org/netbeans/modules/project/uiapi/ActionsFactory.java,v retrieving revision 1.8 diff -u -r1.8 ActionsFactory.java --- projects/projectuiapi/src/org/netbeans/modules/project/uiapi/ActionsFactory.java 11 Jul 2005 12:18:12 -0000 1.8 +++ projects/projectuiapi/src/org/netbeans/modules/project/uiapi/ActionsFactory.java 29 Jul 2005 14:58:15 -0000 @@ -37,6 +37,10 @@ public Action deleteProjectAction(); + public Action copyProjectAction(); + + public Action moveProjectAction(); + public Action newProjectAction(); // Actions sensitive to project selection @@ -54,5 +58,7 @@ // Actions sensitive to file public Action fileCommandAction( String command, String name, Icon icon ); + + public Action renameProjectAction(); } Index: projects/projectuiapi/src/org/netbeans/modules/project/uiapi/Bundle.properties =================================================================== RCS file: /cvs/projects/projectuiapi/src/org/netbeans/modules/project/uiapi/Bundle.properties,v retrieving revision 1.2 diff -u -r1.2 Bundle.properties --- projects/projectuiapi/src/org/netbeans/modules/project/uiapi/Bundle.properties 23 Jan 2005 17:40:11 -0000 1.2 +++ projects/projectuiapi/src/org/netbeans/modules/project/uiapi/Bundle.properties 29 Jul 2005 14:58:15 -0000 @@ -34,3 +34,34 @@ LBL_Customizer_Categories=Categories\: + +#DefaultAntProjectOperations: +LBL_Progress_Cleaning_Project=Cleaning Project +LBL_Progress_Deleting_File=Deleting {0} +LBL_Project_cannot_be_deleted.=Project {0} cannot be deleted. +LBL_Delete_Project_Caption=Delete Project +LBL_Deleting_Project=Deleting Project\: +#currently not used: +#LBL_Project_Deletion_in_Progress_Caption=Project Deletion in Progress + +#DefaultAntProjectDeletePanel: +LBL_Pre_Delete_Warning=Are you sure you want to delete project "{0}"? +LBL_Delete_Also_Sources=&Also Delete Sources Under "{0}" folder. + +#ProjectCopyPanel: +#{0}: Integer 0 or 1. 0 for copy project dialog, 1 for move project dialog +#{1}: project's display name +LBL_Copy_Move_Dialog_Text={0,choice,0#Copy|1#Move} "{1}" To: +LBL_Project_Folder=Project Fol&der\: +LBL_Project_Location=Project &Location\: +LBL_Project_Name=Project &Name\: +#ProjectCopyPanel's error messages: +ERR_Location_Does_Not_Exist=Location Does Not Exist +ERR_Project_Folder_Exists=Project Folder Already Exists +#ProjectCopyPanel's warning message: +WRN_External_Sources=The project has one or more external source roots, which cannot be copied. + +#DefaultRenamePanel: +#{0}: project's display name +LBL_Rename_Dialog_Text=Rename "{1}": +LBL_Also_Rename_Project_Folder=&Also Rename Project Folder Index: projects/projectuiapi/src/org/netbeans/modules/project/uiapi/DefaultProjectDeletePanel.form =================================================================== RCS file: projects/projectuiapi/src/org/netbeans/modules/project/uiapi/DefaultProjectDeletePanel.form diff -N projects/projectuiapi/src/org/netbeans/modules/project/uiapi/DefaultProjectDeletePanel.form --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ projects/projectuiapi/src/org/netbeans/modules/project/uiapi/DefaultProjectDeletePanel.form 29 Jul 2005 14:58:15 -0000 @@ -0,0 +1,50 @@ + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: projects/projectuiapi/src/org/netbeans/modules/project/uiapi/DefaultProjectDeletePanel.java =================================================================== RCS file: projects/projectuiapi/src/org/netbeans/modules/project/uiapi/DefaultProjectDeletePanel.java diff -N projects/projectuiapi/src/org/netbeans/modules/project/uiapi/DefaultProjectDeletePanel.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ projects/projectuiapi/src/org/netbeans/modules/project/uiapi/DefaultProjectDeletePanel.java 29 Jul 2005 14:58:15 -0000 @@ -0,0 +1,101 @@ +/* + * 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-2005 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.modules.project.uiapi; + +import java.awt.Component; +import java.awt.Window; +import java.text.MessageFormat; +import java.util.Iterator; +import java.util.List; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.util.NbBundle; + +/** + * + * @author Jan Lahoda + */ +final class DefaultProjectDeletePanel extends javax.swing.JPanel { + + private String projectDisplaName; + private String projectFolder; + private boolean enableCheckbox; + + /** + * Creates new form DefaultProjectDeletePanel + */ + public DefaultProjectDeletePanel(String projectDisplaName, String projectFolder, boolean enableCheckbox) { + this.projectDisplaName = projectDisplaName; + this.projectFolder = projectFolder; + this.enableCheckbox = enableCheckbox; + initComponents(); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; + + warningText = new javax.swing.JTextArea(); + deleteSourcesCheckBox = new javax.swing.JCheckBox(); + + setLayout(new java.awt.GridBagLayout()); + + warningText.setEditable(false); + warningText.setFont(javax.swing.UIManager.getFont("Label.font")); + warningText.setText(getWarningText()); + warningText.setDisabledTextColor(javax.swing.UIManager.getColor("Label.foreground")); + warningText.setOpaque(false); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(12, 12, 0, 12); + add(warningText, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(deleteSourcesCheckBox, getCheckboxText()); + deleteSourcesCheckBox.setEnabled(enableCheckbox); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 3; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(12, 12, 0, 12); + add(deleteSourcesCheckBox, gridBagConstraints); + + } + // //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBox deleteSourcesCheckBox; + private javax.swing.JTextArea warningText; + // End of variables declaration//GEN-END:variables + + public boolean isDeleteSources() { + return deleteSourcesCheckBox.isSelected(); + } + + private String getWarningText() { + return NbBundle.getMessage(DefaultProjectDeletePanel.class, "LBL_Pre_Delete_Warning", new Object[] {projectDisplaName}); + } + + private String getCheckboxText() { + return NbBundle.getMessage(DefaultProjectDeletePanel.class, "LBL_Delete_Also_Sources", new Object[] {projectFolder}); + } + +} Index: projects/projectuiapi/src/org/netbeans/modules/project/uiapi/DefaultProjectOperationsImplementation.java =================================================================== RCS file: projects/projectuiapi/src/org/netbeans/modules/project/uiapi/DefaultProjectOperationsImplementation.java diff -N projects/projectuiapi/src/org/netbeans/modules/project/uiapi/DefaultProjectOperationsImplementation.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ projects/projectuiapi/src/org/netbeans/modules/project/uiapi/DefaultProjectOperationsImplementation.java 29 Jul 2005 14:58:15 -0000 @@ -0,0 +1,540 @@ +/* + * 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-2005 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.modules.project.uiapi; + +import java.awt.Component; +import java.awt.Dialog; +import java.awt.GridBagConstraints; +import java.awt.Insets; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import org.netbeans.api.progress.ProgressHandle; +import org.netbeans.api.progress.ProgressHandleFactory; +import org.netbeans.api.project.FileOwnerQuery; +import org.netbeans.api.project.Project; +import org.netbeans.api.project.ProjectManager; +import org.netbeans.api.project.ProjectUtils; +import org.netbeans.api.project.ui.OpenProjects; +import org.netbeans.spi.project.support.ProjectOperations; +import org.netbeans.api.queries.VisibilityQuery; +import org.openide.DialogDescriptor; +import org.openide.DialogDisplayer; +import org.openide.ErrorManager; +import org.openide.NotifyDescriptor; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.util.NbBundle; +import org.openide.util.RequestProcessor; + + +/** + * + * @author Jan Lahoda + */ +public final class DefaultProjectOperationsImplementation { + + private static final ErrorManager ERR = ErrorManager.getDefault(); // NOI18N + + private DefaultProjectOperationsImplementation() { + } + + private static String getDisplayName(Project project) { + return ProjectUtils.getInformation(project).getDisplayName(); + } + + // + /** + * @return true if success + */ + private static boolean performDelete(Project project, List/*FileObject>*/ toDelete, ProgressHandle handle) { + try { + handle.start(toDelete.size() + 1 /*clean*/); + + int done = 0; + + handle.progress(NbBundle.getMessage(DefaultProjectOperationsImplementation.class, "LBL_Progress_Cleaning_Project")); + + ProjectOperations.notifyDeleting(project); + + handle.progress(++done); + + for (Iterator i = toDelete.iterator(); i.hasNext(); ) { + FileObject f = (FileObject) i.next(); + + handle.progress(NbBundle.getMessage(DefaultProjectOperationsImplementation.class, "LBL_Progress_Deleting_File", new Object[] {FileUtil.getFileDisplayName(f)})); + + if (f != null) + f.delete(); + + handle.progress(++done); + } + + FileObject projectFolder = project.getProjectDirectory(); + + if (projectFolder.getChildren().length == 0) { + //empty, delete: + projectFolder.delete(); + } + + handle.finish(); + + ProjectOperations.notifyDeleted(project); + return true; + } catch (IOException e) { + String displayName = getDisplayName(project); + String message = NbBundle.getMessage(DefaultProjectOperationsImplementation.class, "LBL_Project_cannot_be_deleted.", new Object[] {displayName}); + + ErrorManager.getDefault().annotate(e, message); + ErrorManager.getDefault().notify(ErrorManager.USER, e); + + return false; + } + } + + public static void deleteProject(final Project project) { + Runnable r = new Runnable() { + public void run() { + deleteProject(project, new GUIUserInputHandler()); + } + }; + + if (SwingUtilities.isEventDispatchThread()) { + r.run(); + } else { + SwingUtilities.invokeLater(r); + } + } + + /*package private*/static void deleteProject(final Project project, final UserInputHandler handler) { + String displayName = getDisplayName(project); + FileObject projectFolder = project.getProjectDirectory(); + + if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) { + ERR.log(ErrorManager.INFORMATIONAL, "delete started: " + displayName); // NOI18N + } + + List/**/ metadataFiles = ProjectOperations.getMetadataFiles(project); + List/**/ dataFiles = ProjectOperations.getDataFiles(project); + List/**/ allFiles = new ArrayList/**/(); + + allFiles.addAll(metadataFiles); + allFiles.addAll(dataFiles); + + for (Iterator i = allFiles.iterator(); i.hasNext(); ) { + FileObject f = (FileObject) i.next(); + + if (!FileUtil.isParentOf(projectFolder, f)) { + i.remove(); + } + } + + int userAnswer = handler.userConfirmation(displayName, FileUtil.getFileDisplayName(projectFolder), !dataFiles.isEmpty()); + List/**/ toDeleteImpl = null; + + switch (userAnswer) { + case UserInputHandler.USER_CANCEL: + return ; + case UserInputHandler.USER_OK_METADATA: + toDeleteImpl = metadataFiles; + break; + case UserInputHandler.USER_OK_ALL: + toDeleteImpl = allFiles; + break; + default: + throw new IllegalStateException("Invalid user answer: " + userAnswer); + } + + final ProgressHandle handle = handler.getProgressHandle(); + final List/**/ toDelete = toDeleteImpl; + final boolean[] result = new boolean[1]; + + OpenProjects.getDefault().close(new Project[] {project}); + + handler.delete(new Runnable() { + public void run() { + result[0] = performDelete(project, toDelete, handle); + } + }); + + if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) { + ERR.log(ErrorManager.INFORMATIONAL, "delete done: " + displayName); // NOI18N + } + } + + /*package private*/interface UserInputHandler { + + public int USER_CANCEL = 1; + public int USER_OK_METADATA = 2; + public int USER_OK_ALL = 3; + + public abstract int userConfirmation(String displayName, String projectFolder, boolean enableData); + + public abstract ProgressHandle getProgressHandle(); + + public abstract void delete(Runnable r); + + } + + private static final class GUIUserInputHandler implements UserInputHandler { + + public int userConfirmation(String displayName, String projectFolder, boolean enableData) { + DefaultProjectDeletePanel deletePanel = new DefaultProjectDeletePanel(displayName, projectFolder, enableData); + + String caption = NbBundle.getMessage(DefaultProjectOperationsImplementation.class, "LBL_Delete_Project_Caption"); + + NotifyDescriptor nd = new NotifyDescriptor.Confirmation(deletePanel, caption, NotifyDescriptor.YES_NO_OPTION); + + if (DialogDisplayer.getDefault().notify(nd) == NotifyDescriptor.YES_OPTION) { + if (deletePanel.isDeleteSources()) { + return USER_OK_ALL; + } else { + return USER_OK_METADATA; + } + } else { + return USER_CANCEL; + } + } + + private ProgressHandle handle = null; + + public synchronized ProgressHandle getProgressHandle() { + if (handle == null) { + handle = ProgressHandleFactory.createHandle(NbBundle.getMessage(DefaultProjectOperationsImplementation.class, "LBL_Delete_Project_Caption")); + } + + return handle; + } + + public void delete(final Runnable r) { + RequestProcessor.getDefault().post(new Runnable() { + public void run() { + r.run(); + + if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) { + ERR.log(ErrorManager.INFORMATIONAL, "delete finished"); // NOI18N + } + } + }); + } + + } + + private static JComponent createProgressDialog(ProgressHandle handle) { + JPanel dialog = new JPanel(); + + GridBagConstraints gridBagConstraints; + + JLabel jLabel1 = new JLabel(); + JComponent progress = ProgressHandleFactory.createProgressComponent(handle); + JPanel padding = new JPanel(); + + dialog.setLayout(new java.awt.GridBagLayout()); + + jLabel1.setText(NbBundle.getMessage(DefaultProjectOperationsImplementation.class, "LBL_Deleting_Project")); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new Insets(12, 12, 0, 12); + dialog.add(jLabel1, gridBagConstraints); + + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new Insets(12, 12, 0, 12); + dialog.add(progress, gridBagConstraints); + + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 2; + gridBagConstraints.fill = GridBagConstraints.HORIZONTAL | GridBagConstraints.VERTICAL; + gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new Insets(12, 12, 12, 12); + dialog.add(padding, gridBagConstraints); + + return dialog; + } + // + + // + public static void copyProject(final Project project) { + final ProgressHandle handle = ProgressHandleFactory.createHandle("Copy Project"); + final ProjectCopyPanel panel = new ProjectCopyPanel(handle, project, false); + + showConfirmationDialog(panel, project, "Copy Project", "Copy", new Executor() { + public void execute() { + String nueName = panel.getNewName(); + File newTarget = panel.getNewDirectory(); + + doCopyProject(handle, project, nueName, newTarget); + } + }); + } + + /*package private for tests*/ static void doCopyProject(ProgressHandle handle, Project project, String nueName, File newTarget) { + try { + File target = new File(newTarget, nueName); + + assert !target.exists(); + + ProjectOperations.notifyCopying(project); + + target.mkdirs(); + + FileObject projectDirectory = project.getProjectDirectory(); + List/**/ toCopyList = Arrays.asList(projectDirectory.getChildren()); + + handle.start(toCopyList.size()); + + int workDone = 0; + + for (Iterator i = toCopyList.iterator(); i.hasNext(); ) { + FileObject toCopy = (FileObject) i.next(); + File toCopyFile = FileUtil.toFile(toCopy); + + doCopy(project, toCopy, new File(target, toCopy.getNameExt())); + handle.progress(++workDone); + } + + Project nue = ProjectManager.getDefault().findProject(FileUtil.toFileObject(target)); + + assert nue != null; + + ProjectOperations.notifyCopied(project, nue, FileUtil.toFile(project.getProjectDirectory()), nueName); + + ProjectManager.getDefault().saveProject(nue); + + OpenProjects.getDefault().open(new Project[] {nue}, false); + + handle.finish(); + } catch (IOException e) { + ErrorManager.getDefault().notify(e); + e.printStackTrace(); + } + } + // + + // + public static void moveProject(final Project project) { + final ProgressHandle handle = ProgressHandleFactory.createHandle("Move Project"); + final ProjectCopyPanel panel = new ProjectCopyPanel(handle, project, true); + + showConfirmationDialog(panel, project, "Move Project", "Move", new Executor() { + public void execute() { + String nueName = panel.getNewName(); + File newTarget = panel.getNewDirectory(); + + doMoveProject(handle, project, nueName, newTarget); + } + }); + } + + public static void renameProject(Project project) { + renameProject(project, null); + } + + public static void renameProject(final Project project, final String nueName) { + final ProgressHandle handle = ProgressHandleFactory.createHandle("Copy Project"); + final DefaultProjectRenamePanel panel = new DefaultProjectRenamePanel(project, nueName); + + showConfirmationDialog(panel, project, "Rename Project", "Rename", new Executor() { + + public void execute() { + String nueName = panel.getNewName(); + + doMoveProject(handle, project, nueName, FileUtil.toFile(project.getProjectDirectory().getParent())); + } + }); + } + + /*package private for tests*/ static void doMoveProject(ProgressHandle handle, Project project, String nueName, File newTarget) { + try { + File target = new File(newTarget, nueName); + + assert !target.exists(); + + ProjectOperations.notifyMoving(project); + + OpenProjects.getDefault().close(new Project[] {project}); + + FileObject projectDirectory = project.getProjectDirectory(); + List/**/ toMoveList = Arrays.asList(projectDirectory.getChildren()); + + target.mkdirs(); + + for (Iterator i = toMoveList.iterator(); i.hasNext(); ) { + FileObject toCopy = (FileObject) i.next(); + File toCopyFile = FileUtil.toFile(toCopy); + + doCopy(project, toCopy, new File(target, toCopy.getNameExt())); + delete(toCopyFile); + } + + projectDirectory.refresh();//TODO: better way. + projectDirectory.refresh(); + + if (projectDirectory.getChildren().length == 0) { + projectDirectory.delete(); + } + + ProjectOperations.notifyDeleted(project); + + Project nue = ProjectManager.getDefault().findProject(FileUtil.toFileObject(target)); + + assert nue != null; + + ProjectOperations.notifyMoved(project, nue, FileUtil.toFile(project.getProjectDirectory()), nueName); + + ProjectManager.getDefault().saveProject(nue); + + OpenProjects.getDefault().open(new Project[] {nue}, false); + } catch (IOException e) { + ErrorManager.getDefault().notify(e); + } + } + // + + // + private static void doCopy(Project original, FileObject from, File to) throws IOException { + if (!VisibilityQuery.getDefault().isVisible(from)) { + //Do not copy invisible files/folders. + return ; + } + + if (!original.getProjectDirectory().equals(FileOwnerQuery.getOwner(from).getProjectDirectory())) { + return ; + } + + if (from.isFolder()) { + to.mkdir(); + FileObject[] kids = from.getChildren(); + for (int i = 0; i < kids.length; i++) { + doCopy(original, kids[i], new File(to, kids[i].getNameExt())); + } + } else { + assert from.isData(); + InputStream is = from.getInputStream(); + try { + OutputStream os = new FileOutputStream(to); + try { + FileUtil.copy(is, os); + } finally { + os.close(); + } + } finally { + is.close(); + } + } + } + + private static void delete(File f) throws IOException { + if (f.isDirectory()) { + File[] children = f.listFiles(); + + for (int cntr = 0; cntr < children.length; cntr++) { + delete(children[cntr]); + } + } + + f.delete(); + } + + private static void showConfirmationDialog(final JComponent panel, Project project, String caption, String confirmButton, final Executor executor) { + final JButton confirm = new JButton(confirmButton); + final JButton cancel = new JButton("Cancel"); + + assert panel instanceof InvalidablePanel; + + ((InvalidablePanel) panel).addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + confirm.setEnabled(((InvalidablePanel) panel).isValid()); + } + }); + + confirm.setEnabled(panel.isValid()); + + final Dialog[] dialog = new Dialog[1]; + + DialogDescriptor dd = new DialogDescriptor(panel, caption, true, new Object[] {confirm, cancel}, confirm, DialogDescriptor.DEFAULT_ALIGN, null, new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (e.getSource() == confirm) { + confirm.setEnabled(false); + cancel.setEnabled(false); + ((InvalidablePanel) panel).showProgress(); + + Component findParent = panel; + + while (findParent != null && !(findParent instanceof Window)) { + findParent = findParent.getParent(); + } + + if (findParent != null) { + ((Window) findParent).pack(); + } + + RequestProcessor.getDefault().post(new Runnable() { + public void run() { + executor.execute(); + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + dialog[0].setVisible(false); + } + }); + } + }); + } + } + }); + + dialog[0] = DialogDisplayer.getDefault().createDialog(dd); + + dialog[0].setVisible(true); + + dialog[0] = null; + } + + private static interface Executor { + public void execute(); + } + + public static interface InvalidablePanel { + public void addChangeListener(ChangeListener l); + public void removeChangeListener(ChangeListener l); + public boolean isValid(); + public void showProgress(); + } + // + +} Index: projects/projectuiapi/src/org/netbeans/modules/project/uiapi/DefaultProjectRenamePanel.form =================================================================== RCS file: projects/projectuiapi/src/org/netbeans/modules/project/uiapi/DefaultProjectRenamePanel.form diff -N projects/projectuiapi/src/org/netbeans/modules/project/uiapi/DefaultProjectRenamePanel.form --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ projects/projectuiapi/src/org/netbeans/modules/project/uiapi/DefaultProjectRenamePanel.form 29 Jul 2005 14:58:15 -0000 @@ -0,0 +1,97 @@ + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: projects/projectuiapi/src/org/netbeans/modules/project/uiapi/DefaultProjectRenamePanel.java =================================================================== RCS file: projects/projectuiapi/src/org/netbeans/modules/project/uiapi/DefaultProjectRenamePanel.java diff -N projects/projectuiapi/src/org/netbeans/modules/project/uiapi/DefaultProjectRenamePanel.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ projects/projectuiapi/src/org/netbeans/modules/project/uiapi/DefaultProjectRenamePanel.java 29 Jul 2005 14:58:15 -0000 @@ -0,0 +1,208 @@ +/* + * DefaultRenamePanel.java + * + * Created on July 13, 2005, 10:03 PM + */ + +package org.netbeans.modules.project.uiapi; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import org.netbeans.api.project.Project; +import org.netbeans.api.project.ProjectUtils; +import org.netbeans.modules.project.uiapi.DefaultProjectOperationsImplementation.InvalidablePanel; +import org.openide.filesystems.FileUtil; +import org.openide.util.NbBundle; + +/** + * + * @author lahvac + */ +public class DefaultProjectRenamePanel extends javax.swing.JPanel implements DocumentListener, InvalidablePanel { + + private Project project; + private List listeners; + + /** + * Creates new form DefaultProjectRenamePanel + */ + public DefaultProjectRenamePanel(Project project, String name) { + this.project = project; + + if (name == null) { + name = ProjectUtils.getInformation(project).getDisplayName(); + } + + this.listeners = new ArrayList(); + + initComponents(); + + projectName.setText(name); + projectName.getDocument().addDocumentListener(this); + updateProjectFolder(); + validateDialog(); + } + + public synchronized void addChangeListener(ChangeListener l) { + listeners.add(l); + } + + public synchronized void removeChangeListener(ChangeListener l) { + listeners.remove(l); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; + + jLabel1 = new javax.swing.JLabel(); + projectFolderLabel = new javax.swing.JLabel(); + projectName = new javax.swing.JTextField(); + projectFolder = new javax.swing.JTextField(); + alsoRenameFolder = new javax.swing.JCheckBox(); + jLabel3 = new javax.swing.JLabel(); + errorMessage = new javax.swing.JLabel(); + + setLayout(new java.awt.GridBagLayout()); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + add(jLabel1, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 3; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + add(projectFolderLabel, gridBagConstraints); + + projectName.setColumns(20); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + add(projectName, gridBagConstraints); + + projectFolder.setEditable(false); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 3; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + add(projectFolder, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(alsoRenameFolder, org.openide.util.NbBundle.getMessage(DefaultProjectRenamePanel.class, "LBL_Also_Rename_Project_Folder")); + alsoRenameFolder.setBorder(new javax.swing.border.EmptyBorder(new java.awt.Insets(0, 0, 0, 0))); + alsoRenameFolder.setMargin(new java.awt.Insets(0, 0, 0, 0)); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 2; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + add(alsoRenameFolder, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel3, NbBundle.getMessage(DefaultProjectRenamePanel.class, "LBL_Rename_Dialog_Text", ProjectUtils.getInformation(project).getDisplayName())); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridwidth = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + add(jLabel3, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 4; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + add(errorMessage, gridBagConstraints); + + } + // //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBox alsoRenameFolder; + private javax.swing.JLabel errorMessage; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel3; + private javax.swing.JTextField projectFolder; + private javax.swing.JLabel projectFolderLabel; + private javax.swing.JTextField projectName; + // End of variables declaration//GEN-END:variables + + public String getNewName() { + return projectName.getText(); + } + + public void changedUpdate(DocumentEvent e) { + //ignored + } + + public void insertUpdate(DocumentEvent e) { + updateProjectFolder(); + validateDialog(); + } + + public void removeUpdate(DocumentEvent e) { + updateProjectFolder(); + validateDialog(); + } + + private void updateProjectFolder() { + File location = FileUtil.toFile(project.getProjectDirectory().getParent()); + File projectFolderFile = new File(location, projectName.getText()); + + projectFolder.setText(projectFolderFile.getAbsolutePath()); + } + + public boolean isValid() { + return " ".equals(errorMessage.getText()); + } + + private void validateDialog() { + String newError = computeError(); + boolean changed = false; + String currentError = errorMessage.getText(); + + newError = newError != null ? newError : " "; + changed = !currentError.equals(newError); + + errorMessage.setText(newError); + + if (changed) { + ChangeListener[] listenersCopy; + + synchronized (this) { + listenersCopy = (ChangeListener[] ) listeners.toArray(new ChangeListener[0]); + } + ChangeEvent evt = new ChangeEvent(this); + + for (int cntr = 0; cntr < listenersCopy.length; cntr++) { + listenersCopy[cntr].stateChanged(evt); + } + } + } + + private String computeError() { + File location = FileUtil.toFile(project.getProjectDirectory().getParent()); + File projectFolderFile = new File(location, projectName.getText()); + + if (projectFolderFile.exists()) { + return NbBundle.getMessage(ProjectCopyPanel.class, "ERR_Project_Folder_Exists"); + } + + return null; + } + + public void showProgress() { + } + +} Index: projects/projectuiapi/src/org/netbeans/modules/project/uiapi/ProjectCopyPanel.form =================================================================== RCS file: projects/projectuiapi/src/org/netbeans/modules/project/uiapi/ProjectCopyPanel.form diff -N projects/projectuiapi/src/org/netbeans/modules/project/uiapi/ProjectCopyPanel.form --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ projects/projectuiapi/src/org/netbeans/modules/project/uiapi/ProjectCopyPanel.form 29 Jul 2005 14:58:15 -0000 @@ -0,0 +1,162 @@ + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: projects/projectuiapi/src/org/netbeans/modules/project/uiapi/ProjectCopyPanel.java =================================================================== RCS file: projects/projectuiapi/src/org/netbeans/modules/project/uiapi/ProjectCopyPanel.java diff -N projects/projectuiapi/src/org/netbeans/modules/project/uiapi/ProjectCopyPanel.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ projects/projectuiapi/src/org/netbeans/modules/project/uiapi/ProjectCopyPanel.java 29 Jul 2005 14:58:15 -0000 @@ -0,0 +1,360 @@ +/* + * J2SEProjectCopyTemporaryPanel.java + * + * Created on June 13, 2005, 4:43 PM + */ + +package org.netbeans.modules.project.uiapi; + +import java.io.File; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import javax.swing.JFileChooser; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.DocumentListener; +import javax.swing.event.DocumentEvent; +import org.netbeans.api.progress.ProgressHandle; +import org.netbeans.api.progress.ProgressHandleFactory; +import org.netbeans.api.project.Project; +import org.netbeans.spi.project.support.ProjectOperations; +import org.netbeans.api.project.ProjectUtils; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.util.NbBundle; + +/** + * + * @author Jan Lahoda + */ +public class ProjectCopyPanel extends javax.swing.JPanel implements DocumentListener, DefaultProjectOperationsImplementation.InvalidablePanel { + + private Project project; + private boolean isMove; + + private List listeners; + private ProgressHandle handle; + + /** + * Creates new form ProjectCopyPanel + */ + public ProjectCopyPanel(ProgressHandle handle, Project project, boolean isMove) { + this.project = project; + this.isMove = isMove; + this.listeners = new ArrayList(); + this.handle = handle; + + + initComponents(); + setProject(); + projectName.getDocument().addDocumentListener(this); + projectLocation.getDocument().addDocumentListener(this); + + progress.setVisible(false); + + if (isMove) { + nameLabel.setVisible(false); + projectName.setVisible(false); + } + } + + public synchronized void addChangeListener(ChangeListener l) { + listeners.add(l); + } + + public synchronized void removeChangeListener(ChangeListener l) { + listeners.remove(l); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; + + jLabel1 = new javax.swing.JLabel(); + jLabel2 = new javax.swing.JLabel(); + projectLocation = new javax.swing.JTextField(); + nameLabel = new javax.swing.JLabel(); + projectName = new javax.swing.JTextField(); + browse = new javax.swing.JButton(); + jLabel4 = new javax.swing.JLabel(); + projectFolder = new javax.swing.JTextField(); + extSourcesWarning = new javax.swing.JLabel(); + errorMessage = new javax.swing.JLabel(); + jPanel1 = new javax.swing.JPanel(); + progress = new javax.swing.JPanel(); + jLabel5 = new javax.swing.JLabel(); + jPanel3 = new javax.swing.JPanel(); + + setLayout(new java.awt.GridBagLayout()); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, NbBundle.getMessage(ProjectCopyPanel.class, "LBL_Copy_Move_Dialog_Text", new Integer(isMove ? 1 : 0), ProjectUtils.getInformation(project).getDisplayName())); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridwidth = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + add(jLabel1, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(ProjectCopyPanel.class, "LBL_Project_Location")); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(12, 0, 0, 12); + add(jLabel2, gridBagConstraints); + + projectLocation.setColumns(20); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(12, 0, 0, 12); + add(projectLocation, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(nameLabel, org.openide.util.NbBundle.getMessage(ProjectCopyPanel.class, "LBL_Project_Name")); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(12, 0, 0, 12); + add(nameLabel, gridBagConstraints); + + projectName.setColumns(20); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(12, 0, 0, 12); + add(projectName, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(browse, "..."); + browse.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + browseActionPerformed(evt); + } + }); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 2; + gridBagConstraints.insets = new java.awt.Insets(12, 0, 0, 0); + add(browse, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(ProjectCopyPanel.class, "LBL_Project_Folder")); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 3; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(12, 0, 0, 12); + add(jLabel4, gridBagConstraints); + + projectFolder.setEditable(false); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 3; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.insets = new java.awt.Insets(12, 0, 0, 12); + add(projectFolder, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 4; + gridBagConstraints.gridwidth = 3; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(12, 0, 0, 12); + add(extSourcesWarning, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 5; + gridBagConstraints.gridwidth = 3; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(12, 0, 0, 12); + add(errorMessage, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 6; + gridBagConstraints.gridwidth = 3; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + add(jPanel1, gridBagConstraints); + + progress.setLayout(new java.awt.GridBagLayout()); + + org.openide.awt.Mnemonics.setLocalizedText(jLabel5, "Copying the project:"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + progress.add(jLabel5, gridBagConstraints); + + jPanel3.add(ProgressHandleFactory.createProgressComponent(handle)); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + progress.add(jPanel3, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 7; + gridBagConstraints.gridwidth = 3; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + add(progress, gridBagConstraints); + + } + // //GEN-END:initComponents + + private void browseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseActionPerformed +// TODO add your handling code here: + File current = new File(projectFolder.getText()); + JFileChooser chooser = new JFileChooser(current); + + chooser.setMultiSelectionEnabled(false); + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + + if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { + projectLocation.setText(chooser.getSelectedFile().getAbsolutePath()); + } + }//GEN-LAST:event_browseActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton browse; + private javax.swing.JLabel errorMessage; + private javax.swing.JLabel extSourcesWarning; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel4; + private javax.swing.JLabel jLabel5; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel3; + private javax.swing.JLabel nameLabel; + private javax.swing.JPanel progress; + private javax.swing.JTextField projectFolder; + private javax.swing.JTextField projectLocation; + private javax.swing.JTextField projectName; + // End of variables declaration//GEN-END:variables + + private void setProject() { + FileObject parent = project.getProjectDirectory().getParent(); + File parentFile = FileUtil.toFile(parent); + + projectLocation.setText(parentFile.getAbsolutePath()); + projectName.setText(isMove ? project.getProjectDirectory().getNameExt() : project.getProjectDirectory().getNameExt() + "Copy"); + updateProjectFolder(); + validateDialog(); + + if (hasExternalSources() && !isMove) { + extSourcesWarning.setText(NbBundle.getMessage(ProjectCopyPanel.class, "WRN_External_Sources")); + } + } + + private boolean hasExternalSources() { + List/**/ files = ProjectOperations.getDataFiles(project); + + for (Iterator i = files.iterator(); i.hasNext(); ) { + FileObject file = (FileObject) i.next(); + + if (!FileUtil.isParentOf(project.getProjectDirectory(), file)) + return true; + } + + return false; + } + + public String getNewName() { + return projectName.getText(); + } + + public File getNewDirectory() { + return new File(projectLocation.getText()); + } + + public void changedUpdate(DocumentEvent e) { + //ignored + } + + public void insertUpdate(DocumentEvent e) { + updateProjectFolder(); + validateDialog(); + } + + public void removeUpdate(DocumentEvent e) { + updateProjectFolder(); + validateDialog(); + } + + private void updateProjectFolder() { + File location = new File(projectLocation.getText()); + File projectFolderFile = new File(location, projectName.getText()); + + projectFolder.setText(projectFolderFile.getAbsolutePath()); + } + + public boolean isValid() { + return " ".equals(errorMessage.getText()); + } + + private void validateDialog() { + String newError = computeError(); + boolean changed = false; + String currentError = errorMessage.getText(); + + newError = newError != null ? newError : " "; + changed = !currentError.equals(newError); + + errorMessage.setText(newError); + + if (changed) { + ChangeListener[] listenersCopy; + + synchronized (this) { + listenersCopy = (ChangeListener[] ) listeners.toArray(new ChangeListener[0]); + } + ChangeEvent evt = new ChangeEvent(this); + + for (int cntr = 0; cntr < listenersCopy.length; cntr++) { + listenersCopy[cntr].stateChanged(evt); + } + } + } + + private String computeError() { + File location = new File(projectLocation.getText()); + + System.err.println("location = " + location ); + if (!location.exists()) { + return NbBundle.getMessage(ProjectCopyPanel.class, "ERR_Location_Does_Not_Exist"); + } + + File projectFolderFile = new File(location, projectName.getText()); + + System.err.println("projectFolderFile = " + projectFolderFile ); + System.err.println("projectFolderFile.exists()=" + projectFolderFile.exists()); + if (projectFolderFile.exists()) { + return NbBundle.getMessage(ProjectCopyPanel.class, "ERR_Project_Folder_Exists"); + } + + return null; + } + + public void showProgress() { + projectFolder.setEnabled(false); + projectLocation.setEnabled(false); + projectName.setEnabled(false); + progress.setVisible(true); + browse.setEnabled(false); + } +} Index: projects/projectuiapi/src/org/netbeans/spi/project/ui/support/CommonProjectActions.java =================================================================== RCS file: /cvs/projects/projectuiapi/src/org/netbeans/spi/project/ui/support/CommonProjectActions.java,v retrieving revision 1.12 diff -u -r1.12 CommonProjectActions.java --- projects/projectuiapi/src/org/netbeans/spi/project/ui/support/CommonProjectActions.java 14 Jul 2005 20:32:53 -0000 1.12 +++ projects/projectuiapi/src/org/netbeans/spi/project/ui/support/CommonProjectActions.java 29 Jul 2005 14:58:16 -0000 @@ -113,6 +113,48 @@ } /** + * Create an action "Copy Project". + * It should be invoked with an action context containing + * one or more {@link org.netbeans.api.project.Project}s. + *

    + * You might include this in the context menu of a logical view. + *

    + * @since 1.10 + * @return an action + */ + public static Action copyProjectAction() { + return Utilities.getActionsFactory().copyProjectAction(); + } + + /** + * Create an action "Move Project". + * It should be invoked with an action context containing + * one or more {@link org.netbeans.api.project.Project}s. + *

    + * You might include this in the context menu of a logical view. + *

    + * @since 1.10 + * @return an action + */ + public static Action moveProjectAction() { + return Utilities.getActionsFactory().moveProjectAction(); + } + + /** + * Create an action "Rename Project". + * It should be invoked with an action context containing + * one or more {@link org.netbeans.api.project.Project}s. + *

    + * You might include this in the context menu of a logical view. + *

    + * @since 1.10 + * @return an action + */ + public static Action renameProjectAction() { + return Utilities.getActionsFactory().renameProjectAction(); + } + + /** * Creates action that invokes New Project wizard. * *

    {@link #EXISTING_SOURCES_FOLDER} keyed action Index: projects/projectuiapi/src/org/netbeans/spi/project/ui/support/DefaultProjectOperations.java =================================================================== RCS file: projects/projectuiapi/src/org/netbeans/spi/project/ui/support/DefaultProjectOperations.java diff -N projects/projectuiapi/src/org/netbeans/spi/project/ui/support/DefaultProjectOperations.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ projects/projectuiapi/src/org/netbeans/spi/project/ui/support/DefaultProjectOperations.java 29 Jul 2005 14:58:16 -0000 @@ -0,0 +1,130 @@ +/* + * 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-2005 Sun + * Microsystems, Inc. All Rights Reserved. + */ +package org.netbeans.spi.project.ui.support; + +import org.netbeans.api.project.Project; +import org.netbeans.spi.project.support.ProjectOperations; +import org.netbeans.modules.project.uiapi.DefaultProjectOperationsImplementation; + +/**Support class to allow the project type implementors to perform {@link ProjectOperations} + * by simply calling a method in this class. Each method in this class provides a default + * confirmation dialog and default behavior. + * + * If the project type requires a different behavior of an operation, it is required to provide its + * own implementation of the operation. + * + * @since 1.10 + * @author Jan Lahoda + */ +public final class DefaultProjectOperations { + + /** + * Creates a new instance of DefaultProjectOperations + */ + private DefaultProjectOperations() { + } + + /**Perform default delete operation. Gathers all necessary data, shows a confirmation + * dialog and deletes the project (if confirmed by the user). + * + * @since 1.10 + * + * @param p project to delete + * @throws IllegalArgumentException if + * p == null or + * if {@link org.netbeans.api.projects.ProjectOperations.isDeleteOperationSupported} + * returns false for this project. + */ + public static void performDefaultDeleteOperation(Project p) throws IllegalArgumentException { + if (p == null) { + throw new IllegalArgumentException("Project is null"); + } + + if (!ProjectOperations.isDeleteOperationSupported(p)) { + throw new IllegalStateException("Attempt to delete project that does not support deletion."); + } + + DefaultProjectOperationsImplementation.deleteProject(p); + } + + /**Perform default copy operation. Gathers all necessary data, shows a confirmation + * dialog and copies the project (if confirmed by the user). + * + * @since 1.10 + * + * @param p project to copy + * @throws IllegalArgumentException if + * p == null or + * {@link org.netbeans.api.projects.ProjectOperations.isCopyOperationSupported} + * returns false for this project. + */ + public static void performDefaultCopyOperation(Project p) throws IllegalArgumentException { + if (p == null) { + throw new IllegalArgumentException("Project is null"); + } + + if (!ProjectOperations.isCopyOperationSupported(p)) { + throw new IllegalStateException("Attempt to delete project that does not support copy."); + } + + DefaultProjectOperationsImplementation.copyProject(p); + } + + /**Perform default move operation. Gathers all necessary data, shows a confirmation + * dialog and moves the project (if confirmed by the user). + * + * @since 1.10 + * + * @param p project to move + * @throws IllegalArgumentException if + * p == null or + * {@link org.netbeans.api.projects.ProjectOperations.ismoveOperationSupported} + * returns false for this project. + */ + public static void performDefaultMoveOperation(Project p) throws IllegalArgumentException { + if (p == null) { + throw new IllegalArgumentException("Project is null"); + } + + if (!ProjectOperations.isMoveOperationSupported(p)) { + throw new IllegalStateException("Attempt to delete project that does not support move."); + } + + DefaultProjectOperationsImplementation.moveProject(p); + } + + /**Perform default rename operation. Gathers all necessary data, shows a confirmation + * dialog and renames the project (if confirmed by the user). + * + * @since 1.10 + * + * @param p project to move + * @param newName new project's name or null + * @throws IllegalArgumentException if + * p == null or + * {@link org.netbeans.api.projects.ProjectOperations.ismoveOperationSupported} + * returns false for this project. + */ + public static void performDefaultRenameOperation(Project p, String newName) throws IllegalStateException { + if (p == null) { + throw new IllegalArgumentException("Project is null"); + } + + if (!ProjectOperations.isMoveOperationSupported(p)) { + throw new IllegalStateException("Attempt to delete project that does not support move."); + } + + DefaultProjectOperationsImplementation.renameProject(p, newName); + } + +} Index: ant/freeform/src/org/netbeans/modules/ant/freeform/Actions.java =================================================================== RCS file: /cvs/ant/freeform/src/org/netbeans/modules/ant/freeform/Actions.java,v retrieving revision 1.15 diff -u -r1.15 Actions.java --- ant/freeform/src/org/netbeans/modules/ant/freeform/Actions.java 11 Jul 2005 12:18:01 -0000 1.15 +++ ant/freeform/src/org/netbeans/modules/ant/freeform/Actions.java 29 Jul 2005 14:58:16 -0000 @@ -40,6 +40,7 @@ import org.netbeans.spi.project.ActionProvider; import org.netbeans.spi.project.support.ant.AntProjectHelper; import org.netbeans.spi.project.ui.support.CommonProjectActions; +import org.netbeans.spi.project.ui.support.DefaultProjectOperations; import org.netbeans.spi.project.ui.support.ProjectSensitiveActions; import org.openide.DialogDisplayer; import org.openide.ErrorManager; @@ -173,7 +174,7 @@ public void invokeAction(String command, Lookup context) throws IllegalArgumentException { if (COMMAND_DELETE.equals(command)) { - project.helper().performDefaultDeleteOperation(); + DefaultProjectOperations.performDefaultDeleteOperation(project); return ; } Element genldata = project.helper().getPrimaryConfigurationData(true); Index: ant/freeform/src/org/netbeans/modules/ant/freeform/FreeformProjectOperations.java =================================================================== RCS file: /cvs/ant/freeform/src/org/netbeans/modules/ant/freeform/FreeformProjectOperations.java,v retrieving revision 1.1 diff -u -r1.1 FreeformProjectOperations.java --- ant/freeform/src/org/netbeans/modules/ant/freeform/FreeformProjectOperations.java 11 Jul 2005 12:18:02 -0000 1.1 +++ ant/freeform/src/org/netbeans/modules/ant/freeform/FreeformProjectOperations.java 29 Jul 2005 14:58:16 -0000 @@ -16,11 +16,10 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; -import java.util.Collections; import java.util.Iterator; import java.util.List; import org.netbeans.modules.ant.freeform.spi.support.Util; -import org.netbeans.spi.project.ProjectOperationsImplementation.DeleteOperationImplementation; +import org.netbeans.spi.project.DeleteOperationImplementation; import org.netbeans.spi.project.support.ant.PropertyEvaluator; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; @@ -101,7 +100,7 @@ } } - public void performClean() throws IOException { + public void notifyDeleting() throws IOException { //TODO: invoke clean action if bound. } Index: ant/project/apichanges.xml =================================================================== RCS file: /cvs/ant/project/apichanges.xml,v retrieving revision 1.7 diff -u -r1.7 apichanges.xml --- ant/project/apichanges.xml 11 Jul 2005 12:18:02 -0000 1.7 +++ ant/project/apichanges.xml 29 Jul 2005 14:58:17 -0000 @@ -78,14 +78,13 @@ -

    Basic Support SPI for Project Delete - + Basic Support SPI for Project Delete/Copy/Rename/Move + - AntProjectHelper.notifyDeleted() and AntProjectHelper.performDefaultDeleteOperation() - added. + Added AntProjectHelper.notifyDeleted(). Added ReferenceHelper.fixReferences.
    Index: ant/project/manifest.mf =================================================================== RCS file: /cvs/ant/project/manifest.mf,v retrieving revision 1.11 diff -u -r1.11 manifest.mf --- ant/project/manifest.mf 11 Jul 2005 12:18:02 -0000 1.11 +++ ant/project/manifest.mf 29 Jul 2005 14:58:17 -0000 @@ -1,5 +1,5 @@ Manifest-Version: 1.0 OpenIDE-Module: org.netbeans.modules.project.ant/1 -OpenIDE-Module-Specification-Version: 1.8 +OpenIDE-Module-Specification-Version: 1.9 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/project/ant/Bundle.properties Index: ant/project/src/org/netbeans/modules/project/ant/AntBasedProjectFactorySingleton.java =================================================================== RCS file: /cvs/ant/project/src/org/netbeans/modules/project/ant/AntBasedProjectFactorySingleton.java,v retrieving revision 1.9 diff -u -r1.9 AntBasedProjectFactorySingleton.java --- ant/project/src/org/netbeans/modules/project/ant/AntBasedProjectFactorySingleton.java 13 Jul 2005 21:53:40 -0000 1.9 +++ ant/project/src/org/netbeans/modules/project/ant/AntBasedProjectFactorySingleton.java 29 Jul 2005 14:58:17 -0000 @@ -138,7 +138,7 @@ return null; } File projectDiskFile = FileUtil.toFile(projectFile); - assert projectDiskFile != null && projectDiskFile.exists(); + assert projectDiskFile != null && projectDiskFile.exists() : "projectDiskFile=" + String.valueOf(projectDiskFile) + ", projectDirectory=" + FileUtil.getFileDisplayName(projectDirectory); Document projectXml; try { projectXml = XMLUtil.parse(new InputSource(projectDiskFile.toURI().toString()), false, true, Util.defaultErrorHandler(), null); Index: ant/project/src/org/netbeans/modules/project/ant/Bundle.properties =================================================================== RCS file: /cvs/ant/project/src/org/netbeans/modules/project/ant/Bundle.properties,v retrieving revision 1.5 diff -u -r1.5 Bundle.properties --- ant/project/src/org/netbeans/modules/project/ant/Bundle.properties 11 Jul 2005 12:18:04 -0000 1.5 +++ ant/project/src/org/netbeans/modules/project/ant/Bundle.properties 29 Jul 2005 14:58:17 -0000 @@ -18,16 +18,3 @@ # UserQuestionHandler TITLE_CannotWriteFile=Cannot Write to File - -#DefaultAntProjectOperations: -LBL_Progress_Cleaning_Project=Cleaning Project -LBL_Progress_Deleting_File=Deleting {0} -LBL_Project_cannot_be_deleted.=Project {0} cannot be deleted. -LBL_Delete_Project_Caption=Delete Project -LBL_Deleting_Project=Deleting Project\: -#currently not used: -#LBL_Project_Deletion_in_Progress_Caption=Project Deletion in Progress - -#DefaultAntProjectDeletePanel: -LBL_Pre_Delete_Warning=Are you sure you want to delete project "{0}"? -LBL_Delete_Also_Sources=&Also Delete Sources Under "{0}" folder. Index: ant/project/src/org/netbeans/modules/project/ant/DefaultAntProjectDeletePanel.form =================================================================== RCS file: ant/project/src/org/netbeans/modules/project/ant/DefaultAntProjectDeletePanel.form diff -N ant/project/src/org/netbeans/modules/project/ant/DefaultAntProjectDeletePanel.form --- ant/project/src/org/netbeans/modules/project/ant/DefaultAntProjectDeletePanel.form 11 Jul 2005 12:18:04 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,50 +0,0 @@ - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Index: ant/project/src/org/netbeans/modules/project/ant/DefaultAntProjectDeletePanel.java =================================================================== RCS file: ant/project/src/org/netbeans/modules/project/ant/DefaultAntProjectDeletePanel.java diff -N ant/project/src/org/netbeans/modules/project/ant/DefaultAntProjectDeletePanel.java --- ant/project/src/org/netbeans/modules/project/ant/DefaultAntProjectDeletePanel.java 11 Jul 2005 12:18:04 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,101 +0,0 @@ -/* - * 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-2005 Sun - * Microsystems, Inc. All Rights Reserved. - */ - -package org.netbeans.modules.project.ant; - -import java.awt.Component; -import java.awt.Window; -import java.text.MessageFormat; -import java.util.Iterator; -import java.util.List; -import org.openide.filesystems.FileObject; -import org.openide.filesystems.FileUtil; -import org.openide.util.NbBundle; - -/** - * - * @author Jan Lahoda - */ -final class DefaultAntProjectDeletePanel extends javax.swing.JPanel { - - private String projectDisplaName; - private String projectFolder; - private boolean enableCheckbox; - - /** - * Creates new form DefaultAntProjectDeletePanel - */ - public DefaultAntProjectDeletePanel(String projectDisplaName, String projectFolder, boolean enableCheckbox) { - this.projectDisplaName = projectDisplaName; - this.projectFolder = projectFolder; - this.enableCheckbox = enableCheckbox; - initComponents(); - } - - /** This method is called from within the constructor to - * initialize the form. - * WARNING: Do NOT modify this code. The content of this method is - * always regenerated by the Form Editor. - */ - // //GEN-BEGIN:initComponents - private void initComponents() { - java.awt.GridBagConstraints gridBagConstraints; - - warningText = new javax.swing.JTextArea(); - deleteSourcesCheckBox = new javax.swing.JCheckBox(); - - setLayout(new java.awt.GridBagLayout()); - - warningText.setEditable(false); - warningText.setFont(javax.swing.UIManager.getFont("Label.font")); - warningText.setText(getWarningText()); - warningText.setDisabledTextColor(javax.swing.UIManager.getColor("Label.foreground")); - warningText.setOpaque(false); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new java.awt.Insets(12, 12, 0, 12); - add(warningText, gridBagConstraints); - - org.openide.awt.Mnemonics.setLocalizedText(deleteSourcesCheckBox, getCheckboxText()); - deleteSourcesCheckBox.setEnabled(enableCheckbox); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 3; - gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; - gridBagConstraints.insets = new java.awt.Insets(12, 12, 0, 12); - add(deleteSourcesCheckBox, gridBagConstraints); - - } - // //GEN-END:initComponents - - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JCheckBox deleteSourcesCheckBox; - private javax.swing.JTextArea warningText; - // End of variables declaration//GEN-END:variables - - public boolean isDeleteSources() { - return deleteSourcesCheckBox.isSelected(); - } - - private String getWarningText() { - return NbBundle.getMessage(DefaultAntProjectDeletePanel.class, "LBL_Pre_Delete_Warning", new Object[] {projectDisplaName}); - } - - private String getCheckboxText() { - return NbBundle.getMessage(DefaultAntProjectDeletePanel.class, "LBL_Delete_Also_Sources", new Object[] {projectFolder}); - } - -} Index: ant/project/src/org/netbeans/modules/project/ant/DefaultAntProjectOperations.java =================================================================== RCS file: ant/project/src/org/netbeans/modules/project/ant/DefaultAntProjectOperations.java diff -N ant/project/src/org/netbeans/modules/project/ant/DefaultAntProjectOperations.java --- ant/project/src/org/netbeans/modules/project/ant/DefaultAntProjectOperations.java 11 Jul 2005 12:18:04 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,283 +0,0 @@ -/* - * 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-2005 Sun - * Microsystems, Inc. All Rights Reserved. - */ - -package org.netbeans.modules.project.ant; - -import java.awt.Dialog; -import java.awt.GridBagConstraints; -import java.awt.Insets; -import java.io.IOException; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.SwingUtilities; -import org.netbeans.api.progress.ProgressHandle; -import org.netbeans.api.progress.ProgressHandleFactory; -import org.netbeans.api.project.Project; -import org.netbeans.api.project.ProjectUtils; -import org.netbeans.api.project.ui.OpenProjects; -import org.netbeans.api.project.ProjectOperations; -import org.netbeans.spi.project.support.ant.AntProjectHelper; -import org.openide.DialogDescriptor; -import org.openide.DialogDisplayer; -import org.openide.ErrorManager; -import org.openide.NotifyDescriptor; -import org.openide.filesystems.FileObject; -import org.openide.filesystems.FileUtil; -import org.openide.util.HelpCtx; -import org.openide.util.NbBundle; -import org.openide.util.RequestProcessor; - - -/** - * - * @author Jan Lahoda - */ -public final class DefaultAntProjectOperations { - - private static final ErrorManager ERR = ErrorManager.getDefault(); // NOI18N - - private DefaultAntProjectOperations() { - } - - private static String getDisplayName(Project project) { - return ProjectUtils.getInformation(project).getDisplayName(); - } - - // - /** - * @return true if success - */ - private static boolean performDelete(AntProjectHelper helper, Project project, List/*FileObject>*/ toDelete, ProgressHandle handle) { - try { - handle.start(toDelete.size() + 1 /*clean*/); - - int done = 0; - - handle.progress(NbBundle.getMessage(DefaultAntProjectOperations.class, "LBL_Progress_Cleaning_Project")); - - ProjectOperations.getDefault().performClean(project); - - handle.progress(++done); - - for (Iterator i = toDelete.iterator(); i.hasNext(); ) { - FileObject f = (FileObject) i.next(); - - handle.progress(NbBundle.getMessage(DefaultAntProjectOperations.class, "LBL_Progress_Deleting_File", new Object[] {FileUtil.getFileDisplayName(f)})); - - if (f != null) - f.delete(); - - handle.progress(++done); - } - - FileObject projectFolder = project.getProjectDirectory(); - - if (projectFolder.getChildren().length == 0) { - //empty, delete: - projectFolder.delete(); - } - - handle.finish(); - - ProjectOperations.getDefault().notifyDeleted(project); - return true; - } catch (IOException e) { - String displayName = getDisplayName(project); - String message = NbBundle.getMessage(DefaultAntProjectOperations.class, "LBL_Project_cannot_be_deleted.", new Object[] {displayName}); - - ErrorManager.getDefault().annotate(e, message); - ErrorManager.getDefault().notify(ErrorManager.USER, e); - - return false; - } - } - - public static void deleteProject(final Project project) { - Runnable r = new Runnable() { - public void run() { - deleteProject(project, new GUIUserInputHandler()); - } - }; - - if (SwingUtilities.isEventDispatchThread()) { - r.run(); - } else { - SwingUtilities.invokeLater(r); - } - } - - /*package private*/static void deleteProject(final Project project, final UserInputHandler handler) { - String displayName = getDisplayName(project); - FileObject projectFolder = project.getProjectDirectory(); - - final AntProjectHelper helper = AntBasedProjectFactorySingleton.getHelperFor(project); - - assert helper != null; - - if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) { - ERR.log(ErrorManager.INFORMATIONAL, "delete started: " + displayName); // NOI18N - } - - List/**/ metadataFiles = ProjectOperations.getDefault().getMetadataFiles(project); - List/**/ dataFiles = ProjectOperations.getDefault().getDataFiles(project); - List/**/ allFiles = new ArrayList/**/(); - - allFiles.addAll(metadataFiles); - allFiles.addAll(dataFiles); - - for (Iterator i = allFiles.iterator(); i.hasNext(); ) { - FileObject f = (FileObject) i.next(); - - if (!FileUtil.isParentOf(projectFolder, f)) { - i.remove(); - } - } - - int userAnswer = handler.userConfirmation(displayName, FileUtil.getFileDisplayName(projectFolder), !dataFiles.isEmpty()); - List/**/ toDeleteImpl = null; - - switch (userAnswer) { - case UserInputHandler.USER_CANCEL: - return ; - case UserInputHandler.USER_OK_METADATA: - toDeleteImpl = metadataFiles; - break; - case UserInputHandler.USER_OK_ALL: - toDeleteImpl = allFiles; - break; - default: - throw new IllegalStateException("Invalid user answer: " + userAnswer); - } - - final ProgressHandle handle = handler.getProgressHandle(); - final List/**/ toDelete = toDeleteImpl; - final boolean[] result = new boolean[1]; - - OpenProjects.getDefault().close(new Project[] {project}); - - handler.delete(new Runnable() { - public void run() { - result[0] = performDelete(helper, project, toDelete, handle); - } - }); - - if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) { - ERR.log(ErrorManager.INFORMATIONAL, "delete done: " + displayName); // NOI18N - } - } - - /*package private*/interface UserInputHandler { - - public int USER_CANCEL = 1; - public int USER_OK_METADATA = 2; - public int USER_OK_ALL = 3; - - public abstract int userConfirmation(String displayName, String projectFolder, boolean enableData); - - public abstract ProgressHandle getProgressHandle(); - - public abstract void delete(Runnable r); - - } - - private static final class GUIUserInputHandler implements UserInputHandler { - - public int userConfirmation(String displayName, String projectFolder, boolean enableData) { - DefaultAntProjectDeletePanel deletePanel = new DefaultAntProjectDeletePanel(displayName, projectFolder, enableData); - - String caption = NbBundle.getMessage(DefaultAntProjectOperations.class, "LBL_Delete_Project_Caption"); - - NotifyDescriptor nd = new NotifyDescriptor.Confirmation(deletePanel, caption, NotifyDescriptor.YES_NO_OPTION); - - if (DialogDisplayer.getDefault().notify(nd) == NotifyDescriptor.YES_OPTION) { - if (deletePanel.isDeleteSources()) { - return USER_OK_ALL; - } else { - return USER_OK_METADATA; - } - } else { - return USER_CANCEL; - } - } - - private ProgressHandle handle = null; - - public synchronized ProgressHandle getProgressHandle() { - if (handle == null) { - handle = ProgressHandleFactory.createHandle(NbBundle.getMessage(DefaultAntProjectOperations.class, "LBL_Delete_Project_Caption")); - } - - return handle; - } - - public void delete(final Runnable r) { - RequestProcessor.getDefault().post(new Runnable() { - public void run() { - r.run(); - - if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) { - ERR.log(ErrorManager.INFORMATIONAL, "delete finished"); // NOI18N - } - } - }); - } - - } - - private static JComponent createProgressDialog(ProgressHandle handle) { - JPanel dialog = new JPanel(); - - GridBagConstraints gridBagConstraints; - - JLabel jLabel1 = new JLabel(); - JComponent progress = ProgressHandleFactory.createProgressComponent(handle); - JPanel padding = new JPanel(); - - dialog.setLayout(new java.awt.GridBagLayout()); - - jLabel1.setText(NbBundle.getMessage(DefaultAntProjectOperations.class, "LBL_Deleting_Project")); - gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new Insets(12, 12, 0, 12); - dialog.add(jLabel1, gridBagConstraints); - - gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; - gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.insets = new Insets(12, 12, 0, 12); - dialog.add(progress, gridBagConstraints); - - gridBagConstraints = new GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 2; - gridBagConstraints.fill = GridBagConstraints.HORIZONTAL | GridBagConstraints.VERTICAL; - gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - gridBagConstraints.insets = new Insets(12, 12, 12, 12); - dialog.add(padding, gridBagConstraints); - - return dialog; - } - // - -} Index: ant/project/src/org/netbeans/spi/project/support/ant/AntProjectHelper.java =================================================================== RCS file: /cvs/ant/project/src/org/netbeans/spi/project/support/ant/AntProjectHelper.java,v retrieving revision 1.31 diff -u -r1.31 AntProjectHelper.java --- ant/project/src/org/netbeans/spi/project/support/ant/AntProjectHelper.java 11 Jul 2005 12:18:05 -0000 1.31 +++ ant/project/src/org/netbeans/spi/project/support/ant/AntProjectHelper.java 29 Jul 2005 14:58:18 -0000 @@ -29,7 +29,6 @@ import org.netbeans.api.project.ProjectManager; import org.netbeans.api.project.ant.AntArtifact; import org.netbeans.modules.project.ant.AntBasedProjectFactorySingleton; -import org.netbeans.modules.project.ant.DefaultAntProjectOperations; import org.netbeans.modules.project.ant.FileChangeSupport; import org.netbeans.modules.project.ant.FileChangeSupportEvent; import org.netbeans.modules.project.ant.FileChangeSupportListener; @@ -38,7 +37,7 @@ import org.netbeans.spi.project.AuxiliaryConfiguration; import org.netbeans.spi.project.CacheDirectoryProvider; import org.netbeans.spi.project.ProjectState; -import org.netbeans.api.project.ProjectOperations; +import org.netbeans.spi.project.support.ProjectOperations; import org.netbeans.spi.queries.FileBuiltQueryImplementation; import org.netbeans.spi.queries.SharabilityQueryImplementation; import org.openide.ErrorManager; @@ -482,26 +481,6 @@ state.notifyDeleted(); } - /**Perform default delete operation. Gathers all necessary data, shows a confirmation - * dialog and deletes the project (if confirmed by the user). - * - * @since 1.8 - * - * @throws IllegalStateException if - * {@link org.netbeans.api.projects.ProjectOperations.getDefault().isDeleteOperationSupported} - * returns false for this project. - */ - public void performDefaultDeleteOperation() throws IllegalStateException { - Project p = AntBasedProjectFactorySingleton.getProjectFor(this); - - assert p != null; - - if (!ProjectOperations.getDefault().isDeleteOperationSupported(p)) { - throw new IllegalStateException("Attempt to delete project that does not support deletion."); - } - - DefaultAntProjectOperations.deleteProject(p); - } /** * Mark this project as being modified without actually changing anything in it. Index: ant/project/src/org/netbeans/spi/project/support/ant/ReferenceHelper.java =================================================================== RCS file: /cvs/ant/project/src/org/netbeans/spi/project/support/ant/ReferenceHelper.java,v retrieving revision 1.26 diff -u -r1.26 ReferenceHelper.java --- ant/project/src/org/netbeans/spi/project/support/ant/ReferenceHelper.java 3 Apr 2005 01:29:16 -0000 1.26 +++ ant/project/src/org/netbeans/spi/project/support/ant/ReferenceHelper.java 29 Jul 2005 14:58:19 -0000 @@ -19,7 +19,9 @@ import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -1229,6 +1231,91 @@ */ AntProjectHelper getAntProjectHelper() { return h; + } + + /**Tries to fix references after copy/rename/move operation on the project. + * Handles relative/absolute paths. + * + * @param originalPath the project folder of the original project + * @see org.netbeans.spi.project.CopyOperationImplementation + * @see org.netbeans.spi.project.MoveOperationImplementation + * @since 1.9 + */ + public void fixReferences(File originalPath) { + String[] prefixesToFix = new String[] {"file.reference.", "project."}; + EditableProperties pub = h.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH); + EditableProperties priv = h.getProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH); + + File projectDir = FileUtil.toFile(h.getProjectDirectory()); + + List pubRemove = new ArrayList(); + List privRemove = new ArrayList(); + Map pubAdd = new HashMap(); + Map privAdd = new HashMap(); + + for (Iterator i = pub.entrySet().iterator(); i.hasNext(); ) { + Map.Entry e = (Map.Entry) i.next(); + String key = (String) e.getKey(); + boolean cont = false; + + for (int cntr = 0; cntr < prefixesToFix.length; cntr++) { + if (key.startsWith(prefixesToFix[cntr])) { + cont = true; + break; + } + } + if (!cont) + continue; + + String value = (String) e.getValue(); + + File absolutePath = FileUtil.normalizeFile(PropertyUtils.resolveFile(originalPath, value)); + + //TODO: extra base dir relativization: + if (!CollocationQuery.areCollocated(absolutePath, projectDir)) { + pubRemove.add(key); + privAdd.put(key, absolutePath.getAbsolutePath()); + } + } + + for (Iterator i = priv.entrySet().iterator(); i.hasNext(); ) { + Map.Entry e = (Map.Entry) i.next(); + String key = (String) e.getKey(); + boolean cont = false; + + for (int cntr = 0; cntr < prefixesToFix.length; cntr++) { + if (key.startsWith(prefixesToFix[cntr])) { + cont = true; + break; + } + } + if (!cont) + continue; + + String value = (String) e.getValue(); + + File absolutePath = FileUtil.normalizeFile(PropertyUtils.resolveFile(originalPath, value)); + + //TODO: extra base dir relativization: + if (CollocationQuery.areCollocated(absolutePath, projectDir)) { + privRemove.add(key); + pubAdd.put(key, PropertyUtils.relativizeFile(projectDir, absolutePath)); + } + } + + for (Iterator i = pubRemove.iterator(); i.hasNext(); ) { + pub.remove(i.next()); + } + + for (Iterator i = privRemove.iterator(); i.hasNext(); ) { + priv.remove(i.next()); + } + + pub.putAll(pubAdd); + priv.putAll(privAdd); + + h.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, pub); + h.putProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH, priv); } /** Index: ant/project/test/unit/src/org/netbeans/modules/project/ant/DefaultAntProjectOperationsTest.java =================================================================== RCS file: ant/project/test/unit/src/org/netbeans/modules/project/ant/DefaultAntProjectOperationsTest.java diff -N ant/project/test/unit/src/org/netbeans/modules/project/ant/DefaultAntProjectOperationsTest.java --- ant/project/test/unit/src/org/netbeans/modules/project/ant/DefaultAntProjectOperationsTest.java 14 Jul 2005 23:43:38 -0000 1.2 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,195 +0,0 @@ -/* - * 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-2005 Sun - * Microsystems, Inc. All Rights Reserved. - */ - -package org.netbeans.modules.project.ant; - -import java.io.File; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import org.netbeans.api.progress.ProgressHandle; -import org.netbeans.api.progress.ProgressHandleFactory; -import org.netbeans.api.project.Project; -import org.netbeans.api.project.ProjectManager; -import org.netbeans.api.project.TestUtil; -import org.netbeans.junit.NbTestCase; -import org.netbeans.modules.project.ant.DefaultAntProjectOperations.UserInputHandler; -import org.netbeans.modules.project.ui.OpenProjectsTrampolineImpl; -import org.netbeans.spi.project.support.ant.AntBasedTestUtil; -import org.netbeans.spi.project.support.ant.AntBasedTestUtil.DeleteProjectOperationImpl; -import org.netbeans.spi.project.support.ant.AntProjectHelperTest; -import org.openide.filesystems.FileObject; -import org.openide.filesystems.FileUtil; - - -/** - * - * @author Jan Lahoda - */ -public class DefaultAntProjectOperationsTest extends NbTestCase { - - public DefaultAntProjectOperationsTest(String testName) { - super(testName); - } - - private FileObject scratch; - private FileObject projdir; - private Project prj; - private File projectDirectory; - - private void createProject(FileObject projdir) throws Exception { - TestUtil.createFileFromContent(AntProjectHelperTest.class.getResource("data/project.xml"), projdir, "nbproject/project.xml"); - TestUtil.createFileFromContent(AntProjectHelperTest.class.getResource("data/private.xml"), projdir, "nbproject/private/private.xml"); - TestUtil.createFileFromContent(AntProjectHelperTest.class.getResource("data/project.properties"), projdir, "nbproject/project.properties"); - TestUtil.createFileFromContent(AntProjectHelperTest.class.getResource("data/private.properties"), projdir, "nbproject/private/private.properties"); - TestUtil.createFileFromContent(AntProjectHelperTest.class.getResource("data/test.txt"), projdir, "src/test/test.txt"); - TestUtil.createFileFromContent(AntProjectHelperTest.class.getResource("data/global.properties"), scratch, "userdir/build.properties"); - } - - protected void setUp() throws Exception { - scratch = TestUtil.makeScratchDir(this); - projdir = scratch.createFolder("proj"); - - createProject(projdir); - - TestUtil.setLookup(new Object[] { - AntBasedTestUtil.testAntBasedProjectType(), - new OpenProjectsTrampolineImpl(), - }); - - prj = ProjectManager.getDefault().findProject(projdir); - - assertNotNull(prj); - - projectDirectory = FileUtil.toFile(projdir); - - assertNotNull(projectDirectory); - } - - public void testDeleteProjectDeleteAll() throws Exception { - TestUserInputHandler handler = new TestUserInputHandler(UserInputHandler.USER_OK_ALL); - - DefaultAntProjectOperations.deleteProject(prj, handler); - - assertTrue(handler.userConfirmationCalled); - assertTrue(handler.enableData); - assertTrue(handler.getProgressHandleCalled); - assertTrue(handler.deleteCalled); - - assertFalse(projectDirectory.exists()); - } - - public void testDeleteProjectDeleteMetadata() throws Exception { - TestUserInputHandler handler = new TestUserInputHandler(UserInputHandler.USER_OK_METADATA); - - DefaultAntProjectOperations.deleteProject(prj, handler); - - assertTrue(handler.userConfirmationCalled); - assertTrue(handler.enableData); - assertTrue(handler.getProgressHandleCalled); - assertTrue(handler.deleteCalled); - - assertTrue(projectDirectory.exists()); - assertTrue(Arrays.equals(new String[] {"src"}, projectDirectory.list())); - } - - public void testDeleteProjectDoNotDelete() throws Exception { - TestUserInputHandler handler = new TestUserInputHandler(UserInputHandler.USER_CANCEL); - - DefaultAntProjectOperations.deleteProject(prj, handler); - - assertTrue(handler.userConfirmationCalled); - assertTrue(handler.enableData); - assertFalse(handler.getProgressHandleCalled); - assertFalse(handler.deleteCalled); - - assertTrue(projectDirectory.exists()); - List/**/ items = Arrays.asList(projectDirectory.list()); - Collections.sort(items); - assertEquals(Arrays.asList(new String[] {"nbproject", "src"}), items); - } - - public void testDeleteProjectNestedProject() throws Exception { - FileObject projdir2 = projdir.createFolder("proj2"); - - createProject(projdir2); - - TestUserInputHandler handler = new TestUserInputHandler(UserInputHandler.USER_OK_ALL); - - DefaultAntProjectOperations.deleteProject(prj, handler); - - assertTrue(handler.userConfirmationCalled); - assertTrue(handler.enableData); - assertTrue(handler.getProgressHandleCalled); - assertTrue(handler.deleteCalled); - - assertTrue(projectDirectory.exists()); - assertTrue(Arrays.equals(new String[] {"proj2"}, projectDirectory.list())); - } - - public void testDeleteProjectExternalSources() throws Exception { - FileObject extDir = scratch.createFolder("external"); - File extDirFile = FileUtil.toFile(extDir); - - assertNotNull(extDirFile); - - ((DeleteProjectOperationImpl) prj.getLookup().lookup(DeleteProjectOperationImpl.class)).setExternalFile(extDir); - - TestUserInputHandler handler = new TestUserInputHandler(UserInputHandler.USER_OK_ALL); - - DefaultAntProjectOperations.deleteProject(prj, handler); - - assertTrue(handler.userConfirmationCalled); - assertTrue(handler.enableData); - assertTrue(handler.getProgressHandleCalled); - assertTrue(handler.deleteCalled); - - assertFalse(projectDirectory.exists()); - - assertTrue(extDirFile.exists()); - } - - private static final class TestUserInputHandler implements UserInputHandler { - - private int answer; - private ProgressHandle handle; - - private boolean userConfirmationCalled; - private boolean enableData; - private boolean getProgressHandleCalled; - private boolean deleteCalled; - - public TestUserInputHandler(int answer) { - this.answer = answer; - this.handle = ProgressHandleFactory.createHandle("test"); - } - - public int userConfirmation(String displayName, String projectFolder, boolean enableData) { - userConfirmationCalled = true; - this.enableData = enableData; - return answer; - } - - public ProgressHandle getProgressHandle() { - getProgressHandleCalled = true; - return handle; - } - - public void delete(Runnable r) { - deleteCalled = true; - r.run(); - } - - } - -} Index: ant/project/test/unit/src/org/netbeans/spi/project/support/ant/AntBasedTestUtil.java =================================================================== RCS file: /cvs/ant/project/test/unit/src/org/netbeans/spi/project/support/ant/AntBasedTestUtil.java,v retrieving revision 1.16 diff -u -r1.16 AntBasedTestUtil.java --- ant/project/test/unit/src/org/netbeans/spi/project/support/ant/AntBasedTestUtil.java 11 Jul 2005 12:18:06 -0000 1.16 +++ ant/project/test/unit/src/org/netbeans/spi/project/support/ant/AntBasedTestUtil.java 29 Jul 2005 14:58:20 -0000 @@ -29,8 +29,6 @@ import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -52,8 +50,6 @@ import org.netbeans.spi.project.AuxiliaryConfiguration; import org.netbeans.api.project.ProjectInformation; import org.netbeans.api.project.ProjectManager; -import org.netbeans.spi.project.ProjectOperationsImplementation; -import org.netbeans.spi.project.ProjectOperationsImplementation.DeleteOperationImplementation; import org.netbeans.spi.project.ant.AntArtifactProvider; import org.netbeans.spi.queries.CollocationQueryImplementation; import org.openide.filesystems.FileObject; @@ -164,7 +160,6 @@ } }, "hello", - new DeleteProjectOperationImpl(this), }); } @@ -249,53 +244,6 @@ } - public static final class DeleteProjectOperationImpl implements DeleteOperationImplementation { - - private boolean wasCleaned = false; - private boolean wasNotified = false; - - private FileObject externalFile = null; - - private TestAntBasedProject project; - - public DeleteProjectOperationImpl(TestAntBasedProject project) { - this.project = project; - } - - public List getMetadataFiles() { - return Collections.singletonList(project.getProjectDirectory().getFileObject("nbproject")); - } - - public List getDataFiles() { - if (externalFile == null) { - return Collections.singletonList(project.getProjectDirectory().getFileObject("src")); - } else { - return Arrays.asList(new FileObject[] {project.getProjectDirectory().getFileObject("src"), externalFile}); - } - } - - public void setExternalFile(FileObject externalFile) { - this.externalFile = externalFile; - } - - public synchronized boolean getWasCleaned() { - return wasCleaned; - } - - public synchronized void performClean() throws IOException { - wasCleaned = true; - } - - public synchronized boolean getWasNotified() { - return wasNotified; - } - - public synchronized void notifyDeleted() throws IOException { - wasNotified = true; - } - - } - /** * Load a properties file from disk. * @param h a project reference Index: ant/project/test/unit/src/org/netbeans/spi/project/support/ant/data/test.txt =================================================================== RCS file: ant/project/test/unit/src/org/netbeans/spi/project/support/ant/data/test.txt diff -N ant/project/test/unit/src/org/netbeans/spi/project/support/ant/data/test.txt Index: ant/src/org/apache/tools/ant/module/xml/AntProjectSupport.java =================================================================== RCS file: /cvs/ant/src/org/apache/tools/ant/module/xml/AntProjectSupport.java,v retrieving revision 1.30 diff -u -r1.30 AntProjectSupport.java --- ant/src/org/apache/tools/ant/module/xml/AntProjectSupport.java 18 Aug 2004 21:54:50 -0000 1.30 +++ ant/src/org/apache/tools/ant/module/xml/AntProjectSupport.java 29 Jul 2005 14:58:20 -0000 @@ -66,7 +66,7 @@ import org.xml.sax.SAXParseException; public class AntProjectSupport implements AntProjectCookie.ParseStatus, javax.swing.event.DocumentListener, - FileChangeListener, PropertyChangeListener { + /*FileChangeListener,*/ PropertyChangeListener { private FileObject fo; Index: java/freeform/src/org/netbeans/modules/java/freeform/SourceLevelQueryImpl.java =================================================================== RCS file: /cvs/java/freeform/src/org/netbeans/modules/java/freeform/SourceLevelQueryImpl.java,v retrieving revision 1.4 diff -u -r1.4 SourceLevelQueryImpl.java --- java/freeform/src/org/netbeans/modules/java/freeform/SourceLevelQueryImpl.java 1 Mar 2005 14:27:13 -0000 1.4 +++ java/freeform/src/org/netbeans/modules/java/freeform/SourceLevelQueryImpl.java 29 Jul 2005 14:58:24 -0000 @@ -7,12 +7,13 @@ * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original - * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun + * Code is Sun Microsystems, Inc. Portions Copyright 1997-2005 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.java.freeform; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -33,9 +34,9 @@ */ final class SourceLevelQueryImpl implements SourceLevelQueryImplementation, AntProjectListener { - private AntProjectHelper helper; - private PropertyEvaluator evaluator; - private AuxiliaryConfiguration aux; + private final AntProjectHelper helper; + private final PropertyEvaluator evaluator; + private final AuxiliaryConfiguration aux; /** * Map from package roots to source levels. @@ -49,15 +50,17 @@ this.helper.addAntProjectListener(this); } - public synchronized String getSourceLevel(FileObject file) { + public String getSourceLevel(FileObject file) { // Check for cached value. - Iterator it = sourceLevels.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = (Map.Entry)it.next(); - FileObject root = (FileObject)entry.getKey(); - if (root == file || FileUtil.isParentOf(root, file)) { - // Already have it. - return (String)entry.getValue(); + synchronized (this) { + Iterator it = sourceLevels.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry entry = (Map.Entry)it.next(); + FileObject root = (FileObject)entry.getKey(); + if (root == file || FileUtil.isParentOf(root, file)) { + // Already have it. + return (String)entry.getValue(); + } } } // Need to compute it. @@ -66,7 +69,7 @@ return null; } List/**/ compilationUnits = Util.findSubElements(java); - it = compilationUnits.iterator(); + Iterator it = compilationUnits.iterator(); while (it.hasNext()) { Element compilationUnitEl = (Element)it.next(); assert compilationUnitEl.getLocalName().equals("compilation-unit") : compilationUnitEl; @@ -75,14 +78,16 @@ while (it2.hasNext()) { FileObject root = (FileObject)it2.next(); if (root == file || FileUtil.isParentOf(root, file)) { - // Got it. Retrieve source level and cache it (for each root). - String lvl = getLevel(compilationUnitEl); - it2 = packageRoots.iterator(); - while (it2.hasNext()) { - FileObject root2 = (FileObject)it2.next(); - sourceLevels.put(root2, lvl); + synchronized (this) { + // Got it. Retrieve source level and cache it (for each root). + String lvl = getLevel(compilationUnitEl); + it2 = packageRoots.iterator(); + while (it2.hasNext()) { + FileObject root2 = (FileObject)it2.next(); + sourceLevels.put(root2, lvl); + } + return lvl; } - return lvl; } } } Index: java/j2seproject/src/org/netbeans/modules/java/j2seproject/J2SEActionProvider.java =================================================================== RCS file: /cvs/java/j2seproject/src/org/netbeans/modules/java/j2seproject/J2SEActionProvider.java,v retrieving revision 1.44 diff -u -r1.44 J2SEActionProvider.java --- java/j2seproject/src/org/netbeans/modules/java/j2seproject/J2SEActionProvider.java 11 Jul 2005 12:17:59 -0000 1.44 +++ java/j2seproject/src/org/netbeans/modules/java/j2seproject/J2SEActionProvider.java 29 Jul 2005 14:58:27 -0000 @@ -18,12 +18,9 @@ import java.io.IOException; import java.net.URL; import java.text.MessageFormat; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; @@ -35,7 +32,6 @@ import org.netbeans.api.fileinfo.NonRecursiveFolder; import org.netbeans.api.java.classpath.ClassPath; import org.netbeans.api.java.project.JavaProjectConstants; -import org.netbeans.api.java.queries.SourceForBinaryQuery; import org.netbeans.api.project.ProjectManager; import org.netbeans.api.project.ProjectUtils; import org.netbeans.modules.java.j2seproject.applet.AppletSupport; @@ -46,6 +42,7 @@ import org.netbeans.spi.project.support.ant.AntProjectHelper; import org.netbeans.spi.project.support.ant.EditableProperties; import org.netbeans.spi.project.support.ant.GeneratedFilesHelper; +import org.netbeans.spi.project.ui.support.DefaultProjectOperations; import org.openide.DialogDescriptor; import org.openide.DialogDisplayer; import org.openide.ErrorManager; @@ -84,6 +81,9 @@ JavaProjectConstants.COMMAND_DEBUG_FIX, COMMAND_DEBUG_STEP_INTO, COMMAND_DELETE, + COMMAND_COPY, + COMMAND_MOVE, + COMMAND_RENAME, }; // Project @@ -140,7 +140,22 @@ public void invokeAction( final String command, final Lookup context ) throws IllegalArgumentException { if (COMMAND_DELETE.equals(command)) { - project.getAntProjectHelper().performDefaultDeleteOperation(); + DefaultProjectOperations.performDefaultDeleteOperation(project); + return ; + } + + if (COMMAND_COPY.equals(command)) { + DefaultProjectOperations.performDefaultCopyOperation(project); + return ; + } + + if (COMMAND_MOVE.equals(command)) { + DefaultProjectOperations.performDefaultMoveOperation(project); + return ; + } + + if (COMMAND_RENAME.equals(command)) { + DefaultProjectOperations.performDefaultRenameOperation(project, null); return ; } Index: java/j2seproject/src/org/netbeans/modules/java/j2seproject/J2SEProject.java =================================================================== RCS file: /cvs/java/j2seproject/src/org/netbeans/modules/java/j2seproject/J2SEProject.java,v retrieving revision 1.54 diff -u -r1.54 J2SEProject.java --- java/j2seproject/src/org/netbeans/modules/java/j2seproject/J2SEProject.java 21 Jul 2005 18:58:18 -0000 1.54 +++ java/j2seproject/src/org/netbeans/modules/java/j2seproject/J2SEProject.java 29 Jul 2005 14:58:28 -0000 @@ -119,6 +119,10 @@ return this.refHelper; } + UpdateHelper getUpdateHelper() { + return this.updateHelper; + } + public Lookup getLookup() { return lookup; } @@ -198,7 +202,7 @@ } // Currently unused (but see #47230): - /** Store configured project name. * / + /** Store configured project name. */ public void setName(final String name) { ProjectManager.mutex().writeAccess(new Mutex.Action() { public Object run() { @@ -214,7 +218,7 @@ } } else { nameEl = data.getOwnerDocument().createElementNS(J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE, "name"); - data.insertBefore(nameEl, / * OK if null * /data.getChildNodes().item(0)); + data.insertBefore(nameEl, /* OK if null */data.getChildNodes().item(0)); } nameEl.appendChild(data.getOwnerDocument().createTextNode(name)); helper.putPrimaryConfigurationData(data, true); @@ -222,7 +226,6 @@ } }); } - */ Index: java/j2seproject/src/org/netbeans/modules/java/j2seproject/J2SEProjectOperations.java =================================================================== RCS file: /cvs/java/j2seproject/src/org/netbeans/modules/java/j2seproject/J2SEProjectOperations.java,v retrieving revision 1.1 diff -u -r1.1 J2SEProjectOperations.java --- java/j2seproject/src/org/netbeans/modules/java/j2seproject/J2SEProjectOperations.java 11 Jul 2005 12:18:00 -0000 1.1 +++ java/j2seproject/src/org/netbeans/modules/java/j2seproject/J2SEProjectOperations.java 29 Jul 2005 14:58:28 -0000 @@ -13,25 +13,35 @@ package org.netbeans.modules.java.j2seproject; +import java.io.File; import java.io.IOException; +import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Properties; import org.apache.tools.ant.module.api.support.ActionUtils; +import org.netbeans.api.project.Project; +import org.netbeans.api.project.ProjectManager; import org.netbeans.spi.project.ActionProvider; -import org.netbeans.spi.project.ProjectOperationsImplementation.DeleteOperationImplementation; +import org.netbeans.spi.project.CopyOperationImplementation; +import org.netbeans.spi.project.DeleteOperationImplementation; +import org.netbeans.spi.project.MoveOperationImplementation; import org.netbeans.spi.project.support.ant.GeneratedFilesHelper; +import org.netbeans.spi.project.support.ant.PropertyUtils; import org.openide.ErrorManager; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; import org.openide.util.Lookup; +import org.openide.util.Mutex; +import org.openide.util.MutexException; import org.openide.util.lookup.Lookups; + /** * * @author Jan Lahoda */ -public class J2SEProjectOperations implements DeleteOperationImplementation { +public class J2SEProjectOperations implements DeleteOperationImplementation, CopyOperationImplementation, MoveOperationImplementation { private J2SEProject project; @@ -80,7 +90,7 @@ return files; } - public void performClean() throws IOException { + public void notifyDeleting() throws IOException { J2SEActionProvider ap = (J2SEActionProvider) project.getLookup().lookup(J2SEActionProvider.class); assert ap != null; @@ -98,6 +108,91 @@ public void notifyDeleted() throws IOException { project.getAntProjectHelper().notifyDeleted(); + } + + public void notifyCopying() { + //nothing. + } + + public void notifyCopied(Project original, File originalPath, String nueName) { + if (project == original) { //TODO: this is illegal + //do nothing for the original project. + return ; + } + + project.getReferenceHelper().fixReferences(originalPath); + + project.setName(nueName); + } + + public void notifyMoving() throws IOException { + notifyDeleting(); + } + + public void notifyMoved(Project original, File originalPath, String nueName) { + if (project == original) { //TODO: this is illegal + //do nothing for the original project. + return ; + } + + project.setName(nueName); + fixExternalSources(originalPath, project.getSourceRoots()); + fixExternalSources(originalPath, project.getTestSourceRoots()); + } + + private void fixExternalSources(final File originalPath, final SourceRoots sr) { + try { + ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction() { + public Object run() throws IOException { + File projectDirectory = FileUtil.toFile(project.getProjectDirectory()); + String[] srcProps = sr.getRootProperties(); + String[] names = sr.getRootNames(); + List/**/ roots = new ArrayList(); + List/**/ displayNames = new ArrayList(); + for (int i = 0; i < srcProps.length; i++) { + String prop = project.evaluator().getProperty(srcProps[i]); + if (prop != null) { + FileObject nueFile = null; + File originalFile = PropertyUtils.resolveFile(originalPath, prop); + + if (isParent(originalPath, originalFile)) { + nueFile = FileUtil.toFileObject(PropertyUtils.resolveFile(projectDirectory, prop)); + } else { + nueFile = FileUtil.toFileObject(originalFile); + } + + if (nueFile == null) { + continue; + } + if (FileUtil.isArchiveFile(nueFile)) { + nueFile = FileUtil.getArchiveRoot(nueFile); + } + roots.add(nueFile.getURL()); + displayNames.add(sr.getRootDisplayName(names[i], srcProps[i])); + } + } + + sr.putRoots((URL[] ) roots.toArray(new URL[0]), (String[] ) displayNames.toArray(new String[0])); //XXX + return null; + } + }); + } catch (MutexException e) { + ErrorManager.getDefault().notify(e); + } + } + + private static boolean isParent(File folder, File fo) { + if (folder.equals(fo)) + return false; + + while (fo != null) { + if (fo.equals(folder)) + return true; + + fo = fo.getParentFile(); + } + + return false; } } Index: java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/J2SELogicalViewProvider.java =================================================================== RCS file: /cvs/java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/J2SELogicalViewProvider.java,v retrieving revision 1.1 diff -u -r1.1 J2SELogicalViewProvider.java --- java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/J2SELogicalViewProvider.java 21 Jul 2005 18:58:17 -0000 1.1 +++ java/j2seproject/src/org/netbeans/modules/java/j2seproject/ui/J2SELogicalViewProvider.java 29 Jul 2005 14:58:28 -0000 @@ -60,6 +60,7 @@ import org.netbeans.spi.project.support.ant.ReferenceHelper; import org.netbeans.spi.project.ui.LogicalViewProvider; import org.netbeans.spi.project.ui.support.CommonProjectActions; +import org.netbeans.spi.project.ui.support.DefaultProjectOperations; import org.netbeans.spi.project.ui.support.ProjectSensitiveActions; import org.openide.ErrorManager; import org.openide.actions.FindAction; @@ -241,7 +242,7 @@ public J2SELogicalViewRootNode() { super(new LogicalViewChildren(project, evaluator, helper, resolver), Lookups.singleton(project)); setIconBaseWithExtension("org/netbeans/modules/java/j2seproject/ui/resources/j2seProject.gif"); - setName(ProjectUtils.getInformation(project).getDisplayName()); + super.setName( ProjectUtils.getInformation( project ).getDisplayName() ); if (hasBrokenLinks()) { broken = true; } @@ -463,7 +464,11 @@ } public boolean canRename() { - return false; + return true; + } + + public void setName(String s) { + DefaultProjectOperations.performDefaultRenameOperation(project, s); } /* @@ -501,6 +506,9 @@ actions.add(CommonProjectActions.openSubprojectsAction()); actions.add(CommonProjectActions.closeProjectAction()); actions.add(null); + actions.add(CommonProjectActions.renameProjectAction()); + actions.add(CommonProjectActions.moveProjectAction()); + actions.add(CommonProjectActions.copyProjectAction()); actions.add(CommonProjectActions.deleteProjectAction()); actions.add(null); actions.add(SystemAction.get(FindAction.class));