blob: 58d8dead504e3e56fa15c72a59dc2ded346ded90 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2004 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
* Jens Lukowski/Innoopract - initial renaming/restructuring
*
*******************************************************************************/
package org.eclipse.wst.sse.ui.internal.debug;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Platform;
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.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.ui.IEditorActionBarContributor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPathEditorInput;
import org.eclipse.ui.IStorageEditorInput;
import org.eclipse.ui.editors.text.FileDocumentProvider;
import org.eclipse.ui.editors.text.ILocationProvider;
import org.eclipse.ui.editors.text.StorageDocumentProvider;
import org.eclipse.ui.editors.text.TextEditor;
import org.eclipse.ui.part.IShowInTargetList;
import org.eclipse.ui.texteditor.AbstractDocumentProvider;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.IElementStateListener;
import org.eclipse.ui.texteditor.ITextEditorActionConstants;
import org.eclipse.ui.texteditor.MarkerRulerAction;
import org.eclipse.wst.sse.core.internal.util.StringUtils;
import org.eclipse.wst.sse.ui.internal.ExtendedConfigurationBuilder;
import org.eclipse.wst.sse.ui.internal.ExtendedEditorActionBuilder;
import org.eclipse.wst.sse.ui.internal.IExtendedContributor;
import org.eclipse.wst.sse.ui.internal.IPopupMenuContributor;
import org.eclipse.wst.sse.ui.internal.Logger;
import org.eclipse.wst.sse.ui.internal.SSEUIMessages;
import org.eclipse.wst.sse.ui.internal.StructuredResourceMarkerAnnotationModel;
import org.eclipse.wst.sse.ui.internal.actions.ActionDefinitionIds;
import org.eclipse.wst.sse.ui.internal.extension.BreakpointProviderBuilder;
import org.eclipse.wst.sse.ui.internal.provisional.extensions.ConfigurationPointCalculator;
import org.eclipse.wst.sse.ui.internal.provisional.extensions.breakpoint.IExtendedStorageEditorInput;
/**
* @author nitin
*
* A text editor capable of using the IBreakpointProvider framework.
*
* This class is intended to be used by clients who wish to use the
* IBreakpointProvider framework but not the StructuredTextEditor, e.g. VBS
* source editors. It is provided AS-IS and marked internal as it is
* unsupported and subject to change at any time.
*/
public class DebugTextEditor extends TextEditor {
private class ShowInTargetLister implements IShowInTargetList {
public String[] getShowInTargetIds() {
return fShowInTargetIds;
}
}
/**
* DocumentProvider for IStorageEditorInputs - supports
* IExtendedStorageEditorInput notifications and assigning breakpoint
* markers.
*/
class StorageInputDocumentProvider extends StorageDocumentProvider implements IElementStateListener {
protected IAnnotationModel createAnnotationModel(Object element) throws CoreException {
IAnnotationModel model = null;
IStorageEditorInput storageInput = (IStorageEditorInput) element;
String ext = BreakpointRulerAction.getFileExtension(storageInput);
IContentType[] types = getEditorInputContentTypes(storageInput);
IResource res = null;
for (int i = 0; res == null && i < types.length; i++) {
res = BreakpointProviderBuilder.getInstance().getResource(storageInput, types[i].getId(), ext);
}
String id = storageInput.getName();
if (storageInput.getStorage() != null)
id = storageInput.getStorage().getFullPath().toString();
if (res != null)
model = new StructuredResourceMarkerAnnotationModel(res, id);
else
model = new StructuredResourceMarkerAnnotationModel(ResourcesPlugin.getWorkspace().getRoot(), id);
return model;
}
protected AbstractDocumentProvider.ElementInfo createElementInfo(Object element) throws CoreException {
if (element instanceof IExtendedStorageEditorInput) {
((IExtendedStorageEditorInput) element).addElementStateListener(this);
}
return super.createElementInfo(element);
}
protected void disposeElementInfo(Object element, ElementInfo info) {
if (element instanceof IExtendedStorageEditorInput) {
((IExtendedStorageEditorInput) element).removeElementStateListener(this);
}
super.disposeElementInfo(element, info);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.editors.text.StorageDocumentProvider#doSaveDocument(org.eclipse.core.runtime.IProgressMonitor,
* java.lang.Object, org.eclipse.jface.text.IDocument, boolean)
*/
protected void doSaveDocument(IProgressMonitor monitor, Object element, IDocument document, boolean overwrite) throws CoreException {
// untested
new FileDocumentProvider().saveDocument(monitor, element, document, overwrite);
}
public void elementContentAboutToBeReplaced(Object element) {
fireElementContentAboutToBeReplaced(element);
}
public void elementContentReplaced(Object element) {
fireElementContentReplaced(element);
}
public void elementDeleted(Object element) {
fireElementDeleted(element);
}
public void elementDirtyStateChanged(Object element, boolean isDirty) {
fireElementDirtyStateChanged(element, isDirty);
}
public void elementMoved(Object originalElement, Object movedElement) {
fireElementMoved(originalElement, movedElement);
}
}
String[] fShowInTargetIds = new String[]{IPageLayout.ID_RES_NAV};
private IShowInTargetList fShowInTargetListAdapter = new ShowInTargetLister();
IDocumentProvider fStorageInputDocumentProvider = null;
public DebugTextEditor() {
super();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.editors.text.TextEditor#createActions()
*/
protected void createActions() {
super.createActions();
// StructuredTextEditor Action - toggle breakpoints
IAction action = new ToggleBreakpointAction(this, getVerticalRuler()) {
protected String getContentType(IDocument document) {
ILocationProvider provider = (ILocationProvider) getEditorInput().getAdapter(ILocationProvider.class);
if (provider != null) {
IPath location = provider.getPath(getEditorInput());
return detectContentType(location).getId();
} else if (getEditorInput() instanceof IPathEditorInput) {
IPath location = ((IPathEditorInput) getEditorInput()).getPath();
return detectContentType(location).getId();
}
return IContentTypeManager.CT_TEXT;
}
};
setAction(ActionDefinitionIds.TOGGLE_BREAKPOINTS, action);
// StructuredTextEditor Action - manage breakpoints
action = new ManageBreakpointAction(this, getVerticalRuler());
setAction(ActionDefinitionIds.MANAGE_BREAKPOINTS, action);
// StructuredTextEditor Action - edit breakpoints
action = new EditBreakpointAction(this, getVerticalRuler());
setAction(ActionDefinitionIds.EDIT_BREAKPOINTS, action);
}
/**
* Loads the Show In Target IDs from the Extended Configuration extension
* point.
*
* @return
*/
protected String[] createShowInTargetIds() {
List allIds = new ArrayList(0);
ExtendedConfigurationBuilder builder = ExtendedConfigurationBuilder.getInstance();
String[] configurationIds = getConfigurationPoints();
for (int i = 0; i < configurationIds.length; i++) {
String[] definitions = builder.getDefinitions("showintarget", configurationIds[i]); //$NON-NLS-1$
for (int j = 0; j < definitions.length; j++) {
String someIds = definitions[j];
if (someIds != null && someIds.length() > 0) {
String[] ids = StringUtils.unpack(someIds);
for (int k = 0; k < ids.length; k++) {
// trim, just to keep things clean
String id = ids[k].trim();
if (!allIds.contains(id)) {
allIds.add(id);
}
}
}
}
}
if (!allIds.contains(IPageLayout.ID_RES_NAV)) {
allIds.add(IPageLayout.ID_RES_NAV);
}
return (String[]) allIds.toArray(new String[0]);
}
IContentType detectContentType(IPath location) {
IContentType type = null;
IResource resource = FileBuffers.getWorkspaceFileAtLocation(location);
if (resource != null) {
if (resource.getType() == IResource.FILE && resource.isAccessible()) {
IContentDescription d = null;
try {
// Optimized description lookup, might not succeed
d = ((IFile) resource).getContentDescription();
if (d != null) {
type = d.getContentType();
}
} catch (CoreException e) {
// Should not be possible given the accessible and file
// type check above
}
if (type == null) {
type = Platform.getContentTypeManager().findContentTypeFor(resource.getName());
}
}
} else {
File file = FileBuffers.getSystemFileAtLocation(location);
if (file != null) {
InputStream input = null;
try {
input = new FileInputStream(file);
type = Platform.getContentTypeManager().findContentTypeFor(input, location.toOSString());
} catch (FileNotFoundException e) {
} catch (IOException e) {
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e1) {
}
}
}
if (type == null) {
type = Platform.getContentTypeManager().findContentTypeFor(file.getName());
}
}
}
if (type == null) {
type = Platform.getContentTypeManager().getContentType(IContentTypeManager.CT_TEXT);
}
return type;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.texteditor.AbstractTextEditor#editorContextMenuAboutToShow(org.eclipse.jface.action.IMenuManager)
*/
protected void editorContextMenuAboutToShow(IMenuManager menu) {
super.editorContextMenuAboutToShow(menu);
IEditorActionBarContributor c = getEditorSite().getActionBarContributor();
if (c instanceof IPopupMenuContributor) {
((IPopupMenuContributor) c).contributeToPopupMenu(menu);
} else {
ExtendedEditorActionBuilder builder = new ExtendedEditorActionBuilder();
IExtendedContributor pmc = builder.readActionExtensions(getConfigurationPoints());
if (pmc != null) {
pmc.setActiveEditor(this);
pmc.contributeToPopupMenu(menu);
}
}
}
/**
* @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
*/
public Object getAdapter(Class required) {
// Navigate action set menu
if (IShowInTargetList.class.equals(required))
return fShowInTargetListAdapter;
return super.getAdapter(required);
}
protected String[] getConfigurationPoints() {
return ConfigurationPointCalculator.getConfigurationPoints(this, getInputContentType(getEditorInput()), ConfigurationPointCalculator.SOURCE, DebugTextEditor.class);
}
IContentType[] getEditorInputContentTypes(IEditorInput input) {
IContentType[] types = null;
IResource resource = null;
if (input.getAdapter(IFile.class) != null) {
resource = (IFile) input.getAdapter(IFile.class);
} else if (input.getAdapter(IFile.class) != null) {
resource = (IResource) input.getAdapter(IResource.class);
}
if (resource.getType() == IResource.FILE && resource.isAccessible()) {
IContentDescription d = null;
try {
// optimized description lookup, might not succeed
d = ((IFile) resource).getContentDescription();
if (d != null) {
types = new IContentType[]{d.getContentType()};
}
} catch (CoreException e) {
// should not be possible given the accessible and file type
// check above
}
}
if (types == null) {
types = Platform.getContentTypeManager().findContentTypesFor(input.getName());
}
return types;
}
/**
* @param editorInput
* @return
*/
private String getInputContentType(IEditorInput editorInput) {
IContentType[] types = getEditorInputContentTypes(editorInput);
if (types != null) {
return types[0].getId();
}
return null;
}
/**
*
* @return
*/
private boolean isDebuggingAvailable() {
boolean debuggingAvailable = false;
IContentType[] types = getEditorInputContentTypes(getEditorInput());
for (int i = 0; !debuggingAvailable && i < types.length; i++) {
debuggingAvailable = debuggingAvailable || BreakpointProviderBuilder.getInstance().isAvailable(types[i].getId(), BreakpointRulerAction.getFileExtension(getEditorInput()));
}
return debuggingAvailable;
}
protected void rulerContextMenuAboutToShow(IMenuManager menu) {
if (isDebuggingAvailable()) {
menu.add(getAction(ActionDefinitionIds.TOGGLE_BREAKPOINTS));
menu.add(getAction(ActionDefinitionIds.MANAGE_BREAKPOINTS));
menu.add(getAction(ActionDefinitionIds.EDIT_BREAKPOINTS));
menu.add(new Separator());
} else {
Logger.log(Logger.INFO, getClass().getName() + " could not enable debugging actions"); //$NON-NLS-1$
}
super.rulerContextMenuAboutToShow(menu);
}
/**
* Ensure that the correct IDocumentProvider is used. For IFile and Files,
* the default provider with a specified AnnotationModelFactory is used.
* For StorageEditorInputs, use a custom provider that creates a usable
* ResourceAnnotationModel
*
* @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#setDocumentProvider(org.eclipse.ui.IEditorInput)
*/
protected void setDocumentProvider(IEditorInput input) {
if (input instanceof IStorageEditorInput && !(input instanceof IFileEditorInput)) {
if (fStorageInputDocumentProvider == null) {
fStorageInputDocumentProvider = new StorageInputDocumentProvider();
}
setDocumentProvider(fStorageInputDocumentProvider);
} else {
super.setDocumentProvider(input);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.texteditor.AbstractTextEditor#updateContentDependentActions()
*/
protected void updateContentDependentActions() {
super.updateContentDependentActions();
if (isDebuggingAvailable()) {
setAction(ITextEditorActionConstants.RULER_DOUBLE_CLICK, getAction(ActionDefinitionIds.TOGGLE_BREAKPOINTS));
}
else {
// The Default Text Editor uses editorContribution to perform this
// mapping, but since it relies on the IEditorSite ID, it can't be
// relied on for MultiPageEditorParts. Instead, force the action
// registration manually.
setAction(ITextEditorActionConstants.RULER_DOUBLE_CLICK, new MarkerRulerAction(SSEUIMessages.getResourceBundle(), "Editor.ManageBookmarks.", this, getVerticalRuler(), IMarker.BOOKMARK, true)); //$NON-NLS-1$
}
fShowInTargetIds = createShowInTargetIds();
}
}