1 /******************************************************************************* 2 * Copyright (c) 2006, 2017 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.jdt.internal.junit.buildpath; 15 16 import java.util.ArrayList; 17 import java.util.List; 18 19 import org.eclipse.jdt.junit.JUnitCore; 20 21 import org.eclipse.core.runtime.CoreException; 22 import org.eclipse.core.runtime.IPath; 23 import org.eclipse.core.runtime.IStatus; 24 import org.eclipse.core.runtime.Status; 25 import org.eclipse.core.runtime.preferences.DefaultScope; 26 import org.eclipse.core.runtime.preferences.IEclipsePreferences; 27 import org.eclipse.core.runtime.preferences.InstanceScope; 28 29 import org.eclipse.jdt.core.ClasspathContainerInitializer; 30 import org.eclipse.jdt.core.IClasspathAttribute; 31 import org.eclipse.jdt.core.IClasspathContainer; 32 import org.eclipse.jdt.core.IClasspathEntry; 33 import org.eclipse.jdt.core.IJavaModel; 34 import org.eclipse.jdt.core.IJavaProject; 35 import org.eclipse.jdt.core.JavaCore; 36 import org.eclipse.jdt.core.JavaModelException; 37 38 import org.eclipse.jdt.internal.junit.JUnitCorePlugin; 39 import org.eclipse.jdt.internal.junit.JUnitMessages; 40 import org.eclipse.jdt.internal.junit.JUnitPreferencesConstants; 41 42 public class JUnitContainerInitializer extends ClasspathContainerInitializer { 43 44 private static final IStatus NOT_SUPPORTED= new Status(IStatus.ERROR, JUnitCorePlugin.CORE_PLUGIN_ID, ClasspathContainerInitializer.ATTRIBUTE_NOT_SUPPORTED, new String(), null); 45 private static final IStatus READ_ONLY= new Status(IStatus.ERROR, JUnitCorePlugin.CORE_PLUGIN_ID, ClasspathContainerInitializer.ATTRIBUTE_READ_ONLY, new String(), null); 46 47 /** 48 * @deprecated just for compatibility 49 */ 50 @Deprecated 51 private final static String JUNIT3_8_1= "3.8.1"; //$NON-NLS-1$ 52 private final static String JUNIT3= "3"; //$NON-NLS-1$ 53 private final static String JUNIT4= "4"; //$NON-NLS-1$ 54 private final static String JUNIT5= "5"; //$NON-NLS-1$ 55 56 private static class JUnitContainer implements IClasspathContainer { 57 58 private final IClasspathEntry[] fEntries; 59 private final IPath fPath; 60 JUnitContainer(IPath path, IClasspathEntry[] entries)61 public JUnitContainer(IPath path, IClasspathEntry[] entries) { 62 fPath= path; 63 fEntries= entries; 64 } 65 66 @Override getClasspathEntries()67 public IClasspathEntry[] getClasspathEntries() { 68 return fEntries; 69 } 70 71 @Override getDescription()72 public String getDescription() { 73 if (JUnitCore.JUNIT5_CONTAINER_PATH.equals(fPath)) { 74 return JUnitMessages.JUnitContainerInitializer_description_junit5; 75 } 76 if (JUnitCore.JUNIT4_CONTAINER_PATH.equals(fPath)) { 77 return JUnitMessages.JUnitContainerInitializer_description_junit4; 78 } 79 return JUnitMessages.JUnitContainerInitializer_description_junit3; 80 } 81 82 @Override getKind()83 public int getKind() { 84 return IClasspathContainer.K_APPLICATION; 85 } 86 87 @Override getPath()88 public IPath getPath() { 89 return fPath; 90 } 91 92 } 93 94 JUnitContainerInitializer()95 public JUnitContainerInitializer() { 96 } 97 98 @Override initialize(IPath containerPath, IJavaProject project)99 public void initialize(IPath containerPath, IJavaProject project) throws CoreException { 100 if (isValidJUnitContainerPath(containerPath)) { 101 JUnitContainer container= getNewContainer(containerPath); 102 JavaCore.setClasspathContainer(containerPath, new IJavaProject[] { project }, new IClasspathContainer[] { container }, null); 103 } 104 105 } 106 getNewContainer(IPath containerPath)107 private static JUnitContainer getNewContainer(IPath containerPath) { 108 List<IClasspathEntry> entriesList= new ArrayList<>(); 109 IClasspathEntry entry= null; 110 IClasspathEntry entry2= null; 111 String version= containerPath.segment(1); 112 if (null != version) switch (version) { 113 case JUNIT3_8_1: 114 case JUNIT3: 115 entry= BuildPathSupport.getJUnit3LibraryEntry(); 116 if (entry == null) { // JUnit 4 includes most of JUnit 3, so let's cheat 117 entry= BuildPathSupport.getJUnit4as3LibraryEntry(); 118 } 119 break; 120 case JUNIT4: 121 entry= BuildPathSupport.getJUnit4LibraryEntry(); 122 entry2= BuildPathSupport.getHamcrestCoreLibraryEntry(); 123 break; 124 case JUNIT5: 125 entriesList.add(BuildPathSupport.getJUnitJupiterApiLibraryEntry()); 126 entriesList.add(BuildPathSupport.getJUnitJupiterEngineLibraryEntry()); 127 entriesList.add(BuildPathSupport.getJUnitJupiterMigrationSupportLibraryEntry()); 128 entriesList.add(BuildPathSupport.getJUnitJupiterParamsLibraryEntry()); 129 entriesList.add(BuildPathSupport.getJUnitPlatformCommonsLibraryEntry()); 130 entriesList.add(BuildPathSupport.getJUnitPlatformEngineLibraryEntry()); 131 entriesList.add(BuildPathSupport.getJUnitPlatformLauncherLibraryEntry()); 132 entriesList.add(BuildPathSupport.getJUnitPlatformRunnerLibraryEntry()); 133 entriesList.add(BuildPathSupport.getJUnitPlatformSuiteApiLibraryEntry()); 134 entriesList.add(BuildPathSupport.getJUnitVintageEngineLibraryEntry()); 135 entriesList.add(BuildPathSupport.getJUnitOpentest4jLibraryEntry()); 136 entriesList.add(BuildPathSupport.getJUnitApiGuardianLibraryEntry()); 137 entriesList.add(BuildPathSupport.getJUnit4LibraryEntry()); 138 entriesList.add(BuildPathSupport.getHamcrestCoreLibraryEntry()); 139 break; 140 default: 141 break; 142 } 143 IClasspathEntry[] entries; 144 if (!entriesList.isEmpty() ) { 145 entries= entriesList.toArray(new IClasspathEntry[entriesList.size()]); 146 } else if (entry == null) { 147 entries= new IClasspathEntry[] { }; 148 } else if (entry2 == null) { 149 entries= new IClasspathEntry[] { entry }; 150 } else { 151 entries= new IClasspathEntry[] { entry, entry2 }; 152 } 153 return new JUnitContainer(containerPath, entries); 154 } 155 156 isValidJUnitContainerPath(IPath path)157 private static boolean isValidJUnitContainerPath(IPath path) { 158 return path != null && path.segmentCount() == 2 && JUnitCore.JUNIT_CONTAINER_ID.equals(path.segment(0)); 159 } 160 161 @Override canUpdateClasspathContainer(IPath containerPath, IJavaProject project)162 public boolean canUpdateClasspathContainer(IPath containerPath, IJavaProject project) { 163 return true; 164 } 165 166 @Override getAccessRulesStatus(IPath containerPath, IJavaProject project)167 public IStatus getAccessRulesStatus(IPath containerPath, IJavaProject project) { 168 return READ_ONLY; 169 } 170 171 @Override getSourceAttachmentStatus(IPath containerPath, IJavaProject project)172 public IStatus getSourceAttachmentStatus(IPath containerPath, IJavaProject project) { 173 return READ_ONLY; 174 } 175 176 @Override getAttributeStatus(IPath containerPath, IJavaProject project, String attributeKey)177 public IStatus getAttributeStatus(IPath containerPath, IJavaProject project, String attributeKey) { 178 if (attributeKey.equals(IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME)) { 179 return Status.OK_STATUS; 180 } 181 return NOT_SUPPORTED; 182 } 183 184 185 @Override requestClasspathContainerUpdate(IPath containerPath, IJavaProject project, IClasspathContainer containerSuggestion)186 public void requestClasspathContainerUpdate(IPath containerPath, IJavaProject project, IClasspathContainer containerSuggestion) throws CoreException { 187 IEclipsePreferences preferences= InstanceScope.INSTANCE.getNode(JUnitCorePlugin.CORE_PLUGIN_ID); 188 189 IClasspathEntry[] entries= containerSuggestion.getClasspathEntries(); 190 if (entries.length >= 1 && isValidJUnitContainerPath(containerPath)) { 191 String version= containerPath.segment(1); 192 193 // only modifiable entry is Javadoc location 194 for (IClasspathEntry entry : entries) { 195 String preferenceKey= getPreferenceKey(entry, version); 196 IClasspathAttribute[] extraAttributes= entry.getExtraAttributes(); 197 if (extraAttributes.length == 0) { 198 // Revert to default 199 String defaultValue= DefaultScope.INSTANCE.getNode(JUnitCorePlugin.CORE_PLUGIN_ID).get(preferenceKey, ""); //$NON-NLS-1$ 200 if (!defaultValue.equals(preferences.get(preferenceKey, defaultValue))) { 201 preferences.put(preferenceKey, defaultValue); 202 } 203 204 /* 205 * The following would be correct, but would not allow to revert to the default. 206 * There's no concept of "default value" for a classpath attribute, see 207 * org.eclipse.jdt.internal.ui.preferences.JavadocConfigurationBlock.performDefaults() 208 */ 209 // preferenceStore.setValue(preferenceKey, ""); 210 } else { 211 for (IClasspathAttribute attrib : extraAttributes) { 212 if (attrib.getName().equals(IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME)) { 213 if (preferenceKey != null) { 214 preferences.put(preferenceKey, attrib.getValue()); 215 } 216 break; 217 } 218 } 219 } 220 } 221 rebindClasspathEntries(project.getJavaModel(), containerPath); 222 } 223 } 224 getPreferenceKey(IClasspathEntry entry, String version)225 private String getPreferenceKey(IClasspathEntry entry, String version) { 226 if (JUNIT3.equals(version)) { 227 return JUnitPreferencesConstants.JUNIT3_JAVADOC; 228 } else { 229 String lastSegment= entry.getPath().lastSegment(); 230 if (JUNIT4.equals(version)) { 231 if (lastSegment.contains("junit")) { //$NON-NLS-1$ 232 return JUnitPreferencesConstants.JUNIT4_JAVADOC; 233 } else { 234 return JUnitPreferencesConstants.HAMCREST_CORE_JAVADOC; 235 } 236 } else if (JUNIT5.equals(version)) { 237 if (lastSegment.contains("jupiter.api")) { //$NON-NLS-1$ 238 return JUnitPreferencesConstants.JUNIT_JUPITER_API_JAVADOC; 239 } else if (lastSegment.contains("jupiter.engine")) { //$NON-NLS-1$ 240 return JUnitPreferencesConstants.JUNIT_JUPITER_ENGINE_JAVADOC; 241 } else if (lastSegment.contains("jupiter.migrationsupport")) { //$NON-NLS-1$ 242 return JUnitPreferencesConstants.JUNIT_JUPITER_MIGRATIONSUPPORT_JAVADOC; 243 } else if (lastSegment.contains("jupiter.params")) { //$NON-NLS-1$ 244 return JUnitPreferencesConstants.JUNIT_JUPITER_PARAMS_JAVADOC; 245 } else if (lastSegment.contains("platform.commons")) { //$NON-NLS-1$ 246 return JUnitPreferencesConstants.JUNIT_PLATFORM_COMMONS_JAVADOC; 247 } else if (lastSegment.contains("platform.engine")) { //$NON-NLS-1$ 248 return JUnitPreferencesConstants.JUNIT_PLATFORM_ENGINE_JAVADOC; 249 } else if (lastSegment.contains("platform.launcher")) { //$NON-NLS-1$ 250 return JUnitPreferencesConstants.JUNIT_PLATFORM_LAUNCHER_JAVADOC; 251 } else if (lastSegment.contains("platform.runner")) { //$NON-NLS-1$ 252 return JUnitPreferencesConstants.JUNIT_PLATFORM_RUNNER_JAVADOC; 253 } else if (lastSegment.contains("platform.suite.api")) { //$NON-NLS-1$ 254 return JUnitPreferencesConstants.JUNIT_PLATFORM_SUITE_API_JAVADOC; 255 } else if (lastSegment.contains("vintage.engine")) { //$NON-NLS-1$ 256 return JUnitPreferencesConstants.JUNIT_VINTAGE_ENGINE_JAVADOC; 257 } else if (lastSegment.contains("opentest4j")) { //$NON-NLS-1$ 258 return JUnitPreferencesConstants.JUNIT_OPENTEST4J_JAVADOC; 259 } else if (lastSegment.contains("apiguardian")) { //$NON-NLS-1$ 260 return JUnitPreferencesConstants.JUNIT_APIGUARDIAN_JAVADOC; 261 } else if (lastSegment.contains("junit")) { //$NON-NLS-1$ 262 return JUnitPreferencesConstants.JUNIT4_JAVADOC; 263 } else { 264 return JUnitPreferencesConstants.HAMCREST_CORE_JAVADOC; 265 } 266 } 267 } 268 return null; 269 } 270 rebindClasspathEntries(IJavaModel model, IPath containerPath)271 private static void rebindClasspathEntries(IJavaModel model, IPath containerPath) throws JavaModelException { 272 ArrayList<IJavaProject> affectedProjects= new ArrayList<>(); 273 274 IJavaProject[] projects= model.getJavaProjects(); 275 for (IJavaProject project : projects) { 276 IClasspathEntry[] entries= project.getRawClasspath(); 277 for (IClasspathEntry curr : entries) { 278 if (curr.getEntryKind() == IClasspathEntry.CPE_CONTAINER && containerPath.equals(curr.getPath())) { 279 affectedProjects.add(project); 280 } 281 } 282 } 283 if (!affectedProjects.isEmpty()) { 284 IJavaProject[] affected= affectedProjects.toArray(new IJavaProject[affectedProjects.size()]); 285 IClasspathContainer[] containers= new IClasspathContainer[affected.length]; 286 for (int i= 0; i < containers.length; i++) { 287 containers[i]= getNewContainer(containerPath); 288 } 289 JavaCore.setClasspathContainer(containerPath, affected, containers, null); 290 } 291 } 292 293 /** 294 * @see org.eclipse.jdt.core.ClasspathContainerInitializer#getDescription(org.eclipse.core.runtime.IPath, org.eclipse.jdt.core.IJavaProject) 295 */ 296 @Override getDescription(IPath containerPath, IJavaProject project)297 public String getDescription(IPath containerPath, IJavaProject project) { 298 if (isValidJUnitContainerPath(containerPath)) { 299 String version= containerPath.segment(1); 300 if (null != version) switch (version) { 301 case JUNIT3_8_1: 302 case JUNIT3: 303 return JUnitMessages.JUnitContainerInitializer_description_initializer_junit3; 304 case JUNIT4: 305 return JUnitMessages.JUnitContainerInitializer_description_initializer_junit4; 306 case JUNIT5: 307 return JUnitMessages.JUnitContainerInitializer_description_initializer_junit5; 308 default: 309 break; 310 } 311 } 312 return JUnitMessages.JUnitContainerInitializer_description_initializer_unresolved; 313 } 314 315 @Override getComparisonID(IPath containerPath, IJavaProject project)316 public Object getComparisonID(IPath containerPath, IJavaProject project) { 317 return containerPath; 318 } 319 320 } 321