/**
* Copyright (c) 2005-2007 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 - Initial API and implementation
*/
package org.eclipse.emf.edit.ui.util;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorRegistry;
import org.eclipse.ui.IURIEditorInput;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.emf.common.EMFPlugin;
import org.eclipse.emf.common.ui.URIEditorInput;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.common.util.UniqueEList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.emf.edit.ui.EMFEditUIPlugin;
import org.osgi.framework.Bundle;
/**
* @since 2.2.0
*/
public class EditUIUtil
{
/**
* Opens the default editor for the resource that contains the specified
* EObject. This method only works if the resource's URI is a
* platform resource URI.
*/
public static boolean openEditor(EObject eObject) throws PartInitException
{
if (eObject != null)
{
Resource resource = eObject.eResource();
if (resource != null)
{
URI uri = resource.getURI();
if (uri != null)
{
IEditorInput editorInput = null;
if (uri.isPlatformResource())
{
String path = uri.toPlatformString(true);
IResource workspaceResource = ResourcesPlugin.getWorkspace().getRoot().findMember(new Path(path));
if (workspaceResource instanceof IFile)
{
editorInput = EclipseUtil.createFileEditorInput((IFile)workspaceResource);
}
}
else
{
editorInput = new URIEditorInput(uri);
}
if (editorInput != null)
{
IWorkbench workbench = PlatformUI.getWorkbench();
IWorkbenchPage page = workbench.getActiveWorkbenchWindow().getActivePage();
IEditorPart editorPart = page.openEditor(editorInput, workbench.getEditorRegistry().getDefaultEditor(uri.lastSegment()).getId());
return editorPart != null;
}
}
}
}
return false;
}
public static URI getURI(IEditorInput editorInput)
{
URI result = null;
if (EMFPlugin.IS_ECLIPSE_RUNNING)
{
result = EclipseUtil.getURI(editorInput);
}
if (result == null)
{
if (editorInput instanceof URIEditorInput)
{
result = ((URIEditorInput)editorInput).getURI().trimFragment();
}
else
{
result = URI.createURI(editorInput.getName());
}
}
return result;
}
/**
* Returns the default editor for a given file name. This method is like {@link IEditorRegistry#getDefaultEditor(String)},
* but it will not return <code>null</code> unless all applicable content types have no associated editor.
*
* @param fileName the file name in the system
* @return the descriptor of the default editor, or <code>null</code> if not found
* @since 2.4
*/
public static IEditorDescriptor getDefaultEditor(String fileName)
{
return fileName != null && fileName.length() != 0 ?
getDefaultEditor(fileName, Platform.getContentTypeManager().findContentTypesFor(fileName)) :
null;
}
/**
* Returns the default editor for a given contents and file name.
* <p>
* If a file name is not provided, the entire content type registry will be queried. For performance reasons, it is
* highly recommended to provide a file name if available.
*
* @param contents an input stream
* @param fileName the file name associated to the contents, or <code>null</code>
* @return the descriptor of the default editor, or <code>null</code> if not found
* @since 2.4
*/
public static IEditorDescriptor getDefaultEditor(InputStream contents, String fileName)
{
if (contents != null)
{
try
{
return getDefaultEditor(fileName, Platform.getContentTypeManager().findContentTypesFor(contents, fileName));
}
catch (IOException e)
{
EMFEditUIPlugin.INSTANCE.log(e);
}
}
return getDefaultEditor(fileName);
}
private static IEditorDescriptor getDefaultEditor(String fileName, IContentType[] contentTypes)
{
IEditorRegistry editorRegistry = PlatformUI.getWorkbench().getEditorRegistry();
if (contentTypes.length == 0)
{
return editorRegistry.getDefaultEditor(fileName, null);
}
IEditorDescriptor result = null;
for (int i = 0; result == null && i < contentTypes.length; i++)
{
result = editorRegistry.getDefaultEditor(fileName, contentTypes[i]);
}
return result;
}
/**
* Returns the default editor for a given URI. This method actually attempts to open an input stream for the URI and
* uses its contents, along with the filename (the URI's last segment), to obtain appropriate content types.
* <p>
* If a URI converter is specified, it is used to open the stream. Otherwise, the global default
* {@link URIConverter#INSTANCE instance} is used.
*
* @param uri a URI
* @param uriConverter URI converter from which to obtain an input stream, or <code>null</code>
* @return the descriptor of the default editor, or <code>null</code> if not found
* @since 2.4
*/
public static IEditorDescriptor getDefaultEditor(URI uri, URIConverter uriConverter)
{
String fileName = URI.decode(uri.lastSegment());
if (uriConverter == null)
{
uriConverter = URIConverter.INSTANCE;
}
InputStream stream = null;
try
{
stream = uriConverter.createInputStream(uri);
return getDefaultEditor(stream, fileName);
}
catch (IOException e)
{
EMFEditUIPlugin.INSTANCE.log(e);
return getDefaultEditor(fileName);
}
finally
{
close(stream);
}
}
private static void close(InputStream stream)
{
if (stream != null)
{
try
{
stream.close();
}
catch (IOException e) { EMFEditUIPlugin.INSTANCE.log(e); }
}
}
/**
* Returns the editors for a given file name. This method is like {@link IEditorRegistry#getEditors(String)},
* but its result will include editors for all applicable content types.
*
* @param fileName the file name in the system
* @param defaultsOnly if <code>true</code>, only the default editor for each content type will be included in the result
* @return the descriptors of the editors
* @since 2.4
*/
public static IEditorDescriptor[] getEditors(String fileName, boolean defaultsOnly)
{
return fileName != null && fileName.length() != 0 ?
getEditors(fileName, Platform.getContentTypeManager().findContentTypesFor(fileName), defaultsOnly) :
new IEditorDescriptor[0];
}
/**
* Returns the editors for a given contents and file name.
* <p>
* If a file name is not provided, the entire content type registry will be queried. For performance reasons, it is
* highly recommended to provide a file name if available.
*
* @param contents an input stream
* @param fileName the file name associated to the contents, or <code>null</code>
* @param defaultsOnly if <code>true</code>, only the default editor for each content type will be included in the result
* @return the descriptors of the editors
* @since 2.4
*/
public static IEditorDescriptor[] getEditors(InputStream contents, String fileName, boolean defaultsOnly)
{
if (contents != null)
{
try
{
return getEditors(fileName, Platform.getContentTypeManager().findContentTypesFor(contents, fileName), defaultsOnly);
}
catch (IOException e)
{
EMFEditUIPlugin.INSTANCE.log(e);
}
}
return getEditors(fileName, defaultsOnly);
}
private static IEditorDescriptor[] getEditors(String fileName, IContentType[] contentTypes, boolean defaultsOnly)
{
IEditorRegistry editorRegistry = PlatformUI.getWorkbench().getEditorRegistry();
if (contentTypes.length == 0)
{
return editorRegistry.getEditors(fileName, null);
}
List<IEditorDescriptor> result = new UniqueEList<IEditorDescriptor>();
for (IContentType contentType : contentTypes)
{
if (defaultsOnly)
{
IEditorDescriptor editor = editorRegistry.getDefaultEditor(fileName, contentType);
if (editor != null)
{
result.add(editor);
}
}
else
{
result.addAll(Arrays.asList(editorRegistry.getEditors(fileName, contentType)));
}
}
return result.toArray(new IEditorDescriptor[result.size()]);
}
/**
* Returns the editors for a given URI. This method actually attempts to open an input stream for the URI and
* uses its contents, along with the filename (the URI's last segment), to obtain appropriate content types.
* <p>
* If a URI converter is specified, it is used to open the stream. Otherwise, the global default
* {@link URIConverter#INSTANCE instance} is used.
*
* @param uri a URI
* @param uriConverter a URI converter from which to obtain an input stream, or <code>null</code>
* @param defaultsOnly if <code>true</code>, only the default editor for each content type will be included in the result
* @return the descriptors of the editors
* @since 2.4
*/
public static IEditorDescriptor[] getEditors(URI uri, URIConverter uriConverter, boolean defaultsOnly)
{
String fileName = URI.decode(uri.lastSegment());
if (uriConverter == null)
{
uriConverter = URIConverter.INSTANCE;
}
InputStream stream = null;
try
{
stream = uriConverter.createInputStream(uri);
return getEditors(stream, fileName, defaultsOnly);
}
catch (IOException e)
{
EMFEditUIPlugin.INSTANCE.log(e);
return getEditors(fileName, defaultsOnly);
}
finally
{
close(stream);
}
}
private static class EclipseUtil
{
static final Class<?> FILE_CLASS;
static
{
Class<?> fileClass = null;
try
{
fileClass = IFile.class;
}
catch (Throwable exception)
{
// Ignore any exceptions and assume the class isn't available.
}
FILE_CLASS = fileClass;
}
static final Class<?> FILE_REVISION_CLASS;
static final Method FILE_REVISION_GET_URI_METHOD;
static
{
Class<?> fileRevisionClass = null;
Method fileRevisionGetURIMethod = null;
Bundle bundle = Platform.getBundle("org.eclipse.team.core");
if (bundle != null && (bundle.getState() & (Bundle.ACTIVE | Bundle.STARTING | Bundle.RESOLVED)) != 0)
{
try
{
fileRevisionClass = bundle.loadClass("org.eclipse.team.core.history.IFileRevision");
fileRevisionGetURIMethod = fileRevisionClass.getMethod("getURI");
}
catch (Throwable exeption)
{
// Ignore any exceptions and assume the class isn't available.
}
}
FILE_REVISION_CLASS = fileRevisionClass;
FILE_REVISION_GET_URI_METHOD = fileRevisionGetURIMethod;
}
static final Class<?> URI_EDITOR_INPUT_CLASS;
static
{
Class<?> uriEditorInputClass = null;
try
{
uriEditorInputClass = IURIEditorInput.class;
}
catch (Throwable exception)
{
// The class is not available.
}
URI_EDITOR_INPUT_CLASS = uriEditorInputClass;
}
public static URI getURI(IEditorInput editorInput)
{
if (FILE_CLASS != null)
{
IFile file = (IFile)editorInput.getAdapter(FILE_CLASS);
if (file != null)
{
return URI.createPlatformResourceURI(file.getFullPath().toString(), true);
}
}
if (FILE_REVISION_CLASS != null)
{
Object fileRevision = editorInput.getAdapter(FILE_REVISION_CLASS);
if (fileRevision != null)
{
try
{
return URI.createURI(((java.net.URI)FILE_REVISION_GET_URI_METHOD.invoke(fileRevision)).toString());
}
catch (Throwable exception)
{
EMFEditUIPlugin.INSTANCE.log(exception);
}
}
}
if (URI_EDITOR_INPUT_CLASS != null)
{
if (editorInput instanceof IURIEditorInput)
{
return URI.createURI(((IURIEditorInput)editorInput).getURI().toString()).trimFragment();
}
}
return null;
}
public static IEditorInput createFileEditorInput(IFile file)
{
return new FileEditorInput(file);
}
}
}