1 /******************************************************************************* 2 * Copyright (c) 2003, 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 * Jan-Ove Weichel <janove.weichel@vogella.com> - Bug 411578 14 * Andrey Loskutov <loskutov@gmx.de> - Bug 485201, 496475 15 * Mickael Istria (Red Hat Inc.) - Bug 90292 (default editor) and family 16 *******************************************************************************/ 17 package org.eclipse.ui.ide; 18 19 import java.io.IOException; 20 import java.io.InputStream; 21 import java.net.URI; 22 import java.util.ArrayList; 23 import java.util.Collections; 24 import java.util.List; 25 26 import org.eclipse.core.filesystem.EFS; 27 import org.eclipse.core.filesystem.IFileStore; 28 import org.eclipse.core.resources.IFile; 29 import org.eclipse.core.resources.IFolder; 30 import org.eclipse.core.resources.IMarker; 31 import org.eclipse.core.resources.IProject; 32 import org.eclipse.core.resources.IResource; 33 import org.eclipse.core.resources.IResourceDelta; 34 import org.eclipse.core.resources.IResourceStatus; 35 import org.eclipse.core.resources.IWorkspace; 36 import org.eclipse.core.resources.IWorkspaceRoot; 37 import org.eclipse.core.resources.ResourcesPlugin; 38 import org.eclipse.core.resources.mapping.IModelProviderDescriptor; 39 import org.eclipse.core.resources.mapping.IResourceChangeDescriptionFactory; 40 import org.eclipse.core.resources.mapping.ModelProvider; 41 import org.eclipse.core.resources.mapping.ModelStatus; 42 import org.eclipse.core.resources.mapping.ResourceChangeValidator; 43 import org.eclipse.core.runtime.Adapters; 44 import org.eclipse.core.runtime.CoreException; 45 import org.eclipse.core.runtime.IAdapterFactory; 46 import org.eclipse.core.runtime.IAdapterManager; 47 import org.eclipse.core.runtime.IStatus; 48 import org.eclipse.core.runtime.MultiStatus; 49 import org.eclipse.core.runtime.OperationCanceledException; 50 import org.eclipse.core.runtime.Platform; 51 import org.eclipse.core.runtime.QualifiedName; 52 import org.eclipse.core.runtime.SafeRunner; 53 import org.eclipse.core.runtime.content.IContentDescription; 54 import org.eclipse.core.runtime.content.IContentType; 55 import org.eclipse.core.runtime.content.IContentTypeMatcher; 56 import org.eclipse.jface.dialogs.ErrorDialog; 57 import org.eclipse.jface.dialogs.IDialogConstants; 58 import org.eclipse.jface.util.SafeRunnable; 59 import org.eclipse.jface.viewers.IStructuredSelection; 60 import org.eclipse.osgi.util.NLS; 61 import org.eclipse.swt.SWT; 62 import org.eclipse.swt.widgets.Composite; 63 import org.eclipse.swt.widgets.Shell; 64 import org.eclipse.ui.IEditorDescriptor; 65 import org.eclipse.ui.IEditorInput; 66 import org.eclipse.ui.IEditorPart; 67 import org.eclipse.ui.IEditorReference; 68 import org.eclipse.ui.IEditorRegistry; 69 import org.eclipse.ui.IMarkerHelpRegistry; 70 import org.eclipse.ui.IWorkbenchPage; 71 import org.eclipse.ui.IWorkbenchPartReference; 72 import org.eclipse.ui.IWorkbenchWindow; 73 import org.eclipse.ui.MultiPartInitException; 74 import org.eclipse.ui.PartInitException; 75 import org.eclipse.ui.PlatformUI; 76 import org.eclipse.ui.internal.ide.EditorAssociationOverrideDescriptor; 77 import org.eclipse.ui.internal.ide.IDEWorkbenchMessages; 78 import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; 79 import org.eclipse.ui.internal.ide.model.StandardPropertiesAdapterFactory; 80 import org.eclipse.ui.internal.ide.model.WorkbenchAdapterFactory; 81 import org.eclipse.ui.internal.ide.registry.MarkerHelpRegistry; 82 import org.eclipse.ui.internal.ide.registry.MarkerHelpRegistryReader; 83 import org.eclipse.ui.internal.ide.registry.SystemEditorOrTextEditorStrategy; 84 import org.eclipse.ui.internal.ide.registry.UnassociatedEditorStrategyRegistry; 85 import org.eclipse.ui.internal.misc.UIStats; 86 import org.eclipse.ui.part.FileEditorInput; 87 88 /** 89 * Collection of IDE-specific APIs factored out of existing workbench. This 90 * class cannot be instantiated; all functionality is provided by static methods 91 * and fields. 92 * 93 * @since 3.0 94 */ 95 public final class IDE { 96 /** 97 * The persistent property key used on IFile resources to contain the preferred 98 * editor ID to use. 99 * <p> 100 * Example of retrieving the persisted editor id: 101 * </p> 102 * 103 * <pre> 104 * <code> 105 * IFile file = ... 106 * IEditorDescriptor editorDesc = null; 107 * try { 108 * String editorID = file.getPersistentProperty(EDITOR_KEY); 109 * if (editorID != null) { 110 * editorDesc = editorReg.findEditor(editorID); 111 * } 112 * } catch (CoreException e) { 113 * // handle problem accessing persistent property here 114 * } 115 * </code> 116 * </pre> 117 * 118 * <p> 119 * Example of persisting the editor id: 120 * </p> 121 * 122 * <pre> 123 * <code> 124 * IFile file = ... 125 * try { 126 * file.setPersistentProperty(EDITOR_KEY, editorDesc.getId()); 127 * } catch (CoreException e) { 128 * // handle problem setting persistent property here 129 * } 130 * </code> 131 * </pre> 132 * 133 */ 134 public static final QualifiedName EDITOR_KEY = new QualifiedName( 135 "org.eclipse.ui.internal.registry.ResourceEditorRegistry", "EditorProperty");//$NON-NLS-2$//$NON-NLS-1$ 136 137 /** 138 * An optional attribute within a workspace marker (<code>IMarker</code>) 139 * which identifies the preferred editor type to be opened. 140 */ 141 public static final String EDITOR_ID_ATTR = "org.eclipse.ui.editorID"; //$NON-NLS-1$ 142 143 /** 144 * The resource based perspective identifier. 145 */ 146 public static final String RESOURCE_PERSPECTIVE_ID = "org.eclipse.ui.resourcePerspective"; //$NON-NLS-1$ 147 148 /** 149 * A preference key to decide which {@link IUnassociatedEditorStrategy} to use 150 * when trying to open files without associated editors. 151 * 152 * @since 3.12 153 */ 154 public static final String UNASSOCIATED_EDITOR_STRATEGY_PREFERENCE_KEY = "unassociatedEditorStrategy";//$NON-NLS-1$ 155 156 /** 157 * Marker help registry mapping markers to help context ids and resolutions; 158 * lazily initialized on fist access. 159 */ 160 private static MarkerHelpRegistry markerHelpRegistry = null; 161 162 private static volatile IEditorAssociationOverride[] editorAssociationOverrides; 163 164 165 /** 166 * Standard shared images defined by the IDE. These are over and above the 167 * standard workbench images declared in {@link org.eclipse.ui.ISharedImages 168 * ISharedImages}. 169 * <p> 170 * This interface is not intended to be implemented by clients. 171 * </p> 172 * 173 * @see org.eclipse.ui.ISharedImages 174 */ 175 public interface SharedImages { 176 /** 177 * Identifies a project image. 178 */ 179 public static final String IMG_OBJ_PROJECT = "IMG_OBJ_PROJECT"; //$NON-NLS-1$ 180 181 /** 182 * Identifies a closed project image. 183 */ 184 public static final String IMG_OBJ_PROJECT_CLOSED = "IMG_OBJ_PROJECT_CLOSED"; //$NON-NLS-1$ 185 186 /** 187 * Identifies the image used for "open marker". 188 */ 189 public static final String IMG_OPEN_MARKER = "IMG_OPEN_MARKER"; //$NON-NLS-1$ 190 191 /** 192 * Identifies the default image used to indicate a task. 193 */ 194 public static final String IMG_OBJS_TASK_TSK = "IMG_OBJS_TASK_TSK"; //$NON-NLS-1$ 195 196 /** 197 * Identifies the default image used to indicate a bookmark. 198 */ 199 public static final String IMG_OBJS_BKMRK_TSK = "IMG_OBJS_BKMRK_TSK"; //$NON-NLS-1$ 200 } 201 202 /** 203 * Preferences defined by the IDE workbench. 204 * <p> 205 * This interface is not intended to be implemented by clients. 206 * </p> 207 * @noimplement This interface is not intended to be implemented by clients. 208 */ 209 public interface Preferences { 210 211 212 /** 213 * A named preference for how a new perspective should be opened when a 214 * new project is created. 215 * <p> 216 * Value is of type <code>String</code>. The possible values are 217 * defined by the constants 218 * <code>OPEN_PERSPECTIVE_WINDOW, OPEN_PERSPECTIVE_PAGE, 219 * OPEN_PERSPECTIVE_REPLACE, and NO_NEW_PERSPECTIVE</code>. 220 * </p> 221 * 222 * @see org.eclipse.ui.IWorkbenchPreferenceConstants#OPEN_PERSPECTIVE_WINDOW 223 * @see org.eclipse.ui.IWorkbenchPreferenceConstants#OPEN_PERSPECTIVE_PAGE 224 * @see org.eclipse.ui.IWorkbenchPreferenceConstants#OPEN_PERSPECTIVE_REPLACE 225 * @see org.eclipse.ui.IWorkbenchPreferenceConstants#NO_NEW_PERSPECTIVE 226 */ 227 public static final String PROJECT_OPEN_NEW_PERSPECTIVE = "PROJECT_OPEN_NEW_PERSPECTIVE"; //$NON-NLS-1$ 228 229 /** 230 * <p> 231 * Specifies whether or not the workspace selection dialog should be 232 * shown on startup. 233 * </p> 234 * <p> 235 * The default value for this preference is <code>true</code>. 236 * </p> 237 * 238 * @since 3.1 239 */ 240 public static final String SHOW_WORKSPACE_SELECTION_DIALOG = "SHOW_WORKSPACE_SELECTION_DIALOG"; //$NON-NLS-1$ 241 242 /** 243 * Specifies whether the "Recent Workspaces" should be shown 244 * 245 * @since 3.12 246 */ 247 public static final String SHOW_RECENT_WORKSPACES = "SHOW_RECENT_WORKSPACES"; //$NON-NLS-1$ 248 249 /** 250 * <p> 251 * Stores the maximum number of workspaces that should be displayed in 252 * the ChooseWorkspaceDialog. 253 * </p> 254 * 255 * @since 3.1 256 */ 257 public static final String MAX_RECENT_WORKSPACES = "MAX_RECENT_WORKSPACES"; //$NON-NLS-1$ 258 259 /** 260 * <p> 261 * Stores a comma separated list of the recently used workspace paths. 262 * </p> 263 * 264 * @since 3.1 265 */ 266 public static final String RECENT_WORKSPACES = "RECENT_WORKSPACES"; //$NON-NLS-1$ 267 268 /** 269 * <p> 270 * Stores the version of the protocol used to decode/encode the list of 271 * recent workspaces. 272 * </p> 273 * 274 * @since 3.1 275 */ 276 public static final String RECENT_WORKSPACES_PROTOCOL = "RECENT_WORKSPACES_PROTOCOL"; //$NON-NLS-1$ 277 278 /** 279 * Workspace name, will be displayed in the window title. This 280 * preference must only be changed on the UI thread. 281 * @since 3.10 282 */ 283 public static final String WORKSPACE_NAME = "WORKSPACE_NAME"; //$NON-NLS-1$ 284 } 285 286 /** 287 * Block instantiation. 288 */ IDE()289 private IDE() { 290 // do nothing 291 } 292 293 /** 294 * Returns the marker help registry for the workbench. 295 * 296 * @return the marker help registry 297 */ getMarkerHelpRegistry()298 public static IMarkerHelpRegistry getMarkerHelpRegistry() { 299 if (markerHelpRegistry == null) { 300 markerHelpRegistry = new MarkerHelpRegistry(); 301 new MarkerHelpRegistryReader().addHelp(markerHelpRegistry); 302 } 303 return markerHelpRegistry; 304 } 305 306 /** 307 * Sets the cursor and selection state for the given editor to reveal the 308 * position of the given marker. This is done on a best effort basis. If the 309 * editor does not provide an <code>IGotoMarker</code> interface (either 310 * directly or via <code>IAdaptable.getAdapter</code>), this has no 311 * effect. 312 * 313 * @param editor 314 * the editor 315 * @param marker 316 * the marker 317 */ gotoMarker(IEditorPart editor, IMarker marker)318 public static void gotoMarker(IEditorPart editor, IMarker marker) { 319 IGotoMarker gotoMarker = Adapters.adapt(editor, IGotoMarker.class); 320 if (gotoMarker != null) { 321 gotoMarker.gotoMarker(marker); 322 } 323 } 324 325 /** 326 * Opens an editor on the given object. 327 * <p> 328 * If the page already has an editor open on the target object then that 329 * editor is brought to front; otherwise, a new editor is opened. 330 * <p> 331 * 332 * @param page 333 * the page in which the editor will be opened 334 * @param input 335 * the editor input 336 * @param editorId 337 * the id of the editor extension to use 338 * @return an open editor or <code>null</code> if an external editor was 339 * opened 340 * @exception PartInitException 341 * if the editor could not be initialized 342 * @see org.eclipse.ui.IWorkbenchPage#openEditor(IEditorInput, String) 343 */ openEditor(IWorkbenchPage page, IEditorInput input, String editorId)344 public static IEditorPart openEditor(IWorkbenchPage page, 345 IEditorInput input, String editorId) throws PartInitException { 346 // sanity checks 347 if (page == null) { 348 throw new IllegalArgumentException(); 349 } 350 351 // open the editor on the file 352 return page.openEditor(input, editorId); 353 } 354 355 /** 356 * Opens an editor on the given IFileStore object. 357 * <p> 358 * Unlike the other <code>openEditor</code> methods, this one can be used 359 * to open files that reside outside the workspace resource set. 360 * </p> 361 * <p> 362 * If the page already has an editor open on the target object then that 363 * editor is brought to front; otherwise, a new editor is opened. 364 * </p> 365 * 366 * @param page 367 * the page in which the editor will be opened 368 * @param uri 369 * the URI of the file store representing the file to open 370 * @param editorId 371 * the id of the editor extension to use 372 * @param activate 373 * if <code>true</code> the editor will be activated opened 374 * @return an open editor or <code>null</code> if an external editor was 375 * opened 376 * @exception PartInitException 377 * if the editor could not be initialized 378 * 379 * @see org.eclipse.ui.IWorkbenchPage#openEditor(IEditorInput, String) 380 * @see EFS#getStore(URI) 381 * 382 * @since 3.3 383 */ openEditor(IWorkbenchPage page, URI uri, String editorId, boolean activate)384 public static IEditorPart openEditor(IWorkbenchPage page, URI uri, 385 String editorId, boolean activate) throws PartInitException { 386 // sanity checks 387 if (page == null) { 388 throw new IllegalArgumentException(); 389 } 390 391 IFileStore fileStore; 392 try { 393 fileStore = EFS.getStore(uri); 394 } catch (CoreException e) { 395 throw new PartInitException( 396 IDEWorkbenchMessages.IDE_coreExceptionFileStore, e); 397 } 398 399 IEditorInput input = getEditorInput(fileStore); 400 401 // open the editor on the file 402 return page.openEditor(input, editorId, activate); 403 } 404 405 /** 406 * Create the Editor Input appropriate for the given <code>IFileStore</code>. 407 * The result is a normal file editor input if the file exists in the 408 * workspace and, if not, we create a wrapper capable of managing an 409 * 'external' file using its <code>IFileStore</code>. 410 * 411 * @param fileStore 412 * The file store to provide the editor input for 413 * @return The editor input associated with the given file store 414 * @since 3.3 415 */ getEditorInput(IFileStore fileStore)416 private static IEditorInput getEditorInput(IFileStore fileStore) { 417 IFile workspaceFile = getWorkspaceFile(fileStore); 418 if (workspaceFile != null) 419 return new FileEditorInput(workspaceFile); 420 return new FileStoreEditorInput(fileStore); 421 } 422 423 /** 424 * Determine whether or not the <code>IFileStore</code> represents a file 425 * currently in the workspace. 426 * 427 * @param fileStore 428 * The <code>IFileStore</code> to test 429 * @return The workspace's <code>IFile</code> if it exists or 430 * <code>null</code> if not 431 */ getWorkspaceFile(IFileStore fileStore)432 private static IFile getWorkspaceFile(IFileStore fileStore) { 433 IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); 434 IFile[] files = root.findFilesForLocationURI(fileStore.toURI()); 435 files = filterNonExistentFiles(files); 436 if (files == null || files.length == 0) 437 return null; 438 439 // for now only return the first file 440 return files[0]; 441 } 442 443 /** 444 * Filter the incoming array of <code>IFile</code> elements by removing 445 * any that do not currently exist in the workspace. 446 * 447 * @param files 448 * The array of <code>IFile</code> elements 449 * @return The filtered array 450 */ filterNonExistentFiles(IFile[] files)451 private static IFile[] filterNonExistentFiles(IFile[] files) { 452 if (files == null) 453 return null; 454 455 int length = files.length; 456 ArrayList<IFile> existentFiles = new ArrayList<>(length); 457 for (int i = 0; i < length; i++) { 458 if (files[i].exists()) 459 existentFiles.add(files[i]); 460 } 461 return existentFiles.toArray(new IFile[existentFiles.size()]); 462 } 463 464 /** 465 * Opens an editor on the given object. 466 * <p> 467 * If the page already has an editor open on the target object then that 468 * editor is brought to front; otherwise, a new editor is opened. If 469 * <code>activate == true</code> the editor will be activated. 470 * <p> 471 * 472 * @param page 473 * the page in which the editor will be opened 474 * @param input 475 * the editor input 476 * @param editorId 477 * the id of the editor extension to use 478 * @param activate 479 * if <code>true</code> the editor will be activated 480 * @return an open editor or <code>null</code> if an external editor was 481 * opened 482 * @exception PartInitException 483 * if the editor could not be initialized 484 * @see org.eclipse.ui.IWorkbenchPage#openEditor(IEditorInput, String, 485 * boolean) 486 */ openEditor(IWorkbenchPage page, IEditorInput input, String editorId, boolean activate)487 public static IEditorPart openEditor(IWorkbenchPage page, 488 IEditorInput input, String editorId, boolean activate) 489 throws PartInitException { 490 // sanity checks 491 if (page == null) { 492 throw new IllegalArgumentException(); 493 } 494 495 // open the editor on the file 496 return page.openEditor(input, editorId, activate); 497 } 498 499 /** 500 * Opens an editor on the given file resource. This method will attempt to 501 * resolve the editor based on content-type bindings as well as traditional 502 * name/extension bindings. 503 * <p> 504 * If the page already has an editor open on the target object then that 505 * editor is brought to front; otherwise, a new editor is opened. If 506 * <code>activate == true</code> the editor will be activated. 507 * <p> 508 * 509 * @param page 510 * the page in which the editor will be opened 511 * @param input 512 * the editor input 513 * @param activate 514 * if <code>true</code> the editor will be activated 515 * @return an open editor or <code>null</code> if an external editor was 516 * opened or if opening was canceled 517 * @exception PartInitException 518 * if the editor could not be initialized 519 * @see org.eclipse.ui.IWorkbenchPage#openEditor(org.eclipse.ui.IEditorInput, 520 * String, boolean) 521 */ openEditor(IWorkbenchPage page, IFile input, boolean activate)522 public static IEditorPart openEditor(IWorkbenchPage page, IFile input, 523 boolean activate) throws PartInitException { 524 return openEditor(page, input, activate, true); 525 } 526 527 /** 528 * Opens an editor on the given file resource. This method will attempt to 529 * resolve the editor based on content-type bindings as well as traditional 530 * name/extension bindings if <code>determineContentType</code> is 531 * <code>true</code>. 532 * <p> 533 * If the page already has an editor open on the target object then that 534 * editor is brought to front; otherwise, a new editor is opened. If 535 * <code>activate == true</code> the editor will be activated. 536 * <p> 537 * 538 * @param page 539 * the page in which the editor will be opened 540 * @param input 541 * the editor input 542 * @param activate 543 * if <code>true</code> the editor will be activated 544 * @param determineContentType 545 * attempt to resolve the content type for this file 546 * @return an open editor or <code>null</code> if an external editor was 547 * opened or if opening was canceled 548 * @exception PartInitException 549 * if the editor could not be initialized 550 * @see org.eclipse.ui.IWorkbenchPage#openEditor(org.eclipse.ui.IEditorInput, 551 * String, boolean) 552 * @since 3.1 553 */ openEditor(IWorkbenchPage page, IFile input, boolean activate, boolean determineContentType)554 public static IEditorPart openEditor(IWorkbenchPage page, IFile input, 555 boolean activate, boolean determineContentType) 556 throws PartInitException { 557 // sanity checks 558 if (page == null) { 559 throw new IllegalArgumentException(); 560 } 561 562 // open the editor on the file 563 IEditorDescriptor editorDesc; 564 try { 565 editorDesc = getEditorDescriptor(input, determineContentType, true); 566 } catch (OperationCanceledException ex) { 567 return null; 568 } 569 return page.openEditor(new FileEditorInput(input), editorDesc.getId(), 570 activate); 571 } 572 573 /** 574 * Opens an editor on the given file resource. This method will attempt to 575 * resolve the editor based on content-type bindings as well as traditional 576 * name/extension bindings. 577 * <p> 578 * If the page already has an editor open on the target object then that 579 * editor is brought to front; otherwise, a new editor is opened. 580 * <p> 581 * 582 * @param page 583 * the page in which the editor will be opened 584 * @param input 585 * the editor input 586 * @return an open editor or <code>null</code> if an external editor was 587 * opened or if opening was canceled 588 * @exception PartInitException 589 * if the editor could not be initialized 590 * @see org.eclipse.ui.IWorkbenchPage#openEditor(IEditorInput, String) 591 */ openEditor(IWorkbenchPage page, IFile input)592 public static IEditorPart openEditor(IWorkbenchPage page, IFile input) 593 throws PartInitException { 594 // sanity checks 595 if (page == null) { 596 throw new IllegalArgumentException(); 597 } 598 599 // open the editor on the file 600 IEditorDescriptor editorDesc; 601 try { 602 editorDesc = getEditorDescriptor(input, true, true); 603 } catch (OperationCanceledException ex) { 604 return null; 605 } 606 return page.openEditor(new FileEditorInput(input), editorDesc.getId()); 607 } 608 609 /** 610 * Opens an editor on the given file resource. 611 * <p> 612 * If the page already has an editor open on the target object then that 613 * editor is brought to front; otherwise, a new editor is opened. 614 * <p> 615 * 616 * @param page 617 * the page in which the editor will be opened 618 * @param input 619 * the editor input 620 * @param editorId 621 * the id of the editor extension to use 622 * @return an open editor or <code>null</code> if an external editor was 623 * opened 624 * @exception PartInitException 625 * if the editor could not be initialized 626 * @see org.eclipse.ui.IWorkbenchPage#openEditor(IEditorInput, String) 627 */ openEditor(IWorkbenchPage page, IFile input, String editorId)628 public static IEditorPart openEditor(IWorkbenchPage page, IFile input, 629 String editorId) throws PartInitException { 630 // sanity checks 631 if (page == null) { 632 throw new IllegalArgumentException(); 633 } 634 635 // open the editor on the file 636 return page.openEditor(new FileEditorInput(input), editorId); 637 } 638 639 /** 640 * Opens an editor on the given file resource. 641 * <p> 642 * If the page already has an editor open on the target object then that 643 * editor is brought to front; otherwise, a new editor is opened. If 644 * <code>activate == true</code> the editor will be activated. 645 * <p> 646 * 647 * @param page 648 * the page in which the editor will be opened 649 * @param input 650 * the editor input 651 * @param editorId 652 * the id of the editor extension to use 653 * @param activate 654 * if <code>true</code> the editor will be activated 655 * @return an open editor or <code>null</code> if an external editor was 656 * opened 657 * @exception PartInitException 658 * if the editor could not be initialized 659 * @see org.eclipse.ui.IWorkbenchPage#openEditor(IEditorInput, String, 660 * boolean) 661 */ openEditor(IWorkbenchPage page, IFile input, String editorId, boolean activate)662 public static IEditorPart openEditor(IWorkbenchPage page, IFile input, 663 String editorId, boolean activate) throws PartInitException { 664 // sanity checks 665 if (page == null) { 666 throw new IllegalArgumentException(); 667 } 668 669 // open the editor on the file 670 return page.openEditor(new FileEditorInput(input), editorId, activate); 671 } 672 673 /** 674 * Returns an editor descriptor appropriate for opening the given file 675 * resource. 676 * <p> 677 * The editor descriptor is determined using a multi-step process. This 678 * method will attempt to resolve the editor based on content-type bindings 679 * as well as traditional name/extension bindings. 680 * </p> 681 * <ol> 682 * <li>The <code>IResource</code> is consulted for a persistent property named 683 * <code>IDE.EDITOR_KEY</code> containing the preferred editor id to be 684 * used.</li> 685 * <li>The workbench editor registry is consulted to determine if an editor 686 * extension has been registered for the file type. If so, an instance of 687 * the editor extension is opened on the file. See 688 * <code>IEditorRegistry.getDefaultEditor(String)</code>.</li> 689 * <li>The operating system is consulted to determine if an in-place 690 * component editor is available (e.g. OLE editor on Win32 platforms).</li> 691 * <li>The operating system is consulted to determine if an external editor 692 * is available.</li> 693 * <li>The workbench editor registry is consulted to determine if the 694 * default text editor is available.</li> 695 * </ol> 696 * 697 * @param file 698 * the file 699 * @return an editor descriptor, appropriate for opening the file 700 * @throws PartInitException 701 * if no editor can be found 702 * @deprecated Since 3.12, use 703 * {@link IDE#getEditorDescriptor(IFile, boolean, boolean)} 704 */ 705 @Deprecated getEditorDescriptor(IFile file)706 public static IEditorDescriptor getEditorDescriptor(IFile file) throws PartInitException { 707 return getEditorDescriptor(file, true); 708 } 709 710 /** 711 * Returns an editor descriptor appropriate for opening the given file 712 * resource. 713 * <p> 714 * The editor descriptor is determined using a multi-step process. This 715 * method will attempt to resolve the editor based on content-type bindings 716 * as well as traditional name/extension bindings if 717 * <code>determineContentType</code>is <code>true</code>. 718 * </p> 719 * <ol> 720 * <li>The <code>IResource</code> is consulted for a persistent property named 721 * <code>IDE.EDITOR_KEY</code> containing the preferred editor id to be 722 * used.</li> 723 * <li>The workbench editor registry is consulted to determine if an editor 724 * extension has been registered for the file type. If so, an instance of 725 * the editor extension is opened on the file. See 726 * <code>IEditorRegistry.getDefaultEditor(String)</code>.</li> 727 * <li>The operating system is consulted to determine if an in-place 728 * component editor is available (e.g. OLE editor on Win32 platforms).</li> 729 * <li>The operating system is consulted to determine if an external editor 730 * is available.</li> 731 * <li>The workbench editor registry is consulted to determine if the 732 * default text editor is available.</li> 733 * </ol> 734 * 735 * @param file 736 * the file 737 * @param determineContentType 738 * query the content type system for the content type of the file 739 * @return an editor descriptor, appropriate for opening the file 740 * @throws PartInitException 741 * if no editor can be found 742 * @since 3.1 743 * @deprecated Since 3.12, use 744 * {@link IDE#getEditorDescriptor(IFile, boolean, boolean)} 745 * instead. 746 */ 747 @Deprecated getEditorDescriptor(IFile file, boolean determineContentType)748 public static IEditorDescriptor getEditorDescriptor(IFile file, boolean determineContentType) throws PartInitException { 749 750 if (file == null) { 751 throw new IllegalArgumentException(); 752 } 753 754 return getEditorDescriptor(file.getName(), PlatformUI.getWorkbench() 755 .getEditorRegistry(), getDefaultEditor(file, 756 determineContentType)); 757 } 758 759 /** 760 * Returns an editor descriptor appropriate for opening the given file resource. 761 * <p> 762 * The editor descriptor is determined using a multi-step process. This method 763 * will attempt to resolve the editor based on content-type bindings as well as 764 * traditional name/extension bindings if <code>determineContentType</code>is 765 * <code>true</code>. 766 * </p> 767 * <ol> 768 * <li>The <code>IResource</code> is consulted for a persistent property named 769 * <code>IDE.EDITOR_KEY</code> containing the preferred editor id to be 770 * used.</li> 771 * <li>The workbench editor registry is consulted to determine if an editor 772 * extension has been registered for the file type. If so, an instance of the 773 * editor extension is opened on the file. See 774 * <code>IEditorRegistry.getDefaultEditor(String)</code>.</li> 775 * <li>The preferred {@link IUnassociatedEditorStrategy} is consulted.</li> 776 * <li>The {@link SystemEditorOrTextEditorStrategy} is consulted, whose behavior 777 * is 778 * <ol> 779 * <li>The operating system is consulted to determine if an in-place component 780 * editor is available (e.g. OLE editor on Win32 platforms).</li> 781 * <li>The operating system is consulted to determine if an external editor is 782 * available.</li> 783 * <li>The workbench editor registry is consulted to determine if the default 784 * text editor is available.</li> 785 * </ol> 786 * </li> 787 * </ol> 788 * 789 * @param file the file 790 * @param determineContentType query the content type system for the content 791 * type of the file 792 * @param allowInteractive whether we allow user interactions 793 * @return an editor descriptor, appropriate for opening the file 794 * @throws PartInitException if no editor can be found 795 * @throws OperationCanceledException in case descriptor lookup was canceled by 796 * the user 797 * @since 3.12 798 */ getEditorDescriptor(IFile file, boolean determineContentType, boolean allowInteractive)799 public static IEditorDescriptor getEditorDescriptor(IFile file, boolean determineContentType, boolean allowInteractive) 800 throws PartInitException, OperationCanceledException { 801 802 if (file == null) { 803 throw new IllegalArgumentException(); 804 } 805 806 return getEditorDescriptor(file.getName(), PlatformUI.getWorkbench().getEditorRegistry(), 807 getDefaultEditor(file, determineContentType), allowInteractive); 808 } 809 810 /** 811 * Returns an editor descriptor appropriate for opening the given file store. 812 * <p> 813 * The editor descriptor is determined using a multi-step process. This method 814 * will attempt to resolve the editor based on content-type bindings as well as 815 * traditional name/extension bindings. 816 * </p> 817 * <ol> 818 * <li>The workbench editor registry is consulted to determine if an editor 819 * extension has been registered for the file type. If so, an instance of the 820 * editor extension is opened on the file. See 821 * <code>IEditorRegistry.getDefaultEditor(String)</code>.</li> 822 * <li>The preferred {@link IUnassociatedEditorStrategy} is consulted.</li> 823 * <li>The {@link SystemEditorOrTextEditorStrategy} is consulted, whose behavior 824 * is 825 * <ol> 826 * <li>The operating system is consulted to determine if an in-place component 827 * editor is available (e.g. OLE editor on Win32 platforms).</li> 828 * <li>The operating system is consulted to determine if an external editor is 829 * available.</li> 830 * <li>The workbench editor registry is consulted to determine if the default 831 * text editor is available.</li> 832 * </ol> 833 * </li> 834 * </ol> 835 * 836 * @param fileStore the file store 837 * @param allowInteractive Whether user interactions are allowed 838 * @return editor descriptor of an editor, appropriate for opening the file 839 * @throws PartInitException if no editor can be found 840 * @since 3.16 841 */ getEditorDescriptorForFileStore(IFileStore fileStore, boolean allowInteractive)842 public static IEditorDescriptor getEditorDescriptorForFileStore(IFileStore fileStore, boolean allowInteractive) 843 throws PartInitException { 844 String name = fileStore.fetchInfo().getName(); 845 if (name == null) { 846 throw new IllegalArgumentException(); 847 } 848 849 IContentType contentType = null; 850 try (InputStream is = fileStore.openInputStream(EFS.NONE, null)) { 851 contentType = Platform.getContentTypeManager().findContentTypeFor(is, name); 852 } catch (CoreException | IOException ex) { 853 // continue without content type 854 } 855 856 IEditorRegistry editorReg = PlatformUI.getWorkbench().getEditorRegistry(); 857 858 IEditorDescriptor defaultEditor = editorReg.getDefaultEditor(name, contentType); 859 defaultEditor = overrideDefaultEditorAssociation(new FileStoreEditorInput(fileStore), contentType, 860 defaultEditor); 861 return getEditorDescriptor(name, editorReg, defaultEditor, allowInteractive); 862 } 863 864 /** 865 * Applies the <code>org.eclipse.ui.ide.editorAssociationOverride</code> extensions to the given 866 * input. 867 * <p> 868 * <strong>Note:</strong> It is recommended to get the descriptor for the default editor by 869 * calling {@link #getDefaultEditor(IFile, boolean)}. This method here should only be used if 870 * this is not possible for whatever reason. 871 * </p> 872 * 873 * @param editorInput the editor input for the editor 874 * @param contentType the content type of the input or <code>null</code> if not available 875 * @param editorDescriptor the current association for the given input or <code>null</code> if 876 * none 877 * @return the editor descriptor to be used for the given input or <code>null</code> if none. 878 * Can be <code>editorDescriptor</code>. 879 * @see IEditorAssociationOverride#overrideDefaultEditor(IEditorInput, IContentType, 880 * IEditorDescriptor) 881 * @since 3.8 882 */ overrideDefaultEditorAssociation(IEditorInput editorInput, IContentType contentType, IEditorDescriptor editorDescriptor)883 public static IEditorDescriptor overrideDefaultEditorAssociation(IEditorInput editorInput, IContentType contentType, IEditorDescriptor editorDescriptor) { 884 for (IEditorAssociationOverride override : getEditorAssociationOverrides()) { 885 editorDescriptor = override.overrideDefaultEditor(editorInput, contentType, editorDescriptor); 886 } 887 return editorDescriptor; 888 } 889 890 /** 891 * Applies the <code>org.eclipse.ui.ide.editorAssociationOverride</code> extensions to the given 892 * input. 893 * 894 * @param fileName the name of the file for which to choose the editor 895 * @param contentType the content type of the input or <code>null</code> if not available 896 * @param editorDescriptor the current association for the given input or <code>null</code> if 897 * none 898 * @return the editor descriptor to be used for the given input or <code>null</code> if none. 899 * Can be <code>editorDescriptor</code>. 900 * @see IEditorAssociationOverride#overrideDefaultEditor(String, IContentType, 901 * IEditorDescriptor) 902 * @since 3.8 903 */ overrideDefaultEditorAssociation(String fileName, IContentType contentType, IEditorDescriptor editorDescriptor)904 private static IEditorDescriptor overrideDefaultEditorAssociation(String fileName, IContentType contentType, IEditorDescriptor editorDescriptor) { 905 for (IEditorAssociationOverride override : getEditorAssociationOverrides()) { 906 editorDescriptor = override.overrideDefaultEditor(fileName, contentType, editorDescriptor); 907 } 908 return editorDescriptor; 909 } 910 911 /** 912 * Applies the <code>org.eclipse.ui.ide.editorAssociationOverride</code> extensions to the given 913 * input. 914 * 915 * @param editorInput the editor input for the editor 916 * @param contentType the content type of the input or <code>null</code> if not available 917 * @param editorDescriptors the current association for the given input 918 * @return the editor descriptors to be used for the given input - can be 919 * <code>editorDescriptors</code>. The order is not relevant. 920 * @see IEditorAssociationOverride#overrideEditors(IEditorInput, IContentType, 921 * IEditorDescriptor[]) 922 * @since 3.8 923 */ overrideEditorAssociations(IEditorInput editorInput, IContentType contentType, IEditorDescriptor[] editorDescriptors)924 public static IEditorDescriptor[] overrideEditorAssociations(IEditorInput editorInput, IContentType contentType, IEditorDescriptor[] editorDescriptors) { 925 for (IEditorAssociationOverride override : getEditorAssociationOverrides()) { 926 editorDescriptors = override.overrideEditors(editorInput, contentType, editorDescriptors); 927 } 928 return removeNullEntries(editorDescriptors); 929 } 930 931 /** 932 * Applies the <code>org.eclipse.ui.ide.editorAssociationOverride</code> extensions to the given 933 * input. 934 * 935 * @param fileName the name of the file for which to choose the editor 936 * @param contentType the content type of the input or <code>null</code> if not available 937 * @param editorDescriptors the current association for the given input 938 * @return the editor descriptors to be used for the given input - can be 939 * <code>editorDescriptors</code>. The order is not relevant. 940 * @see IEditorAssociationOverride#overrideEditors(IEditorInput, IContentType, 941 * IEditorDescriptor[]) 942 * @since 3.8 943 */ overrideEditorAssociations(String fileName, IContentType contentType, IEditorDescriptor[] editorDescriptors)944 public static IEditorDescriptor[] overrideEditorAssociations(String fileName, IContentType contentType, IEditorDescriptor[] editorDescriptors) { 945 for (IEditorAssociationOverride override : getEditorAssociationOverrides()) { 946 editorDescriptors = override.overrideEditors(fileName, contentType, editorDescriptors); 947 } 948 return removeNullEntries(editorDescriptors); 949 } 950 removeNullEntries(IEditorDescriptor[] editorDescriptors)951 private static IEditorDescriptor[] removeNullEntries(IEditorDescriptor[] editorDescriptors) { 952 boolean nullDescriptorFound = false; 953 for (IEditorDescriptor editorDesc : editorDescriptors) { 954 if (editorDesc == null) { 955 nullDescriptorFound = true; 956 break; 957 } 958 } 959 if (!nullDescriptorFound) { 960 return editorDescriptors; 961 } 962 List<IEditorDescriptor> nonNullDescriptors = new ArrayList<>(editorDescriptors.length); 963 for (IEditorDescriptor editorDesc : editorDescriptors) { 964 if (editorDesc != null) { 965 nonNullDescriptors.add(editorDesc); 966 } 967 } 968 return nonNullDescriptors.toArray(new IEditorDescriptor[nonNullDescriptors.size()]); 969 } 970 971 /** 972 * Returns an editor descriptor appropriate for opening a file resource with 973 * the given name. 974 * <p> 975 * The editor descriptor is determined using a multi-step process. This 976 * method will attempt to infer content type from the file name. 977 * </p> 978 * <ol> 979 * <li>The workbench editor registry is consulted to determine if an editor 980 * extension has been registered for the file type. If so, an instance of 981 * the editor extension is opened on the file. See 982 * <code>IEditorRegistry.getDefaultEditor(String)</code>.</li> 983 * <li>The operating system is consulted to determine if an in-place 984 * component editor is available (e.g. OLE editor on Win32 platforms).</li> 985 * <li>The operating system is consulted to determine if an external editor 986 * is available.</li> 987 * <li>The workbench editor registry is consulted to determine if the 988 * default text editor is available.</li> 989 * </ol> 990 * 991 * @param name 992 * the file name 993 * @return an editor descriptor, appropriate for opening the file 994 * @throws PartInitException 995 * if no editor can be found 996 * @since 3.1 997 * @deprecated Since 3.12, use 998 * {@link IDE#getEditorDescriptor(String, boolean, boolean)} 999 * instead. 1000 */ 1001 @Deprecated getEditorDescriptor(String name)1002 public static IEditorDescriptor getEditorDescriptor(String name) 1003 throws PartInitException { 1004 return getEditorDescriptor(name, true); 1005 } 1006 1007 /** 1008 * Returns an editor descriptor appropriate for opening a file resource with 1009 * the given name. 1010 * <p> 1011 * The editor descriptor is determined using a multi-step process. This 1012 * method will attempt to infer the content type of the file if 1013 * <code>inferContentType</code> is <code>true</code>. 1014 * </p> 1015 * <ol> 1016 * <li>The workbench editor registry is consulted to determine if an editor 1017 * extension has been registered for the file type. If so, an instance of 1018 * the editor extension is opened on the file. See 1019 * <code>IEditorRegistry.getDefaultEditor(String)</code>.</li> 1020 * <li>The operating system is consulted to determine if an in-place 1021 * component editor is available (e.g. OLE editor on Win32 platforms).</li> 1022 * <li>The operating system is consulted to determine if an external editor 1023 * is available.</li> 1024 * <li>The workbench editor registry is consulted to determine if the 1025 * default text editor is available.</li> 1026 * </ol> 1027 * 1028 * @param name 1029 * the file name 1030 * @param inferContentType 1031 * attempt to infer the content type from the file name if this 1032 * is <code>true</code> 1033 * @return an editor descriptor, appropriate for opening the file 1034 * @throws PartInitException 1035 * if no editor can be found 1036 * @since 3.1 1037 * @deprecated Since 3.12, use 1038 * {@link IDE#getEditorDescriptor(String, boolean, boolean)} 1039 * instead. 1040 */ 1041 @Deprecated getEditorDescriptor(String name, boolean inferContentType)1042 public static IEditorDescriptor getEditorDescriptor(String name, boolean inferContentType) 1043 throws PartInitException { 1044 1045 if (name == null) { 1046 throw new IllegalArgumentException(); 1047 } 1048 1049 IContentType contentType = inferContentType ? Platform 1050 .getContentTypeManager().findContentTypeFor(name) : null; 1051 IEditorRegistry editorReg = PlatformUI.getWorkbench() 1052 .getEditorRegistry(); 1053 1054 IEditorDescriptor defaultEditor = editorReg.getDefaultEditor(name, contentType); 1055 defaultEditor = getEditorDescriptor(name, editorReg, defaultEditor); 1056 return overrideDefaultEditorAssociation(name, contentType, defaultEditor); 1057 } 1058 1059 /** 1060 * Returns an editor descriptor appropriate for opening a file resource with the 1061 * given name. 1062 * <p> 1063 * The editor descriptor is determined using a multi-step process. This method 1064 * will attempt to infer the content type of the file if 1065 * <code>inferContentType</code> is <code>true</code>. 1066 * </p> 1067 * <ol> 1068 * <li>The workbench editor registry is consulted to determine if an editor 1069 * extension has been registered for the file type. If so, an instance of the 1070 * editor extension is opened on the file. See 1071 * <code>IEditorRegistry.getDefaultEditor(String)</code>.</li> 1072 * <li>The preferred {@link IUnassociatedEditorStrategy} is consulted.</li> 1073 * <li>The {@link SystemEditorOrTextEditorStrategy} is consulted, whose behavior 1074 * is 1075 * <ol> 1076 * <li>The operating system is consulted to determine if an in-place component 1077 * editor is available (e.g. OLE editor on Win32 platforms).</li> 1078 * <li>The operating system is consulted to determine if an external editor is 1079 * available.</li> 1080 * <li>The workbench editor registry is consulted to determine if the default 1081 * text editor is available.</li> 1082 * </ol> 1083 * </li> 1084 * </ol> 1085 * 1086 * @param name the file name 1087 * @param inferContentType attempt to infer the content type from the file name 1088 * if this is <code>true</code> 1089 * @param allowInteractive whether we allow user interactions. 1090 * @return an editor descriptor, appropriate for opening the file 1091 * @throws PartInitException if no editor can be found 1092 * @throws OperationCanceledException in case descriptor lookup was canceled by 1093 * the user 1094 * @since 3.12 1095 */ getEditorDescriptor(String name, boolean inferContentType, boolean allowInteractive)1096 public static IEditorDescriptor getEditorDescriptor(String name, boolean inferContentType, boolean allowInteractive) 1097 throws PartInitException, OperationCanceledException { 1098 1099 if (name == null) { 1100 throw new IllegalArgumentException(); 1101 } 1102 1103 IContentType contentType = inferContentType ? Platform 1104 .getContentTypeManager().findContentTypeFor(name) : null; 1105 IEditorRegistry editorReg = PlatformUI.getWorkbench() 1106 .getEditorRegistry(); 1107 1108 IEditorDescriptor defaultEditor = editorReg.getDefaultEditor(name, contentType); 1109 defaultEditor = getEditorDescriptor(name, editorReg, defaultEditor, allowInteractive); 1110 return overrideDefaultEditorAssociation(name, contentType, defaultEditor); 1111 } 1112 1113 /** 1114 * Get the editor descriptor for a given name using the editorDescriptor 1115 * passed in as a default as a starting point. It may delegate computation 1116 * to the active {@link IUnassociatedEditorStrategy}. 1117 * 1118 * @param name 1119 * The name of the element to open. 1120 * @param editorReg 1121 * The editor registry to do the lookups from. 1122 * @param defaultDescriptor 1123 * IEditorDescriptor or <code>null</code> 1124 * @param allowInteractive 1125 * Whether we ask selected {@link IUnassociatedEditorStrategy}, that 1126 * can be interactive. 1127 * @return IEditorDescriptor 1128 * @throws PartInitException 1129 * if no valid editor can be found 1130 * @throws OperationCanceledException 1131 * in case descriptor lookup was canceled by the user 1132 * 1133 * @since 3.12 1134 */ getEditorDescriptor(String name, IEditorRegistry editorReg, IEditorDescriptor defaultDescriptor, boolean allowInteractive)1135 private static IEditorDescriptor getEditorDescriptor(String name, IEditorRegistry editorReg, 1136 IEditorDescriptor defaultDescriptor, boolean allowInteractive) 1137 throws PartInitException, OperationCanceledException { 1138 1139 if (defaultDescriptor != null) { 1140 return defaultDescriptor; 1141 } 1142 1143 IUnassociatedEditorStrategy strategy = getUnassociatedEditorStrategy(allowInteractive); 1144 IEditorDescriptor editorDesc; 1145 try { 1146 editorDesc = strategy.getEditorDescriptor(name, editorReg); 1147 } catch (CoreException e) { 1148 throw new PartInitException(IDEWorkbenchMessages.IDE_noFileEditorFound, e); 1149 } 1150 1151 // if no valid editor found, bail out 1152 if (editorDesc == null) { 1153 throw new PartInitException( 1154 IDEWorkbenchMessages.IDE_noFileEditorFound); 1155 } 1156 1157 return editorDesc; 1158 } 1159 1160 /** 1161 * Get the editor descriptor for a given name using the editorDescriptor 1162 * passed in as a default as a starting point. 1163 * 1164 * @param name 1165 * The name of the element to open. 1166 * @param editorReg 1167 * The editor registry to do the lookups from. 1168 * @param defaultDescriptor 1169 * IEditorDescriptor or <code>null</code> 1170 * @return IEditorDescriptor 1171 * @throws PartInitException 1172 * if no valid editor can be found 1173 * 1174 * @since 3.1 1175 * @deprecated Since 3.12, use {@link IDE#getEditorDescriptor(String, boolean, boolean)} instead 1176 */ 1177 @Deprecated getEditorDescriptor(String name, IEditorRegistry editorReg, IEditorDescriptor defaultDescriptor)1178 private static IEditorDescriptor getEditorDescriptor(String name, 1179 IEditorRegistry editorReg, IEditorDescriptor defaultDescriptor) 1180 throws PartInitException { 1181 1182 if (defaultDescriptor != null) { 1183 return defaultDescriptor; 1184 } 1185 1186 IEditorDescriptor editorDesc = defaultDescriptor; 1187 1188 // next check the OS for in-place editor (OLE on Win32) 1189 if (editorReg.isSystemInPlaceEditorAvailable(name)) { 1190 editorDesc = editorReg 1191 .findEditor(IEditorRegistry.SYSTEM_INPLACE_EDITOR_ID); 1192 } 1193 1194 // next check with the OS for an external editor 1195 if (editorDesc == null 1196 && editorReg.isSystemExternalEditorAvailable(name)) { 1197 editorDesc = editorReg 1198 .findEditor(IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID); 1199 } 1200 1201 // next lookup the default text editor 1202 if (editorDesc == null) { 1203 editorDesc = editorReg 1204 .findEditor(IDEWorkbenchPlugin.DEFAULT_TEXT_EDITOR_ID); 1205 } 1206 1207 // if no valid editor found, bail out 1208 if (editorDesc == null) { 1209 throw new PartInitException( 1210 IDEWorkbenchMessages.IDE_noFileEditorFound); 1211 } 1212 1213 return editorDesc; 1214 } 1215 1216 /** 1217 * @param allowInteractive 1218 * Whether interactive strategies are considered 1219 * @return The strategy to use in order to open unknown file. Either as set 1220 * by preference, or a {@link SystemEditorOrTextEditorStrategy} if 1221 * none is explicitly configured. Never returns {@code null}. 1222 */ getUnassociatedEditorStrategy(boolean allowInteractive)1223 private static IUnassociatedEditorStrategy getUnassociatedEditorStrategy(boolean allowInteractive) { 1224 String preferedStrategy = IDEWorkbenchPlugin.getDefault().getPreferenceStore() 1225 .getString(UNASSOCIATED_EDITOR_STRATEGY_PREFERENCE_KEY); 1226 IUnassociatedEditorStrategy res = null; 1227 UnassociatedEditorStrategyRegistry registry = IDEWorkbenchPlugin.getDefault() 1228 .getUnassociatedEditorStrategyRegistry(); 1229 if (allowInteractive || !registry.isInteractive(preferedStrategy)) { 1230 res = registry.getStrategy(preferedStrategy); 1231 } 1232 if (res == null) { 1233 res = new SystemEditorOrTextEditorStrategy(); 1234 } 1235 return res; 1236 } 1237 1238 /** 1239 * Opens an editor on the file resource of the given marker. 1240 * <p> 1241 * If this page already has an editor open on the marker resource file that 1242 * editor is brought to front; otherwise, a new editor is opened.The cursor 1243 * and selection state of the editor are then updated from information 1244 * recorded in the marker. 1245 * </p> 1246 * <p> 1247 * If the marker contains an <code>EDITOR_ID_ATTR</code> attribute the 1248 * attribute value will be used to determine the editor type to be opened. 1249 * If not, the registered editor for the marker resource file will be used. 1250 * </p> 1251 * 1252 * @param page 1253 * the workbench page to open the editor in 1254 * @param marker 1255 * the marker to open 1256 * @return an open editor or <code>null</code> not possible 1257 * @exception PartInitException 1258 * if the editor could not be initialized 1259 * @see #openEditor(org.eclipse.ui.IWorkbenchPage, 1260 * org.eclipse.core.resources.IMarker, boolean) 1261 */ openEditor(IWorkbenchPage page, IMarker marker)1262 public static IEditorPart openEditor(IWorkbenchPage page, IMarker marker) 1263 throws PartInitException { 1264 return openEditor(page, marker, true); 1265 } 1266 1267 /** 1268 * Opens an editor on the file resource of the given marker. 1269 * <p> 1270 * If this page already has an editor open on the marker resource file that 1271 * editor is brought to front; otherwise, a new editor is opened. If 1272 * <code>activate == true</code> the editor will be activated. The cursor 1273 * and selection state of the editor are then updated from information 1274 * recorded in the marker. 1275 * </p> 1276 * <p> 1277 * If the marker contains an <code>EDITOR_ID_ATTR</code> attribute the 1278 * attribute value will be used to determine the editor type to be opened. 1279 * If not, the registered editor for the marker resource file will be used. 1280 * </p> 1281 * 1282 * @param page 1283 * the workbench page to open the editor in 1284 * @param marker 1285 * the marker to open 1286 * @param activate 1287 * if <code>true</code> the editor will be activated 1288 * @return an open editor or <code>null</code> if not possible or if opening 1289 * was canceled 1290 * @exception PartInitException 1291 * if the editor could not be initialized 1292 */ openEditor(IWorkbenchPage page, IMarker marker, boolean activate)1293 public static IEditorPart openEditor(IWorkbenchPage page, IMarker marker, 1294 boolean activate) throws PartInitException { 1295 // sanity checks 1296 if (page == null || marker == null) { 1297 throw new IllegalArgumentException(); 1298 } 1299 1300 // get the marker resource file 1301 if (!(marker.getResource() instanceof IFile)) { 1302 IDEWorkbenchPlugin 1303 .log("Open editor on marker failed; marker resource not an IFile"); //$NON-NLS-1$ 1304 return null; 1305 } 1306 IFile file = (IFile) marker.getResource(); 1307 1308 // get the preferred editor id from the marker 1309 IEditorRegistry editorReg = PlatformUI.getWorkbench() 1310 .getEditorRegistry(); 1311 IEditorDescriptor editorDesc = null; 1312 try { 1313 String editorID = (String) marker.getAttribute(EDITOR_ID_ATTR); 1314 if (editorID != null) { 1315 editorDesc = editorReg.findEditor(editorID); 1316 } 1317 } catch (CoreException e) { 1318 // ignore this 1319 } 1320 1321 // open the editor on the marker resource file 1322 IEditorPart editor = null; 1323 if (editorDesc == null) { 1324 editor = openEditor(page, file, activate); 1325 } else { 1326 editor = page.openEditor(new FileEditorInput(file), editorDesc 1327 .getId(), activate, IWorkbenchPage.MATCH_ID | IWorkbenchPage.MATCH_INPUT); 1328 } 1329 1330 // get the editor to update its position based on the marker 1331 if (editor != null) { 1332 gotoMarker(editor, marker); 1333 } 1334 1335 return editor; 1336 } 1337 1338 /** 1339 * Opens an editor on the given IFileStore object. 1340 * <p> 1341 * Unlike the other <code>openEditor</code> methods, this one 1342 * can be used to open files that reside outside the workspace 1343 * resource set. 1344 * </p> 1345 * <p> 1346 * If the page already has an editor open on the target object then that 1347 * editor is brought to front; otherwise, a new editor is opened. 1348 * </p> 1349 * 1350 * @param page 1351 * the page in which the editor will be opened 1352 * @param fileStore 1353 * the IFileStore representing the file to open 1354 * @return an open editor or <code>null</code> if an external editor was 1355 * opened or if opening was canceled 1356 * @exception PartInitException 1357 * if the editor could not be initialized 1358 * @see org.eclipse.ui.IWorkbenchPage#openEditor(IEditorInput, String) 1359 * @since 3.3 1360 */ openEditorOnFileStore(IWorkbenchPage page, IFileStore fileStore)1361 public static IEditorPart openEditorOnFileStore(IWorkbenchPage page, IFileStore fileStore) throws PartInitException { 1362 //sanity checks 1363 if (page == null) { 1364 throw new IllegalArgumentException(); 1365 } 1366 1367 IEditorInput input = getEditorInput(fileStore); 1368 String editorId; 1369 try { 1370 editorId = getEditorDescriptorForFileStore(fileStore, true).getId(); 1371 } catch (OperationCanceledException ex) { 1372 return null; 1373 } 1374 1375 // open the editor on the file 1376 return page.openEditor(input, editorId); 1377 } 1378 1379 /** 1380 * Opens an internal editor on the given IFileStore object. 1381 * <p> 1382 * Unlike the other <code>openEditor</code> methods, this one can be used to 1383 * open files that reside outside the workspace resource set. 1384 * </p> 1385 * <p> 1386 * If the page already has an editor open on the target object then that 1387 * editor is brought to front; otherwise, a new editor is opened. 1388 * </p> 1389 * 1390 * @param page 1391 * the page in which the editor will be opened 1392 * @param fileStore 1393 * the IFileStore representing the file to open 1394 * @return an open editor or <code>null</code> if an external editor was 1395 * opened 1396 * @exception PartInitException 1397 * if no internal editor can be found or if the editor could 1398 * not be initialized 1399 * @see org.eclipse.ui.IWorkbenchPage#openEditor(IEditorInput, String) 1400 * @since 3.6 1401 */ openInternalEditorOnFileStore(IWorkbenchPage page, IFileStore fileStore)1402 public static IEditorPart openInternalEditorOnFileStore(IWorkbenchPage page, IFileStore fileStore) throws PartInitException { 1403 if (page == null) 1404 throw new IllegalArgumentException(); 1405 if (fileStore == null) 1406 throw new IllegalArgumentException(); 1407 1408 IEditorInput input = getEditorInput(fileStore); 1409 String name = fileStore.fetchInfo().getName(); 1410 if (name == null) 1411 throw new IllegalArgumentException(); 1412 1413 IContentType[] contentTypes = null; 1414 InputStream is = null; 1415 try { 1416 is = fileStore.openInputStream(EFS.NONE, null); 1417 contentTypes = Platform.getContentTypeManager().findContentTypesFor(is, name); 1418 } catch (CoreException | IOException ex) { 1419 // it's OK, ignore 1420 } finally { 1421 if (is != null) { 1422 try { 1423 is.close(); 1424 } catch (IOException e) { 1425 // nothing good can be done here, ignore 1426 } 1427 } 1428 } 1429 1430 IEditorRegistry editorReg = PlatformUI.getWorkbench().getEditorRegistry(); 1431 if (contentTypes != null) { 1432 for (IContentType contentType : contentTypes) { 1433 IEditorDescriptor editorDesc = editorReg.getDefaultEditor(name, contentType); 1434 editorDesc = overrideDefaultEditorAssociation(input, contentType, editorDesc); 1435 if ((editorDesc != null) && (editorDesc.isInternal())) 1436 return page.openEditor(input, editorDesc.getId()); 1437 } 1438 } 1439 1440 // no content types are available, use file name associations 1441 IEditorDescriptor[] editors = editorReg.getEditors(name); 1442 if (editors != null) { 1443 editors = overrideEditorAssociations(input, null, editors); 1444 for (IEditorDescriptor editor : editors) { 1445 if ((editor != null) && (editor.isInternal())) 1446 return page.openEditor(input, editor.getId()); 1447 } 1448 } 1449 1450 // fallback to the default text editor 1451 IEditorDescriptor textEditor = editorReg.findEditor(IDEWorkbenchPlugin.DEFAULT_TEXT_EDITOR_ID); 1452 if (textEditor == null) 1453 throw new PartInitException(IDEWorkbenchMessages.IDE_noFileEditorFound); 1454 return page.openEditor(input, textEditor.getId()); 1455 } 1456 1457 /** 1458 * Save all dirty editors in the workbench whose editor input is a child 1459 * resource of one of the <code>IResource</code>'s provided. Opens a 1460 * dialog to prompt the user if <code>confirm</code> is true. Return true 1461 * if successful. Return false if the user has canceled the command. 1462 * 1463 * @since 3.0 1464 * 1465 * @param resourceRoots the resource roots under which editor input should 1466 * be saved, other will be left dirty 1467 * @param confirm <code>true</code> to ask the user before saving unsaved 1468 * changes (recommended), and <code>false</code> to save 1469 * unsaved changes without asking 1470 * @return <code>true</code> if the command succeeded, and 1471 * <code>false</code> if the operation was canceled by the user or 1472 * an error occurred while saving 1473 */ saveAllEditors(final IResource[] resourceRoots, final boolean confirm)1474 public static boolean saveAllEditors(final IResource[] resourceRoots, 1475 final boolean confirm) { 1476 1477 if (resourceRoots.length == 0) { 1478 return true; 1479 } 1480 1481 final boolean[] result = new boolean[] { true }; 1482 SafeRunner.run(new SafeRunnable(IDEWorkbenchMessages.ErrorOnSaveAll) { 1483 @Override 1484 public void run() { 1485 IWorkbenchWindow w = PlatformUI.getWorkbench() 1486 .getActiveWorkbenchWindow(); 1487 if (w == null) { 1488 IWorkbenchWindow[] windows = PlatformUI.getWorkbench() 1489 .getWorkbenchWindows(); 1490 if (windows.length > 0) 1491 w = windows[0]; 1492 } 1493 if (w != null) { 1494 result[0] = PlatformUI.getWorkbench().saveAll(w, w, 1495 new ResourceSaveableFilter(resourceRoots), confirm); 1496 } 1497 } 1498 }); 1499 return result[0]; 1500 } 1501 1502 /** 1503 * Sets the default editor id for a given file. This value will be used to 1504 * determine the default editor descriptor for the file in future calls to 1505 * <code>getDefaultEditor(IFile)</code>. 1506 * 1507 * @param file 1508 * the file 1509 * @param editorID 1510 * the editor id 1511 */ setDefaultEditor(IFile file, String editorID)1512 public static void setDefaultEditor(IFile file, String editorID) { 1513 try { 1514 file.setPersistentProperty(EDITOR_KEY, editorID); 1515 } catch (CoreException e) { 1516 // do nothing 1517 } 1518 } 1519 1520 /** 1521 * Returns the default editor for a given file. This method will attempt to 1522 * resolve the editor based on content-type bindings as well as traditional 1523 * name/extension bindings. 1524 * <p> 1525 * A default editor id may be registered for a specific file using 1526 * <code>setDefaultEditor</code>. If the given file has a registered 1527 * default editor id the default editor will derived from it. If not, the 1528 * default editor is determined by taking the file name for the file and 1529 * obtaining the default editor for that name. 1530 * </p> 1531 * 1532 * @param file 1533 * the file 1534 * @return the descriptor of the default editor, or <code>null</code> if 1535 * not found 1536 */ getDefaultEditor(IFile file)1537 public static IEditorDescriptor getDefaultEditor(IFile file) { 1538 return getDefaultEditor(file, true); 1539 } 1540 1541 /** 1542 * Returns the default editor for a given file. This method will attempt to 1543 * resolve the editor based on content-type bindings as well as traditional 1544 * name/extension bindings if <code>determineContentType</code> is 1545 * <code>true</code>. 1546 * <p> 1547 * A default editor id may be registered for a specific file using 1548 * <code>setDefaultEditor</code>. If the given file has a registered 1549 * default editor id the default editor will derived from it. If not, the 1550 * default editor is determined by taking the file name for the file and 1551 * obtaining the default editor for that name. 1552 * </p> 1553 * 1554 * @param file 1555 * the file 1556 * @param determineContentType 1557 * determine the content type for the given file 1558 * @return the descriptor of the default editor, or <code>null</code> if 1559 * not found 1560 * @since 3.1 1561 */ getDefaultEditor(IFile file, boolean determineContentType)1562 public static IEditorDescriptor getDefaultEditor(IFile file, 1563 boolean determineContentType) { 1564 // Try file specific editor. 1565 IEditorRegistry editorReg = PlatformUI.getWorkbench() 1566 .getEditorRegistry(); 1567 1568 IContentType contentType = null; 1569 if (determineContentType) { 1570 contentType = getContentType(file); 1571 } 1572 1573 try { 1574 String editorID = file.getPersistentProperty(EDITOR_KEY); 1575 if (editorID != null) { 1576 IEditorDescriptor desc = editorReg.findEditor(editorID); 1577 if (desc != null) { 1578 return overrideDefaultEditorAssociation(new FileEditorInput(file), contentType, desc); 1579 } 1580 } 1581 } catch (CoreException e) { 1582 // do nothing 1583 } 1584 1585 // Try lookup with filename 1586 IEditorDescriptor desc = editorReg.getDefaultEditor(file.getName(), contentType); 1587 return overrideDefaultEditorAssociation(new FileEditorInput(file), contentType, desc); 1588 } 1589 1590 /** 1591 * Extracts and returns the <code>IResource</code>s in the given 1592 * selection or the resource objects they adapts to. 1593 * 1594 * @param originalSelection 1595 * the original selection, possibly empty 1596 * @return list of resources (element type: <code>IResource</code>), 1597 * possibly empty 1598 */ computeSelectedResources(IStructuredSelection originalSelection)1599 public static List<IResource> computeSelectedResources(IStructuredSelection originalSelection) { 1600 List<IResource> resources = null; 1601 for (Object next : originalSelection) { 1602 IResource resource = Adapters.adapt(next, IResource.class); 1603 if (resource != null) { 1604 if (resources == null) { 1605 // lazy init to avoid creating empty lists 1606 // assume selection contains mostly resources most times 1607 resources = new ArrayList<>(originalSelection.size()); 1608 } 1609 resources.add(resource); 1610 } 1611 } 1612 if (resources == null) { 1613 return Collections.emptyList(); 1614 } 1615 return resources; 1616 1617 } 1618 1619 /** 1620 * Return the content type for the given file. 1621 * 1622 * @param file 1623 * the file to test 1624 * @return the content type, or <code>null</code> if it cannot be 1625 * determined. 1626 * @since 3.1 1627 */ getContentType(IFile file)1628 public static IContentType getContentType(IFile file) { 1629 try { 1630 UIStats.start(UIStats.CONTENT_TYPE_LOOKUP, file.getName()); 1631 IContentDescription contentDescription = file 1632 .getContentDescription(); 1633 if (contentDescription == null) { 1634 return null; 1635 } 1636 return contentDescription.getContentType(); 1637 } catch (CoreException e) { 1638 if (e.getStatus().getCode() == IResourceStatus.OUT_OF_SYNC_LOCAL) { 1639 // Determine the content type from the file name. 1640 return Platform.getContentTypeManager() 1641 .findContentTypeFor(file.getName()); 1642 } 1643 return null; 1644 } finally { 1645 UIStats.end(UIStats.CONTENT_TYPE_LOOKUP, file, file.getName()); 1646 } 1647 } 1648 1649 /** 1650 * Guess at the content type of the given file based on the filename. 1651 * 1652 * @param file 1653 * the file to test 1654 * @return the content type, or <code>null</code> if it cannot be 1655 * determined. 1656 * @since 3.2 1657 */ guessContentType(IFile file)1658 public static IContentType guessContentType(IFile file) { 1659 String fileName = file.getName(); 1660 try { 1661 UIStats.start(UIStats.CONTENT_TYPE_LOOKUP, fileName); 1662 IContentTypeMatcher matcher = file.getProject() 1663 .getContentTypeMatcher(); 1664 return matcher.findContentTypeFor(fileName); 1665 } catch (CoreException e) { 1666 return null; 1667 } finally { 1668 UIStats.end(UIStats.CONTENT_TYPE_LOOKUP, file, fileName); 1669 } 1670 } 1671 1672 /** 1673 * Prompt the user to inform them of the possible side effects of an 1674 * operation on resources. Do not prompt for side effects from ignored model 1675 * providers. A model provider can be ignored if it is the client calling 1676 * this API. Any message from the provided model provider id or any model 1677 * providers it extends will be ignored. 1678 * 1679 * @param shell 1680 * the shell to parent the prompt dialog 1681 * @param title 1682 * the title of the dialog 1683 * @param message 1684 * the message for the dialog 1685 * @param delta 1686 * a delta built using an 1687 * {@link IResourceChangeDescriptionFactory} 1688 * @param ignoreModelProviderIds 1689 * model providers to be ignored 1690 * @param syncExec 1691 * prompt in a sync exec (required when called from a non-UI 1692 * thread) 1693 * @return whether the user chose to continue 1694 * @since 3.2 1695 */ promptToConfirm(final Shell shell, final String title, String message, IResourceDelta delta, String[] ignoreModelProviderIds, boolean syncExec)1696 public static boolean promptToConfirm(final Shell shell, 1697 final String title, String message, IResourceDelta delta, 1698 String[] ignoreModelProviderIds, boolean syncExec) { 1699 IStatus status = ResourceChangeValidator.getValidator().validateChange( 1700 delta, null); 1701 if (status.isOK()) { 1702 return true; 1703 } 1704 final IStatus displayStatus; 1705 if (status.isMultiStatus()) { 1706 List<IStatus> result = new ArrayList<>(); 1707 IStatus[] children = status.getChildren(); 1708 for (IStatus child : children) { 1709 if (!isIgnoredStatus(child, ignoreModelProviderIds)) { 1710 result.add(child); 1711 } 1712 } 1713 if (result.isEmpty()) { 1714 return true; 1715 } 1716 if (result.size() == 1) { 1717 displayStatus = result.get(0); 1718 } else { 1719 displayStatus = new MultiStatus(status.getPlugin(), status.getCode(), 1720 result.toArray(new IStatus[result.size()]), status.getMessage(), status.getException()); 1721 } 1722 } else { 1723 if (isIgnoredStatus(status, ignoreModelProviderIds)) { 1724 return true; 1725 } 1726 displayStatus = status; 1727 } 1728 1729 if (message == null) { 1730 message = IDEWorkbenchMessages.IDE_sideEffectWarning; 1731 } 1732 final String dialogMessage = NLS.bind( 1733 IDEWorkbenchMessages.IDE_areYouSure, message); 1734 1735 final boolean[] result = new boolean[] { false }; 1736 Runnable runnable = () -> { 1737 ErrorDialog dialog = new ErrorDialog(shell, title, 1738 dialogMessage, displayStatus, IStatus.ERROR 1739 | IStatus.WARNING | IStatus.INFO) { 1740 @Override 1741 protected void createButtonsForButtonBar(Composite parent) { 1742 createButton(parent, IDialogConstants.YES_ID, 1743 IDialogConstants.YES_LABEL, false); 1744 createButton(parent, IDialogConstants.NO_ID, 1745 IDialogConstants.NO_LABEL, true); 1746 createDetailsButton(parent); 1747 } 1748 1749 @Override 1750 protected void buttonPressed(int id) { 1751 if (id == IDialogConstants.YES_ID) { 1752 super.buttonPressed(IDialogConstants.OK_ID); 1753 } else if (id == IDialogConstants.NO_ID) { 1754 super.buttonPressed(IDialogConstants.CANCEL_ID); 1755 } 1756 super.buttonPressed(id); 1757 } 1758 @Override 1759 protected int getShellStyle() { 1760 return super.getShellStyle() | SWT.SHEET; 1761 } 1762 }; 1763 int code = dialog.open(); 1764 result[0] = code == 0; 1765 }; 1766 if (syncExec) { 1767 shell.getDisplay().syncExec(runnable); 1768 } else { 1769 runnable.run(); 1770 } 1771 return result[0]; 1772 } 1773 1774 /** 1775 * Register workbench adapters programmatically. This is necessary to enable 1776 * certain types of content in the explorers. 1777 * <p> 1778 * <b>Note:</b> this method should only be called once, in your 1779 * application's WorkbenchAdvisor#initialize(IWorkbenchConfigurer) method. 1780 * </p> 1781 * 1782 * @since 3.5 1783 */ registerAdapters()1784 public static void registerAdapters() { 1785 IAdapterManager manager = Platform.getAdapterManager(); 1786 IAdapterFactory factory = new WorkbenchAdapterFactory(); 1787 manager.registerAdapters(factory, IWorkspace.class); 1788 manager.registerAdapters(factory, IWorkspaceRoot.class); 1789 manager.registerAdapters(factory, IProject.class); 1790 manager.registerAdapters(factory, IFolder.class); 1791 manager.registerAdapters(factory, IFile.class); 1792 manager.registerAdapters(factory, IMarker.class); 1793 1794 // properties adapters 1795 IAdapterFactory paFactory = new StandardPropertiesAdapterFactory(); 1796 manager.registerAdapters(paFactory, IWorkspace.class); 1797 manager.registerAdapters(paFactory, IWorkspaceRoot.class); 1798 manager.registerAdapters(paFactory, IProject.class); 1799 manager.registerAdapters(paFactory, IFolder.class); 1800 manager.registerAdapters(paFactory, IFile.class); 1801 manager.registerAdapters(paFactory, IMarker.class); 1802 manager.registerAdapters(paFactory, IEditorPart.class); 1803 } 1804 isIgnoredStatus(IStatus status, String[] ignoreModelProviderIds)1805 private static boolean isIgnoredStatus(IStatus status, 1806 String[] ignoreModelProviderIds) { 1807 if (ignoreModelProviderIds == null) { 1808 return false; 1809 } 1810 if (status instanceof ModelStatus) { 1811 ModelStatus ms = (ModelStatus) status; 1812 for (String id : ignoreModelProviderIds) { 1813 if (ms.getModelProviderId().equals(id)) { 1814 return true; 1815 } 1816 IModelProviderDescriptor desc = ModelProvider 1817 .getModelProviderDescriptor(id); 1818 String[] extended = desc.getExtendedModels(); 1819 if (isIgnoredStatus(status, extended)) { 1820 return true; 1821 } 1822 } 1823 } 1824 return false; 1825 } 1826 1827 /** 1828 * Opens editors on given file resources. 1829 * <p> 1830 * If the page already has an editor open on the target object then that 1831 * editor is brought to front; otherwise, a new editor is opened. The editor created 1832 * for the first input will be activated. 1833 * </p> 1834 * @param page the page in which the editor will be opened 1835 * @param inputs the inputs for the editors 1836 * @return references to the editors opened; the corresponding editors might not be materialized 1837 * @exception MultiPartInitException if at least one of the editors could not be initialized 1838 * @since 3.5 1839 */ openEditors(IWorkbenchPage page, IFile[] inputs)1840 public static IEditorReference[] openEditors(IWorkbenchPage page, IFile[] inputs) throws MultiPartInitException { 1841 if ((page == null) || (inputs == null)) 1842 throw new IllegalArgumentException(); 1843 1844 String[] editorDescriptions = new String[inputs.length]; 1845 IEditorInput[] editorInputs = new IEditorInput[inputs.length]; 1846 for(int i = 0 ; i < inputs.length; i++) { 1847 editorInputs[i] = new FileEditorInput(inputs[i]); 1848 try { 1849 editorDescriptions[i] = getEditorDescriptor(inputs[i], true, true).getId(); 1850 } catch (PartInitException e) { 1851 PartInitException[] exceptions = new PartInitException[inputs.length]; 1852 exceptions[i] = e; 1853 throw new MultiPartInitException(new IWorkbenchPartReference[inputs.length], exceptions); 1854 } 1855 } 1856 return page.openEditors(editorInputs, editorDescriptions, IWorkbenchPage.MATCH_INPUT); 1857 } 1858 getEditorAssociationOverrides()1859 private static IEditorAssociationOverride[] getEditorAssociationOverrides() { 1860 if (editorAssociationOverrides == null) { 1861 EditorAssociationOverrideDescriptor[] descriptors = EditorAssociationOverrideDescriptor.getContributedEditorAssociationOverrides(); 1862 List<IEditorAssociationOverride> overrides = new ArrayList<>(descriptors.length); 1863 for (EditorAssociationOverrideDescriptor descriptor : descriptors) { 1864 try { 1865 IEditorAssociationOverride override = descriptor.createOverride(); 1866 overrides.add(override); 1867 } catch (CoreException e) { 1868 IDEWorkbenchPlugin 1869 .log("Error while creating IEditorAssociationOverride from: " + descriptor.getId(), e); //$NON-NLS-1$ 1870 } 1871 } 1872 editorAssociationOverrides = overrides.toArray(new IEditorAssociationOverride[overrides.size()]); 1873 } 1874 return editorAssociationOverrides; 1875 } 1876 } 1877