blob: 3dcf87c775a2b7f8db0083f7c59a3f037b5c668a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 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
*******************************************************************************/
package org.eclipse.jst.jsp.ui.openon;
import org.eclipse.core.resources.IFile;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.ILocalVariable;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.ISourceReference;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.ui.JavaElementLabelProvider;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.window.Window;
import org.eclipse.jst.jsp.core.internal.java.IJSPTranslation;
import org.eclipse.jst.jsp.core.internal.java.JSPTranslation;
import org.eclipse.jst.jsp.core.internal.java.JSPTranslationAdapter;
import org.eclipse.jst.jsp.ui.internal.JSPUIPlugin;
import org.eclipse.jst.jsp.ui.internal.Logger;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.wst.sse.core.IStructuredModel;
import org.eclipse.wst.sse.core.util.ResourceUtil;
import org.eclipse.wst.sse.ui.openon.AbstractOpenOn;
import org.eclipse.wst.xml.core.document.XMLDocument;
import org.eclipse.wst.xml.core.document.XMLModel;
/**
* This action opens classes referenced in JSP Java content of a JSP page.
*/
public class JSPJavaOpenOnJSP extends AbstractOpenOn {
//private final String SSE_MODEL_ID = IModelManagerPlugin.ID; //$NON-NLS-1$
private final String SELECT_JAVA_TITLE = JSPUIPlugin.getResourceString("%JSPJavaOpenOnJSP.0"); //$NON-NLS-1$
private final String SELECT_JAVA_MESSAGE = JSPUIPlugin.getResourceString("%JSPJavaOpenOnJSP.1"); //$NON-NLS-1$
/**
* Get JSP translation object
*
* @return JSPTranslation if one exists, null otherwise
*/
private JSPTranslation getJSPTranslation() {
// get JSP translation object for this action's editor's document
XMLModel xmlModel = (XMLModel) getModelManager().getExistingModelForRead(getDocument());
if (xmlModel != null) {
XMLDocument xmlDoc = xmlModel.getDocument();
xmlModel.releaseFromRead();
JSPTranslationAdapter adapter = (JSPTranslationAdapter) xmlDoc.getAdapterFor(IJSPTranslation.class);
if (adapter != null) {
return adapter.getJSPTranslation();
}
}
return null;
}
/*
* (non-Javadoc)
*
* @see com.ibm.sse.editor.AbstractOpenOn#doOpenOn(org.eclipse.jface.text.IRegion)
*/
protected void doOpenOn(IRegion region) {
JSPTranslation jspTranslation = getJSPTranslation();
if (jspTranslation != null) {
IJavaElement element = getJavaElement(region, jspTranslation);
// open local variable in the JSP file...
if (element instanceof ILocalVariable) {
// source reference has java text range info
if (element instanceof ISourceReference) {
try {
// get Java range, translate coordinate to JSP
ISourceRange range = ((ISourceReference) element).getSourceRange();
int jspStart = jspTranslation.getJspOffset(range.getOffset());
// open the JSP editor
IEditorPart jspEditor = openDocumentEditor();
// set the cursor to the declaration of the variable
if (jspEditor instanceof ITextEditor) {
((ITextEditor) jspEditor).setHighlightRange(jspStart, 0, true);
}
}
catch (JavaModelException jme) {
Logger.logException("error getting source range from java element (local variable)", jme); //$NON-NLS-1$
}
}
}
else {
try {
IEditorPart part = JavaUI.openInEditor(element);
if (part != null) {
if (element != null)
JavaUI.revealInEditor(part, element);
}
else {
// could not open editor
openFileFailed();
}
}
catch (Exception e) {
Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
}
}
}
}
/**
* Determine the one Java element to open file on
*
* @param region
* IRegion
* @param translation
* jsp java translation
* @return the one Java element to open file on
*/
private IJavaElement getJavaElement(IRegion region, JSPTranslation translation) {
if (region == null) {
return null;
}
IJavaElement[] elements = translation.getElementsFromJspRange(region.getOffset(), region.getOffset() + region.getLength());
if (elements == null || elements.length == 0)
return null;
IJavaElement candidate = elements[0];
// more than one Java element was selected so ask user which element
// should open file open
if (elements.length > 1) {
candidate = selectJavaElement(elements);
}
return candidate;
}
/**
* Shows a dialog for resolving an ambigous java element. This method was
* copied from org.eclipse.jdt.internal.ui.actions.OpenActionUtil except I
* set the shell, title, message in this method instead of passing it and
* this method is private
*/
private IJavaElement selectJavaElement(IJavaElement[] elements) {
int nResults = elements.length;
if (nResults == 0)
return null;
if (nResults == 1)
return elements[0];
int flags = JavaElementLabelProvider.SHOW_DEFAULT | JavaElementLabelProvider.SHOW_QUALIFIED | JavaElementLabelProvider.SHOW_ROOT;
ElementListSelectionDialog dialog = new ElementListSelectionDialog(null, new JavaElementLabelProvider(flags));
dialog.setTitle(SELECT_JAVA_TITLE);
dialog.setMessage(SELECT_JAVA_MESSAGE);
dialog.setElements(elements);
if (dialog.open() == Window.OK) {
Object[] selection = dialog.getResult();
if (selection != null && selection.length > 0) {
nResults = selection.length;
for (int i = 0; i < nResults; i++) {
Object current = selection[i];
if (current instanceof IJavaElement)
return (IJavaElement) current;
}
}
}
return null;
}
/*
* (non-Javadoc)
*
* @see com.ibm.sse.editor.AbstractOpenOn#doGetOpenOnRegion(int)
*/
protected IRegion doGetOpenOnRegion(int offset) {
IRegion region;
// check and make sure this is a valid Java type
JSPTranslation jspTranslation = getJSPTranslation();
IJavaElement[] elements = jspTranslation.getElementsFromJspRange(offset, offset);
// if no Java element found, this is not a valid openable region
if (elements == null || elements.length == 0)
region = null;
else {
// return the type region
region = selectWord(getDocument(), offset);
}
return region;
}
/**
* Java always selects word when defining region
*
* @param document
* @param anchor
* @return IRegion
*/
private IRegion selectWord(IDocument document, int anchor) {
try {
int offset = anchor;
char c;
while (offset >= 0) {
c = document.getChar(offset);
if (!Character.isJavaIdentifierPart(c))
break;
--offset;
}
int start = offset;
offset = anchor;
int length = document.getLength();
while (offset < length) {
c = document.getChar(offset);
if (!Character.isJavaIdentifierPart(c))
break;
++offset;
}
int end = offset;
if (start == end)
return new Region(start, 0);
else
return new Region(start + 1, end - start - 1);
}
catch (BadLocationException x) {
return null;
}
}
/**
* Open the editor associated with the current document
*
* @return the editor opened or null if an external editor was opened or
* no editor was opened
*/
private IEditorPart openDocumentEditor() {
IEditorPart theEditor = null;
IStructuredModel model = null;
IFile file = null;
try {
model = getModelManager().getExistingModelForRead(getDocument());
IFile[] files = ResourceUtil.getFilesFor(model);
int i = 0;
while (i < files.length && file == null) {
if (files[i].exists()) {
file = files[i];
}
else {
++i;
}
}
}
finally {
if (model != null) {
model.releaseFromRead();
}
}
if (file != null) {
theEditor = openFileInEditor(file);
}
return theEditor;
}
}