org.eclipse.compare.internal.CompareUIPlugin Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2000, 2015 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Carsten Pfeiffer - CompareUIPlugin.getCommonType() returns null if left or right side is not available - https://bugs.eclipse.org/311843
* Stefan Xenos (Google) - bug 448968 - Add diagnostic logging
*******************************************************************************/
package org.eclipse.compare.internal;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.StringTokenizer;
import org.eclipse.compare.CompareConfiguration;
import org.eclipse.compare.CompareEditorInput;
import org.eclipse.compare.IResourceProvider;
import org.eclipse.compare.IStreamContentAccessor;
import org.eclipse.compare.IStreamMerger;
import org.eclipse.compare.ITypedElement;
import org.eclipse.compare.internal.core.ComparePlugin;
import org.eclipse.compare.structuremergeviewer.ICompareInput;
import org.eclipse.compare.structuremergeviewer.IStructureCreator;
import org.eclipse.compare.structuremergeviewer.StructureDiffViewer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Adapters;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.content.IContentDescription;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.core.runtime.content.IContentTypeManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.osgi.service.debug.DebugOptions;
import org.eclipse.osgi.service.debug.DebugOptionsListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorRegistry;
import org.eclipse.ui.IReusableEditor;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.model.IWorkbenchAdapter;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
/**
* The Compare UI plug-in defines the entry point to initiate a configurable
* compare operation on arbitrary resources. The result of the compare
* is opened into a compare editor where the details can be browsed and
* edited in dynamically selected structure and content viewers.
*
* The Compare UI provides a registry for content and structure compare viewers,
* which is initialized from extensions contributed to extension points
* declared by this plug-in.
*
* This class is the plug-in runtime class for the
* "org.eclipse.compare"
plug-in.
*
*/
public final class CompareUIPlugin extends AbstractUIPlugin {
static class CompareRegistry {
private final static String ID_ATTRIBUTE= "id"; //$NON-NLS-1$
private final static String EXTENSIONS_ATTRIBUTE= "extensions"; //$NON-NLS-1$
private final static String CONTENT_TYPE_ID_ATTRIBUTE= "contentTypeId"; //$NON-NLS-1$
private HashMap fIdMap; // maps ids to data
private HashMap> fExtensionMap; // multimap: maps extensions to list of data
private HashMap> fContentTypeBindings; // multimap: maps content type bindings to list of data
void register(IConfigurationElement element, T data) {
String id= element.getAttribute(ID_ATTRIBUTE);
if (id != null) {
if (fIdMap == null)
fIdMap= new HashMap<>();
fIdMap.put(id, data);
}
String types= element.getAttribute(EXTENSIONS_ATTRIBUTE);
if (types != null) {
if (fExtensionMap == null)
fExtensionMap= new HashMap<>();
StringTokenizer tokenizer= new StringTokenizer(types, ","); //$NON-NLS-1$
while (tokenizer.hasMoreElements()) {
String extension= tokenizer.nextToken().trim();
List l = fExtensionMap.get(normalizeCase(extension));
if (l == null)
fExtensionMap.put(normalizeCase(extension), l = new ArrayList<>());
l.add(data);
}
}
}
void createBinding(IConfigurationElement element, String idAttributeName) {
String type= element.getAttribute(CONTENT_TYPE_ID_ATTRIBUTE);
String id= element.getAttribute(idAttributeName);
if (id == null)
logErrorMessage(Utilities.getFormattedString("CompareUIPlugin.targetIdAttributeMissing", idAttributeName)); //$NON-NLS-1$
if (type != null && id != null && fIdMap != null) {
T o= fIdMap.get(id);
if (o != null) {
IContentType ct= fgContentTypeManager.getContentType(type);
if (ct != null) {
if (fContentTypeBindings == null)
fContentTypeBindings= new HashMap<>();
List l = fContentTypeBindings.get(ct);
if (l == null)
fContentTypeBindings.put(ct, l = new ArrayList<>());
l.add(o);
} else {
logErrorMessage(Utilities.getFormattedString("CompareUIPlugin.contentTypeNotFound", type)); //$NON-NLS-1$
}
} else {
logErrorMessage(Utilities.getFormattedString("CompareUIPlugin.targetNotFound", id)); //$NON-NLS-1$
}
}
}
T search(IContentType type) {
List list = searchAll(type);
return list != null ? list.get(0) : null;
}
List searchAll(IContentType type) {
if (fContentTypeBindings != null) {
for (; type != null; type= type.getBaseType()) {
List data= fContentTypeBindings.get(type);
if (data != null)
return data;
}
}
return null;
}
T search(String extension) {
List list = searchAll(extension);
return list != null ? list.get(0) : null;
}
List searchAll(String extension) {
if (fExtensionMap != null)
return fExtensionMap.get(normalizeCase(extension));
return null;
}
}
/** Status code describing an internal error */
public static final int INTERNAL_ERROR= 1;
private static boolean NORMALIZE_CASE= true;
public static final String PLUGIN_ID= "org.eclipse.compare"; //$NON-NLS-1$
private static final String BINARY_TYPE= "binary"; //$NON-NLS-1$
private static final String STREAM_MERGER_EXTENSION_POINT= "streamMergers"; //$NON-NLS-1$
private static final String STREAM_MERGER= "streamMerger"; //$NON-NLS-1$
private static final String STREAM_MERGER_ID_ATTRIBUTE= "streamMergerId"; //$NON-NLS-1$
private static final String STRUCTURE_CREATOR_EXTENSION_POINT= "structureCreators"; //$NON-NLS-1$
private static final String STRUCTURE_CREATOR= "structureCreator"; //$NON-NLS-1$
private static final String STRUCTURE_CREATOR_ID_ATTRIBUTE= "structureCreatorId"; //$NON-NLS-1$
private static final String VIEWER_TAG= "viewer"; //$NON-NLS-1$
private static final String FILTER_TAG = "filter"; //$NON-NLS-1$
private static final String STRUCTURE_MERGE_VIEWER_EXTENSION_POINT= "structureMergeViewers"; //$NON-NLS-1$
private static final String STRUCTURE_MERGE_VIEWER_ID_ATTRIBUTE= "structureMergeViewerId"; //$NON-NLS-1$
private static final String CONTENT_MERGE_VIEWER_EXTENSION_POINT= "contentMergeViewers"; //$NON-NLS-1$
private static final String COMPARE_FILTER_EXTENTION_POINT = "compareFilters"; //$NON-NLS-1$
private static final String COMPARE_FILTER_ID_ATTRIBUTE = "filterId"; //$NON-NLS-1$
private static final String CONTENT_MERGE_VIEWER_ID_ATTRIBUTE= "contentMergeViewerId"; //$NON-NLS-1$
private static final String CONTENT_VIEWER_EXTENSION_POINT= "contentViewers"; //$NON-NLS-1$
private static final String CONTENT_VIEWER_ID_ATTRIBUTE= "contentViewerId"; //$NON-NLS-1$
private static final String CONTENT_TYPE_BINDING= "contentTypeBinding"; //$NON-NLS-1$
private static final String COMPARE_EDITOR= PLUGIN_ID + ".CompareEditor"; //$NON-NLS-1$
private static final String STRUCTUREVIEWER_ALIASES_PREFERENCE_NAME= "StructureViewerAliases"; //$NON-NLS-1$
// content type
private static final IContentTypeManager fgContentTypeManager= Platform.getContentTypeManager();
public static final int NO_DIFFERENCE = 10000;
/**
* The plugin singleton.
*/
private static CompareUIPlugin fgComparePlugin;
/** Maps type to icons */
private static Map fgImages= new Hashtable(10);
/** Maps type to ImageDescriptors */
private static Map fgImageDescriptors= new Hashtable(10);
/** Maps ImageDescriptors to Images */
private static Map fgImages2= new Hashtable(10);
private static List fgDisposeOnShutdownImages= new ArrayList();
private ResourceBundle fResourceBundle;
private boolean fRegistriesInitialized;
private CompareRegistry fStreamMergers= new CompareRegistry<>();
private CompareRegistry fStructureCreators= new CompareRegistry<>();
private CompareRegistry fStructureMergeViewers= new CompareRegistry<>();
private CompareRegistry fContentViewers= new CompareRegistry<>();
private CompareRegistry fContentMergeViewers= new CompareRegistry<>();
private CompareRegistry fCompareFilters = new CompareRegistry<>();
private Map fStructureViewerAliases;
private CompareResourceFilter fFilter;
private IPropertyChangeListener fPropertyChangeListener;
private ServiceRegistration debugRegistration;
/**
* Creates the CompareUIPlugin
object and registers all
* structure creators, content merge viewers, and structure merge viewers
* contributed to this plug-in's extension points.
*
* Note that instances of plug-in runtime classes are automatically created
* by the platform in the course of plug-in activation.
*/
public CompareUIPlugin() {
super();
Assert.isTrue(fgComparePlugin == null);
fgComparePlugin= this;
}
@Override
public void start(BundleContext context) throws Exception {
super.start(context);
Hashtable properties = new Hashtable<>(2);
properties.put(DebugOptions.LISTENER_SYMBOLICNAME, PLUGIN_ID);
debugRegistration = context.registerService(DebugOptionsListener.class, Policy.DEBUG_OPTIONS_LISTENER,
properties);
ComparePlugin.getDefault().setCappingDisabled(
getPreferenceStore().getBoolean(
ComparePreferencePage.CAPPING_DISABLED));
}
@Override
public void stop(BundleContext context) throws Exception {
IPreferenceStore ps= getPreferenceStore();
rememberAliases(ps);
if (fPropertyChangeListener != null) {
ps.removePropertyChangeListener(fPropertyChangeListener);
fPropertyChangeListener= null;
}
super.stop(context);
if (fgDisposeOnShutdownImages != null) {
Iterator i= fgDisposeOnShutdownImages.iterator();
while (i.hasNext()) {
Image img= i.next();
if (!img.isDisposed())
img.dispose();
}
fgImages= null;
}
if (debugRegistration != null) {
debugRegistration.unregister();
debugRegistration = null;
}
}
/**
* Returns the singleton instance of this plug-in runtime class.
*
* @return the compare plug-in instance
*/
public static CompareUIPlugin getDefault() {
return fgComparePlugin;
}
/**
* Returns this plug-in's resource bundle.
*
* @return the plugin's resource bundle
*/
public ResourceBundle getResourceBundle() {
if (fResourceBundle == null)
fResourceBundle= Platform.getResourceBundle(getBundle());
return fResourceBundle;
}
/**
* Returns this plug-in's unique identifier.
*
* @return the plugin's unique identifier
*/
public static String getPluginId() {
return getDefault().getBundle().getSymbolicName();
}
private void initializeRegistries() {
if (!fRegistriesInitialized) {
registerExtensions();
fRegistriesInitialized= true;
}
}
/**
* Registers all stream mergers, structure creators, content merge viewers, and structure merge viewers
* that are found in the XML plugin files.
*/
private void registerExtensions() {
IExtensionRegistry registry= Platform.getExtensionRegistry();
// collect all IStreamMergers
IConfigurationElement[] elements= registry.getConfigurationElementsFor(PLUGIN_ID, STREAM_MERGER_EXTENSION_POINT);
for (int i= 0; i < elements.length; i++) {
IConfigurationElement element= elements[i];
if (STREAM_MERGER.equals(element.getName()))
fStreamMergers.register(element, new StreamMergerDescriptor(element));
}
for (int i= 0; i < elements.length; i++) {
IConfigurationElement element= elements[i];
if (CONTENT_TYPE_BINDING.equals(element.getName()))
fStreamMergers.createBinding(element, STREAM_MERGER_ID_ATTRIBUTE);
}
// collect all IStructureCreators
elements= registry.getConfigurationElementsFor(PLUGIN_ID, STRUCTURE_CREATOR_EXTENSION_POINT);
for (int i= 0; i < elements.length; i++) {
IConfigurationElement element= elements[i];
String name= element.getName();
if (!CONTENT_TYPE_BINDING.equals(name)) {
if (!STRUCTURE_CREATOR.equals(name))
logErrorMessage(Utilities.getFormattedString("CompareUIPlugin.unexpectedTag", name, STRUCTURE_CREATOR)); //$NON-NLS-1$
fStructureCreators.register(element, new StructureCreatorDescriptor(element));
}
}
for (int i= 0; i < elements.length; i++) {
IConfigurationElement element= elements[i];
if (CONTENT_TYPE_BINDING.equals(element.getName()))
fStructureCreators.createBinding(element, STRUCTURE_CREATOR_ID_ATTRIBUTE);
}
// collect all viewers which define the structure merge viewer extension point
elements= registry.getConfigurationElementsFor(PLUGIN_ID, STRUCTURE_MERGE_VIEWER_EXTENSION_POINT);
for (int i= 0; i < elements.length; i++) {
IConfigurationElement element= elements[i];
String name= element.getName();
if (!CONTENT_TYPE_BINDING.equals(name)) {
if (!VIEWER_TAG.equals(name))
logErrorMessage(Utilities.getFormattedString("CompareUIPlugin.unexpectedTag", name, VIEWER_TAG)); //$NON-NLS-1$
fStructureMergeViewers.register(element, new ViewerDescriptor(element));
}
}
for (int i= 0; i < elements.length; i++) {
IConfigurationElement element= elements[i];
if (CONTENT_TYPE_BINDING.equals(element.getName()))
fStructureMergeViewers.createBinding(element, STRUCTURE_MERGE_VIEWER_ID_ATTRIBUTE);
}
// collect all viewers which define the content merge viewer extension point
elements= registry.getConfigurationElementsFor(PLUGIN_ID, CONTENT_MERGE_VIEWER_EXTENSION_POINT);
for (int i= 0; i < elements.length; i++) {
IConfigurationElement element= elements[i];
String name= element.getName();
if (!CONTENT_TYPE_BINDING.equals(name)) {
if (!VIEWER_TAG.equals(name))
logErrorMessage(Utilities.getFormattedString("CompareUIPlugin.unexpectedTag", name, VIEWER_TAG)); //$NON-NLS-1$
fContentMergeViewers.register(element, new ViewerDescriptor(element));
}
}
for (int i= 0; i < elements.length; i++) {
IConfigurationElement element= elements[i];
if (CONTENT_TYPE_BINDING.equals(element.getName()))
fContentMergeViewers.createBinding(element, CONTENT_MERGE_VIEWER_ID_ATTRIBUTE);
}
// collect all extensions that define the compare filter extension point
elements = registry.getConfigurationElementsFor(PLUGIN_ID,
COMPARE_FILTER_EXTENTION_POINT);
for (int i = 0; i < elements.length; i++) {
IConfigurationElement element = elements[i];
String name = element.getName();
if (!CONTENT_TYPE_BINDING.equals(name)) {
if (!FILTER_TAG.equals(name))
logErrorMessage(Utilities.getFormattedString(
"CompareUIPlugin.unexpectedTag", name, FILTER_TAG)); //$NON-NLS-1$
fCompareFilters.register(element, new CompareFilterDescriptor(element));
}
}
for (int i = 0; i < elements.length; i++) {
IConfigurationElement element = elements[i];
if (CONTENT_TYPE_BINDING.equals(element.getName()))
fCompareFilters.createBinding(element,
COMPARE_FILTER_ID_ATTRIBUTE);
}
// collect all viewers which define the content viewer extension point
elements= registry.getConfigurationElementsFor(PLUGIN_ID, CONTENT_VIEWER_EXTENSION_POINT);
for (int i= 0; i < elements.length; i++) {
IConfigurationElement element= elements[i];
String name= element.getName();
if (!CONTENT_TYPE_BINDING.equals(name)) {
if (!VIEWER_TAG.equals(name))
logErrorMessage(Utilities.getFormattedString("CompareUIPlugin.unexpectedTag", name, VIEWER_TAG)); //$NON-NLS-1$
fContentViewers.register(element, new ViewerDescriptor(element));
}
}
for (int i= 0; i < elements.length; i++) {
IConfigurationElement element= elements[i];
if (CONTENT_TYPE_BINDING.equals(element.getName()))
fContentViewers.createBinding(element, CONTENT_VIEWER_ID_ATTRIBUTE);
}
}
public static IWorkbench getActiveWorkbench() {
CompareUIPlugin plugin= getDefault();
if (plugin == null)
return null;
return plugin.getWorkbench();
}
public static IWorkbenchWindow getActiveWorkbenchWindow() {
IWorkbench workbench= getActiveWorkbench();
if (workbench == null)
return null;
return workbench.getActiveWorkbenchWindow();
}
/**
* Returns the active workbench page or null
if
* no active workbench page can be determined.
*
* @return the active workbench page or null
if
* no active workbench page can be determined
*/
private static IWorkbenchPage getActivePage() {
IWorkbenchWindow window= getActiveWorkbenchWindow();
if (window == null)
return null;
return window.getActivePage();
}
/**
* Returns the SWT Shell of the active workbench window or null
if
* no workbench window is active.
*
* @return the SWT Shell of the active workbench window, or null
if
* no workbench window is active
*/
public static Shell getShell() {
IWorkbenchWindow window = getActiveWorkbenchWindow();
if (window == null)
return null;
return window.getShell();
}
/**
* Registers the given image for being disposed when this plug-in is shutdown.
*
* @param image the image to register for disposal
*/
public static void disposeOnShutdown(Image image) {
if (image != null)
fgDisposeOnShutdownImages.add(image);
}
/**
* Performs the comparison described by the given input and opens a compare
* editor on the result.
*
* @param input
* the input on which to open the compare editor
* @param page
* the workbench page on which to create a new compare editor
* @param editor
* if not null the input is opened in this editor
* @param activate
* if true
the editor will be activated
* @see IWorkbenchPage#openEditor(org.eclipse.ui.IEditorInput, String,
* boolean)
* @see CompareEditorInput
*/
public void openCompareEditor(final CompareEditorInput input,
final IWorkbenchPage page, final IReusableEditor editor,
final boolean activate) {
CompareConfiguration configuration = input.getCompareConfiguration();
if (configuration != null) {
IPreferenceStore ps= configuration.getPreferenceStore();
if (ps != null)
configuration.setProperty(
CompareConfiguration.USE_OUTLINE_VIEW,
Boolean.valueOf(ps.getBoolean(ComparePreferencePage.USE_OUTLINE_VIEW)));
}
if (input.canRunAsJob()) {
openEditorInBackground(input, page, editor, activate);
} else {
if (compareResultOK(input, null)) {
internalOpenEditor(input, page, editor, activate);
}
}
}
private void openEditorInBackground(final CompareEditorInput input,
final IWorkbenchPage page, final IReusableEditor editor,
final boolean activate) {
internalOpenEditor(input, page, editor, activate);
}
private void internalOpenEditor(final CompareEditorInput input,
final IWorkbenchPage wp, final IReusableEditor editor,
final boolean activate) {
Runnable runnable = new Runnable() {
@Override
public void run() {
if (editor != null && !editor.getSite().getShell().isDisposed()) { // reuse the given editor
editor.setInput(input);
return;
}
IWorkbenchPage page = wp;
if (page == null)
page= getActivePage();
if (page != null) {
// open new CompareEditor on page
try {
page.openEditor(input, COMPARE_EDITOR, activate);
} catch (PartInitException e) {
MessageDialog.openError(getShell(), Utilities.getString("CompareUIPlugin.openEditorError"), e.getMessage()); //$NON-NLS-1$
}
} else {
MessageDialog.openError(getShell(),
Utilities.getString("CompareUIPlugin.openEditorError"), //$NON-NLS-1$
Utilities.getString("CompareUIPlugin.noActiveWorkbenchPage")); //$NON-NLS-1$
}
}
};
syncExec(runnable);
}
/**
* Performs the comparison described by the given input and opens a
* compare dialog on the result.
*
* @param input the input on which to open the compare editor
* @see CompareEditorInput
*/
public void openCompareDialog(final CompareEditorInput input) {
// We don't ever open dialogs in the background
if (compareResultOK(input, null)) {
internalOpenDialog(input);
}
}
public IStatus prepareInput(CompareEditorInput input, IProgressMonitor monitor) {
try {
input.run(monitor);
String message= input.getMessage();
if (message != null) {
return new Status(IStatus.ERROR, CompareUIPlugin.PLUGIN_ID, 0, message, null);
}
if (input.getCompareResult() == null) {
return new Status(IStatus.ERROR, CompareUIPlugin.PLUGIN_ID, NO_DIFFERENCE, Utilities.getString("CompareUIPlugin.noDifferences"), null); //$NON-NLS-1$
}
return Status.OK_STATUS;
} catch (InterruptedException e) {
throw new OperationCanceledException();
} catch (InvocationTargetException e) {
return new Status(IStatus.ERROR, CompareUIPlugin.PLUGIN_ID, 0, Utilities.getString("CompareUIPlugin.compareFailed"), e.getTargetException()); //$NON-NLS-1$
}
}
/*
* @return true
if compare result is OK to show, false
otherwise
*/
public boolean compareResultOK(CompareEditorInput input, IRunnableContext context) {
final Shell shell= getShell();
try {
// run operation in separate thread and make it cancelable
if (context == null)
context = PlatformUI.getWorkbench().getProgressService();
context.run(true, true, input);
String message= input.getMessage();
if (message != null) {
MessageDialog.openError(shell, Utilities.getString("CompareUIPlugin.compareFailed"), message); //$NON-NLS-1$
return false;
}
if (input.getCompareResult() == null) {
MessageDialog.openInformation(shell, Utilities.getString("CompareUIPlugin.dialogTitle"), Utilities.getString("CompareUIPlugin.noDifferences")); //$NON-NLS-2$ //$NON-NLS-1$
return false;
}
return true;
} catch (InterruptedException x) {
// canceled by user
} catch (InvocationTargetException x) {
MessageDialog.openError(shell, Utilities.getString("CompareUIPlugin.compareFailed"), x.getTargetException().getMessage()); //$NON-NLS-1$
}
return false;
}
/*
* Registers an image for the given type.
*/
private static void registerImage(String type, Image image, boolean dispose) {
fgImages.put(normalizeCase(type), image);
if (image != null && dispose) {
fgDisposeOnShutdownImages.add(image);
}
}
/**
* Registers an image descriptor for the given type.
*
* @param type the type
* @param descriptor the image descriptor
*/
public static void registerImageDescriptor(String type, ImageDescriptor descriptor) {
fgImageDescriptors.put(normalizeCase(type), descriptor);
}
public static ImageDescriptor getImageDescriptor(String relativePath) {
if (fgComparePlugin == null)
return null;
IPath path= Utilities.getIconPath(null).append(relativePath);
URL url= FileLocator.find(fgComparePlugin.getBundle(), path, null);
if (url == null)
return null;
return ImageDescriptor.createFromURL(url);
}
/**
* Returns a shared image for the given type, or a generic image if none
* has been registered for the given type.
*
* Note: Images returned from this method will be automatically disposed
* of when this plug-in shuts down. Callers must not dispose of these
* images themselves.
*
*
* @param type the type
* @return the image
*/
public static Image getImage(String type) {
type= normalizeCase(type);
boolean dispose= false;
Image image= null;
if (type != null)
image= fgImages.get(type);
if (image == null) {
ImageDescriptor id= fgImageDescriptors.get(type);
if (id != null) {
image= id.createImage();
dispose= true;
}
if (image == null) {
if (fgComparePlugin != null) {
if (ITypedElement.FOLDER_TYPE.equals(type)) {
image= getDefault().getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER);
//image= SharedImages.getImage(ISharedImages.IMG_OBJ_FOLDER);
} else {
image= createWorkbenchImage(type);
dispose= true;
}
} else {
id= fgImageDescriptors.get(normalizeCase("file")); //$NON-NLS-1$
image= id.createImage();
dispose= true;
}
}
if (image != null)
registerImage(type, image, dispose);
}
return image;
}
/**
* Returns a shared image for the given adaptable.
* This convenience method queries the given adaptable
* for its IWorkbenchAdapter.getImageDescriptor
, which it
* uses to create an image if it does not already have one.
*
* Note: Images returned from this method will be automatically disposed
* of when this plug-in shuts down. Callers must not dispose of these
* images themselves.
*
*
* @param adaptable the adaptable for which to find an image
* @return an image
*/
public static Image getImage(IAdaptable adaptable) {
if (adaptable != null) {
IWorkbenchAdapter o= Adapters.adapt(adaptable, IWorkbenchAdapter.class);
ImageDescriptor id= o.getImageDescriptor(adaptable);
if (id != null) {
Image image= fgImages2.get(id);
if (image == null) {
image= id.createImage();
try {
fgImages2.put(id, image);
} catch (NullPointerException e) {
// NeedWork
}
fgDisposeOnShutdownImages.add(image);
}
return image;
}
}
return null;
}
private static Image createWorkbenchImage(String type) {
IEditorRegistry er= getDefault().getWorkbench().getEditorRegistry();
ImageDescriptor id= er.getImageDescriptor("foo." + type); //$NON-NLS-1$
return id.createImage();
}
/**
* Returns an structure creator descriptor for the given type.
*
* @param type the type for which to find a descriptor
* @return a descriptor for the given type, or null
if no
* descriptor has been registered
*/
public StructureCreatorDescriptor getStructureCreator(String type) {
initializeRegistries();
return fStructureCreators.search(type);
}
/**
* Returns a stream merger for the given type.
*
* @param type the type for which to find a stream merger
* @return a stream merger for the given type, or null
if no
* stream merger has been registered
*/
public IStreamMerger createStreamMerger(String type) {
initializeRegistries();
StreamMergerDescriptor descriptor= fStreamMergers.search(type);
if (descriptor != null)
return descriptor.createStreamMerger();
return null;
}
/**
* Returns a stream merger for the given content type.
*
* @param type the type for which to find a stream merger
* @return a stream merger for the given type, or null
if no
* stream merger has been registered
*/
public IStreamMerger createStreamMerger(IContentType type) {
initializeRegistries();
StreamMergerDescriptor descriptor= fStreamMergers.search(type);
if (descriptor != null)
return descriptor.createStreamMerger();
return null;
}
public ViewerDescriptor[] findStructureViewerDescriptor(Viewer oldViewer,
ICompareInput input, CompareConfiguration configuration) {
if (input == null)
return null;
// we don't show the structure of additions or deletions
if (input == null || input.getLeft() == null || input.getRight() == null)
return null;
Set result = new LinkedHashSet<>();
// content type search
IContentType ctype= getCommonType(input);
if (ctype != null) {
initializeRegistries();
List list = fStructureMergeViewers.searchAll(ctype);
if (list != null)
result.addAll(list);
}
// old style search
String[] types= getTypes(input);
String type= null;
if (isHomogenous(types)) {
type= normalizeCase(types[0]);
initializeRegistries();
List list = fStructureMergeViewers.searchAll(type);
if (list != null)
result.addAll(list);
String alias= getStructureViewerAlias(type);
if (alias != null) {
list = fStructureMergeViewers.searchAll(alias);
if (list != null)
result.addAll(list);
}
}
return result.size() > 0 ? result.toArray(new ViewerDescriptor[0]) : null;
}
/**
* Returns a structure compare viewer based on an old viewer and an input object.
* If the old viewer is suitable for showing the input, the old viewer
* is returned. Otherwise, the input's type is used to find a viewer descriptor in the registry
* which in turn is used to create a structure compare viewer under the given parent composite.
* If no viewer descriptor can be found null
is returned.
*
* @param oldViewer a new viewer is only created if this old viewer cannot show the given input
* @param input the input object for which to find a structure viewer
* @param parent the SWT parent composite under which the new viewer is created
* @param configuration a configuration which is passed to a newly created viewer
* @return the compare viewer which is suitable for the given input object or null
*/
public Viewer findStructureViewer(Viewer oldViewer, ICompareInput input, Composite parent,
CompareConfiguration configuration) {
ViewerDescriptor[] descriptors = findStructureViewerDescriptor(oldViewer, input, configuration);
if (descriptors == null || descriptors.length == 0) {
// we didn't found any viewer so far.
// now we try to find a structure creator for the generic StructureDiffViewer
IContentType ctype= getCommonType(input);
String[] types= getTypes(input);
String type= null;
if (isHomogenous(types)) {
type= normalizeCase(types[0]);
}
initializeRegistries();
StructureCreatorDescriptor scc= fStructureCreators.search(ctype); // search for content type
if (scc == null && type != null)
scc= getStructureCreator(type); // search for old-style type scheme
if (scc != null) {
IStructureCreator sc= scc.createStructureCreator();
if (sc != null) {
StructureDiffViewer sdv= new StructureDiffViewer(parent, configuration);
sdv.setStructureCreator(sc);
return sdv;
}
}
return null;
}
return getViewer(descriptors[0], oldViewer, parent, configuration);
}
public CompareFilterDescriptor[] findCompareFilters(Object in) {
Collection