| 1 | /******************************************************************************* |
| 2 | * Copyright (c) 2007, 2009 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 | package org.eclipse.pde.api.tools.internal.provisional; |
| 12 | |
| 13 | import java.util.ArrayList; |
| 14 | import java.util.HashSet; |
| 15 | import java.util.Iterator; |
| 16 | import java.util.List; |
| 17 | |
| 18 | import org.eclipse.core.resources.IProject; |
| 19 | import org.eclipse.core.resources.ISaveContext; |
| 20 | import org.eclipse.core.resources.ISaveParticipant; |
| 21 | import org.eclipse.core.resources.ProjectScope; |
| 22 | import org.eclipse.core.resources.ResourcesPlugin; |
| 23 | import org.eclipse.core.runtime.CoreException; |
| 24 | import org.eclipse.core.runtime.IStatus; |
| 25 | import org.eclipse.core.runtime.Platform; |
| 26 | import org.eclipse.core.runtime.Plugin; |
| 27 | import org.eclipse.core.runtime.Status; |
| 28 | import org.eclipse.core.runtime.preferences.DefaultScope; |
| 29 | import org.eclipse.core.runtime.preferences.IEclipsePreferences; |
| 30 | import org.eclipse.core.runtime.preferences.IPreferencesService; |
| 31 | import org.eclipse.core.runtime.preferences.IScopeContext; |
| 32 | import org.eclipse.core.runtime.preferences.InstanceScope; |
| 33 | import org.eclipse.pde.api.tools.internal.ApiBaselineManager; |
| 34 | import org.eclipse.pde.api.tools.internal.ApiDescription; |
| 35 | import org.eclipse.pde.api.tools.internal.ApiDescriptionManager; |
| 36 | import org.eclipse.pde.api.tools.internal.ApiFilterStore; |
| 37 | import org.eclipse.pde.api.tools.internal.JavadocTagManager; |
| 38 | import org.eclipse.pde.api.tools.internal.SessionManager; |
| 39 | import org.eclipse.pde.api.tools.internal.builder.AbstractProblemDetector; |
| 40 | import org.eclipse.pde.api.tools.internal.builder.ApiAnalysisBuilder; |
| 41 | import org.eclipse.pde.api.tools.internal.builder.ReferenceAnalyzer; |
| 42 | import org.eclipse.pde.api.tools.internal.builder.ReferenceExtractor; |
| 43 | import org.eclipse.pde.api.tools.internal.builder.ReferenceResolver; |
| 44 | import org.eclipse.pde.api.tools.internal.comparator.ClassFileComparator; |
| 45 | import org.eclipse.pde.api.tools.internal.descriptors.ElementDescriptorImpl; |
| 46 | import org.eclipse.pde.api.tools.internal.model.PluginProjectApiComponent; |
| 47 | import org.eclipse.pde.api.tools.internal.provisional.comparator.ApiComparator; |
| 48 | import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblemTypes; |
| 49 | import org.eclipse.pde.api.tools.internal.provisional.scanner.TagScanner; |
| 50 | import org.eclipse.pde.api.tools.internal.util.FileManager; |
| 51 | import org.osgi.framework.BundleContext; |
| 52 | import org.osgi.service.prefs.BackingStoreException; |
| 53 | |
| 54 | /** |
| 55 | * API Tools core plug-in. |
| 56 | * API tools can be run with or without an OSGi framework. |
| 57 | * |
| 58 | * @since 1.0.0 |
| 59 | */ |
| 60 | public class ApiPlugin extends Plugin implements ISaveParticipant { |
| 61 | |
| 62 | /** |
| 63 | * Constant representing the name of the javadoc tag extension point. |
| 64 | * Value is <code>apiJavadocTags</code> |
| 65 | */ |
| 66 | public static final String EXTENSION_JAVADOC_TAGS = "apiJavadocTags"; //$NON-NLS-1$ |
| 67 | /** |
| 68 | * The plug-in identifier of the PDE API tool support |
| 69 | * (value <code>"org.eclipse.pde.api.tools"</code>). |
| 70 | */ |
| 71 | public static final String PLUGIN_ID = "org.eclipse.pde.api.tools" ; //$NON-NLS-1$ |
| 72 | /** |
| 73 | * The API tooling nature id |
| 74 | * (value <code>"org.eclipse.pde.api.tools.apiAnalysisNature"</code>). |
| 75 | */ |
| 76 | public static final String NATURE_ID = PLUGIN_ID + ".apiAnalysisNature" ; //$NON-NLS-1$ |
| 77 | /** |
| 78 | * Status code indicating an unexpected internal error. |
| 79 | */ |
| 80 | public static final int INTERNAL_ERROR = 120; |
| 81 | /** |
| 82 | * Status code indicating an unexpected error |
| 83 | */ |
| 84 | public static final int ERROR = 121; |
| 85 | |
| 86 | /** |
| 87 | * Status code indicating a resolution error |
| 88 | */ |
| 89 | public static final int REPORT_RESOLUTION_ERRORS = 122; |
| 90 | |
| 91 | /** |
| 92 | * Status code indicating that a baseline is disposed |
| 93 | */ |
| 94 | public static final int REPORT_BASELINE_IS_DISPOSED = 123; |
| 95 | |
| 96 | /** |
| 97 | * Constant representing severity levels for error/warning preferences |
| 98 | * Value is: <code>0</code> |
| 99 | */ |
| 100 | public static final int SEVERITY_IGNORE = 0; |
| 101 | /** |
| 102 | * Constant representing severity levels for error/warning preferences |
| 103 | * Value is: <code>1</code> |
| 104 | */ |
| 105 | public static final int SEVERITY_WARNING = 1; |
| 106 | /** |
| 107 | * Constant representing severity levels for error/warning preferences |
| 108 | * Value is: <code>2</code> |
| 109 | */ |
| 110 | public static final int SEVERITY_ERROR = 2; |
| 111 | |
| 112 | /** |
| 113 | * Constant representing the preference value 'ignore'. |
| 114 | * Value is: <code>Ignore</code> |
| 115 | */ |
| 116 | public static final String VALUE_IGNORE = "Ignore"; //$NON-NLS-1$ |
| 117 | /** |
| 118 | * Constant representing the preference value 'warning'. |
| 119 | * Value is: <code>Warning</code> |
| 120 | */ |
| 121 | public static final String VALUE_WARNING = "Warning"; //$NON-NLS-1$ |
| 122 | /** |
| 123 | * Constant representing the preference value 'error'. |
| 124 | * Value is: <code>Error</code> |
| 125 | */ |
| 126 | public static final String VALUE_ERROR = "Error"; //$NON-NLS-1$ |
| 127 | /** |
| 128 | * Constant representing the preference value 'disabled'. |
| 129 | * Value is: <code>Disabled</code> |
| 130 | */ |
| 131 | public static final String VALUE_DISABLED = "Disabled"; //$NON-NLS-1$ |
| 132 | /** |
| 133 | * Constant representing the preference value 'enabled'. |
| 134 | * Value is: <code>Enabled</code> |
| 135 | */ |
| 136 | public static final String VALUE_ENABLED = "Enabled"; //$NON-NLS-1$ |
| 137 | /** |
| 138 | * The identifier for the Api builder |
| 139 | * Value is: <code>"org.eclipse.pde.api.tools.apiAnalysisBuilder"</code> |
| 140 | */ |
| 141 | public static final String BUILDER_ID = PLUGIN_ID + ".apiAnalysisBuilder" ; //$NON-NLS-1$ |
| 142 | |
| 143 | public static final String BASELINE_IS_DISPOSED = "baseline is disposed"; //$NON-NLS-1$ |
| 144 | /** |
| 145 | * Singleton instance of the plugin |
| 146 | */ |
| 147 | private static ApiPlugin fgDefault = null; |
| 148 | /** |
| 149 | * Singleton instance of the {@link JavadocTagManager} |
| 150 | */ |
| 151 | private static JavadocTagManager fgTagManager = null; |
| 152 | /** |
| 153 | * Singleton instance of the {@link ISessionManager} |
| 154 | */ |
| 155 | private static ISessionManager fgSessionManager = null; |
| 156 | /** |
| 157 | * Private debug options |
| 158 | */ |
| 159 | private static final String BUILDER_DEBUG = PLUGIN_ID + "/debug/builder" ; //$NON-NLS-1$ |
| 160 | private static final String DELTA_DEBUG = PLUGIN_ID + "/debug/delta" ; //$NON-NLS-1$ |
| 161 | private static final String CLASSFILE_VISITOR_DEBUG = PLUGIN_ID + "/debug/classfilevisitor" ; //$NON-NLS-1$ |
| 162 | private static final String DESCRIPTOR_FRAMEWORK_DEBUG = PLUGIN_ID + "/debug/descriptor/framework" ; //$NON-NLS-1$ |
| 163 | private static final String TAG_SCANNER_DEBUG = PLUGIN_ID + "/debug/tagscanner" ; //$NON-NLS-1$ |
| 164 | private static final String PLUGIN_WORKSPACE_COMPONENT_DEBUG = PLUGIN_ID + "/debug/pluginworkspacecomponent"; //$NON-NLS-1$ |
| 165 | private static final String API_PROFILE_MANAGER_DEBUG = PLUGIN_ID + "/debug/profilemanager"; //$NON-NLS-1$ |
| 166 | private static final String API_FILTER_STORE_DEBUG = PLUGIN_ID + "/debug/apifilterstore"; //$NON-NLS-1$ |
| 167 | private static final String API_REFERENCE_ANALYZER_DEBUG = PLUGIN_ID + "/debug/refanalyzer"; //$NON-NLS-1$ |
| 168 | private static final String PROBLEM_DETECTOR_DEBUG = PLUGIN_ID + "/debug/problemdetector"; //$NON-NLS-1$ |
| 169 | private static final String REFERENCE_RESOLVER_DEBUG = PLUGIN_ID + "/debug/refresolver"; //$NON-NLS-1$ |
| 170 | private static final String API_DESCRIPTION = PLUGIN_ID + "/debug/apidescription"; //$NON-NLS-1$ |
| 171 | |
| 172 | public final static String TRUE = "true"; //$NON-NLS-1$ |
| 173 | |
| 174 | public static String[] AllCompatibilityKeys = new String[] { |
| 175 | IApiProblemTypes.API_COMPONENT_REMOVED_TYPE, |
| 176 | IApiProblemTypes.API_COMPONENT_REMOVED_API_TYPE, |
| 177 | IApiProblemTypes.API_COMPONENT_REMOVED_REEXPORTED_TYPE, |
| 178 | IApiProblemTypes.API_COMPONENT_REMOVED_REEXPORTED_API_TYPE, |
| 179 | IApiProblemTypes.ANNOTATION_REMOVED_FIELD, |
| 180 | IApiProblemTypes.ANNOTATION_REMOVED_METHOD, |
| 181 | IApiProblemTypes.ANNOTATION_REMOVED_TYPE_MEMBER, |
| 182 | IApiProblemTypes.ANNOTATION_CHANGED_TYPE_CONVERSION, |
| 183 | IApiProblemTypes.ANNOTATION_ADDED_METHOD_NO_DEFAULT_VALUE, |
| 184 | IApiProblemTypes.INTERFACE_ADDED_FIELD, |
| 185 | IApiProblemTypes.INTERFACE_ADDED_METHOD, |
| 186 | IApiProblemTypes.INTERFACE_ADDED_RESTRICTIONS, |
| 187 | IApiProblemTypes.INTERFACE_ADDED_SUPER_INTERFACE_WITH_METHODS, |
| 188 | IApiProblemTypes.INTERFACE_ADDED_TYPE_PARAMETER, |
| 189 | IApiProblemTypes.INTERFACE_REMOVED_TYPE_PARAMETER, |
| 190 | IApiProblemTypes.INTERFACE_REMOVED_FIELD, |
| 191 | IApiProblemTypes.INTERFACE_REMOVED_METHOD, |
| 192 | IApiProblemTypes.INTERFACE_REMOVED_TYPE_MEMBER, |
| 193 | IApiProblemTypes.INTERFACE_CHANGED_TYPE_CONVERSION, |
| 194 | IApiProblemTypes.INTERFACE_CHANGED_CONTRACTED_SUPERINTERFACES_SET, |
| 195 | IApiProblemTypes.ENUM_CHANGED_CONTRACTED_SUPERINTERFACES_SET, |
| 196 | IApiProblemTypes.ENUM_CHANGED_TYPE_CONVERSION, |
| 197 | IApiProblemTypes.ENUM_REMOVED_FIELD, |
| 198 | IApiProblemTypes.ENUM_REMOVED_ENUM_CONSTANT, |
| 199 | IApiProblemTypes.ENUM_REMOVED_METHOD, |
| 200 | IApiProblemTypes.ENUM_REMOVED_TYPE_MEMBER, |
| 201 | IApiProblemTypes.CLASS_ADDED_METHOD, |
| 202 | IApiProblemTypes.CLASS_ADDED_RESTRICTIONS, |
| 203 | IApiProblemTypes.CLASS_ADDED_TYPE_PARAMETER, |
| 204 | IApiProblemTypes.CLASS_CHANGED_CONTRACTED_SUPERINTERFACES_SET, |
| 205 | IApiProblemTypes.CLASS_CHANGED_NON_ABSTRACT_TO_ABSTRACT, |
| 206 | IApiProblemTypes.CLASS_CHANGED_NON_FINAL_TO_FINAL, |
| 207 | IApiProblemTypes.CLASS_CHANGED_TYPE_CONVERSION, |
| 208 | IApiProblemTypes.CLASS_CHANGED_DECREASE_ACCESS, |
| 209 | IApiProblemTypes.CLASS_REMOVED_FIELD, |
| 210 | IApiProblemTypes.CLASS_REMOVED_METHOD, |
| 211 | IApiProblemTypes.CLASS_REMOVED_CONSTRUCTOR, |
| 212 | IApiProblemTypes.CLASS_REMOVED_SUPERCLASS, |
| 213 | IApiProblemTypes.CLASS_REMOVED_TYPE_MEMBER, |
| 214 | IApiProblemTypes.CLASS_REMOVED_TYPE_PARAMETER, |
| 215 | IApiProblemTypes.FIELD_ADDED_VALUE, |
| 216 | IApiProblemTypes.FIELD_CHANGED_TYPE, |
| 217 | IApiProblemTypes.FIELD_CHANGED_VALUE, |
| 218 | IApiProblemTypes.FIELD_CHANGED_DECREASE_ACCESS, |
| 219 | IApiProblemTypes.FIELD_CHANGED_FINAL_TO_NON_FINAL_STATIC_CONSTANT, |
| 220 | IApiProblemTypes.FIELD_CHANGED_NON_FINAL_TO_FINAL, |
| 221 | IApiProblemTypes.FIELD_CHANGED_STATIC_TO_NON_STATIC, |
| 222 | IApiProblemTypes.FIELD_CHANGED_NON_STATIC_TO_STATIC, |
| 223 | IApiProblemTypes.FIELD_REMOVED_VALUE, |
| 224 | IApiProblemTypes.FIELD_REMOVED_TYPE_ARGUMENT, |
| 225 | IApiProblemTypes.METHOD_ADDED_RESTRICTIONS, |
| 226 | IApiProblemTypes.METHOD_ADDED_TYPE_PARAMETER, |
| 227 | IApiProblemTypes.METHOD_CHANGED_VARARGS_TO_ARRAY, |
| 228 | IApiProblemTypes.METHOD_CHANGED_DECREASE_ACCESS, |
| 229 | IApiProblemTypes.METHOD_CHANGED_NON_ABSTRACT_TO_ABSTRACT, |
| 230 | IApiProblemTypes.METHOD_CHANGED_NON_STATIC_TO_STATIC, |
| 231 | IApiProblemTypes.METHOD_CHANGED_STATIC_TO_NON_STATIC, |
| 232 | IApiProblemTypes.METHOD_CHANGED_NON_FINAL_TO_FINAL, |
| 233 | IApiProblemTypes.METHOD_REMOVED_ANNOTATION_DEFAULT_VALUE, |
| 234 | IApiProblemTypes.METHOD_REMOVED_TYPE_PARAMETER, |
| 235 | IApiProblemTypes.CONSTRUCTOR_ADDED_TYPE_PARAMETER, |
| 236 | IApiProblemTypes.CONSTRUCTOR_CHANGED_VARARGS_TO_ARRAY, |
| 237 | IApiProblemTypes.CONSTRUCTOR_CHANGED_DECREASE_ACCESS, |
| 238 | IApiProblemTypes.CONSTRUCTOR_REMOVED_TYPE_PARAMETER, |
| 239 | IApiProblemTypes.TYPE_PARAMETER_ADDED_CLASS_BOUND, |
| 240 | IApiProblemTypes.TYPE_PARAMETER_CHANGED_CLASS_BOUND, |
| 241 | IApiProblemTypes.TYPE_PARAMETER_REMOVED_CLASS_BOUND, |
| 242 | IApiProblemTypes.TYPE_PARAMETER_ADDED_INTERFACE_BOUND, |
| 243 | IApiProblemTypes.TYPE_PARAMETER_CHANGED_INTERFACE_BOUND, |
| 244 | IApiProblemTypes.TYPE_PARAMETER_REMOVED_INTERFACE_BOUND, |
| 245 | IApiProblemTypes.TYPE_PARAMETER_REMOVED_INTERFACE_BOUND, |
| 246 | IApiProblemTypes.REPORT_API_BREAKAGE_WHEN_MAJOR_VERSION_INCREMENTED, |
| 247 | // IApiProblemTypes.REPORT_API_CHANGE_WHEN_MINOR_VERSION_INCREMENTED, |
| 248 | }; |
| 249 | /** |
| 250 | * A set of listeners that want to participate in the saving life-cycle of the workbench |
| 251 | * via this plugin |
| 252 | */ |
| 253 | private HashSet savelisteners = new HashSet(); |
| 254 | |
| 255 | /** |
| 256 | * This is used to log resolution errors only once per session |
| 257 | */ |
| 258 | private int logBits = 0; |
| 259 | |
| 260 | /** |
| 261 | * This is used to log resolution errors only once per session. |
| 262 | * This is used outside the workbench. |
| 263 | */ |
| 264 | private static int LogBits= 0; |
| 265 | |
| 266 | private static final int RESOLUTION_LOG_BIT = 1; |
| 267 | private static final int BASELINE_DISPOSED_LOG_BIT = 2; |
| 268 | |
| 269 | /** |
| 270 | * Constructor |
| 271 | */ |
| 272 | public ApiPlugin() { |
| 273 | super(); |
| 274 | fgDefault = this; |
| 275 | } |
| 276 | |
| 277 | /** |
| 278 | * @return The singleton instance of the plugin |
| 279 | */ |
| 280 | public static ApiPlugin getDefault() { |
| 281 | return fgDefault; |
| 282 | } |
| 283 | |
| 284 | /** |
| 285 | * Logs the specified status with this plug-in's log. |
| 286 | * |
| 287 | * @param status status to log |
| 288 | */ |
| 289 | public static void log(IStatus status) { |
| 290 | ApiPlugin getDefault = getDefault(); |
| 291 | if (getDefault == null) { |
| 292 | switch(status.getCode()) { |
| 293 | case REPORT_RESOLUTION_ERRORS : |
| 294 | if ((LogBits & RESOLUTION_LOG_BIT) == 0) { |
| 295 | Throwable exception = status.getException(); |
| 296 | if (exception != null) { |
| 297 | exception.printStackTrace(); |
| 298 | } |
| 299 | LogBits |= RESOLUTION_LOG_BIT; |
| 300 | } |
| 301 | break; |
| 302 | case REPORT_BASELINE_IS_DISPOSED : |
| 303 | if ((LogBits & BASELINE_DISPOSED_LOG_BIT) == 0) { |
| 304 | Throwable exception = status.getException(); |
| 305 | if (exception != null) { |
| 306 | exception.printStackTrace(); |
| 307 | } |
| 308 | LogBits |= BASELINE_DISPOSED_LOG_BIT; |
| 309 | } |
| 310 | break; |
| 311 | default: |
| 312 | Throwable exception = status.getException(); |
| 313 | if (exception != null) { |
| 314 | exception.printStackTrace(); |
| 315 | } |
| 316 | } |
| 317 | } else { |
| 318 | switch(status.getCode()) { |
| 319 | case REPORT_RESOLUTION_ERRORS : |
| 320 | if ((getDefault.logBits & RESOLUTION_LOG_BIT) == 0) { |
| 321 | getDefault.getLog().log(status); |
| 322 | getDefault.logBits |= RESOLUTION_LOG_BIT; |
| 323 | } |
| 324 | break; |
| 325 | case REPORT_BASELINE_IS_DISPOSED : |
| 326 | if ((getDefault.logBits & BASELINE_DISPOSED_LOG_BIT) == 0) { |
| 327 | getDefault.getLog().log(status); |
| 328 | getDefault.logBits |= BASELINE_DISPOSED_LOG_BIT; |
| 329 | } |
| 330 | break; |
| 331 | default: |
| 332 | getDefault.getLog().log(status); |
| 333 | } |
| 334 | } |
| 335 | } |
| 336 | |
| 337 | /** |
| 338 | * Logs the specified throwable with this plug-in's log. |
| 339 | * |
| 340 | * @param t throwable to log |
| 341 | */ |
| 342 | public static void log(Throwable t) { |
| 343 | log(newErrorStatus("Error logged from API Tools Core: ", t)); //$NON-NLS-1$ |
| 344 | } |
| 345 | |
| 346 | /** |
| 347 | * Logs an internal error with the specified message. |
| 348 | * |
| 349 | * @param message the error message to log |
| 350 | */ |
| 351 | public static void logErrorMessage(String message) { |
| 352 | // this message is intentionally not internationalized, as an exception may |
| 353 | // be due to the resource bundle itself |
| 354 | log(newErrorStatus("Internal message logged from API Tools Core: " + message, null)); //$NON-NLS-1$ |
| 355 | } |
| 356 | |
| 357 | /** |
| 358 | * Returns a new error status for this plug-in with the given message |
| 359 | * @param message the message to be included in the status |
| 360 | * @param exception the exception to be included in the status or <code>null</code> if none |
| 361 | * @return a new error status |
| 362 | */ |
| 363 | public static IStatus newErrorStatus(String message, Throwable exception) { |
| 364 | return new Status(IStatus.ERROR, PLUGIN_ID, INTERNAL_ERROR, message, exception); |
| 365 | } |
| 366 | |
| 367 | /** |
| 368 | * Returns whether the API tools bundle is running inside an OSGi framework. |
| 369 | * |
| 370 | * @return whether the API tools bundle is running inside an OSGi framework |
| 371 | */ |
| 372 | public static boolean isRunningInFramework() { |
| 373 | return fgDefault != null; |
| 374 | } |
| 375 | |
| 376 | /** |
| 377 | * Returns the {@link IApiBaselineManager}, allowing clients to add/remove and search |
| 378 | * for {@link org.eclipse.pde.api.tools.internal.provisional.model.IApiBaseline}s stored in the manager. |
| 379 | * |
| 380 | * @return the singleton instance of the {@link IApiProfileManager} |
| 381 | */ |
| 382 | public IApiBaselineManager getApiBaselineManager() { |
| 383 | return ApiBaselineManager.getManager(); |
| 384 | } |
| 385 | |
| 386 | /** |
| 387 | * @return The singleton instance of the {@link JavadocTagManager} |
| 388 | */ |
| 389 | public static JavadocTagManager getJavadocTagManager() { |
| 390 | if(fgTagManager == null) { |
| 391 | fgTagManager = new JavadocTagManager(); |
| 392 | } |
| 393 | return fgTagManager; |
| 394 | } |
| 395 | |
| 396 | /** |
| 397 | * Adds the given save participant to the listing of participants to |
| 398 | * be notified when the workbench saving life-cycle occurs. If the specified |
| 399 | * participant is <code>null</code> no changes are made. |
| 400 | * @param participant |
| 401 | */ |
| 402 | public void addSaveParticipant(ISaveParticipant participant) { |
| 403 | if(participant != null) { |
| 404 | savelisteners.add(participant); |
| 405 | } |
| 406 | } |
| 407 | |
| 408 | /** |
| 409 | * Removes the given save participant from the current listing. |
| 410 | * If the specified participant is <code>null</code> no changes are made. |
| 411 | * @param participant |
| 412 | */ |
| 413 | public void removeSaveParticipant(ISaveParticipant participant) { |
| 414 | if(participant != null) { |
| 415 | savelisteners.remove(participant); |
| 416 | } |
| 417 | } |
| 418 | |
| 419 | /* (non-Javadoc) |
| 420 | * @see org.eclipse.core.resources.ISaveParticipant#doneSaving(org.eclipse.core.resources.ISaveContext) |
| 421 | */ |
| 422 | public void doneSaving(ISaveContext context) { |
| 423 | ISaveParticipant sp = null; |
| 424 | for(Iterator iter = savelisteners.iterator(); iter.hasNext();) { |
| 425 | sp = (ISaveParticipant) iter.next(); |
| 426 | sp.doneSaving(context); |
| 427 | } |
| 428 | } |
| 429 | |
| 430 | /* (non-Javadoc) |
| 431 | * @see org.eclipse.core.resources.ISaveParticipant#prepareToSave(org.eclipse.core.resources.ISaveContext) |
| 432 | */ |
| 433 | public void prepareToSave(ISaveContext context) throws CoreException { |
| 434 | ISaveParticipant sp = null; |
| 435 | for(Iterator iter = savelisteners.iterator(); iter.hasNext();) { |
| 436 | sp = (ISaveParticipant) iter.next(); |
| 437 | sp.prepareToSave(context); |
| 438 | } |
| 439 | } |
| 440 | |
| 441 | /* (non-Javadoc) |
| 442 | * @see org.eclipse.core.resources.ISaveParticipant#rollback(org.eclipse.core.resources.ISaveContext) |
| 443 | */ |
| 444 | public void rollback(ISaveContext context) { |
| 445 | ISaveParticipant sp = null; |
| 446 | for(Iterator iter = savelisteners.iterator(); iter.hasNext();) { |
| 447 | sp = (ISaveParticipant) iter.next(); |
| 448 | sp.rollback(context); |
| 449 | } |
| 450 | } |
| 451 | |
| 452 | /* (non-Javadoc) |
| 453 | * @see org.eclipse.core.resources.ISaveParticipant#saving(org.eclipse.core.resources.ISaveContext) |
| 454 | */ |
| 455 | public void saving(ISaveContext context) throws CoreException { |
| 456 | if(context.getKind() == ISaveContext.FULL_SAVE) { |
| 457 | context.needDelta(); |
| 458 | } |
| 459 | ISaveParticipant sp = null; |
| 460 | for(Iterator iter = savelisteners.iterator(); iter.hasNext();) { |
| 461 | sp = (ISaveParticipant) iter.next(); |
| 462 | sp.saving(context); |
| 463 | } |
| 464 | IEclipsePreferences node = new InstanceScope().getNode(PLUGIN_ID); |
| 465 | if(node != null) { |
| 466 | try { |
| 467 | node.flush(); |
| 468 | } catch (BackingStoreException e) { |
| 469 | log(e); |
| 470 | } |
| 471 | } |
| 472 | } |
| 473 | |
| 474 | /* (non-Javadoc) |
| 475 | * @see org.eclipse.core.runtime.Plugin#start(org.osgi.framework.BundleContext) |
| 476 | */ |
| 477 | public void start(BundleContext context) throws Exception { |
| 478 | try { |
| 479 | super.start(context); |
| 480 | } finally { |
| 481 | ResourcesPlugin.getWorkspace().addSaveParticipant(this, this); |
| 482 | configurePluginDebugOptions(); |
| 483 | } |
| 484 | } |
| 485 | |
| 486 | /* (non-Javadoc) |
| 487 | * @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext) |
| 488 | */ |
| 489 | public void stop(BundleContext context) throws Exception { |
| 490 | try { |
| 491 | ApiDescriptionManager.shutdown(); |
| 492 | ApiBaselineManager.getManager().stop(); |
| 493 | ResourcesPlugin.getWorkspace().removeSaveParticipant(this); |
| 494 | FileManager.getManager().deleteFiles(); |
| 495 | } |
| 496 | finally { |
| 497 | super.stop(context); |
| 498 | } |
| 499 | } |
| 500 | |
| 501 | /** |
| 502 | * Returns the severity for the specific key from the given {@link IProject}. |
| 503 | * If the project does not have project specific settings, the workspace preference |
| 504 | * is returned. If <code>null</code> is passed in as the project the workspace |
| 505 | * preferences are consulted. |
| 506 | * |
| 507 | * @param prefkey the given preference key |
| 508 | * @param project the given project or <code>null</code> |
| 509 | * @return the severity level for the given pref key |
| 510 | */ |
| 511 | public int getSeverityLevel(String prefkey, IProject project) { |
| 512 | IPreferencesService service = Platform.getPreferencesService(); |
| 513 | List scopes = new ArrayList(); |
| 514 | scopes.add(new InstanceScope()); |
| 515 | if(project != null) { |
| 516 | scopes.add(new ProjectScope(project)); |
| 517 | } |
| 518 | String value = service.getString(PLUGIN_ID, prefkey, null, (IScopeContext[]) scopes.toArray(new IScopeContext[scopes.size()])); |
| 519 | if(value == null) { |
| 520 | value = service.getString(PLUGIN_ID, prefkey, VALUE_IGNORE, new IScopeContext[]{new DefaultScope()}); |
| 521 | } |
| 522 | if(VALUE_ERROR.equals(value)) { |
| 523 | return SEVERITY_ERROR; |
| 524 | } |
| 525 | if(VALUE_WARNING.equals(value)) { |
| 526 | return SEVERITY_WARNING; |
| 527 | } |
| 528 | return SEVERITY_IGNORE; |
| 529 | } |
| 530 | |
| 531 | public ISessionManager getSessionManager() { |
| 532 | if(fgSessionManager == null) { |
| 533 | fgSessionManager = new SessionManager(); |
| 534 | } |
| 535 | return fgSessionManager; |
| 536 | } |
| 537 | |
| 538 | /** |
| 539 | * Returns the enable state for the specific key from the given {@link IProject}. |
| 540 | * If the project does not have project specific settings, the workspace preference |
| 541 | * is returned. If <code>null</code> is passed in as the project the workspace |
| 542 | * preferences are consulted. |
| 543 | * |
| 544 | * @param prefkey the given preference key |
| 545 | * @param project the given project or <code>null</code> |
| 546 | * @return the enable state |
| 547 | */ |
| 548 | public String getEnableState(String prefkey, IProject project) { |
| 549 | IPreferencesService service = Platform.getPreferencesService(); |
| 550 | List scopes = new ArrayList(); |
| 551 | scopes.add(new InstanceScope()); |
| 552 | if(project != null) { |
| 553 | scopes.add(new ProjectScope(project)); |
| 554 | } |
| 555 | String value = service.getString(PLUGIN_ID, prefkey, null, (IScopeContext[]) scopes.toArray(new IScopeContext[scopes.size()])); |
| 556 | if(value == null) { |
| 557 | value = service.getString(PLUGIN_ID, prefkey, VALUE_DISABLED, new IScopeContext[]{new DefaultScope()}); |
| 558 | } |
| 559 | return value; |
| 560 | } |
| 561 | /** |
| 562 | * Method to configure all of the debug options for this plugin |
| 563 | */ |
| 564 | public void configurePluginDebugOptions(){ |
| 565 | if(ApiPlugin.getDefault().isDebugging()){ |
| 566 | String option = Platform.getDebugOption(BUILDER_DEBUG); |
| 567 | if(option != null) { |
| 568 | ApiAnalysisBuilder.setDebug(option.equalsIgnoreCase(TRUE)); |
| 569 | } |
| 570 | option = Platform.getDebugOption(DELTA_DEBUG); |
| 571 | if(option != null) { |
| 572 | boolean debugValue = option.equalsIgnoreCase(TRUE); |
| 573 | ClassFileComparator.setDebug(debugValue); |
| 574 | ApiComparator.setDebug(debugValue); |
| 575 | } |
| 576 | option = Platform.getDebugOption(CLASSFILE_VISITOR_DEBUG); |
| 577 | if(option != null) { |
| 578 | ReferenceExtractor.setDebug(option.equalsIgnoreCase(TRUE)); |
| 579 | } |
| 580 | option = Platform.getDebugOption(DESCRIPTOR_FRAMEWORK_DEBUG); |
| 581 | if(option != null) { |
| 582 | ElementDescriptorImpl.setDebug(option.equalsIgnoreCase(TRUE)); |
| 583 | } |
| 584 | option = Platform.getDebugOption(TAG_SCANNER_DEBUG); |
| 585 | if(option != null) { |
| 586 | TagScanner.setDebug(option.equalsIgnoreCase(TRUE)); |
| 587 | } |
| 588 | option = Platform.getDebugOption(PLUGIN_WORKSPACE_COMPONENT_DEBUG); |
| 589 | if(option != null) { |
| 590 | PluginProjectApiComponent.setDebug(option.equalsIgnoreCase(TRUE)); |
| 591 | } |
| 592 | option = Platform.getDebugOption(API_PROFILE_MANAGER_DEBUG); |
| 593 | if(option != null) { |
| 594 | ApiBaselineManager.setDebug(option.equalsIgnoreCase(TRUE)); |
| 595 | } |
| 596 | option = Platform.getDebugOption(API_FILTER_STORE_DEBUG); |
| 597 | if(option != null) { |
| 598 | ApiFilterStore.setDebug(option.equalsIgnoreCase(TRUE)); |
| 599 | } |
| 600 | option = Platform.getDebugOption(API_REFERENCE_ANALYZER_DEBUG); |
| 601 | if(option != null) { |
| 602 | ReferenceAnalyzer.setDebug(option.equalsIgnoreCase(TRUE)); |
| 603 | } |
| 604 | option = Platform.getDebugOption(REFERENCE_RESOLVER_DEBUG); |
| 605 | if(option != null) { |
| 606 | ReferenceResolver.setDebug(option.equalsIgnoreCase(TRUE)); |
| 607 | } |
| 608 | option = Platform.getDebugOption(PROBLEM_DETECTOR_DEBUG); |
| 609 | if(option != null) { |
| 610 | AbstractProblemDetector.setDebug(option.equals(TRUE)); |
| 611 | } |
| 612 | option = Platform.getDebugOption(API_DESCRIPTION); |
| 613 | if(option != null) { |
| 614 | ApiDescription.setDebug(option.equals(TRUE)); |
| 615 | } |
| 616 | } |
| 617 | } |
| 618 | } |