KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > junit > OpenTestAction


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

19
20 package org.netbeans.modules.junit;
21
22 import com.sun.source.tree.ClassTree;
23 import com.sun.source.tree.CompilationUnitTree;
24 import com.sun.source.tree.MethodTree;
25 import com.sun.source.tree.Tree;
26 import com.sun.source.util.SourcePositions;
27 import com.sun.source.util.TreePathScanner;
28 import com.sun.source.util.Trees;
29 import java.io.IOException JavaDoc;
30 import java.net.URL JavaDoc;
31 import java.util.ArrayList JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.logging.Level JavaDoc;
34 import java.util.logging.Level JavaDoc;
35 import java.util.logging.Logger JavaDoc;
36 import javax.lang.model.element.Element;
37 import javax.swing.Action JavaDoc;
38 import javax.swing.JEditorPane JavaDoc;
39 import javax.swing.text.StyledDocument JavaDoc;
40 import org.netbeans.api.java.classpath.ClassPath;
41 import org.netbeans.api.java.queries.UnitTestForSourceQuery;
42 import org.netbeans.api.java.source.CancellableTask;
43 import org.netbeans.api.java.source.CompilationController;
44 import org.netbeans.api.java.source.ElementHandle;
45 import org.netbeans.api.java.source.JavaSource;
46 import org.netbeans.api.java.source.JavaSource.Phase;
47 import org.netbeans.spi.java.classpath.PathResourceImplementation;
48 import org.netbeans.spi.java.classpath.support.ClassPathSupport;
49 import org.openide.ErrorManager;
50 import org.openide.cookies.EditorCookie;
51 import org.openide.cookies.LineCookie;
52 import org.openide.cookies.OpenCookie;
53 import org.openide.filesystems.FileObject;
54 import org.openide.loaders.DataObject;
55 import org.openide.loaders.DataObjectNotFoundException;
56 import org.openide.nodes.Node;
57 import org.openide.text.Line;
58 import org.openide.text.NbDocument;
59 import org.openide.util.HelpCtx;
60 import org.openide.util.NbBundle;
61
62 /** Action sensitive to some DataFolder or SourceCookie cookie
63  * which tries to open JUnit test corresponding to the selected source file.
64  *
65  * @author Nathan W. Phelps, David Konecny
66  * @author Marian Petras
67  * @ version 1.0
68  */

69 @SuppressWarnings JavaDoc("serial")
70 public class OpenTestAction extends TestAction {
71
72     public OpenTestAction() {
73         putValue("noIconInMenu", Boolean.TRUE);
74     }
75     
76
77     protected void performAction (Node[] nodes) {
78         FileObject selectedFO;
79         
80         for (int i = 0; i < nodes.length; i++) {
81             // get test class or suite class file, if it was not such one pointed by the node
82
selectedFO = TestUtil.getFileObjectFromNode(nodes[i]);
83             if (selectedFO == null) {
84                 TestUtil.notifyUser(NbBundle.getMessage(OpenTestAction.class, "MSG_file_from_node_failed"));
85                 continue;
86             }
87             ClassPath cp = ClassPath.getClassPath(selectedFO, ClassPath.SOURCE);
88             if (cp == null) {
89                 TestUtil.notifyUser(NbBundle.getMessage(OpenTestAction.class,
90                     "MSG_no_project", selectedFO));
91                 continue;
92             }
93  
94             FileObject packageRoot = cp.findOwnerRoot(selectedFO);
95             URL JavaDoc[] testRoots = UnitTestForSourceQuery.findUnitTests(packageRoot);
96             FileObject fileToOpen = null;
97             for (int j = 0 ; j < testRoots.length; j++) {
98                 fileToOpen = findUnitTestInTestRoot(cp, selectedFO, testRoots[j]);
99                 if (fileToOpen != null) break;
100             }
101             
102             if (fileToOpen != null) {
103                 openFile(fileToOpen);
104             } else {
105                 String JavaDoc testClsName = getTestName(cp, selectedFO).replace('/','.');
106                 String JavaDoc pkgName = cp.getResourceName(selectedFO, '.', false);
107                 boolean isPackage = selectedFO.isFolder();
108                 boolean isDefPkg = isPackage && (pkgName.length() == 0);
109                 String JavaDoc msgPattern = !isPackage
110                        ? "MSG_test_class_not_found" //NOI18N
111
: isDefPkg
112                          ? "MSG_testsuite_class_not_found_def_pkg" //NOI18N
113
: "MSG_testsuite_class_not_found"; //NOI18N
114

115                 String JavaDoc[] params = isDefPkg ? new String JavaDoc[] { testClsName }
116                                            : new String JavaDoc[] { testClsName,
117                                                             pkgName };
118                                  
119                 TestUtil.notifyUser(NbBundle.getMessage(OpenTestAction.class,
120                                                         msgPattern, params),
121                                     ErrorManager.INFORMATIONAL);
122                 continue;
123             }
124         }
125     }
126
127     private static FileObject findUnitTestInTestRoot(ClassPath cp, FileObject selectedFO, URL JavaDoc testRoot) {
128         ClassPath testClassPath = null;
129         if (testRoot == null) { //no tests, use sources instead
130
testClassPath = cp;
131         } else {
132             try {
133                 List JavaDoc<PathResourceImplementation> cpItems
134                         = new ArrayList JavaDoc<PathResourceImplementation>();
135                 cpItems.add(ClassPathSupport.createResource(testRoot));
136                 testClassPath = ClassPathSupport.createClassPath(cpItems);
137             } catch (IllegalArgumentException JavaDoc ex) {
138                 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
139                 testClassPath = cp;
140             }
141         }
142         String JavaDoc testName = getTestName(cp, selectedFO);
143         return testClassPath.findResource(testName+".java");
144     }
145
146     private static String JavaDoc getTestName(ClassPath cp, FileObject selectedFO) {
147         String JavaDoc resource = cp.getResourceName(selectedFO, '/', false);
148         String JavaDoc testName = null;
149         if (selectedFO.isFolder()) {
150         //find Suite for package
151
testName = TestUtil.convertPackage2SuiteName(resource);
152         } else {
153         // find Test for class
154
testName = TestUtil.convertClass2TestName(resource);
155         }
156         
157         return testName;
158     }
159     
160     /**
161      * Open given file in editor.
162      * @return true if file was opened or false
163      */

164     public static boolean openFile(FileObject fo) {
165         DataObject dobj;
166         try {
167             dobj = DataObject.find(fo);
168         } catch (DataObjectNotFoundException e) {
169             getLogger().log(Level.WARNING, null, e);
170             return false;
171         }
172         assert dobj != null;
173         
174         EditorCookie editorCookie = dobj.getCookie(EditorCookie.class);
175         if (editorCookie != null) {
176             editorCookie.open();
177             return true;
178         }
179         
180         OpenCookie openCookie = dobj.getCookie(OpenCookie.class);
181         if (openCookie != null) {
182             openCookie.open();
183             return true;
184         }
185         
186         return false;
187     }
188     
189     /**
190      */

191     static boolean openFileAtElement(FileObject fileObject,
192                                      ElementHandle<Element> element) {
193         final DataObject dataObject;
194         try {
195             dataObject = DataObject.find(fileObject);
196         } catch (DataObjectNotFoundException e) {
197             getLogger().log(Level.INFO, null, e);
198             return false;
199         }
200         assert dataObject != null;
201
202         final EditorCookie editorCookie = dataObject.getCookie(EditorCookie.class);
203         if (editorCookie != null) {
204             
205             StyledDocument JavaDoc doc;
206             try {
207                 doc = editorCookie.openDocument();
208             } catch (IOException JavaDoc ex) {
209                 String JavaDoc msg = ex.getLocalizedMessage();
210                 if (msg == null) {
211                     msg = ex.getMessage();
212                 }
213                 getLogger().log(Level.SEVERE, msg, ex);
214                 return false;
215             }
216             
217             editorCookie.open();
218             
219             LineCookie lineCookie = dataObject.getCookie(LineCookie.class);
220             if ((lineCookie != null) && (element != null) && (doc != null)) {
221                 int currentPos = -1;
222                 JEditorPane JavaDoc[] editorPanes = editorCookie.getOpenedPanes();
223                 if ((editorPanes != null) && (editorPanes.length != 0)) {
224                     currentPos = editorPanes[0].getCaretPosition();
225                 }
226                 int[] elementPositionBounds = null;
227                 try {
228                     elementPositionBounds = getPositionRange(fileObject, element);
229                 } catch (IOException JavaDoc ex) {
230                     getLogger().log(Level.WARNING, null, ex);
231                 }
232                 if ((currentPos == -1)
233                     || (elementPositionBounds != null)
234                        && ((currentPos < elementPositionBounds[0])
235                            ||(currentPos >= elementPositionBounds[1]))) {
236                     int startPos = elementPositionBounds[0];
237                     int lineNum = NbDocument.findLineNumber(doc, startPos);
238                     if (lineNum != -1) {
239                         Line line = lineCookie.getLineSet().getCurrent(lineNum);
240                         try {
241                             int lineOffset = NbDocument.findLineOffset(doc,
242                                                                        lineNum);
243                             int column = startPos - lineOffset;
244                             line.show(Line.SHOW_GOTO, column);
245                         } catch (IndexOutOfBoundsException JavaDoc ex) {
246                             Logger.getLogger(OpenTestAction.class.getName())
247                                   .log(Level.INFO, null, ex);
248                             line.show(Line.SHOW_GOTO);
249                         }
250                     }
251                 }
252             }
253             return true;
254         }
255         
256         OpenCookie openCookie = dataObject.getCookie(OpenCookie.class);
257         if (openCookie != null) {
258             openCookie.open();
259             return true;
260         }
261         
262         return false;
263     }
264     
265     /**
266      */

267     private static Logger JavaDoc getLogger() {
268         return Logger.getLogger(OpenTestAction.class.getName());
269     }
270     
271     /**
272      */

273     private static int[] getPositionRange(
274                          FileObject fileObj,
275                          ElementHandle<Element> elemHandle) throws IOException JavaDoc {
276         PositionRangeFinder posFinder = new PositionRangeFinder(fileObj, elemHandle);
277         JavaSource.forFileObject(fileObj).runUserActionTask(posFinder, true);
278         return posFinder.getPositionRange();
279     }
280         
281     /**
282      *
283      */

284     private static class PositionRangeFinder
285                             implements CancellableTask<CompilationController> {
286         
287         private final FileObject fileObj;
288         private final ElementHandle<Element> elemHandle;
289         private int[] positionRange = null;
290         private volatile boolean cancelled;
291         
292         /**
293          */

294         private PositionRangeFinder(FileObject fileObj,
295                                     ElementHandle<Element> elemHandle) {
296             this.fileObj = fileObj;
297             this.elemHandle = elemHandle;
298         }
299         
300         /**
301          */

302         public void run(CompilationController controller) throws IOException JavaDoc {
303             try {
304                 controller.toPhase(Phase.RESOLVED); //cursor position needed
305
} catch (IOException JavaDoc ex) {
306                 Logger.getLogger("global").log(Level.SEVERE, null, ex); //NOI18N
307
}
308             if (cancelled) {
309                 return;
310             }
311             
312             Element element = elemHandle.resolve(controller);
313             if (cancelled || (element == null)) {
314                 return;
315             }
316
317             Trees trees = controller.getTrees();
318             CompilationUnitTree compUnit = controller.getCompilationUnit();
319             DeclarationTreeFinder treeFinder = new DeclarationTreeFinder(
320                                                         element, trees);
321             treeFinder.scan(compUnit, null);
322             Tree tree = treeFinder.getDeclarationTree();
323
324             if (tree != null) {
325                 SourcePositions srcPositions = trees.getSourcePositions();
326                 long startPos = srcPositions.getStartPosition(compUnit, tree);
327                 long endPos = srcPositions.getEndPosition(compUnit, tree);
328                 
329                 if ((startPos >= 0) && (startPos <= (long) Integer.MAX_VALUE)
330                      && (endPos >= 0) && (endPos <= (long) Integer.MAX_VALUE)) {
331                     positionRange = new int[2];
332                     positionRange[0] = (int) startPos;
333                     positionRange[1] = (int) endPos;
334                 }
335             }
336         }
337
338         /**
339          */

340         public void cancel() {
341             cancelled = true;
342         }
343         
344         /**
345          */

346         int[] getPositionRange() {
347             return positionRange;
348         }
349
350     }
351     
352     /**
353      *
354      */

355     private static class DeclarationTreeFinder extends TreePathScanner<Void JavaDoc, Void JavaDoc> {
356
357         private final Element element;
358         private final Trees trees;
359         private Tree declTree;
360         
361         /**
362          */

363         private DeclarationTreeFinder(Element element, Trees trees) {
364             this.element = element;
365             this.trees = trees;
366         }
367         
368     @Override JavaDoc
369         public Void JavaDoc visitClass(ClassTree tree, Void JavaDoc d) {
370             if (declTree == null) {
371                 handleDeclaration();
372                 super.visitClass(tree, d);
373             }
374             return null;
375         }
376         
377     @Override JavaDoc
378         public Void JavaDoc visitMethod(MethodTree tree, Void JavaDoc d) {
379             if (declTree == null) {
380                 handleDeclaration();
381                 super.visitMethod(tree, d);
382             }
383             return null;
384         }
385         
386         /**
387          */

388         public void handleDeclaration() {
389             Element found = trees.getElement(getCurrentPath());
390             
391             if (element.equals(found)) {
392                 declTree = getCurrentPath().getLeaf();
393             }
394         }
395         
396         /**
397          */

398         Tree getDeclarationTree() {
399             return declTree;
400         }
401         
402     }
403     
404     public String JavaDoc getName () {
405         return NbBundle.getMessage (OpenTestAction.class, "LBL_Action_OpenTest");
406     }
407
408      protected String JavaDoc iconResource () {
409          return "org/netbeans/modules/junit/resources/OpenTestActionIcon.gif";
410      }
411
412     public HelpCtx getHelpCtx () {
413         return new HelpCtx(OpenTestAction.class);
414     }
415
416     /** Perform special enablement check in addition to the normal one.
417     protected boolean enable (Node[] nodes) {
418     if (! super.enable (nodes)) return false;
419     if (...) ...;
420     }
421     */

422
423     protected void initialize () {
424     super.initialize ();
425         putProperty(Action.SHORT_DESCRIPTION, NbBundle.getMessage(OpenTestAction.class, "HINT_Action_OpenTest"));
426     }
427
428 }
429
Popular Tags