KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > apisupport > project > ui > XTestProjectMenuItem


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 package org.netbeans.modules.apisupport.project.ui;
20
21 import java.awt.event.ActionEvent JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.Arrays JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.Properties JavaDoc;
27 import java.util.logging.Logger JavaDoc;
28 import javax.swing.AbstractAction JavaDoc;
29 import javax.swing.Action JavaDoc;
30 import javax.swing.JComponent JavaDoc;
31 import javax.swing.JMenu JavaDoc;
32 import javax.swing.JMenuItem JavaDoc;
33 import javax.swing.JSeparator JavaDoc;
34 import org.apache.tools.ant.module.api.AntProjectCookie;
35 import org.apache.tools.ant.module.api.support.ActionUtils;
36 import org.apache.tools.ant.module.api.support.TargetLister;
37 import org.netbeans.api.project.Project;
38 import org.openide.ErrorManager;
39 import org.openide.awt.Actions;
40 import org.openide.awt.Mnemonics;
41 import org.openide.filesystems.FileObject;
42 import org.openide.filesystems.FileStateInvalidException;
43 import org.openide.loaders.DataObject;
44 import org.openide.loaders.DataObjectNotFoundException;
45 import org.openide.util.ContextAwareAction;
46 import org.openide.util.Lookup;
47 import org.openide.util.Task;
48 import org.openide.util.TaskListener;
49 import org.openide.util.actions.Presenter;
50 import org.openide.util.NbBundle;
51 import org.openide.awt.DynamicMenuContent;
52 import org.openide.awt.HtmlBrowser;
53 import org.openide.execution.ExecutorTask;
54
55 /**
56  * Defines XTest actions for top level project logical node. Inspired by CVS
57  * sub menu org.netbeans.modules.versioning.system.cvss.ui.actions.ProjectCvsMenuItem.
58  * Used also in xtest/module.
59  *
60  * <pre>
61  * XTest >
62  * Clean
63  * --------------------------
64  * Build unit Tests
65  * Run unit Tests
66  * Measure unit Test Coverage
67  * --------------------------
68  * Build qa-functional Tests
69  * Run qa-functional Tests
70  * Measure qa-functional Test Coverage
71  * </pre>
72  *
73  * <p>The menu is available only for projects that contains some tests.
74  *
75  * @author Jiri.Skrivanek@sun.com
76  */

77 public final class XTestProjectMenuItem extends AbstractAction JavaDoc implements Presenter.Popup, ContextAwareAction {
78     
79     public static final String JavaDoc NAME = NbBundle.getBundle(XTestProjectMenuItem.class).getString("CTL_MenuItem_XTest");
80     private Lookup context;
81     
82     /** Creates XTest sub menu. */
83     public XTestProjectMenuItem() {
84         this(null);
85     }
86
87     /** Creates XTest sub menu.
88      * @param actionContext context of action
89      */

90     public XTestProjectMenuItem(Lookup actionContext) {
91         super(NAME);
92         this.context = actionContext;
93     }
94
95     /** No action for sub menu holder.
96      * @param ignore action event
97      */

98     public void actionPerformed(ActionEvent JavaDoc ignore) {
99         // empty
100
}
101     
102     /** Returns created popup menu.
103      * @return created popup menu.
104      */

105     public JMenuItem JavaDoc getPopupPresenter() {
106         return new XTestProjectMenuItems();
107     }
108     
109     public Action JavaDoc createContextAwareInstance(Lookup actionContext) {
110         return new XTestProjectMenuItem(actionContext);
111     }
112
113     /** Sub menu items. */
114     class XTestProjectMenuItems extends JMenuItem JavaDoc implements DynamicMenuContent {
115         
116         public JComponent JavaDoc[] getMenuPresenters() {
117             Action JavaDoc [] actions = actions();
118             if(actions == null) {
119                 // hide sub menu
120
return new JComponent JavaDoc[0];
121             }
122             final JMenu JavaDoc menu = new JMenu JavaDoc();
123             Mnemonics.setLocalizedText(menu, NAME);
124             for (int i = 0; i < actions.length; i++) {
125                 Action JavaDoc action = actions[i];
126                 if (action == null) {
127                     menu.add(new JSeparator JavaDoc());
128                 } else {
129                     JMenuItem JavaDoc item = new JMenuItem JavaDoc();
130                     Actions.connect(item, actions[i], false);
131                     menu.add(item);
132                 }
133             }
134             return new JComponent JavaDoc[] { menu };
135         }
136         
137         public JComponent JavaDoc[] synchMenuPresenters(JComponent JavaDoc[] items) {
138             return items;
139         }
140     }
141     
142     /** Returns array of actions for all test types in selected project. */
143     private Action JavaDoc[] actions() {
144         Project project = (Project)context.lookup(Project.class);
145         // It should not happen but issue 86977 claims it happens.
146
if(project == null) {
147             return null;
148         }
149         if(project.getLookup().lookup(ModuleActions.class) == null) {
150             // do not create sub menu for non-NbModuleProject
151
return null;
152         }
153         ArrayList JavaDoc actions = new ArrayList JavaDoc();
154
155         String JavaDoc[] testTypes = findTestTypes(project);
156         if(testTypes.length > 0) {
157             actions.add(createAction(NbBundle.getMessage(XTestProjectMenuItem.class, "CTL_MenuItem_Clean"),
158                                      project, "", new String JavaDoc[] {"realclean"}, false));
159             actions.add(null);
160         } else {
161             // hide XTest submenu
162
return null;
163             // or
164
//actions.add(createAction("Create XTest Infrastructure", project, "", new String[] {""}, false));
165
// and open new file wizard Testing Tools|XTest Infrastructure (enable it always)
166
}
167         for(int i=0;i<testTypes.length;i++) {
168             // "Build "+testTypes[i]+" Tests"
169
actions.add(createAction(NbBundle.getMessage(XTestProjectMenuItem.class, "CTL_MenuItem_BuildTests", testTypes[i]), // NOI18N
170
project, testTypes[i], new String JavaDoc[] {"buildtests"}, false)); // NOI18N
171
// "Run "+testTypes[i]+" Tests"
172
actions.add(createAction(NbBundle.getMessage(XTestProjectMenuItem.class, "CTL_MenuItem_RunTests", testTypes[i]), // NOI18N
173
project, testTypes[i], new String JavaDoc[] {"runtests"}, true)); // NOI18N
174
if(targetExists(findTestBuildXml(project), "coverage")) { //NOI18N
175
// "Measure "+testTypes[i]+" Tests Coverage"
176
actions.add(createAction(NbBundle.getMessage(XTestProjectMenuItem.class, "CTL_MenuItem_MeasureCoverage", testTypes[i]), // NOI18N
177
project, testTypes[i], new String JavaDoc[] {"coverage"}, true)); // NOI18N
178
}
179             // add separator
180
if(testTypes.length-1 > i) {
181                 actions.add(null);
182             }
183         }
184         return (Action JavaDoc[])actions.toArray(new Action JavaDoc[actions.size()]);
185     }
186     
187     private AbstractAction JavaDoc createAction(String JavaDoc displayName, final Project project,
188             final String JavaDoc testType, final String JavaDoc[] targets, final boolean showResults) {
189         
190         return new AbstractAction JavaDoc(displayName) {
191             /** Enabled only if one project is selected and test/build.xml exists. */
192             public boolean isEnabled() {
193                 // enable only if one project is selected
194
if(context.lookup(new Lookup.Template(Project.class)).allInstances().size() == 1) {
195                     return findTestBuildXml(project) != null;
196                 }
197                 return false;
198             }
199             
200             /** Run given target and show test results if requested. */
201             public void actionPerformed(ActionEvent JavaDoc ignore) {
202                 Properties JavaDoc props = new Properties JavaDoc();
203                 props.setProperty("xtest.testtype", testType); // NOI18N
204
try {
205                     ExecutorTask task = ActionUtils.runTarget(findTestBuildXml(project), targets, props);
206                     task.addTaskListener(new TaskListener() {
207                         public void taskFinished(Task task) {
208                             if(((ExecutorTask)task).result() == 0 && showResults) {
209                                 if(targets[0].equals("coverage")) { //NOI18N
210
showCoverageResults(project);
211                                 } else {
212                                     showTestResults(project);
213                                 }
214                             }
215                         }
216                     });
217                 } catch (IOException JavaDoc e) {
218                     ErrorManager.getDefault().notify(e);
219                 }
220             }
221         };
222     }
223     
224     /** Returns true if target is available in build script. */
225     private static boolean targetExists(FileObject buildXml, String JavaDoc targetName) {
226         if(buildXml == null) {
227             return false;
228         }
229         DataObject d;
230         try {
231             d = DataObject.find(buildXml);
232         } catch (DataObjectNotFoundException ex) {
233             ErrorManager.getDefault().notify(ex);
234             return false;
235         }
236         AntProjectCookie apc = (AntProjectCookie)d.getCookie(AntProjectCookie.class);
237         Iterator JavaDoc iter;
238         try {
239             iter = TargetLister.getTargets(apc).iterator();
240         } catch (IOException JavaDoc ex) {
241             // something wrong in build.xml => target not found
242
Logger.getAnonymousLogger().fine(ex.getMessage());
243             return false;
244         }
245         while(iter.hasNext()) {
246             if(((TargetLister.Target)iter.next()).getName().equals(targetName)) {
247                 return true;
248             }
249         }
250         return false;
251     }
252     
253     /** Returns FileObject representing test/build.xml or null if it doesn't exist. */
254     private static FileObject findTestBuildXml(Project project) {
255         return project.getProjectDirectory().getFileObject("test/build.xml"); // NOI18N
256
}
257     
258     /** Opens test/results/index.html in browser of specified project.
259      * @param project project to open test results for
260      */

261     private static void showTestResults(Project project) {
262         showBrowser(project.getProjectDirectory().getFileObject("test/results/index.html")); // NOI18N
263
}
264
265     /** Opens test/coverage/coverage.html in browser.
266      * @param project project to open test results for
267      */

268     private static void showCoverageResults(Project project) {
269         showBrowser(project.getProjectDirectory().getFileObject("test/coverage/coverage.html")); // NOI18N
270
}
271
272     /** Opens location in browser.
273      * @param resultsFO FileObject to be opened in browser
274      */

275     private static void showBrowser(FileObject resultsFO) {
276         if(resultsFO != null) {
277             try {
278                 HtmlBrowser.URLDisplayer.getDefault().showURL(resultsFO.getURL());
279             } catch (FileStateInvalidException ex) {
280                 ErrorManager.getDefault().notify(ex);
281             }
282         }
283     }
284
285     /** Returns sorted array of available test types in given project. It searches
286      * for pairs build-testtype.xml, cfg-testtype.xml and returns array
287      * of available test types. */

288     private static String JavaDoc[] findTestTypes(Project project) {
289         FileObject testFO = project.getProjectDirectory().getFileObject("test"); // NOI18N
290
if(testFO == null) {
291             return new String JavaDoc[0];
292         }
293         FileObject[] fos = testFO.getChildren(); // NOI18N
294
ArrayList JavaDoc testTypes = new ArrayList JavaDoc();
295         for(int i=0;i<fos.length;i++) {
296             if(fos[i].getExt().equalsIgnoreCase("xml") && fos[i].getName().matches("build-.*")) { // NOI18N
297
String JavaDoc testType = fos[i].getName().substring(fos[i].getName().indexOf('-')+1);
298                 if(project.getProjectDirectory().getFileObject("test/cfg-"+testType+".xml") != null) { // NOI18N
299
testTypes.add(testType);
300                 }
301             }
302         }
303         String JavaDoc [] result = (String JavaDoc[])testTypes.toArray(new String JavaDoc[testTypes.size()]);
304         Arrays.sort(result);
305         return result;
306     }
307 }
308
Popular Tags