KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > java > freeform > JavaActions


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.java.freeform;
21
22 import java.io.File JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.InputStream JavaDoc;
25 import java.io.OutputStream JavaDoc;
26 import java.net.MalformedURLException JavaDoc;
27 import java.net.URL JavaDoc;
28 import java.util.ArrayList JavaDoc;
29 import java.util.Collection JavaDoc;
30 import java.util.Collections JavaDoc;
31 import java.util.HashSet JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.List JavaDoc;
34 import java.util.Map JavaDoc;
35 import java.util.Set JavaDoc;
36 import java.util.StringTokenizer JavaDoc;
37 import javax.swing.JButton JavaDoc;
38 import javax.xml.parsers.ParserConfigurationException JavaDoc;
39 import javax.xml.parsers.SAXParser JavaDoc;
40 import javax.xml.parsers.SAXParserFactory JavaDoc;
41 import org.netbeans.api.project.Project;
42 import org.netbeans.api.project.ProjectManager;
43 import org.netbeans.api.project.ProjectUtils;
44 import org.netbeans.modules.ant.freeform.spi.support.Util;
45 import org.netbeans.modules.java.freeform.jdkselection.JdkConfiguration;
46 import org.netbeans.modules.java.freeform.ui.ProjectModel;
47 import org.netbeans.spi.project.ActionProvider;
48 import org.netbeans.spi.project.AuxiliaryConfiguration;
49 import org.netbeans.spi.project.support.ant.AntProjectHelper;
50 import org.netbeans.spi.project.support.ant.PropertyEvaluator;
51 import org.netbeans.spi.project.support.ant.PropertyUtils;
52 import org.netbeans.spi.project.ui.CustomizerProvider;
53 import org.openide.DialogDisplayer;
54 import org.openide.ErrorManager;
55 import org.openide.NotifyDescriptor;
56 import org.openide.cookies.LineCookie;
57 import org.openide.filesystems.FileLock;
58 import org.openide.filesystems.FileObject;
59 import org.openide.filesystems.FileSystem;
60 import org.openide.filesystems.FileUtil;
61 import org.openide.loaders.DataObject;
62 import org.openide.loaders.DataObjectNotFoundException;
63 import org.openide.text.Line;
64 import org.openide.util.Exceptions;
65 import org.openide.util.Lookup;
66 import org.openide.util.NbBundle;
67 import org.openide.xml.XMLUtil;
68 import org.w3c.dom.Attr JavaDoc;
69 import org.w3c.dom.Comment JavaDoc;
70 import org.w3c.dom.Document JavaDoc;
71 import org.w3c.dom.Element JavaDoc;
72 import org.w3c.dom.NamedNodeMap JavaDoc;
73 import org.w3c.dom.NodeList JavaDoc;
74 import org.xml.sax.Attributes JavaDoc;
75 import org.xml.sax.InputSource JavaDoc;
76 import org.xml.sax.Locator JavaDoc;
77 import org.xml.sax.SAXException JavaDoc;
78 import org.xml.sax.helpers.DefaultHandler JavaDoc;
79
80 /**
81  * Handles providing implementations of some Java-oriented IDE-specific actions.
82  * @see "issue #46886"
83  */

84 final class JavaActions implements ActionProvider {
85     
86     /* Too problematic for importing <classpath> from existing <java>, since Ant would want NS on that too (oddly):
87     private static final String NS_JPDA = "antlib:org.netbeans.modules.debugger.jpda.ant"; // NOI18N
88      */

89
90     static final String JavaDoc JAVA_FILE_PATTERN = "\\.java$";
91
92     private static final String JavaDoc[] ACTIONS = {
93         ActionProvider.COMMAND_COMPILE_SINGLE,
94         ActionProvider.COMMAND_DEBUG,
95         ActionProvider.COMMAND_RUN_SINGLE,
96         ActionProvider.COMMAND_DEBUG_SINGLE
97         // XXX more
98
};
99     
100     /**
101      * Script to hold file-sensitive generated targets like compile.single.
102      * (Or for generated targets for debug which cannot reuse any existing target body.)
103      * These pick up at least project.dir from project.xml and the entire
104      * target body is fixed by the IDE, except for some strings determined
105      * by information from project.xml like the classpath. The basedir
106      * is set to the project directory so that properties match their
107      * semantics in project.xml.
108      */

109     static final String JavaDoc FILE_SCRIPT_PATH = "nbproject/ide-file-targets.xml"; // NOI18N
110
/**
111      * Script to hold non-file-sensitive generated targets like debug.
112      * These import the original build script and share its basedir, so that
113      * properties match the semantics of build.xml.
114      */

115     static final String JavaDoc GENERAL_SCRIPT_PATH = "nbproject/ide-targets.xml"; // NOI18N
116

117     private final Project project;
118     private final AntProjectHelper helper;
119     private final PropertyEvaluator evaluator;
120     private final AuxiliaryConfiguration aux;
121     private boolean setOutputsNotified;
122     
123     public JavaActions(Project project, AntProjectHelper helper, PropertyEvaluator evaluator, AuxiliaryConfiguration aux) {
124         this.project = project;
125         this.helper = helper;
126         this.evaluator = evaluator;
127         this.aux = aux;
128     }
129
130     public String JavaDoc[] getSupportedActions() {
131         return ACTIONS;
132     }
133     
134     public boolean isActionEnabled(String JavaDoc command, Lookup context) throws IllegalArgumentException JavaDoc {
135         if (command.equals(ActionProvider.COMMAND_COMPILE_SINGLE)) {
136             return findPackageRoot(context) != null;
137         } else if (command.equals(ActionProvider.COMMAND_DEBUG)) {
138             return true;
139         } else if (command.equals(ActionProvider.COMMAND_RUN_SINGLE)) {
140             return (findPackageRoot(context) != null) && isSingleJavaFileSelected(context);
141         } else if (command.equals(ActionProvider.COMMAND_DEBUG_SINGLE)) {
142             return (findPackageRoot(context) != null) && isSingleJavaFileSelected(context);
143         } else {
144             throw new IllegalArgumentException JavaDoc(command);
145         }
146     }
147
148     public void invokeAction(final String JavaDoc command, final Lookup context) throws IllegalArgumentException JavaDoc {
149         try {
150             project.getProjectDirectory().getFileSystem().runAtomicAction(new FileSystem.AtomicAction() {
151                 public void run() throws IOException JavaDoc {
152                     try {
153                         if (command.equals(ActionProvider.COMMAND_COMPILE_SINGLE)) {
154                             handleCompileSingle(context);
155                         } else if (command.equals(ActionProvider.COMMAND_DEBUG)) {
156                             handleDebug();
157                         } else if (command.equals(ActionProvider.COMMAND_RUN_SINGLE)) {
158                             handleRunSingle(context);
159                         } else if (command.equals(ActionProvider.COMMAND_DEBUG_SINGLE)) {
160                             handleDebugSingle(context);
161                         } else {
162                             throw new IllegalArgumentException JavaDoc(command);
163                         }
164                     } catch (SAXException JavaDoc e) {
165                         throw (IOException JavaDoc) new IOException JavaDoc(e.toString()).initCause(e);
166                     }
167                 }
168             });
169         } catch (IOException JavaDoc e) {
170             ErrorManager.getDefault().notify(e);
171         }
172     }
173     
174     /**
175      * Display an alert asking the user whether to really generate a target.
176      * @param commandDisplayName the display name of the action to be bound
177      * @param scriptPath the path that to the script that will be generated or written to
178      * @return true if IDE should proceed
179      */

180     private boolean alert(String JavaDoc commandDisplayName, String JavaDoc scriptPath) {
181         String JavaDoc projectDisplayName = ProjectUtils.getInformation(project).getDisplayName();
182         String JavaDoc title = NbBundle.getMessage(JavaActions.class, "TITLE_generate_target_dialog", commandDisplayName, projectDisplayName);
183         String JavaDoc body = NbBundle.getMessage(JavaActions.class, "TEXT_generate_target_dialog", commandDisplayName, scriptPath);
184         NotifyDescriptor d = new NotifyDescriptor.Message(body, NotifyDescriptor.QUESTION_MESSAGE);
185         d.setTitle(title);
186         d.setOptionType(NotifyDescriptor.OK_CANCEL_OPTION);
187         JButton JavaDoc generate = new JButton JavaDoc(NbBundle.getMessage(JavaActions.class, "LBL_generate"));
188         generate.setDefaultCapable(true);
189         d.setOptions(new Object JavaDoc[] {generate, NotifyDescriptor.CANCEL_OPTION});
190         return DialogDisplayer.getDefault().notify(d) == generate;
191     }
192     
193     /**
194      * Warns the user about missing project outputs setting
195      * @param commandDisplayName the display name of the action to be bound
196      */

197     private boolean alertOutputs (String JavaDoc commandDisplayName) {
198         JButton JavaDoc setOutputOption = new JButton JavaDoc (NbBundle.getMessage(JavaActions.class,"CTL_SetOutput"));
199         setOutputOption.getAccessibleContext().setAccessibleDescription (NbBundle.getMessage(JavaActions.class,"AD_SetOutput"));
200         setOutputOption.setDefaultCapable(true);
201         String JavaDoc projectDisplayName = ProjectUtils.getInformation(project).getDisplayName();
202         String JavaDoc title = NbBundle.getMessage(JavaActions.class, "TITLE_set_outputs_dialog", commandDisplayName, projectDisplayName);
203         String JavaDoc body = NbBundle.getMessage(JavaActions.class,"TEXT_set_outputs_dialog");
204         NotifyDescriptor d = new NotifyDescriptor.Message (body, NotifyDescriptor.QUESTION_MESSAGE);
205         d.setTitle(title);
206         d.setOptionType(NotifyDescriptor.OK_CANCEL_OPTION);
207         d.setOptions(new Object JavaDoc[] {setOutputOption, NotifyDescriptor.CANCEL_OPTION});
208         if (DialogDisplayer.getDefault().notify (d) == setOutputOption) {
209             CustomizerProvider customizerProvider = project.getLookup().lookup(CustomizerProvider.class);
210             assert customizerProvider != null;
211             customizerProvider.showCustomizer();
212             return true;
213         }
214         return false;
215     }
216
217     /**
218      * Implementation of Compile File.
219      */

220     private void handleCompileSingle(Lookup context) throws IOException JavaDoc, SAXException JavaDoc {
221         // XXX could also try copy + mod from build.xml? but less likely to have <compile> in an accessible place...
222
if (!alert(NbBundle.getMessage(JavaActions.class, "ACTION_compile.single"), FILE_SCRIPT_PATH)) {
223             return;
224         }
225         Document JavaDoc doc = readCustomScript(FILE_SCRIPT_PATH);
226         ensurePropertiesCopied(doc.getDocumentElement());
227         Comment JavaDoc comm = doc.createComment(" " + NbBundle.getMessage(JavaActions.class, "COMMENT_edit_target") + " ");
228         doc.getDocumentElement().appendChild(comm);
229         comm = doc.createComment(" " + NbBundle.getMessage(JavaActions.class, "COMMENT_more_info_x.single") + " ");
230         doc.getDocumentElement().appendChild(comm);
231         String JavaDoc propertyName = "files"; // NOI18N
232
AntLocation root = findPackageRoot(context);
233         assert root != null : context;
234         Element JavaDoc target = createCompileSingleTarget(doc, context, propertyName, root);
235         doc.getDocumentElement().appendChild(target);
236         writeCustomScript(doc, FILE_SCRIPT_PATH);
237         // XXX #53622: support also folders (i.e. just files w/o ext??):
238
String JavaDoc targetName = target.getAttribute("name");
239         addBinding(ActionProvider.COMMAND_COMPILE_SINGLE, FILE_SCRIPT_PATH, targetName, propertyName, root.virtual, JAVA_FILE_PATTERN, "relative-path", ","); // NOI18N
240
jumpToBinding(ActionProvider.COMMAND_COMPILE_SINGLE);
241         jumpToBuildScript(FILE_SCRIPT_PATH, targetName);
242     }
243     
244     Element JavaDoc createCompileSingleTarget(Document JavaDoc doc, Lookup context, String JavaDoc propertyName, AntLocation root) {
245         String JavaDoc targetName = "compile-selected-files-in-" + root.physical.getNameExt(); // NOI18N
246
// XXX do a uniquification check
247
Element JavaDoc target = doc.createElement("target"); // NOI18N
248
addJdkInitDeps(target);
249         target.setAttribute("name", targetName); // NOI18N
250
Element JavaDoc fail = doc.createElement("fail"); // NOI18N
251
fail.setAttribute("unless", propertyName); // NOI18N
252
fail.appendChild(doc.createTextNode(NbBundle.getMessage(JavaActions.class, "COMMENT_must_set_property", propertyName)));
253         target.appendChild(fail);
254         String JavaDoc classesDir = findClassesOutputDir(root.virtual);
255         if (classesDir == null) {
256             target.appendChild(doc.createComment(" " + NbBundle.getMessage(JavaActions.class, "COMMENT_must_set_build_classes_dir") + " "));
257             classesDir = "${build.classes.dir}"; // NOI18N
258
}
259         Element JavaDoc mkdir = doc.createElement("mkdir"); // NOI18N
260
mkdir.setAttribute("dir", classesDir); // NOI18N
261
target.appendChild(mkdir);
262         Element JavaDoc javac = doc.createElement("javac"); // NOI18N
263
javac.setAttribute("srcdir", root.virtual); // NOI18N
264
javac.setAttribute("destdir", classesDir); // NOI18N
265
javac.setAttribute("includes", "${" + propertyName + "}"); // NOI18N
266
String JavaDoc sourceLevel = findSourceLevel(root.virtual);
267         if (sourceLevel != null) {
268             javac.setAttribute("source", sourceLevel); // NOI18N
269
}
270         String JavaDoc cp = findCUClasspath(root.virtual, "compile");
271         if (cp != null) {
272             Element JavaDoc classpath = doc.createElement("classpath"); // NOI18N
273
classpath.setAttribute("path", cp); // NOI18N
274
javac.appendChild(classpath);
275         }
276         target.appendChild(javac);
277         return target;
278     }
279     
280     private void handleDebug() throws IOException JavaDoc, SAXException JavaDoc {
281         if (!this.setOutputsNotified) {
282             ProjectModel pm = ProjectModel.createModel(Util.getProjectLocation(this.helper, this.evaluator),
283                 FileUtil.toFile(project.getProjectDirectory()), this.evaluator, this.helper);
284             List JavaDoc<ProjectModel.CompilationUnitKey> cuKeys = pm.createCompilationUnitKeys();
285             assert cuKeys != null;
286             boolean hasOutputs = false;
287             for (Iterator JavaDoc it = cuKeys.iterator(); it.hasNext();) {
288                 ProjectModel.CompilationUnitKey ck = (ProjectModel.CompilationUnitKey) it.next();
289                 JavaProjectGenerator.JavaCompilationUnit cu = pm.getCompilationUnit(ck,false);
290                 if (cu.output != null && cu.output.size()>0) {
291                     hasOutputs = true;
292                     break;
293                 }
294             }
295             if (!hasOutputs) {
296                 alertOutputs (NbBundle.getMessage(JavaActions.class, "ACTION_debug"));
297                 this.setOutputsNotified = true;
298                 return;
299             }
300         }
301         String JavaDoc[] bindings = findCommandBinding(ActionProvider.COMMAND_RUN);
302         Element JavaDoc task = null;
303         Element JavaDoc origTarget = null;
304         if (bindings != null && bindings.length <= 2) {
305             origTarget = findExistingBuildTarget(ActionProvider.COMMAND_RUN);
306             //The origTarget may be null if the user has removed it from build.xml
307
if (origTarget != null) {
308                 task = targetUsesTaskExactlyOnce(origTarget, "java"); // NOI18N
309
}
310         }
311         
312         if (!alert(NbBundle.getMessage(JavaActions.class, "ACTION_debug"), task != null ? GENERAL_SCRIPT_PATH : FILE_SCRIPT_PATH)) {
313             return;
314         }
315         
316         String JavaDoc generatedTargetName = "debug-nb"; // NOI18N
317
String JavaDoc generatedScriptPath;
318         Document JavaDoc doc;
319         Element JavaDoc generatedTarget;
320         if (task != null) {
321             // We can copy the original run target with some modifications.
322
generatedScriptPath = GENERAL_SCRIPT_PATH;
323             doc = readCustomScript(GENERAL_SCRIPT_PATH);
324             ensureImports(doc.getDocumentElement(), bindings[0]);
325             generatedTarget = createDebugTargetFromTemplate(generatedTargetName, origTarget, task, doc);
326         } else {
327             // No info, need to generate a dummy debug target.
328
generatedScriptPath = FILE_SCRIPT_PATH;
329             doc = readCustomScript(FILE_SCRIPT_PATH);
330             ensurePropertiesCopied(doc.getDocumentElement());
331             generatedTarget = createDebugTargetFromScratch(generatedTargetName, doc);
332         }
333         Comment JavaDoc comm = doc.createComment(" " + NbBundle.getMessage(JavaActions.class, "COMMENT_edit_target") + " ");
334         doc.getDocumentElement().appendChild(comm);
335         comm = doc.createComment(" " + NbBundle.getMessage(JavaActions.class, "COMMENT_more_info_debug") + " ");
336         doc.getDocumentElement().appendChild(comm);
337         doc.getDocumentElement().appendChild(generatedTarget);
338         writeCustomScript(doc, generatedScriptPath);
339         addBinding(ActionProvider.COMMAND_DEBUG, generatedScriptPath, generatedTargetName, null, null, null, null, null);
340         jumpToBinding(ActionProvider.COMMAND_DEBUG);
341         jumpToBuildScript(generatedScriptPath, generatedTargetName);
342     }
343     
344     private Element JavaDoc createNbjpdastart(Document JavaDoc ownerDocument) {
345         Element JavaDoc nbjpdastart = ownerDocument.createElement("nbjpdastart"); // NOI18N
346
nbjpdastart.setAttribute("name", ProjectUtils.getInformation(project).getDisplayName()); // NOI18N
347
nbjpdastart.setAttribute("addressproperty", "jpda.address"); // NOI18N
348
nbjpdastart.setAttribute("transport", "dt_socket"); // NOI18N
349
return nbjpdastart;
350     }
351     
352     private static final String JavaDoc[] DEBUG_VM_ARGS = {
353         "-Xdebug", // NOI18N
354
"-Xrunjdwp:transport=dt_socket,address=${jpda.address}", // NOI18N
355
};
356     private void addDebugVMArgs(Element JavaDoc java, Document JavaDoc ownerDocument) {
357         //Add fork="true" if not alredy there
358
NamedNodeMap JavaDoc attrs = java.getAttributes();
359         boolean found = false;
360         for (int i=0; i<attrs.getLength(); i++) {
361             Attr JavaDoc attr = (Attr JavaDoc) attrs.item(i);
362             if ("fork".equals(attr.getName())) { //NOI18N
363
String JavaDoc value = attr.getValue();
364                 if ("on".equalsIgnoreCase (value) || //NOI18N
365
"true".equalsIgnoreCase(value) || //NOI18N
366
"yes".equalsIgnoreCase(value)) { //NOI18N
367
found = true;
368                 }
369                 break;
370             }
371         }
372         if (!found) {
373             java.setAttribute("fork", "true"); //NOI18N
374
}
375         for (int i = 0; i < DEBUG_VM_ARGS.length; i++) {
376             Element JavaDoc jvmarg = ownerDocument.createElement("jvmarg"); // NOI18N
377
jvmarg.setAttribute("value", DEBUG_VM_ARGS[i]); // NOI18N
378
java.appendChild(jvmarg);
379         }
380     }
381     
382     Element JavaDoc createDebugTargetFromTemplate(String JavaDoc generatedTargetName, Element JavaDoc origTarget, Element JavaDoc origTask, Document JavaDoc ownerDocument) {
383         NodeList JavaDoc tasks = origTarget.getChildNodes();
384         int taskIndex = -1;
385         for (int i = 0; i < tasks.getLength(); i++) {
386             if (tasks.item(i) == origTask) {
387                 taskIndex = i;
388                 break;
389             }
390         }
391         assert taskIndex != -1;
392         Element JavaDoc target = (Element JavaDoc) ownerDocument.importNode(origTarget, true);
393         addJdkInitDeps(target);
394         Element JavaDoc task = (Element JavaDoc) target.getChildNodes().item(taskIndex);
395         target.setAttribute("name", generatedTargetName); // NOI18N
396
Element JavaDoc nbjpdastart = createNbjpdastart(ownerDocument);
397         String JavaDoc textualCp = task.getAttribute("classpath"); // NOI18N
398
if (textualCp.length() > 0) {
399             Element JavaDoc classpath = ownerDocument.createElement("classpath"); // NOI18N
400
classpath.setAttribute("path", textualCp); // NOI18N
401
nbjpdastart.appendChild(classpath);
402         } else {
403             NodeList JavaDoc origClasspath = task.getElementsByTagName("classpath"); // NOI18N
404
if (origClasspath.getLength() == 1) {
405                 Element JavaDoc classpath = (Element JavaDoc) ownerDocument.importNode(origClasspath.item(0), true);
406                 nbjpdastart.appendChild(classpath);
407             }
408         }
409         target.insertBefore(nbjpdastart, task);
410         addDebugVMArgs(task, ownerDocument);
411         return target;
412     }
413     
414     Element JavaDoc createDebugTargetFromScratch(String JavaDoc generatedTargetName, Document JavaDoc ownerDocument) {
415         Element JavaDoc target = ownerDocument.createElement("target");
416         addJdkInitDeps(target);
417         target.setAttribute("name", generatedTargetName); // NOI18N
418
Element JavaDoc path = ownerDocument.createElement("path"); // NOI18N
419
// XXX would be better to determine runtime CP from project.xml and put it here instead (if that is possible)...
420
path.setAttribute("id", "cp"); // NOI18N
421
path.appendChild(ownerDocument.createComment(" " + NbBundle.getMessage(JavaActions.class, "COMMENT_set_runtime_cp") + " "));
422         target.appendChild(path);
423         Element JavaDoc nbjpdastart = createNbjpdastart(ownerDocument);
424         Element JavaDoc classpath = ownerDocument.createElement("classpath"); // NOI18N
425
classpath.setAttribute("refid", "cp"); // NOI18N
426
nbjpdastart.appendChild(classpath);
427         target.appendChild(nbjpdastart);
428         target.appendChild(ownerDocument.createComment(" " + NbBundle.getMessage(JavaActions.class, "COMMENT_set_main_class") + " "));
429         Element JavaDoc java = ownerDocument.createElement("java"); // NOI18N
430
java.setAttribute("classname", "some.main.Class"); // NOI18N
431
classpath = ownerDocument.createElement("classpath"); // NOI18N
432
classpath.setAttribute("refid", "cp"); // NOI18N
433
java.appendChild(classpath);
434         addDebugVMArgs(java, ownerDocument);
435         target.appendChild(java);
436         return target;
437     }
438     
439     /**
440      * Read a generated script if it exists, else create a skeleton.
441      * Imports jdk.xml if appropriate.
442      * @param scriptPath e.g. {@link #FILE_SCRIPT_PATH} or {@link #GENERAL_SCRIPT_PATH}
443      */

444     Document JavaDoc readCustomScript(String JavaDoc scriptPath) throws IOException JavaDoc, SAXException JavaDoc {
445         // XXX if there is TAX support for rewriting XML files, use that here...
446
FileObject script = helper.getProjectDirectory().getFileObject(scriptPath);
447         Document JavaDoc doc;
448         if (script != null) {
449             InputStream JavaDoc is = script.getInputStream();
450             try {
451                 doc = XMLUtil.parse(new InputSource JavaDoc(is), false, true, null, null);
452             } finally {
453                 is.close();
454             }
455         } else {
456             doc = XMLUtil.createDocument("project", /*XXX:"antlib:org.apache.tools.ant"*/null, null, null); // NOI18N
457
Element JavaDoc root = doc.getDocumentElement();
458             String JavaDoc projname = ProjectUtils.getInformation(project).getDisplayName();
459             root.setAttribute("name", NbBundle.getMessage(JavaActions.class, "LBL_generated_script_name", projname));
460         }
461         if (helper.getProjectDirectory().getFileObject(JdkConfiguration.JDK_XML) != null) {
462             JdkConfiguration.insertJdkXmlImport(doc);
463         }
464         return doc;
465     }
466     
467     /**
468      * Make sure that if the project defines ${project.dir} in project.xml that
469      * a custom build script also defines this property.
470      * Generally, copy any properties defined in project.xml to Ant syntax.
471      * Used for generated targets which essentially copy Ant fragments from project.xml
472      * (rather than the user's build.xml).
473      * Also sets the basedir to the (IDE) project directory.
474      * Idempotent, takes effect only once.
475      * Use with {@link #FILE_SCRIPT_PATH}.
476      * @param antProject XML of an Ant project (document element)
477      */

478     void ensurePropertiesCopied(Element JavaDoc antProject) {
479         if (antProject.getAttribute("basedir").length() > 0) {
480             // Do not do it twice to the same script.
481
return;
482         }
483         antProject.setAttribute("basedir", /* ".." times count('/', FILE_SCRIPT_PATH) */".."); // NOI18N
484
// Look for <properties> in project.xml and make corresponding definitions in the Ant script.
485
Element JavaDoc data = Util.getPrimaryConfigurationData(helper);
486         Element JavaDoc properties = Util.findElement(data, "properties", Util.NAMESPACE);
487         if (properties != null) {
488             for (Element JavaDoc el : Util.findSubElements(properties)) {
489                 Element JavaDoc nue = antProject.getOwnerDocument().createElement("property"); // NOI18N
490
if (el.getLocalName().equals("property")) { // NOI18N
491
String JavaDoc name = el.getAttribute("name"); // NOI18N
492
assert name != null;
493                     String JavaDoc text = Util.findText(el);
494                     assert text != null;
495                     nue.setAttribute("name", name);
496                     nue.setAttribute("value", text);
497                 } else if (el.getLocalName().equals("property-file")) { // NOI18N
498
String JavaDoc text = Util.findText(el);
499                     assert text != null;
500                     nue.setAttribute("file", text);
501                 } else {
502                     assert false : el;
503                 }
504                 antProject.appendChild(nue);
505             }
506         }
507     }
508     
509     /**
510      * Make sure that the custom build script imports the original build script
511      * and is using the same base dir.
512      * Used for generated targets which essentially copy Ant targets from build.xml.
513      * Use with {@link #GENERAL_SCRIPT_PATH}.
514      * Idempotent, takes effect only once.
515      * @param antProject XML of an Ant project (document element)
516      * @oaram origScriptPath Ant name of original build script's path
517      */

518     void ensureImports(Element JavaDoc antProject, String JavaDoc origScriptPath) throws IOException JavaDoc, SAXException JavaDoc {
519         if (antProject.getAttribute("basedir").length() > 0) {
520             // Do not do it twice to the same script.
521
return;
522         }
523         String JavaDoc origScriptPathEval = evaluator.evaluate(origScriptPath);
524         if (origScriptPathEval == null) {
525             // Can't do anything, forget it.
526
return;
527         }
528         String JavaDoc origScriptURI = helper.resolveFile(origScriptPathEval).toURI().toString();
529         Document JavaDoc origScriptDocument = XMLUtil.parse(new InputSource JavaDoc(origScriptURI), false, true, null, null);
530         String JavaDoc origBasedir = origScriptDocument.getDocumentElement().getAttribute("basedir"); // NOI18N
531
if (origBasedir.length() == 0) {
532             origBasedir = "."; // NOI18N
533
}
534         String JavaDoc basedir, importPath;
535         File JavaDoc origScript = new File JavaDoc(origScriptPathEval);
536         if (origScript.isAbsolute()) {
537             // Use full path.
538
importPath = origScriptPathEval;
539             if (new File JavaDoc(origBasedir).isAbsolute()) {
540                 basedir = origBasedir;
541             } else {
542                 basedir = PropertyUtils.resolveFile(origScript.getParentFile(), origBasedir).getAbsolutePath();
543             }
544         } else {
545             // Import relative to that path.
546
// Note that <import>'s path is always relative to the location of the importing script, regardless of the basedir.
547
String JavaDoc prefix = /* ".." times count('/', FILE_SCRIPT_PATH) */"../"; // NOI18N
548
importPath = prefix + origScriptPathEval;
549             if (new File JavaDoc(origBasedir).isAbsolute()) {
550                 basedir = origBasedir;
551             } else {
552                 int slash = origScriptPathEval.replace(File.separatorChar, '/').lastIndexOf('/');
553                 if (slash == -1) {
554                     basedir = prefix + origBasedir;
555                 } else {
556                     basedir = prefix + origScriptPathEval.substring(0, slash + 1) + origBasedir;
557                 }
558                 // Trim:
559
basedir = basedir.replaceAll("/\\.$", ""); // NOI18N
560
}
561         }
562         antProject.setAttribute("basedir", basedir); // NOI18N
563
Element JavaDoc importEl = antProject.getOwnerDocument().createElement("import"); // NOI18N
564
importEl.setAttribute("file", importPath); // NOI18N
565
antProject.appendChild(importEl);
566     }
567     
568     /**
569      * Write a script with a new or modified document.
570      * @param scriptPath e.g. {@link #FILE_SCRIPT_PATH} or {@link #GENERAL_SCRIPT_PATH}
571      */

572     void writeCustomScript(Document JavaDoc doc, String JavaDoc scriptPath) throws IOException JavaDoc {
573         FileObject script = helper.getProjectDirectory().getFileObject(scriptPath);
574         if (script == null) {
575             script = FileUtil.createData(helper.getProjectDirectory(), scriptPath);
576         }
577         FileLock lock = script.lock();
578         try {
579             OutputStream JavaDoc os = script.getOutputStream(lock);
580             try {
581                 XMLUtil.write(doc, os, "UTF-8"); // NOI18N
582
} finally {
583                 os.close();
584             }
585         } finally {
586             lock.releaseLock();
587         }
588     }
589     
590     private List JavaDoc<Element JavaDoc> compilationUnits() {
591         Element JavaDoc java = aux.getConfigurationFragment(JavaProjectNature.EL_JAVA, JavaProjectNature.NS_JAVA_2, true);
592         if (java == null) {
593             return Collections.emptyList();
594         }
595         return Util.findSubElements(java);
596     }
597     
598     /**
599      * Find a Java package root in which the selection is contained.
600      * @param context lookup with Java source files and/or folders and/or junk
601      * @return the package root if there is one, or null if the lookup is empty, has junk, or has multiple roots
602      */

603     AntLocation findPackageRoot(Lookup context) {
604         for (Element JavaDoc compilationUnitEl : compilationUnits()) {
605             assert compilationUnitEl.getLocalName().equals("compilation-unit") : compilationUnitEl;
606             List JavaDoc<String JavaDoc> packageRootNames = Classpaths.findPackageRootNames(compilationUnitEl);
607             Map JavaDoc<String JavaDoc,FileObject> packageRootsByName = Classpaths.findPackageRootsByName(helper, evaluator, packageRootNames);
608             for (Map.Entry JavaDoc<String JavaDoc,FileObject> entry : packageRootsByName.entrySet()) {
609                 FileObject root = entry.getValue();
610                 if (containsSelectedJavaSources(root, context)) {
611                     return new AntLocation(entry.getKey(), root);
612                 }
613             }
614         }
615         // Couldn't find it.
616
return null;
617     }
618     
619     /**
620      * Check to see if a (node-like) selection contains one or more Java sources (or folders) inside the root.
621      */

622     static boolean containsSelectedJavaSources(FileObject root, Lookup context) {
623         Set JavaDoc<FileObject> selection = new HashSet JavaDoc<FileObject>(context.lookupAll(FileObject.class));
624         for (DataObject dob : context.lookupAll(DataObject.class)) {
625             selection.add(dob.getPrimaryFile());
626         }
627         if (selection.isEmpty()) {
628             return false;
629         }
630         for (FileObject f : selection) {
631             if (f.isData() && !f.hasExt("java")) { // NOI18N
632
return false;
633             }
634             if (f != root && !FileUtil.isParentOf(root, f)) {
635                 return false;
636             }
637         }
638         return true;
639     }
640     
641     /**
642      * Represents a location as referred to by the Ant script.
643      * Contains both its logical representation, and actual (current) location (or null).
644      */

645     static final class AntLocation {
646         public final String JavaDoc virtual;
647         public final FileObject physical;
648         public AntLocation(String JavaDoc virtual, FileObject physical) {
649             this.virtual = virtual;
650             this.physical = physical;
651         }
652         public String JavaDoc toString() {
653             return "AntLocation[" + virtual + "=" + physical + "]"; // NOI18N
654
}
655     }
656     
657     /**
658      * Try to find the compilation unit containing a source root.
659      * @param sources a source root in the project (as a virtual Ant name)
660      * @return the compilation unit owning it, or null if not found
661      */

662     private Element JavaDoc findCompilationUnit(String JavaDoc sources) {
663         for (Element JavaDoc compilationUnitEl : compilationUnits()) {
664             for (Element JavaDoc packageRoot : Util.findSubElements(compilationUnitEl)) {
665                 if (packageRoot.getLocalName().equals("package-root")) { // NOI18N
666
if (Util.findText(packageRoot).equals(sources)) {
667                         return compilationUnitEl;
668                     }
669                 }
670             }
671         }
672         return null;
673     }
674     
675     /**
676      * Try to determine where classes from a given package root should be compiled to.
677      * @param sources a source root in the project (as a virtual Ant name)
678      * @return an output directory (never a JAR), as a virtual name, or null if none could be found
679      */

680     String JavaDoc findClassesOutputDir(String JavaDoc sources) {
681         Element JavaDoc compilationUnitEl = findCompilationUnit(sources);
682         if (compilationUnitEl != null) {
683             return findClassesOutputDir(compilationUnitEl);
684         } else {
685             return null;
686         }
687     }
688     
689     /**
690      * Find output classes given a compilation unit from project.xml.
691      */

692     private String JavaDoc findClassesOutputDir(Element JavaDoc compilationUnitEl) {
693         // Look for an appropriate <built-to>.
694
for (Element JavaDoc builtTo : Util.findSubElements(compilationUnitEl)) {
695             if (builtTo.getLocalName().equals("built-to")) { // NOI18N
696
String JavaDoc rawtext = Util.findText(builtTo);
697                 // Check that it is not an archive.
698
String JavaDoc evaltext = evaluator.evaluate(rawtext);
699                 if (evaltext != null) {
700                     File JavaDoc dest = helper.resolveFile(evaltext);
701                     URL JavaDoc destU;
702                     try {
703                         destU = dest.toURI().toURL();
704                     } catch (MalformedURLException JavaDoc e) {
705                         throw new AssertionError JavaDoc(e);
706                     }
707                     if (!FileUtil.isArchiveFile(destU)) {
708                         // OK, dir, take it.
709
return rawtext;
710                     }
711                 }
712             }
713         }
714         return null;
715     }
716     
717     /**
718      * Try to find the source level corresponding to a source root.
719      * @param sources a source root in the project (as a virtual Ant name)
720      * @return the source level, or null if none was specified or there was no such source root
721      */

722     String JavaDoc findSourceLevel(String JavaDoc sources) {
723         Element JavaDoc compilationUnitEl = findCompilationUnit(sources);
724         if (compilationUnitEl != null) {
725             Element JavaDoc sourceLevel = Util.findElement(compilationUnitEl, "source-level", JavaProjectNature.NS_JAVA_2);
726             if (sourceLevel != null) {
727                 return Util.findText(sourceLevel);
728             }
729         }
730         return null;
731     }
732     
733     /**
734      * Try to find the compile-time classpath corresponding to a source root.
735      * @param sources a source root in the project (as a virtual Ant name)
736      * @return the classpath (in Ant form), or null if none was specified or there was no such source root
737      */

738     String JavaDoc findCUClasspath(String JavaDoc sources, String JavaDoc moud) {
739         Element JavaDoc compilationUnitEl = findCompilationUnit(sources);
740         if (compilationUnitEl != null) {
741             for (Element JavaDoc classpath : Util.findSubElements(compilationUnitEl)) {
742                 if (classpath.getLocalName().equals("classpath")) { // NOI18N
743
String JavaDoc mode = classpath.getAttribute("mode"); // NOI18N
744
if (mode.equals(moud)) {
745                         return Util.findText(classpath);
746                     }
747                 }
748             }
749         }
750         return null;
751     }
752
753     /**
754      * Finds all build-to elements in project.xml and returns their content as array
755      * @param srcRoot source root in the project
756      * @return array with content of all <built-to> elements built by CU containing the srcRoot
757      */

758     private String JavaDoc[] findCUOutputs(String JavaDoc srcRoot) {
759         List JavaDoc<String JavaDoc> outputs = new ArrayList JavaDoc<String JavaDoc>();
760         Element JavaDoc cuElem = findCompilationUnit(srcRoot);
761         if (cuElem != null) {
762             NodeList JavaDoc builts = cuElem.getElementsByTagName("built-to"); // NOI18N
763
for (int i = 0; i < builts.getLength(); i++) {
764                 outputs.add(builts.item(i).getTextContent());
765             }
766         }
767         return outputs.toArray(new String JavaDoc[outputs.size()]);
768     }
769
770     //The order of the root elements as specified in the schema.
771
//Used to add <ide-actions> at the correct place.
772
private static final String JavaDoc[] rootElementsOrder = {"name", "properties", "folders", "ide-actions", "export", "view", "subprojects"}; // NOI18N
773

774     /**
775      * Add an action binding to project.xml.
776      * If there is no required context, the action is also added to the context menu of the project node.
777      * @param command the command name
778      * @param scriptPath the path to the generated script
779      * @param target the name of the target (in scriptPath)
780      * @param propertyName a property name to hold the selection (or null for no context, in which case remainder should be null)
781      * @param dir the raw text to use for the directory name
782      * @param pattern the regular expression to match, or null
783      * @param format the format to use
784      * @param separator the separator to use for multiple files, or null for single file only
785      */

786     void addBinding(String JavaDoc command, String JavaDoc scriptPath, String JavaDoc target, String JavaDoc propertyName, String JavaDoc dir, String JavaDoc pattern, String JavaDoc format, String JavaDoc separator) throws IOException JavaDoc {
787         // XXX cannot use FreeformProjectGenerator since that is currently not a public support SPI from ant/freeform
788
// XXX should this try to find an existing binding? probably not, since it is assumed that if there was one, we would never get here to begin with
789
Element JavaDoc data = Util.getPrimaryConfigurationData(helper);
790         Element JavaDoc ideActions = Util.findElement(data, "ide-actions", Util.NAMESPACE); // NOI18N
791
if (ideActions == null) {
792             //fix for #58442:
793
ideActions = data.getOwnerDocument().createElementNS(Util.NAMESPACE, "ide-actions"); // NOI18N
794
Util.appendChildElement(data, ideActions, rootElementsOrder);
795         }
796         Document JavaDoc doc = data.getOwnerDocument();
797         Element JavaDoc action = doc.createElementNS(Util.NAMESPACE, "action"); // NOI18N
798
action.setAttribute("name", command); // NOI18N
799
Element JavaDoc script = doc.createElementNS(Util.NAMESPACE, "script"); // NOI18N
800
script.appendChild(doc.createTextNode(scriptPath));
801         action.appendChild(script);
802         Element JavaDoc targetEl = doc.createElementNS(Util.NAMESPACE, "target"); // NOI18N
803
targetEl.appendChild(doc.createTextNode(target));
804         action.appendChild(targetEl);
805         if (propertyName != null) {
806             Element JavaDoc context = doc.createElementNS(Util.NAMESPACE, "context"); // NOI18N
807
Element JavaDoc property = doc.createElementNS(Util.NAMESPACE, "property"); // NOI18N
808
property.appendChild(doc.createTextNode(propertyName));
809             context.appendChild(property);
810             Element JavaDoc folder = doc.createElementNS(Util.NAMESPACE, "folder"); // NOI18N
811
folder.appendChild(doc.createTextNode(dir));
812             context.appendChild(folder);
813             if (pattern != null) {
814                 Element JavaDoc patternEl = doc.createElementNS(Util.NAMESPACE, "pattern"); // NOI18N
815
patternEl.appendChild(doc.createTextNode(pattern));
816                 context.appendChild(patternEl);
817             }
818             Element JavaDoc formatEl = doc.createElementNS(Util.NAMESPACE, "format"); // NOI18N
819
formatEl.appendChild(doc.createTextNode(format));
820             context.appendChild(formatEl);
821             Element JavaDoc arity = doc.createElementNS(Util.NAMESPACE, "arity"); // NOI18N
822
if (separator != null) {
823                 Element JavaDoc separatorEl = doc.createElementNS(Util.NAMESPACE, "separated-files"); // NOI18N
824
separatorEl.appendChild(doc.createTextNode(separator));
825                 arity.appendChild(separatorEl);
826             } else {
827                 arity.appendChild(doc.createElementNS(Util.NAMESPACE, "one-file-only")); // NOI18N
828
}
829             context.appendChild(arity);
830             action.appendChild(context);
831         } else {
832             // Add a context menu item, since it applies to the project as a whole.
833
// Assume there is already a <context-menu> defined, which is quite likely.
834
Element JavaDoc view = Util.findElement(data, "view", Util.NAMESPACE); // NOI18N
835
if (view != null) {
836                 Element JavaDoc contextMenu = Util.findElement(view, "context-menu", Util.NAMESPACE); // NOI18N
837
if (contextMenu != null) {
838                     Element JavaDoc ideAction = doc.createElementNS(Util.NAMESPACE, "ide-action"); // NOI18N
839
ideAction.setAttribute("name", command); // NOI18N
840
contextMenu.appendChild(ideAction);
841                 }
842             }
843         }
844         ideActions.appendChild(action);
845         Util.putPrimaryConfigurationData(helper, data);
846         ProjectManager.getDefault().saveProject(project);
847     }
848
849     /**
850      * Jump to a target in the editor.
851      * @param scriptPath the script to open
852      * @param target the name of the target (in scriptPath)
853      */

854     private void jumpToBuildScript(String JavaDoc scriptPath, String JavaDoc target) {
855         jumpToFile(scriptPath, target, "target", "name"); // NOI18N
856
}
857     
858     /**
859      * Jump to an action binding in the editor.
860      * @param command an {@link ActionProvider} command name found in project.xml
861      */

862     private void jumpToBinding(String JavaDoc command) {
863         jumpToFile(AntProjectHelper.PROJECT_XML_PATH, command, "action", "name"); // NOI18N
864
}
865
866     /**
867      * Jump to some line in an XML file.
868      * @param path project-relative path to the file
869      * @param match {@see #findLine}
870      * @param elementLocalName {@see #findLine}
871      * @param elementAttributeName {@see #findLine}
872      */

873     private void jumpToFile(String JavaDoc path, String JavaDoc match, String JavaDoc elementLocalName, String JavaDoc elementAttributeName) {
874         FileObject file = helper.getProjectDirectory().getFileObject(path);
875         if (file == null) {
876             return;
877         }
878         int line;
879         try {
880             line = findLine(file, match, elementLocalName, elementAttributeName);
881         } catch (Exception JavaDoc e) {
882             ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
883             return;
884         }
885         if (line == -1) {
886             // Just open it.
887
line = 0;
888         }
889         DataObject fileDO;
890         try {
891             fileDO = DataObject.find(file);
892         } catch (DataObjectNotFoundException e) {
893             throw new AssertionError JavaDoc(e);
894         }
895         LineCookie lines = fileDO.getCookie(LineCookie.class);
896         if (lines != null) {
897             try {
898                 lines.getLineSet().getCurrent(line).show(Line.SHOW_GOTO);
899             } catch (IndexOutOfBoundsException JavaDoc e) {
900                 // XXX reproducibly thrown if the document was already open. Why?? (file.refresh() above does not help.)
901
ErrorManager.getDefault().getInstance(JavaActions.class.getName()).log(ErrorManager.WARNING, e + " [file=" + file + " match=" + match + " line=" + line + "]"); // NOI18N
902
lines.getLineSet().getCurrent(0).show(Line.SHOW_GOTO);
903             }
904         }
905     }
906     
907     /**
908      * Find the line number of a target in an Ant script, or some other line in an XML file.
909      * Able to find a certain element with a certain attribute matching a given value.
910      * See also AntTargetNode.TargetOpenCookie.
911      * @param file an Ant script or other XML file
912      * @param match the attribute value to match (e.g. target name)
913      * @param elementLocalName the (local) name of the element to look for
914      * @param elementAttributeName the name of the attribute to match on
915      * @return the line number (0-based), or -1 if not found
916      */

917     static final int findLine(FileObject file, final String JavaDoc match, final String JavaDoc elementLocalName, final String JavaDoc elementAttributeName) throws IOException JavaDoc, SAXException JavaDoc, ParserConfigurationException JavaDoc {
918         InputSource JavaDoc in = new InputSource JavaDoc(file.getURL().toString());
919         SAXParserFactory JavaDoc factory = SAXParserFactory.newInstance();
920         factory.setNamespaceAware(true);
921         SAXParser JavaDoc parser = factory.newSAXParser();
922         final int[] line = new int[] {-1};
923         class Handler extends DefaultHandler JavaDoc {
924             private Locator JavaDoc locator;
925             public void setDocumentLocator(Locator JavaDoc l) {
926                 locator = l;
927             }
928             public void startElement(String JavaDoc uri, String JavaDoc localname, String JavaDoc qname, Attributes JavaDoc attr) throws SAXException JavaDoc {
929                 if (line[0] == -1) {
930                     if (localname.equals(elementLocalName) && match.equals(attr.getValue(elementAttributeName))) { // NOI18N
931
line[0] = locator.getLineNumber() - 1;
932                     }
933                 }
934             }
935         }
936         parser.parse(in, new Handler JavaDoc());
937         return line[0];
938     }
939     
940     /**
941      * Attempt to find the Ant build script target bound to a given IDE command.
942      * @param command an {@link ActionProvider} command
943      * @return the XML for the target if it could be found (and there was no more than one target bound), else null
944      */

945     Element JavaDoc findExistingBuildTarget(String JavaDoc command) throws IOException JavaDoc, SAXException JavaDoc {
946         String JavaDoc[] binding = findCommandBinding(command);
947         if (binding == null) {
948             return null;
949         }
950         String JavaDoc scriptName = binding[0];
951         assert scriptName != null;
952         String JavaDoc targetName;
953         if (binding.length == 1) {
954             targetName = null;
955         } else if (binding.length == 2) {
956             targetName = binding[1];
957         } else {
958             // Too many bindings; we do not support this.
959
return null;
960         }
961         String JavaDoc scriptPath = evaluator.evaluate(scriptName);
962         if (scriptPath == null) {
963             return null;
964         }
965         File JavaDoc scriptFile = helper.resolveFile(scriptPath);
966         String JavaDoc scriptURI = scriptFile.toURI().toString();
967         Document JavaDoc doc = XMLUtil.parse(new InputSource JavaDoc(scriptURI), false, true, null, null);
968         if (targetName == null) {
969             targetName = doc.getDocumentElement().getAttribute("default"); // NOI18N
970
if (targetName == null) {
971                 return null;
972             }
973         }
974         for (Element JavaDoc target : Util.findSubElements(doc.getDocumentElement())) {
975             if (target.getLocalName().equals("target") && targetName.equals(target.getAttribute("name"))) { // NOI18N
976
return target;
977             }
978         }
979         return null;
980     }
981
982     /**
983      * Find the target binding for some command.
984      * @param command an {@link ActionProvider} command
985      * @return an array of a script name (Ant syntax, never null) and zero or more target names (none means default target)
986      * or null if no binding could be found for this command
987      */

988     String JavaDoc[] findCommandBinding(String JavaDoc command) {
989         Element JavaDoc data = Util.getPrimaryConfigurationData(helper);
990         Element JavaDoc ideActions = Util.findElement(data, "ide-actions", Util.NAMESPACE); // NOI18N
991
if (ideActions == null) {
992             return null;
993         }
994         String JavaDoc scriptName = "build.xml"; // NOI18N
995
for (Element JavaDoc action : Util.findSubElements(ideActions)) {
996             assert action.getLocalName().equals("action");
997             if (action.getAttribute("name").equals(command)) {
998                 Element JavaDoc script = Util.findElement(action, "script", Util.NAMESPACE); // NOI18N
999
if (script != null) {
1000                    scriptName = Util.findText(script);
1001                }
1002                List JavaDoc<String JavaDoc> scriptPlusTargetNames = new ArrayList JavaDoc<String JavaDoc>();
1003                scriptPlusTargetNames.add(scriptName);
1004                for (Element JavaDoc target : Util.findSubElements(action)) {
1005                    if (target.getLocalName().equals("target")) { // NOI18N
1006
scriptPlusTargetNames.add(Util.findText(target));
1007                    }
1008                }
1009                if (scriptName.equals(JdkConfiguration.NBJDK_XML) && scriptPlusTargetNames.size() > 1) {
1010                    // Try to find the original script instead.
1011
FileObject nbjdkFO = helper.getProjectDirectory().getFileObject(JdkConfiguration.NBJDK_XML);
1012                    if (nbjdkFO != null) {
1013                        try {
1014                            Document JavaDoc nbjdk = XMLUtil.parse(new InputSource JavaDoc(nbjdkFO.getURL().toString()), false, false, null, null);
1015                            NodeList JavaDoc nl = nbjdk.getElementsByTagName("target"); // NOI18N
1016
for (int i = 0; i < nl.getLength(); i++) {
1017                                if (((Element JavaDoc) nl.item(i)).getAttribute("name").equals(scriptPlusTargetNames.get(1))) { // NOI18N
1018
NodeList JavaDoc nl2 = ((Element JavaDoc) nl.item(i)).getElementsByTagName("ant"); // NOI18N
1019
if (nl2.getLength() == 1) {
1020                                        String JavaDoc antfile = ((Element JavaDoc) nl2.item(0)).getAttribute("antfile"); // NOI18N
1021
if (antfile.length() == 0) {
1022                                            antfile = "build.xml"; // NOI18N
1023
}
1024                                        scriptPlusTargetNames.set(0, antfile);
1025                                        break;
1026                                    }
1027                                }
1028                            }
1029                        } catch (Exception JavaDoc x) {
1030                            Exceptions.printStackTrace(x);
1031                        }
1032                    }
1033                }
1034                return scriptPlusTargetNames.toArray(new String JavaDoc[scriptPlusTargetNames.size()]);
1035            }
1036        }
1037        return null;
1038    }
1039    
1040    /**
1041     * Check to see if a given Ant target uses a given task once (and only once).
1042     * @param target an Ant <code>&lt;target&gt;</code> element
1043     * @param taskName the (unqualified) name of an Ant task
1044     * @return a task element with that name, or null if there is none or more than one
1045     */

1046    Element JavaDoc targetUsesTaskExactlyOnce(Element JavaDoc target, String JavaDoc taskName) {
1047        // XXX should maybe also look for any other usage of the task in the same script in case there is none in the mentioned target
1048
Element JavaDoc foundTask = null;
1049        for (Element JavaDoc task : Util.findSubElements(target)) {
1050            if (task.getLocalName().equals(taskName)) {
1051                if (foundTask != null) {
1052                    // Duplicate.
1053
return null;
1054                } else {
1055                    foundTask = task;
1056                }
1057            }
1058        }
1059        return foundTask;
1060    }
1061
1062    private void handleRunSingle(Lookup context) throws IOException JavaDoc, SAXException JavaDoc {
1063        if (!alert(NbBundle.getMessage(JavaActions.class, "ACTION_run.single"), FILE_SCRIPT_PATH)) {
1064            return;
1065        }
1066        Document JavaDoc doc = readCustomScript(FILE_SCRIPT_PATH);
1067        AntLocation root = handleInitials(doc, context);
1068        assert root != null : context;
1069        String JavaDoc propertyName = "run.class"; // NOI18N
1070
String JavaDoc targetName = "run-selected-file-in-" + root.physical.getNameExt(); // NOI18N
1071
Element JavaDoc target = createRunSingleTargetElem(doc, targetName, propertyName, root);
1072        doc.getDocumentElement().appendChild(target);
1073        writeCustomScript(doc, FILE_SCRIPT_PATH);
1074        addBinding(ActionProvider.COMMAND_RUN_SINGLE, FILE_SCRIPT_PATH, targetName,
1075                propertyName, root.virtual, JAVA_FILE_PATTERN, "java-name", null); // NOI18N
1076
jumpToBinding(ActionProvider.COMMAND_RUN_SINGLE);
1077        jumpToBuildScript(FILE_SCRIPT_PATH, targetName);
1078    }
1079
1080    private void handleDebugSingle(Lookup context) throws IOException JavaDoc, SAXException JavaDoc {
1081        if (!alert(NbBundle.getMessage(JavaActions.class, "ACTION_debug.single"), FILE_SCRIPT_PATH)) {
1082            return;
1083        }
1084        Document JavaDoc doc = readCustomScript(FILE_SCRIPT_PATH);
1085        AntLocation root = handleInitials(doc, context);
1086        assert root != null : context;
1087        String JavaDoc propertyName = "debug.class"; // NOI18N
1088
String JavaDoc targetName = "debug-selected-file-in-" + root.physical.getNameExt(); // NOI18N
1089
Element JavaDoc targetElem = createDebugSingleTargetElem(doc, targetName, propertyName, root);
1090        doc.getDocumentElement().appendChild(targetElem);
1091        writeCustomScript(doc, FILE_SCRIPT_PATH);
1092        addBinding(ActionProvider.COMMAND_DEBUG_SINGLE, FILE_SCRIPT_PATH, targetName,
1093                propertyName, root.virtual, JAVA_FILE_PATTERN, "java-name", null); // NOI18N
1094
jumpToBinding(ActionProvider.COMMAND_DEBUG_SINGLE);
1095        jumpToBuildScript(FILE_SCRIPT_PATH, targetName);
1096    }
1097
1098    Element JavaDoc createRunSingleTargetElem(Document JavaDoc doc, String JavaDoc tgName,
1099                String JavaDoc propName, AntLocation root) throws IOException JavaDoc, SAXException JavaDoc {
1100
1101        Element JavaDoc targetElem = doc.createElement("target"); // NOI18N
1102
addJdkInitDeps(targetElem);
1103        targetElem.setAttribute("name", tgName); // NOI18N
1104
Element JavaDoc failElem = doc.createElement("fail"); // NOI18N
1105
failElem.setAttribute("unless", propName); // NOI18N
1106
failElem.appendChild(doc.createTextNode(NbBundle.getMessage(JavaActions.class,
1107                "COMMENT_must_set_property", propName)));
1108        targetElem.appendChild(failElem);
1109
1110        String JavaDoc depends[] = getRunDepends();
1111        if (depends != null) {
1112            targetElem.appendChild(createAntElem(doc, depends[0], depends[1]));
1113        }
1114
1115        Element JavaDoc javaElem = doc.createElement("java"); // NOI18N
1116
javaElem.setAttribute("classname", "${" + propName + "}"); // NOI18N
1117
javaElem.setAttribute("fork", "true"); // NOI18N
1118
javaElem.setAttribute("failonerror", "true"); // NOI18N
1119

1120        Element JavaDoc cpElem = getPathFromCU(doc, root.virtual, "classpath");
1121        // add comment only if there is no definition
1122
if (cpElem.getChildNodes().getLength() == 0) {
1123            cpElem.appendChild(doc.createComment(" " + NbBundle.getMessage(JavaActions.class,
1124                    "COMMENT_set_runtime_cp") + " "));
1125        }
1126        javaElem.appendChild(cpElem);
1127        targetElem.appendChild(javaElem);
1128        return targetElem;
1129    }
1130
1131    Element JavaDoc createDebugSingleTargetElem(Document JavaDoc doc, String JavaDoc tgName,
1132                String JavaDoc propName, AntLocation root) throws IOException JavaDoc, SAXException JavaDoc {
1133
1134        Element JavaDoc targetElem = doc.createElement("target"); // NOI18N
1135
addJdkInitDeps(targetElem);
1136        targetElem.setAttribute("name", tgName); // NOI18N
1137
Element JavaDoc failElem = doc.createElement("fail"); // NOI18N
1138
failElem.setAttribute("unless", propName); // NOI18N
1139
failElem.appendChild(doc.createTextNode(NbBundle.getMessage(JavaActions.class,
1140                "COMMENT_must_set_property", propName)));
1141        targetElem.appendChild(failElem);
1142
1143        String JavaDoc depends[] = getRunDepends();
1144        if (depends != null) {
1145            targetElem.appendChild(createAntElem(doc, depends[0], depends[1]));
1146        }
1147
1148        Element JavaDoc pElem = getPathFromCU(doc, root.virtual, "path"); // NOI18N
1149
pElem.setAttribute("id", "cp"); // NOI18N
1150
// add comment only if there is no definition
1151
if (pElem.getChildNodes().getLength() == 0) {
1152            pElem.appendChild(doc.createComment(" " + NbBundle.getMessage(JavaActions.class,
1153                    "COMMENT_set_runtime_cp") + " "));
1154        }
1155        targetElem.appendChild(pElem);
1156
1157        Element JavaDoc nbjpdastartElem = createNbjpdastart(doc);
1158        Element JavaDoc cpElem = doc.createElement("classpath"); // NOI18N
1159
cpElem.setAttribute("refid", "cp"); // NOI18N
1160
nbjpdastartElem.appendChild(cpElem);
1161        targetElem.appendChild(nbjpdastartElem);
1162
1163        Element JavaDoc javaElem = doc.createElement("java"); // NOI18N
1164
javaElem.setAttribute("classname", "${" + propName + "}"); // NOI18N
1165

1166        cpElem = doc.createElement("classpath"); // NOI18N
1167
cpElem.setAttribute("refid", "cp"); // NOI18N
1168
javaElem.appendChild(cpElem);
1169        addDebugVMArgs(javaElem, doc);
1170
1171        targetElem.appendChild(javaElem);
1172        return targetElem;
1173    }
1174
1175    private AntLocation handleInitials(Document JavaDoc doc, Lookup context) {
1176        ensurePropertiesCopied(doc.getDocumentElement());
1177        Comment JavaDoc comm = doc.createComment(" " + NbBundle.getMessage(JavaActions.class, "COMMENT_edit_target") + " ");
1178        doc.getDocumentElement().appendChild(comm);
1179        comm = doc.createComment(" " + NbBundle.getMessage(JavaActions.class, "COMMENT_more_info_run.single") + " ");
1180        doc.getDocumentElement().appendChild(comm);
1181        return findPackageRoot(context);
1182    }
1183
1184    /**
1185     * Get value of depends attribute of target mapped as Run target by user
1186     */

1187    String JavaDoc[] getRunDepends() throws IOException JavaDoc, SAXException JavaDoc {
1188        String JavaDoc depends[] = null;
1189        Element JavaDoc targetElem = findExistingBuildTarget(ActionProvider.COMMAND_RUN);
1190        if (targetElem == null)
1191            return null;
1192        String JavaDoc[] bindings = findCommandBinding(ActionProvider.COMMAND_RUN);
1193        String JavaDoc dep = targetElem.getAttribute("depends"); // NOI18N
1194
if (bindings != null && bindings.length <= 2 && !"".equals(dep)) {
1195            depends = new String JavaDoc[2];
1196            depends[0] = bindings[0];
1197            depends[1] = dep;
1198        }
1199        return depends;
1200    }
1201
1202    /**
1203     * Create Path like element (path or classpath) consisting of either execute cp
1204     * if it exists or compilation cp and build products
1205     */

1206    Element JavaDoc getPathFromCU(Document JavaDoc doc, String JavaDoc srcRoot, String JavaDoc type) {
1207        String JavaDoc cp = findCUClasspath(srcRoot, "execute"); // NOI18N
1208
Element JavaDoc pElem = null;
1209        if (cp != null) {
1210            // if EXECUTE cp exists use it
1211
pElem = createPathLikeElem(doc, type, null, new String JavaDoc[] {cp}, null, null, null);
1212        } else {
1213            // if not try to create run cp from COMPILE cp and all output locations
1214
cp = findCUClasspath(srcRoot, "compile"); // NOI18N
1215
String JavaDoc paths[] = cp == null ? null : new String JavaDoc[] {cp};
1216            String JavaDoc outputs[] = findCUOutputs(srcRoot);
1217            pElem = createPathLikeElem(doc, type, null, paths, outputs, null, null);
1218        }
1219        return pElem;
1220    }
1221
1222    /**
1223     * Creates path or classpath element according to params
1224     */

1225    Element JavaDoc createPathLikeElem(Document JavaDoc doc, String JavaDoc type, String JavaDoc id,
1226                String JavaDoc[] paths, String JavaDoc[] locations, String JavaDoc refid, String JavaDoc comm) {
1227
1228        Element JavaDoc pElem = doc.createElement(type); // NOI18N
1229
if (id != null)
1230            pElem.setAttribute("id", id); // NOI18N
1231
if (refid != null)
1232            pElem.setAttribute("refid", refid); // NOI18N
1233
if (comm != null)
1234            pElem.appendChild(doc.createComment(comm));
1235        if (paths != null && paths.length > 0) {
1236            for (int i = 0; i < paths.length; i++) {
1237                Element JavaDoc pathelElem = doc.createElement("pathelement"); // NOI18N
1238
pathelElem.setAttribute("path", paths[i]); // NOI18N
1239
pElem.appendChild(pathelElem);
1240            }
1241        }
1242        if (locations != null && locations.length > 0) {
1243            for (int j = 0; j < locations.length; j++) {
1244                Element JavaDoc pathelElem = doc.createElement("pathelement"); // NOI18N
1245
pathelElem.setAttribute("location", locations[j]); // NOI18N
1246
pElem.appendChild(pathelElem);
1247            }
1248        }
1249        return pElem;
1250    }
1251
1252    /**
1253     * Creates ant element according to params
1254     */

1255    Element JavaDoc createAntElem(Document JavaDoc doc, String JavaDoc antFile, String JavaDoc deps) {
1256        assert antFile != null;
1257        Element JavaDoc antElem = doc.createElement("ant"); // NOI18N
1258
antElem.setAttribute("antfile", antFile);
1259        antElem.setAttribute("inheritall", "false"); // NOI18N
1260
StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(deps, ","); // NOI18N
1261
if (st.countTokens() > 1) {
1262            while (st.hasMoreTokens()) {
1263                String JavaDoc dep = st.nextToken();
1264                Element JavaDoc tgElem = doc.createElement("target"); // NOI18N
1265
tgElem.setAttribute("name", dep.trim()); // NOI18N
1266
antElem.appendChild(tgElem);
1267            }
1268        } else {
1269            antElem.setAttribute("target", deps); // NOI18N
1270
}
1271        return antElem;
1272    }
1273
1274    private boolean isSingleJavaFileSelected(Lookup context) {
1275        Collection JavaDoc<? extends DataObject> selectedDO = context.lookupAll(DataObject.class);
1276        if (selectedDO.size() == 1 && selectedDO.iterator().next().getPrimaryFile().hasExt("java")) {
1277            return true;
1278        }
1279        return false;
1280    }
1281
1282    private void addJdkInitDeps(Element JavaDoc target) {
1283        if (helper.getProjectDirectory().getFileObject(JdkConfiguration.JDK_XML) != null) {
1284            String JavaDoc deps = target.getAttribute("depends"); // NOI18N
1285
target.setAttribute("depends", deps.length() == 0 ? "-jdk-init" : "-jdk-init," + deps); // NOI18N
1286
}
1287    }
1288
1289}
1290
Popular Tags