package org.testng.eclipse.buildpath; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.List; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.equinox.frameworkadmin.BundleInfo; import org.eclipse.jdt.core.IAccessRule; import org.eclipse.jdt.core.IClasspathAttribute; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.osgi.service.resolver.VersionRange; import org.osgi.framework.Bundle; import org.osgi.framework.Version; import org.testng.eclipse.TestNGPlugin; import org.testng.eclipse.util.ResourceUtil; public class BuildPathSupport { private static final PluginDescription TESTNG_PLUGIN_DESC = new PluginDescription("org.testng", new VersionRange("[6.0, 7.0)"), null, null, "org.testng.source", null); private static final PluginDescription JCOMMANDER_PLUGIN_DESC = new PluginDescription("com.beust.jcommander", new VersionRange("[1.5, 2.0)"), null, null, "com.beust.jcommander.source", null); private static final PluginDescription BSH_PLUGIN_DESC = new PluginDescription("org.apache-extras.beanshell.bsh", new VersionRange("[2.0, 2.1)"), null, null, "org.apache-extras.beanshell.bsh.source", null); private static final PluginDescription YAML_PLUGIN_DESC = new PluginDescription("org.yaml.snakeyaml", new VersionRange("[1.0, 2.0)"), null, null, "org.yaml.snakeyaml", null); private static IClasspathEntry[] TESTNG_LIB_ENTRIES_CACHE; private static IPath getBundleLocation() { Bundle bundle = TestNGPlugin.getDefault().getBundle(); return getBundleLocation(bundle); } private static IPath getBundleLocation(Bundle bundle) { if (bundle == null) { return null; } URL local; try { local = FileLocator.toFileURL(bundle.getEntry("/")); //$NON-NLS-1$ } catch (IOException e) { return null; } String fullPath = new File(local.getPath()).getAbsolutePath(); return Path.fromOSString(fullPath); } public static IClasspathEntry getTestNGClasspathEntry() { return JavaCore.newContainerEntry(TestNGContainerInitializer.TESTNG_PATH); } /** * * @return the <code>IClasspathEntry</code> array which contains the testng jar itself and its dependencies, e.g. jcommander */ public static IClasspathEntry[] getTestNGLibraryEntries() { if (TESTNG_LIB_ENTRIES_CACHE == null) { List<IClasspathEntry> result = new ArrayList<IClasspathEntry>(); result.add(TESTNG_PLUGIN_DESC.getLibraryEntry()); result.add(JCOMMANDER_PLUGIN_DESC.getLibraryEntry()); IClasspathEntry bshCpEnt = BSH_PLUGIN_DESC.getLibraryEntry(); if (bshCpEnt != null) { result.add(bshCpEnt); } IClasspathEntry yamlCpEnt = YAML_PLUGIN_DESC.getLibraryEntry(); if (yamlCpEnt != null) { result.add(yamlCpEnt); } TESTNG_LIB_ENTRIES_CACHE = result.toArray(new IClasspathEntry[result.size()]); } return TESTNG_LIB_ENTRIES_CACHE; } public static IPath getBundleFile(String relativePath) { return getBundleLocation().append(relativePath); } public static boolean projectContainsClasspathEntry(IJavaProject project, IClasspathEntry entry) throws JavaModelException { IClasspathEntry[] oldEntries = project.getRawClasspath(); for (IClasspathEntry oldEntry : oldEntries) { if (oldEntry.equals(entry)) { return true; } } return false; } /** * copied from * org.eclipse.jdt.internal.junit.buildpath.BuildPathSupport.JUnitPluginDescription * */ public static class PluginDescription { private final String bundleId; private final VersionRange versionRange; private final String bundleRoot; private final String binaryImportedRoot; private final String sourceBundleId; private final String repositorySource; private String resolvedVersion = null; public PluginDescription(String bundleId, VersionRange versionRange, String bundleRoot, String binaryImportedRoot, String sourceBundleId, String repositorySource) { this.bundleId = bundleId; this.versionRange = versionRange; this.bundleRoot = bundleRoot; this.binaryImportedRoot = binaryImportedRoot; this.sourceBundleId = sourceBundleId; this.repositorySource = repositorySource; } public IPath getBundleLocation() { return getBundleLocation(bundleId, versionRange); } public IPath getSourceBundleLocation() { return getSourceLocation(getBundleLocation()); } private IPath getBundleLocation(String aBundleId, VersionRange aVersionRange) { return getBundleLocation(aBundleId, aVersionRange, false); } private IPath getBundleLocation(String aBundleId, VersionRange aVersionRange, boolean isSourceBundle) { BundleInfo bundleInfo = P2Utils.findBundle(aBundleId, aVersionRange, isSourceBundle); if (bundleInfo != null) { resolvedVersion = bundleInfo.getVersion(); return P2Utils.getBundleLocationPath(bundleInfo); } else { // p2's simple configurator is not available. Let's try with installed // bundles from the running platform. // Note: Source bundles are typically not available at run time! Bundle[] bundles = Platform.getBundles(aBundleId, aVersionRange.toString()); Bundle bestMatch = null; if (bundles != null) { for (int i = 0; i < bundles.length; i++) { Bundle bundle = bundles[i]; if (bestMatch == null || bundle.getState() > bestMatch.getState()) { bestMatch = bundle; } } } if (bestMatch != null) { try { resolvedVersion = bestMatch.getVersion().toString(); URL rootUrl = bestMatch.getEntry("/"); //$NON-NLS-1$ URL fileRootUrl = FileLocator.toFileURL(rootUrl); return new Path(fileRootUrl.getPath()); } catch (IOException ex) { TestNGPlugin.log(ex); } } } return null; } public IClasspathEntry getLibraryEntry() { IPath bundleLocation = getBundleLocation(bundleId, versionRange); if (bundleLocation != null) { IPath bundleRootLocation = null; if (bundleRoot != null) { bundleRootLocation = getLocationIfExists(bundleLocation, bundleRoot); } if (bundleRootLocation == null && binaryImportedRoot != null) { bundleRootLocation = getLocationIfExists(bundleLocation, binaryImportedRoot); } if (bundleRootLocation == null) { bundleRootLocation = getBundleLocation(bundleId, versionRange); } IPath srcLocation = getSourceLocation(bundleLocation); return JavaCore.newLibraryEntry(bundleRootLocation, srcLocation, null, getAccessRules(), new IClasspathAttribute[0], false); } return null; } public IAccessRule[] getAccessRules() { return new IAccessRule[0]; } private IPath getSourceLocation(IPath bundleLocation) { IPath srcLocation = null; if (repositorySource != null) { // Try source in workspace (from repository) srcLocation = getLocationIfExists(bundleLocation, repositorySource); } if (srcLocation == null) { if (bundleLocation != null) { // Try exact version Version version = new Version(resolvedVersion); srcLocation = getBundleLocation(sourceBundleId, new VersionRange(version, true, version, true), true); } if (srcLocation == null) { // Try version range srcLocation = getBundleLocation(sourceBundleId, versionRange, true); } } return srcLocation; } private IPath getLocationIfExists(IPath bundleLocationPath, final String entryInBundle) { IPath srcLocation = null; if (bundleLocationPath != null) { File bundleFile = bundleLocationPath.toFile(); if (bundleFile.isDirectory()) { File srcFile = null; final int starIdx = entryInBundle.indexOf('*'); if (starIdx != -1) { File[] files = bundleFile.listFiles(new FilenameFilter() { private String pre = entryInBundle.substring(0, starIdx); private String post = entryInBundle.substring(starIdx + 1); @Override public boolean accept(File dir, String name) { return name.startsWith(pre) && name.endsWith(post); } }); if (files.length > 0) { srcFile = files[0]; } } if (srcFile == null) srcFile = new File(bundleFile, entryInBundle); if (srcFile.exists()) { srcLocation = new Path(srcFile.getPath()); if (srcFile.isDirectory()) { srcLocation = srcLocation.addTrailingSeparator(); } } } } return srcLocation; } } }