/*******************************************************************************
* Copyright (c) 2007-2012 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.common.text.ext.hyperlink;
import java.util.Arrays;
import java.util.Comparator;
import org.eclipse.core.internal.resources.ICoreConstants;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.internal.core.JarEntryFile;
import org.eclipse.jdt.internal.ui.javaeditor.JarEntryEditorInput;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.ui.IEditorInput;
import org.eclipse.wst.common.componentcore.internal.ComponentResource;
import org.eclipse.wst.common.componentcore.internal.StructureEdit;
import org.eclipse.wst.common.componentcore.internal.WorkbenchComponent;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.jboss.tools.common.el.core.GlobalELReferenceList;
import org.jboss.tools.common.model.XModel;
import org.jboss.tools.common.model.XModelObject;
import org.jboss.tools.common.model.project.IModelNature;
import org.jboss.tools.common.model.util.EclipseResourceUtil;
import org.jboss.tools.common.resref.core.ResourceReference;
import org.jboss.tools.common.text.ext.hyperlink.xpl.AbstractBaseHyperlink;
import org.jboss.tools.common.text.ext.util.StructuredModelWrapper;
import org.jboss.tools.common.text.ext.util.Utils;
/**
*
*/
@SuppressWarnings("restriction")
abstract public class AbstractHyperlink extends AbstractBaseHyperlink implements IHyperlink {
public static final String DOLLAR_PREFIX = "${"; //$NON-NLS-1$
private static final String SUFFIX = "}"; //$NON-NLS-1$
public static final String SHARP_PREFIX = "#{"; //$NON-NLS-1$
public static XModel getXModel(IFile file) {
if (file == null)
return null;
XModelObject fs = EclipseResourceUtil.getObjectByResource(file);
if (fs != null)
return fs.getModel();
fs = EclipseResourceUtil.createObjectForResource(file);
if (fs != null)
return fs.getModel();
IProject project = file.getProject();
IModelNature nature = EclipseResourceUtil.getModelNature(project);
return (nature == null) ? null : nature.getModel();
}
protected IFile getFile() {
StructuredModelWrapper smw = new StructuredModelWrapper();
try {
smw.init(getDocument());
return smw.getFile();
} finally {
smw.dispose();
}
}
protected String getBaseLocation() {
StructuredModelWrapper smw = new StructuredModelWrapper();
try {
smw.init(getDocument());
return smw.getBaseLocation();
} finally {
smw.dispose();
}
}
protected XModel getXModel() {
StructuredModelWrapper smw = new StructuredModelWrapper();
try {
smw.init(getDocument());
return smw.getXModel();
} finally {
smw.dispose();
}
}
public static XModel getXModel(IStructuredModel structuredModel) {
IFile f = getFile(structuredModel);
if (f != null)
return getXModel(f);
if (structuredModel == null)
return null;
String wsRelativePath = structuredModel.getBaseLocation();
if (wsRelativePath == null)
return null;
if (wsRelativePath.startsWith("/")) { //$NON-NLS-1$
while (true) {
int i = wsRelativePath.lastIndexOf('/');
if (i < 0)
return null;
wsRelativePath = wsRelativePath.substring(0, i);
IPath path = new Path(wsRelativePath);
IResource r = ResourcesPlugin.getWorkspace().getRoot().findMember(
path);
if (r != null && r.exists()) {
XModelObject o = EclipseResourceUtil
.createObjectForResource(r);
if (o != null)
return o.getModel();
}
}
}
return null;
}
public static String getBaseLocation(IStructuredModel structuredModel) {
if (structuredModel == null) {
return null;
}
return structuredModel.getBaseLocation();
}
public static IFile getFile(IStructuredModel structuredModel) {
if (structuredModel == null) {
return null;
}
String wsRelativePath = structuredModel.getBaseLocation();
if (wsRelativePath == null) {
return null;
}
if (wsRelativePath.startsWith("/")) { //$NON-NLS-1$
IPath path = new Path(wsRelativePath);
IResource r = ResourcesPlugin.getWorkspace().getRoot().findMember(
path);
if (r != null && r.exists() && r instanceof IFile)
return (IFile) r;
}
String path = Platform.getLocation().append(wsRelativePath)
.toFile().getAbsolutePath();
return EclipseResourceUtil.getFile(path);
}
protected IRegion doGetHyperlinkRegion(int offset) {
return hyperlinkRegion;
}
abstract protected void doHyperlink(IRegion region);
protected IFile getFileFromProject(String fileName) {
IFile documentFile = getFile();
if(documentFile == null || !documentFile.isAccessible()) return null;
fileName = findAndReplaceElVariable(fileName);
IProject project = documentFile.getProject();
String name = Utils.trimFilePath(fileName);
IPath currentPath = documentFile.getLocation()
.removeLastSegments(1);
IResource member = null;
StructureEdit se = StructureEdit.getStructureEditForRead(project);
if (se == null) {
return null;
}
WorkbenchComponent[] modules = se.getWorkbenchModules();
for (int i = 0; i < modules.length; i++) {
if (name.startsWith("/")) { //$NON-NLS-1$
member = findFileByAbsolutePath(project, modules[i], name);
} else {
member = findFileByRelativePath(project, modules[i],
currentPath, name);
if (member == null && name.length() > 0) {
// in some cases path having no leading "/" is
// nevertheless absolute
member = findFileByAbsolutePath(project, modules[i],
"/" + name); //$NON-NLS-1$
}
}
if (member != null && (member instanceof IFile)) {
if (((IFile) member).exists())
return (IFile) member;
}
}
return null;
}
// partly copied from org.jboss.tools.vpe.editor.util.ElService
protected String findAndReplaceElVariable(String fileName){
final IPath workspacePath = Platform.getLocation();
final ResourceReference[] gResources = GlobalELReferenceList.getInstance().getAllResources(workspacePath);
String result = fileName;
ResourceReference[] sortedReferences = sortReferencesByScope(gResources);
for (ResourceReference rf : sortedReferences) {
final String dollarEl = DOLLAR_PREFIX + rf.getLocation() + SUFFIX;
final String sharpEl = SHARP_PREFIX + rf.getLocation() + SUFFIX;
if (fileName.contains(dollarEl)) {
result = result.replace(dollarEl, rf.getProperties());
}
if (fileName.contains(sharpEl)) {
result = result.replace(sharpEl, rf.getProperties());
}
}
return result;
}
// copied from org.jboss.tools.vpe.editor.util.ElService
private ResourceReference[] sortReferencesByScope(ResourceReference[] references) {
ResourceReference[] sortedReferences = references.clone();
Arrays.sort(sortedReferences, new Comparator<ResourceReference>() {
public int compare(ResourceReference r1, ResourceReference r2) {
return r1.getScope() - r2.getScope();
}
});
return sortedReferences;
}
private IFile findFileByRelativePath(IProject project,
WorkbenchComponent module, IPath basePath, String path) {
if (path == null || path.trim().length() == 0)
return null;
path = findAndReplaceElVariable(path);
ComponentResource[] resources = module.findResourcesBySourcePath(
new Path("/"), 0); //$NON-NLS-1$
IPath projectPath = project.getLocation();
IFile member = null;
for (int i = 0; resources != null && i < resources.length; i++) {
IPath runtimePath = resources[i].getRuntimePath();
IPath sourcePath = resources[i].getSourcePath();
// Look in source environment
IPath webRootPath = projectPath.append(sourcePath);
IPath relativePath = Utils.getRelativePath(webRootPath,
basePath);
IPath filePath = relativePath.append(path);
member = project.getFile(sourcePath.append(filePath));
if (member.exists()) {
return member;
}
// Look in runtime environment
if (runtimePath.segmentCount() >= ICoreConstants.MINIMUM_FOLDER_SEGMENT_LENGTH - 1) {
webRootPath = projectPath.append(runtimePath);
relativePath = Utils.getRelativePath(webRootPath, basePath);
filePath = relativePath.append(path);
member = project.getFile(runtimePath.append(filePath));
if (member.exists()) {
return member;
}
}
}
return null;
}
private IFile findFileByAbsolutePath(IProject project,
WorkbenchComponent module, String path) {
ComponentResource[] resources = module.findResourcesBySourcePath(
new Path("/"), 0); //$NON-NLS-1$
path = findAndReplaceElVariable(path);
IFile member = null;
for (int i = 0; resources != null && i < resources.length; i++) {
IPath runtimePath = resources[i].getRuntimePath();
IPath sourcePath = resources[i].getSourcePath();
// Look in source environment
member = project.getFile(sourcePath.append(path));
if(member.exists()) {
return member;
}
// Look in runtime environment
if (runtimePath.segmentCount() >= ICoreConstants.MINIMUM_FOLDER_SEGMENT_LENGTH - 1) {
member = project.getFile(runtimePath.append(path));
if (member.exists()) {
return member;
}
}
}
return null;
}
protected IEditorInput createEditorInput(String fileString) {
String jarName = fileString.substring(0,fileString.indexOf("!")); //$NON-NLS-1$
IFile[] fs = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(new Path(jarName));
if(fs == null || fs.length == 0) return null;
IProject p = fs[0].getProject();
IJavaProject jp = EclipseResourceUtil.getJavaProject(p);
if(jp == null) return null;
IPackageFragmentRoot root = jp.getPackageFragmentRoot(fs[0]);
String entryName = fileString.substring(fileString.indexOf("!")+2,fileString.length()); //$NON-NLS-1$
JarEntryFile f = new JarEntryFile(entryName);
f.setParent(root);
JarEntryEditorInput jarEditorInput = new JarEntryEditorInput(f) {
public boolean equals(Object arg) {
return this.toString().equals(arg.toString());
}
};
return jarEditorInput;
}
/**
* for test purpose
* @return
*/
public IFile getReadyToOpenFile(){
return null;
}
}