001: package org.eclipse.pde.internal.junit.launcher;
002:
003: /*
004: * (c) Copyright IBM Corp. 2000, 2001.
005: * All Rights Reserved.
006: */
007:
008: import java.io.File;
009: import java.io.IOException;
010: import java.net.MalformedURLException;
011: import java.net.URL;
012: import java.util.ArrayList;
013: import java.util.HashSet;
014: import java.util.Iterator;
015: import java.util.Vector;
016:
017: import org.eclipse.core.resources.IContainer;
018: import org.eclipse.core.resources.IProject;
019: import org.eclipse.core.resources.IResource;
020: import org.eclipse.core.resources.IWorkspaceRoot;
021: import org.eclipse.core.runtime.CoreException;
022: import org.eclipse.core.runtime.IPath;
023: import org.eclipse.core.runtime.IStatus;
024: import org.eclipse.core.runtime.MultiStatus;
025: import org.eclipse.core.runtime.Path;
026: import org.eclipse.core.runtime.Platform;
027: import org.eclipse.core.runtime.Status;
028: import org.eclipse.core.runtime.model.Factory;
029: import org.eclipse.core.runtime.model.PluginRegistryModel;
030: import org.eclipse.debug.core.ILaunch;
031: import org.eclipse.debug.core.ILaunchConfiguration;
032: import org.eclipse.debug.core.ILaunchManager;
033: import org.eclipse.debug.core.model.ISourceLocator;
034: import org.eclipse.jdt.core.IJavaProject;
035: import org.eclipse.jdt.core.IType;
036: import org.eclipse.jdt.core.JavaCore;
037: import org.eclipse.jdt.core.JavaModelException;
038: import org.eclipse.jdt.debug.ui.JavaUISourceLocator;
039: import org.eclipse.jdt.internal.junit.launcher.JUnitBaseLaunchConfiguration;
040: import org.eclipse.jdt.launching.ExecutionArguments;
041: import org.eclipse.jdt.launching.JavaRuntime;
042: import org.eclipse.jdt.launching.VMRunnerConfiguration;
043: import org.eclipse.pde.core.plugin.IPluginModelBase;
044: import org.eclipse.pde.internal.core.ICoreConstants;
045: import org.eclipse.pde.internal.core.PDECore;
046: import org.eclipse.pde.internal.core.TargetPlatform;
047: import org.eclipse.pde.internal.core.WorkspaceModelManager;
048: import org.eclipse.pde.internal.junit.ui.JUnitPdePlugin;
049: import org.eclipse.pde.internal.ui.PDEPlugin;
050:
051: /**
052: * Launch configuration delegate for a plain JUnit test.
053: */
054: public class JUnitPdeLaunchConfiguration extends
055: JUnitBaseLaunchConfiguration {
056: public static final String ID_PLUGIN_JUNIT = "org.eclipse.pde.junit.launchconfig"; //$NON-NLS-1$
057:
058: public static final String APPLICATION_NAME_ATTR = JUnitPdePlugin.PLUGIN_ID
059: + ".APPLICATION_NAME";
060: public static final String DELETE_WORKSPACE_ATTR = JUnitPdePlugin.PLUGIN_ID
061: + ".DELETE_WORKSPACE"; //$NON-NLS-1$
062: public static final String WORKSPACE_ATTR = JUnitPdePlugin.PLUGIN_ID
063: + "WORKSPACE_LOCATION";
064:
065: public static final String[] fgApplicationNames = new String[] {
066: "org.eclipse.pde.junit.uitestapplication",
067: "org.eclipse.pde.junit.coretestapplication" };
068: public static final String fgDefaultApp = fgApplicationNames[0];
069:
070: private Vector fDuplicates = new Vector();
071:
072: /*
073: * @see JUnitBaseLauncherDelegate#configureVM(IType[], int, String)
074: */
075: protected VMRunnerConfiguration createVMRunner(
076: ILaunchConfiguration configuration, IType[] testTypes,
077: int port, String runMode) throws CoreException {
078: String applicationName = configuration.getAttribute(
079: APPLICATION_NAME_ATTR, fgDefaultApp);
080: String workspace = configuration.getAttribute(WORKSPACE_ATTR,
081: (String) null);
082: if (workspace == null)
083: workspace = getTempWorkSpaceLocation();
084:
085: //VMRunnerConfiguration vmConfig= WorkbenchLaunchConfigurationDelegate.createWorkspaceRunnerConfiguration(workspace, applicationName, new NullProgressMonitor());
086: VMRunnerConfiguration vmConfig = createWorkspaceRunnerConfiguration(
087: configuration, applicationName, workspace);
088:
089: String testPluginID = getTestPluginId(configuration);
090:
091: Vector postArgsVector = new Vector(20);
092: postArgsVector.add("-consolelog");
093: postArgsVector.add("-port");
094: postArgsVector.add(Integer.toString(port));
095: postArgsVector.add("-testpluginname");
096: postArgsVector.add(testPluginID);
097: // "-debugging",
098: if (keepAlive(configuration)
099: && runMode.equals(ILaunchManager.DEBUG_MODE))
100: postArgsVector.add(0, "-keepalive");
101:
102: // a testname was specified just run the single test
103: String testName = configuration.getAttribute(
104: JUnitBaseLaunchConfiguration.TESTNAME_ATTR, "");
105: if (testName.length() > 0) {
106: postArgsVector.add("-test"); //$NON-NLS-1$
107: postArgsVector.add(testTypes[0].getFullyQualifiedName()
108: + ":" + testName);
109: } else {
110: postArgsVector.add("-classnames");
111: for (int i = 0; i < testTypes.length; i++)
112: postArgsVector
113: .add(testTypes[i].getFullyQualifiedName());
114: }
115:
116: String[] standardArgs = vmConfig.getProgramArguments();
117: String[] postArgs = new String[postArgsVector.size()];
118: postArgsVector.copyInto(postArgs);
119: String[] args = new String[standardArgs.length
120: + postArgsVector.size()];
121:
122: System.arraycopy(standardArgs, 0, args, 0, standardArgs.length);
123: System.arraycopy(postArgs, 0, args, standardArgs.length,
124: postArgs.length);
125:
126: vmConfig.setProgramArguments(args);
127:
128: if (configuration.getAttribute(DELETE_WORKSPACE_ATTR, true)) {
129: try {
130: deleteTestWorkspace(workspace);
131: } catch (IOException e) {
132: throw new CoreException(new Status(IStatus.ERROR,
133: JUnitPdePlugin.PLUGIN_ID, IStatus.ERROR,
134: "Could not delete test workspace.", e));
135: }
136: }
137: return vmConfig;
138: }
139:
140: protected String getTestPluginId(ILaunchConfiguration configuration)
141: throws CoreException {
142: PluginRegistryModel testPluginModel = null;
143: IJavaProject javaProject = getJavaProject(configuration);
144:
145: try {
146: testPluginModel = getPluginRegistryModel(javaProject);
147: } catch (IOException e) {
148: throw new CoreException(new Status(IStatus.ERROR,
149: JUnitPdePlugin.PLUGIN_ID, IStatus.ERROR,
150: "Could not determine test plugin Id.", e));
151: }
152: if (testPluginModel == null)
153: throw new CoreException(
154: new Status(
155: IStatus.ERROR,
156: JUnitPdePlugin.PLUGIN_ID,
157: IStatus.ERROR,
158: "Could not determine test plugin Id - project is not a plugin.",
159: null));
160:
161: String testPluginID = testPluginModel.getPlugins()[0].getId();
162: return testPluginID;
163: }
164:
165: private VMRunnerConfiguration createWorkspaceRunnerConfiguration(
166: ILaunchConfiguration configuration, String appName,
167: String workspaceLocation) throws CoreException {
168: final IPluginModelBase[] plugins = getPlugins();
169: String workspace = workspaceLocation;
170: Path tmpWorkspacePath = new Path(workspace);
171: File propertiesFile = TargetPlatform.createPropertiesFile(
172: plugins, tmpWorkspacePath);
173: String[] classpath = constructClasspath(plugins);
174: String progArgs = getProgramArguments(configuration);
175:
176: if (classpath == null) {
177: throw new CoreException(new Status(IStatus.ERROR,
178: JUnitPdePlugin.PLUGIN_ID, IStatus.ERROR,
179: "Could not compute classpath.", null));
180: }
181: VMRunnerConfiguration vmConfig = new VMRunnerConfiguration(
182: "EclipseRuntimeLauncher", classpath);
183:
184: Vector argv = new Vector(20);
185: argv.add(appName);
186: argv.add(propertiesFile.getPath());
187:
188: // insert the program arguments
189: ExecutionArguments execArgs = new ExecutionArguments(
190: "", progArgs); //$NON-NLS-1$
191: String[] pa = execArgs.getProgramArgumentsArray();
192: for (int i = 0; i < pa.length; i++) {
193: argv.add(pa[i]);
194: }
195:
196: argv.add("-data");
197: argv.add(workspace);
198:
199: argv.add("-dev");
200: argv.add(getBuildOutputFolders(plugins));
201:
202: String[] args = new String[argv.size()];
203: argv.copyInto(args);
204: vmConfig.setProgramArguments(args);
205: return vmConfig;
206: }
207:
208: private PluginRegistryModel getPluginRegistryModel(
209: IJavaProject project) throws IOException {
210: MultiStatus status = new MultiStatus("JUnit PDE Launcher",
211: IStatus.ERROR, "Error scanning plugin.xml", null);
212: Factory factory = new Factory(status);
213: URL url = project.getProject().getLocation().toFile().toURL();
214: url = Platform.asLocalURL(url);
215: url = new URL(url, "plugin.xml");
216: PluginRegistryModel pluginRegistryModel = Platform
217: .parsePlugins(new URL[] { url }, factory);
218: if (pluginRegistryModel != null
219: && pluginRegistryModel.getPlugins().length == 1)
220: return pluginRegistryModel;
221: return null;
222: }
223:
224: private String getTempLocation() {
225: return System.getProperty("java.io.tmpdir") + File.separator;
226: }
227:
228: private String getTempWorkSpaceLocation() {
229: return getTempLocation() + "org.eclipse.pde.junit.workspace";
230: }
231:
232: private void deleteTestWorkspace(String workspace)
233: throws IOException {
234: deleteContent(new File(workspace));
235: }
236:
237: private void deleteContent(File workspace) throws IOException {
238: if (workspace.isDirectory()) {
239: File[] children = workspace.listFiles();
240: for (int i = 0; i < children.length; i++) {
241: deleteContent(children[i]);
242: }
243: }
244: workspace.delete();
245: }
246:
247: IPluginModelBase[] getPlugins() {
248: IPluginModelBase[] wsmodels = getWorkspacePlugins();
249: ArrayList wsList = new ArrayList();
250: for (int i = 0; i < wsmodels.length; i++) {
251: IPluginModelBase model = wsmodels[i];
252: wsList.add(model);
253: }
254:
255: IPluginModelBase[] exmodels = getExternalPlugins();
256: ArrayList exList = new ArrayList();
257: for (int i = 0; i < exmodels.length; i++) {
258: IPluginModelBase model = exmodels[i];
259: //TODO: we should add at least the PDE JUnit and its pre-reqs
260: //if (model.isEnabled())
261: exList.add(model);
262: }
263:
264: ArrayList result = new ArrayList();
265: mergeWithoutDuplicates(wsList, exList, result);
266: IPluginModelBase[] plugins = (IPluginModelBase[]) result
267: .toArray(new IPluginModelBase[result.size()]);
268: return plugins;
269: }
270:
271: protected void setDefaultSourceLocator(ILaunch launch,
272: ILaunchConfiguration configuration) throws CoreException {
273: ISourceLocator sourceLocator = constructSourceLocator(getPlugins());
274: launch.setSourceLocator(sourceLocator);
275: }
276:
277: //
278: // All methods below are copied from org.eclipse.pde.internal.ui.launcher.AdvancedLauncherTab
279: // TODO: request API from PDE
280: static IPluginModelBase[] getWorkspacePlugins() {
281: IPluginModelBase[] plugins = PDECore.getDefault()
282: .getWorkspaceModelManager().getWorkspacePluginModels();
283: IPluginModelBase[] fragments = PDECore.getDefault()
284: .getWorkspaceModelManager()
285: .getWorkspaceFragmentModels();
286: return getAllPlugins(plugins, fragments);
287: }
288:
289: static IPluginModelBase[] getExternalPlugins() {
290: IPluginModelBase[] plugins = PDECore.getDefault()
291: .getExternalModelManager().getModels();
292: IPluginModelBase[] fragments = PDECore.getDefault()
293: .getExternalModelManager().getFragmentModels();
294: return getAllPlugins(plugins, fragments);
295: }
296:
297: static IPluginModelBase[] getAllPlugins(IPluginModelBase[] plugins,
298: IPluginModelBase[] fragments) {
299: IPluginModelBase[] all = new IPluginModelBase[plugins.length
300: + fragments.length];
301: System.arraycopy(plugins, 0, all, 0, plugins.length);
302: System.arraycopy(fragments, 0, all, plugins.length,
303: fragments.length);
304: return all;
305: }
306:
307: private void mergeWithoutDuplicates(ArrayList wsmodels,
308: ArrayList exmodels, ArrayList result) {
309: for (int i = 0; i < wsmodels.size(); i++) {
310: result.add(wsmodels.get(i));
311: }
312:
313: fDuplicates = new Vector();
314: for (int i = 0; i < exmodels.size(); i++) {
315: IPluginModelBase exmodel = (IPluginModelBase) exmodels
316: .get(i);
317: boolean duplicate = false;
318: for (int j = 0; j < wsmodels.size(); j++) {
319: IPluginModelBase wsmodel = (IPluginModelBase) wsmodels
320: .get(j);
321: if (isDuplicate(wsmodel, exmodel)) {
322: fDuplicates.add(exmodel.getPluginBase().getId()
323: + " ("
324: + exmodel.getPluginBase().getVersion()
325: + ")");
326: duplicate = true;
327: break;
328: }
329: }
330: if (!duplicate)
331: result.add(exmodel);
332: }
333: }
334:
335: private boolean isDuplicate(IPluginModelBase wsmodel,
336: IPluginModelBase exmodel) {
337: if (!wsmodel.isLoaded() || !exmodel.isLoaded())
338: return false;
339: String wsPluginId = wsmodel.getPluginBase().getId();
340: String exPluginId = exmodel.getPluginBase().getId();
341: if (wsPluginId == null)
342: return false;
343: return wsPluginId.equalsIgnoreCase(exPluginId);
344: }
345:
346: /**
347: * Constructs a classpath with the slimlauncher and the boot plugin (org.eclipse.core.boot)
348: * If the boot project is in the workspace, the classpath used in the workspace is used.
349: */
350: private String[] constructClasspath(IPluginModelBase[] plugins)
351: throws CoreException {
352: File slimLauncher = PDEPlugin.getFileInPlugin(new Path(
353: "launcher/slimlauncher.jar"));
354: if (slimLauncher == null || !slimLauncher.exists()) {
355: return null;
356: }
357: IPluginModelBase model = findModel("org.eclipse.core.boot",
358: plugins);
359: if (model != null) {
360: IResource resource = model.getUnderlyingResource();
361: if (resource != null) {
362: // in workspace - use the java project
363: IProject project = resource.getProject();
364: IJavaProject jproject = JavaCore.create(project);
365: String[] bootClassPath = JavaRuntime
366: .computeDefaultRuntimeClassPath(jproject);
367: if (bootClassPath != null) {
368: String[] resClassPath = new String[bootClassPath.length + 1];
369: resClassPath[0] = slimLauncher.getPath();
370: System.arraycopy(bootClassPath, 0, resClassPath, 1,
371: bootClassPath.length);
372: return resClassPath;
373: }
374: } else {
375: // outside - locate boot.jar
376: String installLocation = model.getInstallLocation();
377: if (installLocation.startsWith("file:"))
378: installLocation = installLocation.substring(5);
379: File bootJar = new File(installLocation, "boot.jar");
380: if (bootJar.exists()) {
381: return new String[] { slimLauncher.getPath(),
382: bootJar.getPath() };
383: }
384: // Check PDE case (third instance) - it may be in the bin
385: File binDir = new File(installLocation, "bin/");
386: if (binDir.exists()) {
387: return new String[] { slimLauncher.getPath(),
388: binDir.getPath() };
389: }
390: }
391: }
392: // failed to construct the class path: boot plugin not existing or boot.jar not found
393: return null;
394: }
395:
396: private IPluginModelBase findModel(String id,
397: IPluginModelBase[] models) {
398: for (int i = 0; i < models.length; i++) {
399: IPluginModelBase model = (IPluginModelBase) models[i];
400: if (model.getPluginBase().getId().equals(id))
401: return model;
402: }
403: return null;
404: }
405:
406: /**
407: * Constructs a source locator containg all projects selected as plugins.
408: */
409: private ISourceLocator constructSourceLocator(
410: IPluginModelBase[] plugins) throws CoreException {
411: ArrayList javaProjects = new ArrayList(plugins.length);
412: IWorkspaceRoot root = PDEPlugin.getWorkspace().getRoot();
413: for (int i = 0; i < plugins.length; i++) {
414: try {
415: File pluginDir = new File(new URL("file:"
416: + plugins[i].getInstallLocation()).getFile());
417: IContainer container = root
418: .getContainerForLocation(new Path(pluginDir
419: .getPath()));
420: if (container instanceof IProject) {
421: IProject project = (IProject) container;
422: if (WorkspaceModelManager
423: .isJavaPluginProject(project))
424: javaProjects.add(JavaCore.create(project));
425: }
426: } catch (MalformedURLException e) {
427: PDEPlugin.log(e);
428: }
429: }
430: IJavaProject[] projs = (IJavaProject[]) javaProjects
431: .toArray(new IJavaProject[javaProjects.size()]);
432: return new JavaUISourceLocator(projs, false);
433: }
434:
435: private String getBuildOutputFolders(IPluginModelBase[] plugins) {
436: IPluginModelBase[] wsmodels = plugins;
437: HashSet set = new HashSet();
438: set.add("bin");
439: for (int i = 0; i < wsmodels.length; i++) {
440: IResource underlyingResource = wsmodels[i]
441: .getUnderlyingResource();
442: if (underlyingResource != null) {
443: IProject project = underlyingResource.getProject();
444: try {
445: if (project.hasNature(JavaCore.NATURE_ID)) {
446: set.add(JavaCore.create(project)
447: .getOutputLocation().lastSegment());
448: }
449: } catch (JavaModelException e) {
450: } catch (CoreException e) {
451: }
452: }
453: }
454: StringBuffer result = new StringBuffer();
455: for (Iterator iter = set.iterator(); iter.hasNext();) {
456: String folder = iter.next().toString();
457: result.append(folder);
458: if (iter.hasNext())
459: result.append(",");
460: }
461: return result.toString();
462: }
463:
464: static String getDefaultWorkspace() {
465: IPath ppath = new Path(PDECore.getDefault()
466: .getPluginPreferences().getString(
467: ICoreConstants.PLATFORM_PATH));
468: IPath runtimeWorkspace = ppath
469: .append(JUnitPdeMainTab.RT_WORKSPACE);
470: return runtimeWorkspace.toOSString();
471:
472: }
473:
474: }
|