1 /******************************************************************************* 2 * Copyright (c) 2005, 2019 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.pde.internal.core.util; 15 16 import java.util.ArrayList; 17 import java.util.Collection; 18 import java.util.Collections; 19 import java.util.HashMap; 20 import java.util.LinkedHashMap; 21 import java.util.ListIterator; 22 import org.eclipse.core.resources.IProject; 23 import org.eclipse.core.resources.IResource; 24 import org.eclipse.core.runtime.CoreException; 25 import org.eclipse.core.runtime.IPath; 26 import org.eclipse.core.runtime.Path; 27 import org.eclipse.jdt.core.IJavaElement; 28 import org.eclipse.jdt.core.IJavaProject; 29 import org.eclipse.jdt.core.IPackageFragment; 30 import org.eclipse.jdt.core.IPackageFragmentRoot; 31 import org.eclipse.jdt.core.IType; 32 import org.eclipse.jdt.core.JavaCore; 33 import org.eclipse.jdt.core.JavaModelException; 34 import org.eclipse.jdt.core.search.IJavaSearchScope; 35 import org.eclipse.jdt.core.search.SearchEngine; 36 import org.eclipse.jdt.launching.JavaRuntime; 37 import org.eclipse.osgi.service.resolver.BundleDescription; 38 import org.eclipse.osgi.service.resolver.ExportPackageDescription; 39 import org.eclipse.osgi.service.resolver.ImportPackageSpecification; 40 import org.eclipse.osgi.service.resolver.State; 41 import org.eclipse.osgi.service.resolver.StateHelper; 42 import org.eclipse.pde.core.plugin.IPluginLibrary; 43 import org.eclipse.pde.core.plugin.IPluginModelBase; 44 import org.eclipse.pde.core.plugin.PluginRegistry; 45 import org.eclipse.pde.internal.core.ClasspathUtilCore; 46 import org.eclipse.pde.internal.core.PDECore; 47 import org.eclipse.pde.internal.core.PDEPreferencesManager; 48 import org.eclipse.pde.internal.core.SearchablePluginsManager; 49 50 public class PDEJavaHelper { 51 52 /*static class Requestor extends TypeNameRequestor { 53 int count = 0; 54 55 public void acceptType(int modifiers, char[] packageName, char[] simpleTypeName, 56 char[][] enclosingTypeNames, String path) { 57 count += 1; 58 } 59 60 public boolean hasMatches() { 61 return count > 0; 62 } 63 }*/ 64 isDiscouraged(String fullyQualifiedName, IJavaProject project, BundleDescription desc)65 public static boolean isDiscouraged(String fullyQualifiedName, IJavaProject project, BundleDescription desc) { 66 // allow classes within the project itself 67 try { 68 IType type = project.findType(fullyQualifiedName.replace('$', '.')); 69 if (type != null && type.exists()) { 70 HashMap<String, IPackageFragment> map = PDEJavaHelper.getPackageFragmentsHash(project, 71 Collections.emptyList(), false); 72 if (map.containsValue(type.getPackageFragment())) { 73 return false; 74 } 75 } 76 } catch (JavaModelException e) { 77 } 78 79 // just grab the package 80 int dot = fullyQualifiedName.lastIndexOf('.'); 81 if (dot != -1) { 82 fullyQualifiedName = fullyQualifiedName.substring(0, dot); 83 } else { 84 fullyQualifiedName = "."; //$NON-NLS-1$ 85 } 86 87 State state = desc.getContainingState(); 88 StateHelper helper = state.getStateHelper(); 89 ExportPackageDescription[] exports = helper.getVisiblePackages(desc); 90 for (ExportPackageDescription export : exports) { 91 BundleDescription exporter = export.getExporter(); 92 if (exporter == null) { 93 continue; 94 } 95 96 if (fullyQualifiedName.equals(export.getName()) && helper.getAccessCode(desc, export) == StateHelper.ACCESS_DISCOURAGED) { 97 return true; 98 } 99 100 } 101 102 return false; 103 } 104 isOnClasspath(String fullyQualifiedName, IJavaProject project)105 public static boolean isOnClasspath(String fullyQualifiedName, IJavaProject project) { 106 if (fullyQualifiedName.indexOf('$') != -1) { 107 fullyQualifiedName = fullyQualifiedName.replace('$', '.'); 108 } 109 try { 110 IType type = project.findType(fullyQualifiedName); 111 return type != null && type.exists(); 112 } catch (JavaModelException e) { 113 } 114 return false; 115 /*try { 116 Requestor requestor = new Requestor(); 117 new SearchEngine().searchAllTypeNames( 118 fullyQualifiedName.substring(0, fullyQualifiedName.lastIndexOf('.')).toCharArray(), 119 SearchPattern.R_EXACT_MATCH|SearchPattern.R_CASE_SENSITIVE, 120 fullyQualifiedName.substring(fullyQualifiedName.lastIndexOf('.') + 1).toCharArray(), 121 SearchPattern.R_EXACT_MATCH|SearchPattern.R_CASE_SENSITIVE, 122 IJavaSearchConstants.TYPE, 123 SearchEngine.createJavaSearchScope(new IJavaElement[] {project}), 124 requestor, 125 IJavaSearchConstants.FORCE_IMMEDIATE_SEARCH, 126 new NullProgressMonitor()); 127 return requestor.hasMatches(); 128 } catch (JavaModelException e) { 129 } 130 return false;*/ 131 } 132 getSearchScope(IJavaProject project)133 public static IJavaSearchScope getSearchScope(IJavaProject project) { 134 return SearchEngine.createJavaSearchScope(getNonJRERoots(project)); 135 } 136 getSearchScope(IProject project)137 public static IJavaSearchScope getSearchScope(IProject project) { 138 return getSearchScope(JavaCore.create(project)); 139 } 140 getNonJRERoots(IJavaProject project)141 public static IPackageFragmentRoot[] getNonJRERoots(IJavaProject project) { 142 ArrayList<IPackageFragmentRoot> result = new ArrayList<>(); 143 try { 144 IPackageFragmentRoot[] roots = project.getAllPackageFragmentRoots(); 145 for (int i = 0; i < roots.length; i++) { 146 if (!isJRELibrary(roots[i])) { 147 result.add(roots[i]); 148 } 149 } 150 } catch (JavaModelException e) { 151 } 152 return result.toArray(new IPackageFragmentRoot[result.size()]); 153 } 154 isJRELibrary(IPackageFragmentRoot root)155 public static boolean isJRELibrary(IPackageFragmentRoot root) { 156 try { 157 IPath path = root.getRawClasspathEntry().getPath(); 158 if (path.equals(new Path(JavaRuntime.JRE_CONTAINER)) || path.equals(new Path(JavaRuntime.JRELIB_VARIABLE))) { 159 return true; 160 } 161 } catch (JavaModelException e) { 162 } 163 return false; 164 } 165 166 /** 167 * @param packageName - the name of the package 168 * @param pluginID - the id of the containing plug-in - can be null if <code>project</code> is not null 169 * @param project - if null will search for an external package fragment, otherwise will search in project 170 */ getPackageFragment(String packageName, String pluginID, IProject project)171 public static IPackageFragment getPackageFragment(String packageName, String pluginID, IProject project) { 172 if (project == null) { 173 return getExternalPackageFragment(packageName, pluginID); 174 } 175 176 IJavaProject jp = JavaCore.create(project); 177 if (jp != null) { 178 try { 179 IPackageFragmentRoot[] roots = jp.getAllPackageFragmentRoots(); 180 for (IPackageFragmentRoot root : roots) { 181 IPackageFragment frag = root.getPackageFragment(packageName); 182 if (frag.exists()) { 183 return frag; 184 } 185 } 186 } catch (JavaModelException e) { 187 } 188 } 189 return null; 190 } 191 getExternalPackageFragment(String packageName, String pluginID)192 private static IPackageFragment getExternalPackageFragment(String packageName, String pluginID) { 193 if (pluginID == null) { 194 return null; 195 } 196 IPluginModelBase base = null; 197 try { 198 IPluginModelBase plugin = PluginRegistry.findModel(pluginID); 199 if (plugin == null) { 200 return null; 201 } 202 ImportPackageSpecification[] packages = plugin.getBundleDescription().getImportPackages(); 203 for (ImportPackageSpecification spec : packages) { 204 if (spec.getName().equals(packageName)) { 205 ExportPackageDescription desc = (ExportPackageDescription) spec.getSupplier(); 206 if (desc != null) { 207 base = PluginRegistry.findModel(desc.getExporter().getSymbolicName()); 208 } 209 break; 210 } 211 } 212 if (base == null) { 213 return null; 214 } 215 IResource res = base.getUnderlyingResource(); 216 if (res != null) { 217 IJavaProject jp = JavaCore.create(res.getProject()); 218 if (jp != null) { 219 try { 220 IPackageFragmentRoot[] roots = jp.getAllPackageFragmentRoots(); 221 for (IPackageFragmentRoot root : roots) { 222 IPackageFragment frag = root.getPackageFragment(packageName); 223 if (frag.exists()) { 224 return frag; 225 } 226 } 227 } catch (JavaModelException e) { 228 } 229 } 230 } 231 IProject proj = PDECore.getWorkspace().getRoot().getProject(SearchablePluginsManager.PROXY_PROJECT_NAME); 232 if (proj == null) { 233 return searchWorkspaceForPackage(packageName, base); 234 } 235 IJavaProject jp = JavaCore.create(proj); 236 IPath path = new Path(base.getInstallLocation()); 237 // if model is in jar form 238 if (!path.toFile().isDirectory()) { 239 IPackageFragmentRoot root = jp.findPackageFragmentRoot(path); 240 if (root != null) { 241 IPackageFragment frag = root.getPackageFragment(packageName); 242 if (frag.exists()) { 243 return frag; 244 } 245 } 246 // else model is in folder form, try to find model's libraries on filesystem 247 } else { 248 IPluginLibrary[] libs = base.getPluginBase().getLibraries(); 249 for (IPluginLibrary lib : libs) { 250 if (IPluginLibrary.RESOURCE.equals(lib.getType())) { 251 continue; 252 } 253 String libName = ClasspathUtilCore.expandLibraryName(lib.getName()); 254 IPackageFragmentRoot root = jp.findPackageFragmentRoot(path.append(libName)); 255 if (root != null) { 256 IPackageFragment frag = root.getPackageFragment(packageName); 257 if (frag.exists()) { 258 return frag; 259 } 260 } 261 } 262 } 263 } catch (JavaModelException e) { 264 } 265 return searchWorkspaceForPackage(packageName, base); 266 } 267 searchWorkspaceForPackage(String packageName, IPluginModelBase base)268 private static IPackageFragment searchWorkspaceForPackage(String packageName, IPluginModelBase base) { 269 IPluginLibrary[] libs = base.getPluginBase().getLibraries(); 270 ArrayList<IPath> libPaths = new ArrayList<>(); 271 IPath path = new Path(base.getInstallLocation()); 272 if (libs.length == 0) { 273 libPaths.add(path); 274 } 275 for (IPluginLibrary lib : libs) { 276 if (IPluginLibrary.RESOURCE.equals(lib.getType())) { 277 continue; 278 } 279 String libName = ClasspathUtilCore.expandLibraryName(lib.getName()); 280 libPaths.add(path.append(libName)); 281 } 282 IProject[] projects = PDECore.getWorkspace().getRoot().getProjects(); 283 for (int i = 0; i < projects.length; i++) { 284 try { 285 if (!projects[i].hasNature(JavaCore.NATURE_ID) || !projects[i].isOpen()) { 286 continue; 287 } 288 IJavaProject jp = JavaCore.create(projects[i]); 289 ListIterator<IPath> li = libPaths.listIterator(); 290 while (li.hasNext()) { 291 IPackageFragmentRoot root = jp.findPackageFragmentRoot(li.next()); 292 if (root != null) { 293 IPackageFragment frag = root.getPackageFragment(packageName); 294 if (frag.exists()) { 295 return frag; 296 } 297 } 298 } 299 } catch (CoreException e) { 300 } 301 } 302 return null; 303 } 304 getPackageFragments(IJavaProject jProject, Collection<?> existingPackages, boolean allowJava)305 public static IPackageFragment[] getPackageFragments(IJavaProject jProject, Collection<?> existingPackages, boolean allowJava) { 306 // for unique package fragments, use getPackageFragmentsHash2 307 HashMap<String, IPackageFragment> map = getPackageFragmentsHash2(jProject, existingPackages, allowJava); 308 return map.values().toArray(new IPackageFragment[map.size()]); 309 } 310 getPackageFragmentsHash(IJavaProject jProject, Collection<?> existingPackages, boolean allowJava)311 public static HashMap<String, IPackageFragment> getPackageFragmentsHash(IJavaProject jProject, Collection<?> existingPackages, boolean allowJava) { 312 HashMap<String, IPackageFragment> map = new LinkedHashMap<>(); 313 try { 314 IPackageFragmentRoot[] roots = getRoots(jProject); 315 for (IPackageFragmentRoot root : roots) { 316 IJavaElement[] children = root.getChildren(); 317 for (IJavaElement element : children) { 318 IPackageFragment fragment = (IPackageFragment) element; 319 String name = fragment.getElementName(); 320 if (name.length() == 0) { 321 name = "."; //$NON-NLS-1$ 322 } 323 if ((fragment.hasChildren() || fragment.getNonJavaResources().length > 0) && !existingPackages.contains(name)) { 324 if (!name.equals("java") || !name.startsWith("java.") || allowJava) { //$NON-NLS-1$ //$NON-NLS-2$ 325 map.put(fragment.getElementName(), fragment); 326 } 327 } 328 } 329 } 330 } catch (JavaModelException e) { 331 } 332 return map; 333 } getPackageFragmentsHash2(IJavaProject jProject, Collection<?> existingPackages, boolean allowJava)334 public static HashMap<String, IPackageFragment> getPackageFragmentsHash2(IJavaProject jProject, Collection<?> existingPackages, boolean allowJava) { 335 HashMap<String, IPackageFragment> map = new LinkedHashMap<>(); 336 try { 337 IPackageFragmentRoot[] roots = getRoots(jProject); 338 for (IPackageFragmentRoot root : roots) { 339 IJavaElement[] children = root.getChildren(); 340 for (IJavaElement element : children) { 341 IPackageFragment fragment = (IPackageFragment) element; 342 String name = fragment.getElementName(); 343 if (name.length() == 0) { 344 name = "."; //$NON-NLS-1$ 345 } 346 if ((fragment.hasChildren() || fragment.getNonJavaResources().length > 0) && !existingPackages.contains(name)) { 347 if (!name.equals("java") || !name.startsWith("java.") || allowJava) { //$NON-NLS-1$ //$NON-NLS-2$ 348 map.put(fragment.getPath().makeRelative() + "_" + fragment.getElementName(), fragment); //$NON-NLS-1$ 349 } 350 } 351 } 352 } 353 } catch (JavaModelException e) { 354 } 355 return map; 356 } 357 getRoots(IJavaProject jProject)358 private static IPackageFragmentRoot[] getRoots(IJavaProject jProject) { 359 ArrayList<IPackageFragmentRoot> result = new ArrayList<>(); 360 try { 361 IPackageFragmentRoot[] roots = jProject.getPackageFragmentRoots(); 362 for (int i = 0; i < roots.length; i++) { 363 if (roots[i].getKind() == IPackageFragmentRoot.K_SOURCE || jProject.getProject().equals(roots[i].getCorrespondingResource()) || (roots[i].isArchive() && !roots[i].isExternal())) { 364 result.add(roots[i]); 365 } 366 } 367 } catch (JavaModelException e) { 368 } 369 return result.toArray(new IPackageFragmentRoot[result.size()]); 370 } 371 getJavaSourceLevel(IProject project)372 public static String getJavaSourceLevel(IProject project) { 373 return getJavaLevel(project, JavaCore.COMPILER_SOURCE); 374 } 375 getJavaComplianceLevel(IProject project)376 public static String getJavaComplianceLevel(IProject project) { 377 return getJavaLevel(project, JavaCore.COMPILER_COMPLIANCE); 378 } 379 380 /** 381 * Precedence order from high to low: (1) Project specific option; 382 * (2) General preference option; (3) Default option; (4) Java 1.3 383 * @param project 384 * @param optionName 385 */ getJavaLevel(IProject project, String optionName)386 public static String getJavaLevel(IProject project, String optionName) { 387 // Returns the corresponding java project 388 // No need to check for null, will return null 389 IJavaProject javaProject = JavaCore.create(project); 390 String value = null; 391 // Preferred to use the project 392 if ((javaProject != null) && javaProject.exists()) { 393 // Get the project specific option if one exists. Rolls up to the 394 // general preference option if no project specific option exists. 395 value = javaProject.getOption(optionName, true); 396 if (value != null) { 397 return value; 398 } 399 } 400 // Get the general preference option 401 value = new PDEPreferencesManager(JavaCore.PLUGIN_ID).getString(optionName); 402 if (value != null) { 403 return value; 404 } 405 // Get the default option 406 value = JavaCore.getOption(optionName); 407 if (value != null) { 408 return value; 409 } 410 // Return the default 411 return JavaCore.VERSION_1_3; 412 } 413 414 } 415