KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > junit > model > JUnitModel


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.jdt.internal.junit.model;
13
14 import java.io.File JavaDoc;
15 import java.io.FileOutputStream JavaDoc;
16 import java.io.IOException JavaDoc;
17 import java.io.OutputStream JavaDoc;
18 import java.util.ArrayList JavaDoc;
19 import java.util.HashSet JavaDoc;
20 import java.util.LinkedList JavaDoc;
21 import java.util.List JavaDoc;
22
23 import javax.xml.parsers.ParserConfigurationException JavaDoc;
24 import javax.xml.parsers.SAXParser JavaDoc;
25 import javax.xml.parsers.SAXParserFactory JavaDoc;
26 import javax.xml.transform.OutputKeys JavaDoc;
27 import javax.xml.transform.Transformer JavaDoc;
28 import javax.xml.transform.TransformerConfigurationException JavaDoc;
29 import javax.xml.transform.TransformerException JavaDoc;
30 import javax.xml.transform.TransformerFactory JavaDoc;
31 import javax.xml.transform.TransformerFactoryConfigurationError JavaDoc;
32 import javax.xml.transform.sax.SAXSource JavaDoc;
33 import javax.xml.transform.stream.StreamResult JavaDoc;
34
35 import org.eclipse.core.runtime.Assert;
36 import org.eclipse.core.runtime.CoreException;
37 import org.eclipse.core.runtime.IStatus;
38 import org.eclipse.core.runtime.ListenerList;
39
40 import org.eclipse.swt.widgets.Display;
41
42 import org.eclipse.ui.IWorkbenchPage;
43 import org.eclipse.ui.IWorkbenchPart;
44 import org.eclipse.ui.PartInitException;
45
46 import org.eclipse.debug.core.DebugPlugin;
47 import org.eclipse.debug.core.ILaunch;
48 import org.eclipse.debug.core.ILaunchConfiguration;
49 import org.eclipse.debug.core.ILaunchListener;
50 import org.eclipse.debug.core.ILaunchManager;
51
52 import org.eclipse.jdt.core.IJavaProject;
53
54 import org.eclipse.jdt.internal.junit.Messages;
55 import org.eclipse.jdt.internal.junit.launcher.JUnitLaunchConfigurationConstants;
56 import org.eclipse.jdt.internal.junit.model.TestElement.Status;
57 import org.eclipse.jdt.internal.junit.ui.JUnitPlugin;
58 import org.eclipse.jdt.internal.junit.ui.JUnitPreferencesConstants;
59 import org.eclipse.jdt.internal.junit.ui.TestRunnerViewPart;
60
61 import org.xml.sax.InputSource JavaDoc;
62 import org.xml.sax.SAXException JavaDoc;
63
64 /**
65  * Central registry for JUnit test runs.
66  */

67 public final class JUnitModel {
68     
69     private final class JUnitLaunchListener implements ILaunchListener {
70
71         /**
72          * Used to track new launches. We need to do this
73          * so that we only attach a TestRunner once to a launch.
74          * Once a test runner is connected, it is removed from the set.
75          */

76         private HashSet JavaDoc fTrackedLaunches= new HashSet JavaDoc(20);
77
78         /*
79          * @see ILaunchListener#launchAdded(ILaunch)
80          */

81         public void launchAdded(ILaunch launch) {
82             fTrackedLaunches.add(launch);
83         }
84
85         /*
86          * @see ILaunchListener#launchRemoved(ILaunch)
87          */

88         public void launchRemoved(final ILaunch launch) {
89             fTrackedLaunches.remove(launch);
90             //TODO: story for removing old test runs?
91
// getDisplay().asyncExec(new Runnable() {
92
// public void run() {
93
// TestRunnerViewPart testRunnerViewPart= findTestRunnerViewPartInActivePage();
94
// if (testRunnerViewPart != null && testRunnerViewPart.isCreated() && launch.equals(testRunnerViewPart.getLastLaunch()))
95
// testRunnerViewPart.reset();
96
// }
97
// });
98
}
99
100         /*
101          * @see ILaunchListener#launchChanged(ILaunch)
102          */

103         public void launchChanged(final ILaunch launch) {
104             if (!fTrackedLaunches.contains(launch))
105                 return;
106         
107             ILaunchConfiguration config= launch.getLaunchConfiguration();
108             if (config == null)
109                 return;
110             
111             final IJavaProject javaProject= JUnitLaunchConfigurationConstants.getJavaProject(config);
112             if (javaProject == null)
113                 return;
114             
115             // test whether the launch defines the JUnit attributes
116
String JavaDoc portStr= launch.getAttribute(JUnitLaunchConfigurationConstants.ATTR_PORT);
117             if (portStr == null)
118                 return;
119             try {
120                 final int port= Integer.parseInt(portStr);
121                 fTrackedLaunches.remove(launch);
122                 getDisplay().asyncExec(new Runnable JavaDoc() {
123                     public void run() {
124                         connectTestRunner(launch, javaProject, port);
125                     }
126                 });
127             } catch (NumberFormatException JavaDoc e) {
128                 return;
129             }
130         }
131
132         private void connectTestRunner(ILaunch launch, IJavaProject javaProject, int port) {
133             showTestRunnerViewPartInActivePage(findTestRunnerViewPartInActivePage());
134             
135             //TODO: Do notifications have to be sent in UI thread?
136
// Check concurrent access to fTestRunSessions (no problem inside asyncExec())
137
int maxCount= JUnitPlugin.getDefault().getPreferenceStore().getInt(JUnitPreferencesConstants.MAX_TEST_RUNS);
138             int toDelete= fTestRunSessions.size() - maxCount;
139             while (toDelete > 0) {
140                 toDelete--;
141                 TestRunSession session= (TestRunSession) fTestRunSessions.removeLast();
142                 notifyTestRunSessionRemoved(session);
143             }
144             
145             TestRunSession testRunSession= new TestRunSession(launch, javaProject, port);
146             addTestRunSession(testRunSession);
147         }
148
149         private TestRunnerViewPart showTestRunnerViewPartInActivePage(TestRunnerViewPart testRunner) {
150             IWorkbenchPart activePart= null;
151             IWorkbenchPage page= null;
152             try {
153                 // TODO: have to force the creation of view part contents
154
// otherwise the UI will not be updated
155
if (testRunner != null && testRunner.isCreated())
156                     return testRunner;
157                 page= JUnitPlugin.getActivePage();
158                 if (page == null)
159                     return null;
160                 activePart= page.getActivePart();
161                 // show the result view if it isn't shown yet
162
return (TestRunnerViewPart) page.showView(TestRunnerViewPart.NAME);
163             } catch (PartInitException pie) {
164                 JUnitPlugin.log(pie);
165                 return null;
166             } finally{
167                 //restore focus stolen by the creation of the result view
168
if (page != null && activePart != null)
169                     page.activate(activePart);
170             }
171         }
172
173         private TestRunnerViewPart findTestRunnerViewPartInActivePage() {
174             IWorkbenchPage page= JUnitPlugin.getActivePage();
175             if (page == null)
176                 return null;
177             return (TestRunnerViewPart) page.findView(TestRunnerViewPart.NAME);
178         }
179
180         private Display getDisplay() {
181 // Shell shell= getActiveWorkbenchShell();
182
// if (shell != null) {
183
// return shell.getDisplay();
184
// }
185
Display display= Display.getCurrent();
186             if (display == null) {
187                 display= Display.getDefault();
188             }
189             return display;
190         }
191     }
192
193     /** @deprecated */
194     private static final class LegacyTestRunSessionListener implements ITestRunSessionListener {
195         private TestRunSession fActiveTestRunSession;
196         private ITestSessionListener fTestSessionListener;
197         
198         public void sessionAdded(TestRunSession testRunSession) {
199             // Only serve one legacy ITestRunListener at a time, since they cannot distinguish between different concurrent test sessions:
200
if (fActiveTestRunSession != null)
201                 return;
202             
203             fActiveTestRunSession= testRunSession;
204             
205             fTestSessionListener= new ITestSessionListener() {
206                 public void testAdded(TestElement testElement) {
207                 }
208                 
209                 public void sessionStarted() {
210                     org.eclipse.jdt.junit.ITestRunListener[] testRunListeners= JUnitPlugin.getDefault().getTestRunListeners();
211                     for (int i= 0; i < testRunListeners.length; i++) {
212                         testRunListeners[i].testRunStarted(fActiveTestRunSession.getTotalCount());
213                     }
214                 }
215                 public void sessionTerminated() {
216                     org.eclipse.jdt.junit.ITestRunListener[] testRunListeners= JUnitPlugin.getDefault().getTestRunListeners();
217                     for (int i= 0; i < testRunListeners.length; i++) {
218                         testRunListeners[i].testRunTerminated();
219                     }
220                     sessionRemoved(fActiveTestRunSession);
221                 }
222                 public void sessionStopped(long elapsedTime) {
223                     org.eclipse.jdt.junit.ITestRunListener[] testRunListeners= JUnitPlugin.getDefault().getTestRunListeners();
224                     for (int i= 0; i < testRunListeners.length; i++) {
225                         testRunListeners[i].testRunStopped(elapsedTime);
226                     }
227                     sessionRemoved(fActiveTestRunSession);
228                 }
229                 public void sessionEnded(long elapsedTime) {
230                     org.eclipse.jdt.junit.ITestRunListener[] testRunListeners= JUnitPlugin.getDefault().getTestRunListeners();
231                     for (int i= 0; i < testRunListeners.length; i++) {
232                         testRunListeners[i].testRunEnded(elapsedTime);
233                     }
234                     sessionRemoved(fActiveTestRunSession);
235                 }
236                 public void runningBegins() {
237                     // ignore
238
}
239                 public void testStarted(TestCaseElement testCaseElement) {
240                     org.eclipse.jdt.junit.ITestRunListener[] testRunListeners= JUnitPlugin.getDefault().getTestRunListeners();
241                     for (int i= 0; i < testRunListeners.length; i++) {
242                         testRunListeners[i].testStarted(testCaseElement.getId(), testCaseElement.getTestName());
243                     }
244                 }
245                 
246                 public void testFailed(TestElement testElement, Status status, String JavaDoc trace, String JavaDoc expected, String JavaDoc actual) {
247                     org.eclipse.jdt.junit.ITestRunListener[] testRunListeners= JUnitPlugin.getDefault().getTestRunListeners();
248                     for (int i= 0; i < testRunListeners.length; i++) {
249                         testRunListeners[i].testFailed(status.getOldCode(), testElement.getId(), testElement.getTestName(), trace);
250                     }
251                 }
252                 
253                 public void testEnded(TestCaseElement testCaseElement) {
254                     org.eclipse.jdt.junit.ITestRunListener[] testRunListeners= JUnitPlugin.getDefault().getTestRunListeners();
255                     for (int i= 0; i < testRunListeners.length; i++) {
256                         testRunListeners[i].testEnded(testCaseElement.getId(), testCaseElement.getTestName());
257                     }
258                 }
259                 
260                 public void testReran(TestCaseElement testCaseElement, Status status, String JavaDoc trace, String JavaDoc expectedResult, String JavaDoc actualResult) {
261                     org.eclipse.jdt.junit.ITestRunListener[] testRunListeners= JUnitPlugin.getDefault().getTestRunListeners();
262                     for (int i= 0; i < testRunListeners.length; i++) {
263                         testRunListeners[i].testReran(testCaseElement.getId(), testCaseElement.getClassName(), testCaseElement.getTestMethodName(), status.getOldCode(), trace);
264                     }
265                 }
266                 
267                 public boolean acceptsSwapToDisk() {
268                     return true;
269                 }
270             };
271             fActiveTestRunSession.addTestSessionListener(fTestSessionListener);
272         }
273
274         public void sessionRemoved(TestRunSession testRunSession) {
275             if (fActiveTestRunSession == testRunSession) {
276                 fActiveTestRunSession.removeTestSessionListener(fTestSessionListener);
277                 fTestSessionListener= null;
278                 fActiveTestRunSession= null;
279             }
280         }
281     }
282     
283     private final ListenerList fTestRunSessionListeners= new ListenerList();
284     /**
285      * Active test run sessions, youngest first.
286      */

287     private final LinkedList JavaDoc/*<TestRunSession>*/ fTestRunSessions= new LinkedList JavaDoc();
288     private final ILaunchListener fLaunchListener= new JUnitLaunchListener();
289
290     /**
291      * Starts the model (called by the {@link JUnitPlugin} on startup).
292      */

293     public void start() {
294         ILaunchManager launchManager= DebugPlugin.getDefault().getLaunchManager();
295         launchManager.addLaunchListener(fLaunchListener);
296         
297 /*
298  * TODO: restore on restart:
299  * - only import headers!
300  * - only import last n sessions; remove all other files in historyDirectory
301  */

302 // File historyDirectory= JUnitPlugin.getHistoryDirectory();
303
// File[] swapFiles= historyDirectory.listFiles();
304
// if (swapFiles != null) {
305
// Arrays.sort(swapFiles, new Comparator() {
306
// public int compare(Object o1, Object o2) {
307
// String name1= ((File) o1).getName();
308
// String name2= ((File) o2).getName();
309
// return name1.compareTo(name2);
310
// }
311
// });
312
// for (int i= 0; i < swapFiles.length; i++) {
313
// final File file= swapFiles[i];
314
// SafeRunner.run(new ISafeRunnable() {
315
// public void run() throws Exception {
316
// importTestRunSession(file );
317
// }
318
// public void handleException(Throwable exception) {
319
// JUnitPlugin.log(exception);
320
// }
321
// });
322
// }
323
// }
324

325         addTestRunSessionListener(new LegacyTestRunSessionListener());
326     }
327
328     /**
329      * Stops the model (called by the {@link JUnitPlugin} on shutdown).
330      */

331     public void stop() {
332         ILaunchManager launchManager= DebugPlugin.getDefault().getLaunchManager();
333         launchManager.removeLaunchListener(fLaunchListener);
334         
335         File JavaDoc historyDirectory= JUnitPlugin.getHistoryDirectory();
336         File JavaDoc[] swapFiles= historyDirectory.listFiles();
337         if (swapFiles != null) {
338             for (int i= 0; i < swapFiles.length; i++) {
339                 swapFiles[i].delete();
340             }
341         }
342         
343 // for (Iterator iter= fTestRunSessions.iterator(); iter.hasNext();) {
344
// final TestRunSession session= (TestRunSession) iter.next();
345
// SafeRunner.run(new ISafeRunnable() {
346
// public void run() throws Exception {
347
// session.swapOut();
348
// }
349
// public void handleException(Throwable exception) {
350
// JUnitPlugin.log(exception);
351
// }
352
// });
353
// }
354
}
355     
356     
357     public void addTestRunSessionListener(ITestRunSessionListener listener) {
358         fTestRunSessionListeners.add(listener);
359     }
360     
361     public void removeTestRunSessionListener(ITestRunSessionListener listener) {
362         fTestRunSessionListeners.remove(listener);
363     }
364     
365     
366     /**
367      * @return a list of active {@link TestRunSession}s. The list is a copy of
368      * the internal data structure and modifications do not affect the
369      * global list of active sessions. The list is sorted by age, youngest first.
370      */

371     public List JavaDoc getTestRunSessions() {
372         return new ArrayList JavaDoc(fTestRunSessions);
373     }
374     
375     /**
376      * Adds the given {@link TestRunSession} and notifies all registered
377      * {@link ITestRunSessionListener}s.
378      * <p>
379      * <b>To be called in the UI thread only!</b>
380      * </p>
381      *
382      * @param testRunSession the session to add
383      */

384     public void addTestRunSession(TestRunSession testRunSession) {
385         Assert.isNotNull(testRunSession);
386         Assert.isLegal(! fTestRunSessions.contains(testRunSession));
387         fTestRunSessions.addFirst(testRunSession);
388         notifyTestRunSessionAdded(testRunSession);
389     }
390     
391     /**
392      * Imports a test run session from the given file.
393      *
394      * @param file a file containing a test run session transcript
395      * @return the imported test run session
396      * @throws CoreException if the import failed
397      */

398     public static TestRunSession importTestRunSession(File JavaDoc file) throws CoreException {
399         try {
400             SAXParserFactory JavaDoc parserFactory= SAXParserFactory.newInstance();
401 // parserFactory.setValidating(true); // TODO: add DTD and debug flag
402
SAXParser JavaDoc parser= parserFactory.newSAXParser();
403             TestRunHandler handler= new TestRunHandler();
404             parser.parse(file, handler);
405             TestRunSession session= handler.getTestRunSession();
406             JUnitPlugin.getModel().addTestRunSession(session);
407             return session;
408         } catch (ParserConfigurationException JavaDoc e) {
409             throwImportError(file, e);
410         } catch (SAXException JavaDoc e) {
411             throwImportError(file, e);
412         } catch (IOException JavaDoc e) {
413             throwImportError(file, e);
414         }
415         return null; // does not happen
416
}
417     
418     public static void importIntoTestRunSession(File JavaDoc swapFile, TestRunSession testRunSession) throws CoreException {
419         try {
420             SAXParserFactory JavaDoc parserFactory= SAXParserFactory.newInstance();
421 // parserFactory.setValidating(true); // TODO: add DTD and debug flag
422
SAXParser JavaDoc parser= parserFactory.newSAXParser();
423             TestRunHandler handler= new TestRunHandler(testRunSession);
424             parser.parse(swapFile, handler);
425         } catch (ParserConfigurationException JavaDoc e) {
426             throwImportError(swapFile, e);
427         } catch (SAXException JavaDoc e) {
428             throwImportError(swapFile, e);
429         } catch (IOException JavaDoc e) {
430             throwImportError(swapFile, e);
431         }
432     }
433
434     /**
435      * Exports the given test run session.
436      *
437      * @param testRunSession the test run session
438      * @param file the destination
439      * @throws CoreException
440      */

441     public static void exportTestRunSession(TestRunSession testRunSession, File JavaDoc file) throws CoreException {
442         FileOutputStream JavaDoc out= null;
443         try {
444             out= new FileOutputStream JavaDoc(file);
445             exportTestRunSession(testRunSession, out);
446             
447         } catch (IOException JavaDoc e) {
448             throwExportError(file, e);
449         } catch (TransformerConfigurationException JavaDoc e) {
450             throwExportError(file, e);
451         } catch (TransformerException JavaDoc e) {
452             throwExportError(file, e);
453         } finally {
454             if (out != null) {
455                 try {
456                     out.close();
457                 } catch (IOException JavaDoc e2) {
458                     JUnitPlugin.log(e2);
459                 }
460             }
461         }
462     }
463
464     public static void exportTestRunSession(TestRunSession testRunSession, OutputStream JavaDoc out)
465             throws TransformerFactoryConfigurationError JavaDoc, TransformerException JavaDoc {
466         
467         Transformer JavaDoc transformer= TransformerFactory.newInstance().newTransformer();
468         InputSource JavaDoc inputSource= new InputSource JavaDoc();
469         SAXSource JavaDoc source= new SAXSource JavaDoc(new TestRunSessionSerializer(testRunSession), inputSource);
470         StreamResult JavaDoc result= new StreamResult JavaDoc(out);
471         transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
472
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
473
/*
474          * Bug in Xalan: Only indents if proprietary property
475          * org.apache.xalan.templates.OutputProperties.S_KEY_INDENT_AMOUNT is set.
476          *
477          * Bug in Xalan as shipped with J2SE 5.0:
478          * Does not read the indent-amount property at all >:-(.
479          */

480         try {
481             transformer.setOutputProperty("{http://xml.apache.org/xalan}indent-amount", "2"); //$NON-NLS-1$ //$NON-NLS-2$
482
} catch (IllegalArgumentException JavaDoc e) {
483             // no indentation today...
484
}
485         transformer.transform(source, result);
486     }
487     
488     private static void throwExportError(File JavaDoc file, Exception JavaDoc e) throws CoreException {
489         throw new CoreException(new org.eclipse.core.runtime.Status(IStatus.ERROR,
490                 JUnitPlugin.getPluginId(),
491                 Messages.format(ModelMessages.JUnitModel_could_not_write, file.getAbsolutePath()),
492                 e));
493     }
494
495     private static void throwImportError(File JavaDoc file, Exception JavaDoc e) throws CoreException {
496         throw new CoreException(new org.eclipse.core.runtime.Status(IStatus.ERROR,
497                 JUnitPlugin.getPluginId(),
498                 Messages.format(ModelMessages.JUnitModel_could_not_read, file.getAbsolutePath()),
499                 e));
500     }
501     
502     /**
503      * Removes the given {@link TestRunSession} and notifies all registered
504      * {@link ITestRunSessionListener}s.
505      * <p>
506      * <b>To be called in the UI thread only!</b>
507      * </p>
508      *
509      * @param testRunSession the session to remove
510      */

511     public void removeTestRunSession(TestRunSession testRunSession) {
512         boolean existed= fTestRunSessions.remove(testRunSession);
513         if (existed) {
514             notifyTestRunSessionRemoved(testRunSession);
515         }
516         testRunSession.removeSwapFile();
517     }
518     
519     private void notifyTestRunSessionRemoved(TestRunSession testRunSession) {
520         testRunSession.stopTestRun();
521         ILaunch launch= testRunSession.getLaunch();
522         if (launch != null) {
523             ILaunchManager launchManager= DebugPlugin.getDefault().getLaunchManager();
524             launchManager.removeLaunch(launch);
525         }
526         
527         Object JavaDoc[] listeners = fTestRunSessionListeners.getListeners();
528         for (int i = 0; i < listeners.length; ++i) {
529             ((ITestRunSessionListener) listeners[i]).sessionRemoved(testRunSession);
530         }
531     }
532     
533     private void notifyTestRunSessionAdded(TestRunSession testRunSession) {
534         Object JavaDoc[] listeners = fTestRunSessionListeners.getListeners();
535         for (int i = 0; i < listeners.length; ++i) {
536             ((ITestRunSessionListener) listeners[i]).sessionAdded(testRunSession);
537         }
538     }
539
540 }
541
Popular Tags