| /******************************************************************************* |
| * Copyright (c) 2004, 2008 Tasktop Technologies 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: |
| * Tasktop Technologies - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.mylyn.internal.pde.ui; |
| |
| import java.util.Collections; |
| import java.util.List; |
| |
| import org.eclipse.core.internal.resources.File; |
| import org.eclipse.core.internal.resources.Marker; |
| import org.eclipse.core.internal.resources.Workspace; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.jface.text.Document; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.mylyn.commons.core.StatusHandler; |
| import org.eclipse.mylyn.context.core.AbstractContextStructureBridge; |
| import org.eclipse.mylyn.context.core.ContextCore; |
| import org.eclipse.mylyn.context.core.IInteractionElement; |
| import org.eclipse.mylyn.internal.ide.ui.XmlNodeHelper; |
| import org.eclipse.pde.internal.core.text.build.BuildEntry; |
| import org.eclipse.pde.internal.core.text.plugin.PluginNode; |
| import org.eclipse.pde.internal.core.text.plugin.PluginObjectNode; |
| import org.eclipse.pde.internal.ui.editor.PDEFormPage; |
| import org.eclipse.pde.internal.ui.editor.plugin.ManifestEditor; |
| import org.eclipse.ui.IEditorPart; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.views.markers.internal.ConcreteMarker; |
| |
| /** |
| * @author Mik Kersten |
| * |
| */ |
| @SuppressWarnings("restriction") |
| public class PdeStructureBridge extends AbstractContextStructureBridge { |
| |
| public final static String CONTENT_TYPE = "plugin.xml"; //$NON-NLS-1$ |
| |
| @Override |
| public String getContentType() { |
| return CONTENT_TYPE; |
| } |
| |
| @Override |
| public String getContentType(String elementHandle) { |
| if (elementHandle.endsWith(".xml")) { //$NON-NLS-1$ |
| return parentContentType; |
| } else { |
| return CONTENT_TYPE; |
| } |
| } |
| |
| @Override |
| public List<String> getChildHandles(String handle) { |
| return Collections.emptyList(); |
| } |
| |
| @Override |
| public String getParentHandle(String handle) { |
| // we can only get the parent if we have a PluginObjectNode |
| |
| Object object = getObjectForHandle(handle); |
| if (object instanceof PluginObjectNode) { |
| PluginObjectNode parent = (PluginObjectNode) ((PluginObjectNode) object).getParentNode(); |
| if (parent != null) { |
| return getHandleIdentifier(parent); |
| } else { |
| // the parent is the plugin.xml file, so return that handle |
| int delimeterIndex = handle.indexOf(";"); //$NON-NLS-1$ |
| if (delimeterIndex != -1) { |
| String parentHandle = handle.substring(0, delimeterIndex); |
| return parentHandle; |
| } else { |
| return null; |
| } |
| } |
| } else if (object instanceof PluginNode) { |
| PluginNode parent = (PluginNode) ((PluginNode) object).getParentNode(); |
| if (parent != null) { |
| return getHandleIdentifier(parent); |
| } else { |
| // the parent is the plugin.xml file, so return that handle |
| int delimeterIndex = handle.indexOf(";"); //$NON-NLS-1$ |
| if (delimeterIndex != -1) { |
| String parentHandle = handle.substring(0, delimeterIndex); |
| return parentHandle; |
| } else { |
| return null; |
| } |
| } |
| } else if (object instanceof IFile) { |
| // String fileHandle = parentBridge.getParentHandle(handle); |
| AbstractContextStructureBridge parentBridge = ContextCore.getStructureBridge(parentContentType); |
| return parentBridge.getParentHandle(handle); |
| } else { |
| return null; |
| } |
| } |
| |
| /** |
| * @see org.eclipse.mylyn.context.core.AbstractContextStructureBridge#getObjectForHandle(java.lang.String) |
| */ |
| @Override |
| public Object getObjectForHandle(String handle) { |
| if (handle == null) { |
| return null; |
| } |
| int first = handle.indexOf(";"); //$NON-NLS-1$ |
| String filename = ""; //$NON-NLS-1$ |
| if (first == -1) { |
| AbstractContextStructureBridge parentBridge = ContextCore.getStructureBridge(parentContentType); |
| return parentBridge.getObjectForHandle(handle); |
| } else { |
| // extract the filename from the handle since it represents a node |
| filename = handle.substring(0, first); |
| } |
| |
| try { |
| // get the file and create a FileEditorInput |
| IPath path = new Path(filename); |
| IFile f = (IFile) ((Workspace) ResourcesPlugin.getWorkspace()).newResource(path, IResource.FILE); |
| |
| // get the start line for the element |
| int start = Integer.parseInt(handle.substring(first + 1)); |
| |
| // // get the content and the document so that we can get the offset |
| // String content = XmlNodeHelper.getContents(f.getContents()); |
| // IDocument d = new Document(content); |
| |
| // get the offsets for the element |
| // make sure that we are on a character and not whitespace |
| // int offset = d.getLineOffset(start); |
| // while(d.getChar(offset) == ' ') |
| // offset++; |
| |
| // get the current editor which should be the ManifestEditor so that |
| // we can get the element that we want |
| IEditorPart editorPart = null; |
| try { |
| editorPart = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); |
| } catch (NullPointerException e) { |
| // do nothing, this just means that there is no active page |
| } |
| if (editorPart != null && editorPart instanceof ManifestEditor) { |
| PluginObjectNode node = PdeEditingMonitor.getNode((ManifestEditor) editorPart, start, true); |
| // get the element based on the offset |
| return node; |
| } else { |
| String content = XmlNodeHelper.getContents(f.getContents()); |
| IDocument d = new Document(content); |
| PluginObjectNode node = PdeEditingMonitor.getNode(d, f, start, true); |
| return node; |
| } |
| } catch (Exception e) { |
| // ignore, means file doesn't exist |
| // ContextCorePlugin.log(e, "handle failed"); |
| } |
| return null; |
| } |
| |
| /** |
| * Handle is filename;hashcodeOfElementAndAttributes |
| * |
| * @see org.eclipse.mylyn.context.core.AbstractContextStructureBridge#getHandleIdentifier(java.lang.Object) |
| */ |
| @Override |
| public String getHandleIdentifier(Object object) { |
| // we can only create handles for PluginObjectNodes and plugin.xml files |
| if (object instanceof XmlNodeHelper) { |
| return ((XmlNodeHelper) object).getHandle(); |
| } else if (object instanceof PluginObjectNode) { |
| PluginObjectNode node = (PluginObjectNode) object; |
| try { |
| // get the handle for the PluginObjectNode |
| if (node.getModel() == null || node.getModel().getUnderlyingResource() == null |
| || node.getModel().getUnderlyingResource().getFullPath() == null) { |
| // ContextCorePlugin.log("PDE xml node's resource or model is |
| // null: " + node.getName(), this); |
| return null; |
| } |
| IPath path = new Path(node.getModel().getUnderlyingResource().getFullPath().toString()); |
| IFile file = (IFile) ((Workspace) ResourcesPlugin.getWorkspace()).newResource(path, IResource.FILE); |
| String handle = new XmlNodeHelper(file.getFullPath().toString(), |
| PdeEditingMonitor.getStringOfNode(node).hashCode()).getHandle(); |
| return handle; |
| } catch (Exception e) { |
| StatusHandler.log(new Status(IStatus.ERROR, PdeUiBridgePlugin.ID_PLUGIN, "Could not get handle", e)); //$NON-NLS-1$ |
| } |
| } else if (object instanceof PluginNode) { |
| PluginNode node = (PluginNode) object; |
| try { |
| if (node.getModel() == null || node.getModel().getUnderlyingResource() == null |
| || node.getModel().getUnderlyingResource().getFullPath() == null) { |
| // ContextCorePlugin.log("PDE xml node's resource or model is |
| // null: " + node.getName(), this); |
| return null; |
| } |
| IPath path = new Path(node.getModel().getUnderlyingResource().getFullPath().toString()); |
| IFile file = (IFile) ((Workspace) ResourcesPlugin.getWorkspace()).newResource(path, IResource.FILE); |
| String handle = new XmlNodeHelper(file.getFullPath().toString(), |
| PdeEditingMonitor.getStringOfNode(node).hashCode()).getHandle(); |
| return handle; |
| } catch (Exception e) { |
| StatusHandler.log(new Status(IStatus.ERROR, PdeUiBridgePlugin.ID_PLUGIN, "Could not get handle", e)); //$NON-NLS-1$ |
| } |
| |
| } else if (object instanceof File) { |
| // get the handle for the file if it is plugin.xml |
| File file = (File) object; |
| if (file.getFullPath().toString().endsWith("plugin.xml")) { //$NON-NLS-1$ |
| return file.getFullPath().toString(); |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public String getLabel(Object object) { |
| if (object instanceof PluginObjectNode) { |
| PluginObjectNode node = (PluginObjectNode) object; |
| String name = node.getXMLAttributeValue("name"); //$NON-NLS-1$ |
| if (name == null) { |
| name = node.getXMLTagName(); |
| } |
| name = node.getModel().getUnderlyingResource().getName() + ": " + name; //$NON-NLS-1$ |
| return name; |
| } else if (object instanceof File) { |
| File file = (File) object; |
| if (file.getFullPath().toString().endsWith("plugin.xml")) { //$NON-NLS-1$ |
| return "plugin.xml"; //$NON-NLS-1$ |
| } |
| } |
| return ""; //$NON-NLS-1$ |
| } |
| |
| /** |
| * TODO: make a non-handle based test |
| */ |
| @Override |
| public boolean canBeLandmark(String handle) { |
| if (handle == null) { |
| return false; |
| } else { |
| return handle.indexOf(';') == -1; |
| } |
| } |
| |
| @Override |
| public boolean acceptsObject(Object object) { |
| // we only accept PluginObjectNodes and plugin.xml Files |
| if (object instanceof PluginNode || object instanceof PluginObjectNode || object instanceof BuildEntry |
| || object instanceof PDEFormPage) { |
| return true; |
| } else if (object instanceof XmlNodeHelper) { |
| if (((XmlNodeHelper) object).getFilename().endsWith("plugin.xml")) { //$NON-NLS-1$ |
| return true; |
| } |
| } else if (object instanceof File) { |
| File file = (File) object; |
| if (file.getFullPath().toString().endsWith("plugin.xml")) { //$NON-NLS-1$ |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @Override |
| public boolean canFilter(Object element) { |
| return true; |
| } |
| |
| @Override |
| public boolean isDocument(String handle) { |
| return handle.indexOf(';') == -1; |
| } |
| |
| @Override |
| public String getHandleForOffsetInObject(Object object, int offset) { |
| if (object == null) { |
| return null; |
| } |
| |
| IResource markerResource = null; |
| try { |
| if (object instanceof ConcreteMarker) { |
| markerResource = ((ConcreteMarker) object).getMarker().getResource(); |
| } else if (object instanceof Marker) { |
| markerResource = ((Marker) object).getResource(); |
| } |
| } catch (Exception e) { |
| return null; |
| } |
| |
| if (markerResource != null) { |
| // we can only get a handle for a marker with the resource |
| // plugin.xml |
| try { |
| if (markerResource instanceof IFile) { |
| IFile file = (IFile) markerResource; |
| if (file.getFullPath().toString().endsWith("plugin.xml")) { //$NON-NLS-1$ |
| return file.getFullPath().toString(); |
| } else { |
| return null; |
| } |
| } |
| return null; |
| } catch (Throwable t) { |
| StatusHandler.log(new Status(IStatus.WARNING, PdeUiBridgePlugin.ID_PLUGIN, |
| "Could not find element for: " + object)); //$NON-NLS-1$ |
| return null; |
| } |
| } else if (object instanceof IFile) { |
| try { |
| IFile file = (IFile) object; |
| if (file.getFullPath().toString().endsWith("plugin.xml")) { //$NON-NLS-1$ |
| String content = XmlNodeHelper.getContents(file.getContents()); |
| IDocument d = new Document(content); |
| PluginObjectNode node = PdeEditingMonitor.getNode(d, file, offset, false); |
| String handle = new XmlNodeHelper(file.getFullPath().toString(), PdeEditingMonitor.getStringOfNode( |
| node).hashCode()).getHandle(); |
| return handle; |
| } |
| } catch (Exception e) { |
| StatusHandler.log(new Status(IStatus.ERROR, PdeUiBridgePlugin.ID_PLUGIN, |
| "Unable to get handle for offset in object", e)); //$NON-NLS-1$ |
| } |
| } |
| return null; |
| } |
| |
| // public IProject getProjectForObject(Object object) { |
| // while (!(object instanceof IFile)) { |
| // String handle = getParentHandle(getHandleIdentifier(object)); |
| // if (handle == null) |
| // break; |
| // object = getObjectForHandle(handle); |
| // } |
| // if (object instanceof IFile && acceptsObject(object)) { |
| // return ((IFile) object).getProject(); |
| // } |
| // return null; |
| // } |
| |
| public boolean containsProblem(IInteractionElement node) { |
| // TODO Auto-generated method stub |
| return false; |
| } |
| } |