001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.apisupport.project.ui;
043:
044: import java.io.File;
045: import java.io.IOException;
046: import java.util.ArrayList;
047: import java.util.HashMap;
048: import java.util.List;
049: import java.util.Map;
050: import org.apache.tools.ant.module.api.support.ActionUtils;
051: import org.netbeans.api.java.project.JavaProjectConstants;
052: import org.netbeans.api.project.Project;
053: import org.netbeans.api.project.ProjectUtils;
054: import org.netbeans.api.project.SourceGroup;
055: import org.netbeans.api.project.Sources;
056: import org.netbeans.modules.apisupport.project.NbModuleProject;
057: import org.netbeans.modules.apisupport.project.suite.SuiteProject;
058: import org.netbeans.modules.apisupport.project.ui.customizer.SuiteUtils;
059: import org.netbeans.modules.apisupport.project.universe.LocalizedBundleInfo;
060: import org.netbeans.spi.project.ActionProvider;
061: import org.netbeans.spi.project.CopyOperationImplementation;
062: import org.netbeans.spi.project.DeleteOperationImplementation;
063: import org.netbeans.spi.project.MoveOperationImplementation;
064: import org.netbeans.spi.project.support.ant.GeneratedFilesHelper;
065: import org.openide.DialogDisplayer;
066: import org.openide.NotifyDescriptor;
067: import org.openide.filesystems.FileObject;
068: import org.openide.util.NbBundle;
069:
070: /**
071: * @author Martin Krauskopf
072: */
073: public final class ModuleOperations implements
074: DeleteOperationImplementation, MoveOperationImplementation,
075: CopyOperationImplementation {
076:
077: private static final Map<String, SuiteProject> TEMPORARY_CACHE = new HashMap<String, SuiteProject>();
078:
079: private final NbModuleProject project;
080: private final FileObject projectDir;
081:
082: public ModuleOperations(final NbModuleProject project) {
083: this .project = project;
084: this .projectDir = project.getProjectDirectory();
085: }
086:
087: public void notifyDeleting() throws IOException {
088: notifyDeleting(false);
089: }
090:
091: private void notifyDeleting(boolean temporary) throws IOException {
092: FileObject buildXML = projectDir
093: .getFileObject(GeneratedFilesHelper.BUILD_XML_PATH);
094: ActionUtils.runTarget(buildXML,
095: new String[] { ActionProvider.COMMAND_CLEAN }, null)
096: .waitFinished();
097:
098: SuiteProject suite = SuiteUtils.findSuite(project);
099: if (suite != null) {
100: if (temporary) {
101: SuiteUtils.removeModuleFromSuite(project);
102: } else {
103: // XXX we should ask the user in the same way as when we removing the
104: // module in suite logical view. But it is not possible with the
105: // current Project API. (maybe by some wrapper in the ModuleActions)
106: SuiteUtils
107: .removeModuleFromSuiteWithDependencies(project);
108: }
109: }
110:
111: project.notifyDeleting();
112: }
113:
114: public void notifyDeleted() throws IOException {
115: project.getHelper().notifyDeleted();
116: }
117:
118: public void notifyMoving() throws IOException {
119: SuiteProject suite = SuiteUtils.findSuite(project);
120: if (suite != null) {
121: TEMPORARY_CACHE.put(project.getCodeNameBase(), suite);
122: }
123: notifyDeleting(true);
124: }
125:
126: public void notifyMoved(Project original, File originalPath,
127: String nueName) throws IOException {
128: if (original == null) { // called on the original project
129: project.getHelper().notifyDeleted();
130: } else { // called on the new project
131: SuiteProject suite = TEMPORARY_CACHE.remove(project
132: .getCodeNameBase());
133: if (suite != null) {
134: SuiteUtils.addModule(suite, project);
135: }
136: boolean isRename = original.getProjectDirectory()
137: .getParent().equals(
138: project.getProjectDirectory().getParent());
139: if (isRename) {
140: setDisplayName(nueName);
141: }
142: }
143: }
144:
145: public void notifyCopying() throws IOException {
146: SuiteProject suite = SuiteUtils.findSuite(project);
147: if (suite != null) {
148: // Let's remove the project from its suite. Since we want to be a
149: // copy a standalone module for now. And since we cannot control
150: // the phase between a new project is physically copied and when it
151: // is opened we have to use this workaround.
152: TEMPORARY_CACHE.put(project.getCodeNameBase(), suite);
153: SuiteUtils.removeModuleFromSuite(project);
154: }
155: }
156:
157: public void notifyCopied(Project original, File originalPath,
158: String nueName) throws IOException {
159: if (original == null) { // called on the original project
160: SuiteProject suite = TEMPORARY_CACHE.remove(project
161: .getCodeNameBase());
162: if (suite != null) {
163: // Let's readd the original suite component to its suite. Look
164: // into notifyCopying() commens for more details.
165: SuiteUtils.addModule(suite, project);
166: }
167: } else {
168: // Adjust display name so the copy can be recognized from the original.
169: adjustDisplayName();
170: }
171: }
172:
173: public List<FileObject> getMetadataFiles() {
174: List<FileObject> files = new ArrayList<FileObject>();
175: addFile(GeneratedFilesHelper.BUILD_XML_PATH, files);
176: addFile("manifest.mf", files); // NOI18N
177: addFile("nbproject", files); // NOI18N
178: return files;
179: }
180:
181: public List<FileObject> getDataFiles() {
182: List<FileObject> files = new ArrayList<FileObject>();
183:
184: Sources srcs = ProjectUtils.getSources(project);
185: SourceGroup[] grps = srcs
186: .getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
187: for (int i = 0; i < grps.length; i++) {
188: FileObject srcRoot = grps[i].getRootFolder();
189: if (srcRoot.getPath().endsWith("test/unit/src")) { // NOI18N
190: addFile("test", files); // NOI18N
191: } else {
192: files.add(srcRoot);
193: }
194: }
195:
196: return files;
197: }
198:
199: private void addFile(String fileName, List<FileObject> result) {
200: FileObject file = projectDir.getFileObject(fileName);
201: if (file != null) {
202: result.add(file);
203: }
204: }
205:
206: private void adjustDisplayName() throws IOException {
207: // XXX what if the user makes two copies from one module?
208: setDisplayName(ProjectUtils.getInformation(project)
209: .getDisplayName()
210: + " (0)"); // NOI18N
211: }
212:
213: private void setDisplayName(String nueName) throws IOException {
214: LocalizedBundleInfo.Provider lbiProvider = project.getLookup()
215: .lookup(LocalizedBundleInfo.Provider.class);
216: if (lbiProvider != null) {
217: LocalizedBundleInfo info = lbiProvider
218: .getLocalizedBundleInfo();
219: if (info != null) {
220: // XXX what if the user makes two copies from one module?
221: info.setDisplayName(nueName); // NOI18N
222: info.store();
223: }
224: }
225: }
226:
227: static boolean canRun(final NbModuleProject project,
228: final boolean emitWarningToUser) {
229: boolean result = true;
230: String testUserDir = project.evaluator().getProperty(
231: "test.user.dir"); // NOI18N
232: FileObject testUserDirFO = project.getHelper()
233: .resolveFileObject(testUserDir);
234: if (testUserDirFO != null && testUserDirFO.isFolder()) {
235: FileObject lock = testUserDirFO.getFileObject("lock"); // NOI18N
236: if (lock != null && lock.isData()) {
237: if (emitWarningToUser) {
238: DialogDisplayer.getDefault().notify(
239: new NotifyDescriptor.Message(NbBundle
240: .getMessage(ModuleOperations.class,
241: "ERR_ModuleIsBeingRun")));
242: }
243: result = false;
244: }
245: }
246: return result;
247: }
248:
249: }
|