/*******************************************************************************
* Copyright (c) 2007 Exadel, Inc. and 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:
* Exadel, Inc. and Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.common.model.util;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModelMarker;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.swt.graphics.Image;
import org.eclipse.wst.common.componentcore.ComponentCore;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.jboss.tools.common.EclipseUtil;
import org.jboss.tools.common.meta.action.XActionInvoker;
import org.jboss.tools.common.model.XModel;
import org.jboss.tools.common.model.XModelConstants;
import org.jboss.tools.common.model.XModelFactory;
import org.jboss.tools.common.model.XModelObject;
import org.jboss.tools.common.model.XModelObjectConstants;
import org.jboss.tools.common.model.filesystems.FilePathHelper;
import org.jboss.tools.common.model.filesystems.FileSystemsHelper;
import org.jboss.tools.common.model.filesystems.XFileObject;
import org.jboss.tools.common.model.filesystems.impl.FileSystemImpl;
import org.jboss.tools.common.model.filesystems.impl.FileSystemsImpl;
import org.jboss.tools.common.model.filesystems.impl.JarSystemImpl;
import org.jboss.tools.common.model.filesystems.impl.Libs;
import org.jboss.tools.common.model.icons.impl.XModelObjectIcon;
import org.jboss.tools.common.model.impl.XModelObjectImpl;
import org.jboss.tools.common.model.plugin.ModelPlugin;
import org.jboss.tools.common.model.project.IModelNature;
import org.jboss.tools.common.model.project.ModelNature;
import org.jboss.tools.common.model.project.ModelNatureExtension;
import org.jboss.tools.common.util.FileUtils;
import org.jboss.tools.common.util.UniquePaths;
import org.jboss.tools.common.web.WebUtils;
import org.osgi.framework.Bundle;
public class EclipseResourceUtil extends EclipseUtil {
public static IProject getProject(XModelObject o) {
return (o == null) ? null : (IProject)o.getModel().getProperties().get(XModelObjectConstants.PROJECT);
}
public static boolean isProjectFragment(XModel model) {
return (XModelObjectConstants.TRUE.equals(model.getProperties().getProperty("isProjectFragment"))); //$NON-NLS-1$
}
public static IResource getResource(XModelObject object) {
XModelObject f = ((XModelObjectImpl)object).getResourceAncestor();
return (f == null) ? null : (IResource)f.getAdapter(IResource.class);
}
public static String getJavaClassQualifiedName(XModelObject object) {
if(object.getFileType() != XFileObject.FILE) return null;
String ext = object.getAttributeValue(XModelObjectConstants.ATTR_NAME_EXTENSION);
if(!"java".equals(ext) && !"class".equals(ext)) return null; //$NON-NLS-1$ //$NON-NLS-2$
String q = object.getAttributeValue(XModelObjectConstants.ATTR_NAME);
String p = getJavaPackageName(object.getParent());
return (p == null) ? q : p + "." + q; //$NON-NLS-1$
}
public static String getJavaPackageName(XModelObject object) {
if(object == null || object.getFileType() != XFileObject.FOLDER) return null;
String q = object.getAttributeValue(XModelObjectConstants.ATTR_NAME);
XModelObject o = object.getParent();
while(o != null && o.getFileType() == XFileObject.FOLDER) {
q = o.getAttributeValue(XModelObjectConstants.ATTR_NAME) + "." + q; //$NON-NLS-1$
o = o.getParent();
}
return q;
}
public static String getIconPath(XModelObject o) {
String s = o.getMainIconName();
return o.getModelEntity().getMetaModel().getIconList().getIconPath(s, "default.unknown"); //$NON-NLS-1$
}
public static Image getImage(String path) {
return ModelImages.getImage(path);
}
public static Image getImage(XModelObject object) {
return new XModelObjectIcon(object).getEclipseImage();
}
public static XModelObject getObjectByResource(IResource resource) {
if(resource == null) return null;
IProject p = resource.getProject();
IModelNature sp = getModelNature(p);
if(sp == null) return null;
return getObjectByResource(sp.getModel(), resource);
}
public static XModelObject getObjectByResource(XModel model, IResource resource) {
if(resource == null) return null;
IPath path = resource.getLocation();
if (model != null) {
FileSystemsImpl fso = (FileSystemsImpl)FileSystemsHelper.getFileSystems(model);
if(fso == null) return null;
fso.updateOverlapped();
XModelObject result = null;
int pathLength = 10000;
XModelObject[] fs = fso.getChildren(XModelObjectConstants.ENT_FILE_SYSTEM_FOLDER);
for (int i = 0; i < fs.length; i++) {
FileSystemImpl s = (FileSystemImpl)fs[i];
XModelObject o = findResourceInFileSystem(s, resource);
if(o != null) {
if(path == null || pathLength > o.getPath().length()) {
result = o;
pathLength = o.getPath().length();
}
}
}
if(result != null) {
return result;
}
fs = fso.getChildren("FileSystemJar"); //$NON-NLS-1$
String location = path == null ? null : path.toString().replace('\\', '/');
if(location != null && isJar(location)) {
for (int i = 0; i < fs.length; i++) {
JarSystemImpl jar = (JarSystemImpl)fs[i];
String jl = jar.getLocation();
if(jl.equals(location)) return jar;
}
}
}
return null;
}
public static XModelObject getObjectByPath(IProject p, String path) {
if(p == null) return null;
IModelNature sp = getModelNature(p);
return (sp == null) ? null : sp.getModel().getByPath(path);
}
public static XModelObject findFileSystem(IResource resource, XModel model) {
XModelObject fss = FileSystemsHelper.getFileSystems(model);
if(fss == null) return null;
XModelObject[] fs = fss.getChildren();
XModelObject result = null;
IPath resourcePath = resource == null ? null : resource.getFullPath();
IPath path = null;
for (int i = 0; i < fs.length; i++) {
if(!(fs[i] instanceof FileSystemImpl)) continue;
IResource r = (IResource)fs[i].getAdapter(IResource.class);
if(r == null) continue;
IPath p = r.getFullPath();
if(r != null && p.isPrefixOf(resourcePath)) {
if(path == null || path.isPrefixOf(p)) {
result = fs[i];
path = p;
}
}
}
return result;
}
public static XModelObject addFileSystem(IResource resource, XModel model) {
XModelObject fss = FileSystemsHelper.getFileSystems(model);
if(fss == null || resource == null) return null;
Properties properties = new Properties();
String fsLoc = resource.getLocation() != null ? resource.getLocation().toString() : resource.getLocationURI().toString();
if(resource == resource.getProject()) {
fsLoc = "%" + IModelNature.ECLIPSE_PROJECT + "%"; //$NON-NLS-1$ //$NON-NLS-2$
} else {
fsLoc = getRelativeLocation(model, fsLoc);
}
XModelObject[] cs = fss.getChildren(XModelObjectConstants.ENT_FILE_SYSTEM_FOLDER);
for (int i = 0; i < cs.length; i++) {
String loc = cs[i].getAttributeValue(XModelObjectConstants.ATTR_NAME_LOCATION);
if(fsLoc.equals(loc)) return null;
}
properties.setProperty(XModelObjectConstants.ATTR_NAME_LOCATION, fsLoc);
String name = resource.getName();
name = XModelObjectUtil.createNewChildName(name, fss);
properties.setProperty(XModelObjectConstants.ATTR_NAME, name);
FileSystemImpl s = (FileSystemImpl)model.createModelObject(XModelObjectConstants.ENT_FILE_SYSTEM_FOLDER, properties);
boolean b = fss.addChild(s);
if(b) {
fss.setModified(true);
return s;
} else {
return null;
}
}
private static final String[] MODEL_NATURES;
static {
ModelNatureExtension[] es = ModelNatureExtension.getInstances();
MODEL_NATURES = new String[es.length];
for (int i = 0; i < es.length; i++) {
MODEL_NATURES[i] = es[i].getName();
}
}
public static String[] getModelNatureNames() {
return MODEL_NATURES;
}
public static boolean hasNature(XModel model, String nature) {
if(model == null) return false;
IProject p = (IProject)model.getProperties().get(XModelObjectConstants.PROJECT);
if(p == null || !p.isOpen()) return false;
try {
if(p.hasNature(nature)) return true;
} catch (CoreException e) {
ModelPlugin.getPluginLog().logError(e);
}
return false;
}
public static IModelNature getModelNature(IProject p) {
if(p == null || !p.isOpen()) return null;
String[] natures = getModelNatureNames();
for (int i = 0; i < natures.length; i++) {
try {
if(p.hasNature(natures[i])) {
long t1 = System.currentTimeMillis();
if(!ModelNature.checkModelNature(p, natures[i])) {
continue;
}
IModelNature n = (IModelNature)p.getNature(natures[i]);
if(n == null) return null;
n = testNature(n);
if(n == null) {
ModelPlugin.getPluginLog().logWarning("Project " + p + " has corrupted nature: " + natures[i]); //$NON-NLS-1$ //$NON-NLS-2$
removeNatureFromProject(p, natures[i]);
}
return n;
}
} catch (CoreException e) {
ModelPlugin.getPluginLog().logError(e);
}
}
return null;
}
private static IModelNature testNature(IModelNature n) {
if(n == null || n.getModel() == null) return null;
XModel model = n.getModel();
XModelObject object = model.getRoot();
if(object == null) return null;
if(!XModelObjectConstants.ROOT_OBJECT.equals(object.getModelEntity().getName())) return null;
return n;
}
public static IModelNature getModelNature(IProject p, String id) {
if(p == null || !p.isOpen()) return null;
try {
if(p.hasNature(id)) {
if(!ModelNature.checkModelNature(p, id)) {
return null;
}
IModelNature n = (IModelNature)p.getNature(id);
if(n == null) return null;
n = testNature(n);
if(n == null) {
ModelPlugin.getPluginLog().logWarning("Project " + p + " has corrupted nature: " + id); //$NON-NLS-1$ //$NON-NLS-2$
removeNatureFromProject(p, id);
}
return n;
}
} catch (CoreException e) {
ModelPlugin.getPluginLog().logError(e);
}
return null;
}
static Map<IProject,XModel> models = new HashMap<IProject,XModel>();
/**
* If project has no model nature, the method creates new instance of model
* populates it with a filesystems corresponding to the project root
* and links, and returns model object for the resource.
* The model created is not complete project, so it has property
* 'isProjectFragment' set to 'true'.
*/
public static XModelObject createObjectForResource(IResource resource) {
if(resource == null || !resource.exists()) return null;
IProject project = resource.getProject();
if(project == null || !project.isOpen()) return null;
IModelNature sp = getModelNature(project);
if(sp != null) {
XModelObject result = getObjectByResource(resource);
if(result == null) {
XModelObject fs = findFileSystem(resource.getProject(), sp.getModel());
if(fs == null) {
fs = addFileSystem(resource.getProject(), sp.getModel());
if(fs != null) result = getObjectByResource(resource);
}
if(result == null && resource != project) {
IResource r = resource.getParent();
if(r != null && r != project) {
fs = addFileSystem(r, sp.getModel());
if(fs != null) result = getObjectByResource(resource);
}
}
}
return result;
}
XModel model = models.get(project);
if(model != null) {
validateJarSystem(FileSystemsHelper.getFileSystems(model), resource);
XModelObject result = getObjectByResource(model, resource);
if(result == null && resource instanceof IFile) {
IResource r = resource.getParent();
if(r != null && project != r) {
XModelObject fs = addFileSystem(r, model);
if(fs != null) return getObjectByResource(model, resource);
}
}
return result;
}
Properties properties = new Properties();
properties.putAll(System.getProperties());
IResource r = resource;
if(!(r instanceof IProject)) {
while(r != null && !(r.getParent() instanceof IProject ||
(r.getParent() != null && r.getParent().getParent() != null && r.getParent().getParent().isVirtual()))) r = r.getParent();
}
if(r == null) return null;
IPath tempLocation = (r == project ? r : r.getParent()).getLocation();
if(tempLocation == null) return null;
properties.setProperty(XModelConstants.WORKSPACE, tempLocation.toString());
properties.setProperty(IModelNature.ECLIPSE_PROJECT, project.getLocation().toString());
properties.put(XModelObjectConstants.PROJECT, project);
properties.put("isProjectFragment", XModelObjectConstants.TRUE); //$NON-NLS-1$
model = XModelFactory.getModel(properties);
if(deleteProjectListener == null) {
ResourcesPlugin.getWorkspace().addResourceChangeListener(deleteProjectListener = new RCL());
}
models.put(project, model);
XModelObject fs = FileSystemsHelper.getFileSystems(model);
if(fs == null) {
ModelPlugin.getPluginLog().logInfo("Cannot create file systems for project " + project); //$NON-NLS-1$
return null;
}
String fsLoc = null;
FileSystemImpl s = null;
properties = new Properties();
fsLoc = project.getLocation().toString();
properties.setProperty(XModelObjectConstants.ATTR_NAME_LOCATION, fsLoc);
properties.setProperty(XModelObjectConstants.ATTR_NAME, project.getName());
s = (FileSystemImpl)model.createModelObject(XModelObjectConstants.ENT_FILE_SYSTEM_FOLDER, properties);
fs.addChild(s);
Set<IResource> resources = new HashSet<IResource>();
IResource webRoot = getFirstWebContentResource(project);
if(webRoot != null && webRoot.exists() && webRoot != project) {
resources.add(webRoot);
fsLoc = webRoot.getLocation().toString();
properties.setProperty(XModelObjectConstants.ATTR_NAME_LOCATION, fsLoc);
properties.setProperty(XModelObjectConstants.ATTR_NAME, "WEB-ROOT"); //$NON-NLS-1$
s = (FileSystemImpl)model.createModelObject(XModelObjectConstants.ENT_FILE_SYSTEM_FOLDER, properties);
fs.addChild(s);
}
if(webRoot != null && webRoot.exists()) {
IResource webInf = ((IContainer)webRoot).getFolder(new Path("WEB-INF")); //$NON-NLS-1$
if(webInf != null && webInf.exists()) {
resources.add(webInf);
fsLoc = webInf.getLocation().toString();
properties.setProperty(XModelObjectConstants.ATTR_NAME_LOCATION, fsLoc);
properties.setProperty(XModelObjectConstants.ATTR_NAME, "WEB-INF"); //$NON-NLS-1$
s = (FileSystemImpl)model.createModelObject(XModelObjectConstants.ENT_FILE_SYSTEM_FOLDER, properties);
fs.addChild(s);
}
}
updateSrcs(project, fs, resources);
updateLibs(project, fs);
if(!isJar(resource) || getObjectByResource(model, resource) == null) {
properties = new Properties();
fsLoc = (r instanceof IFile) ? r.getParent().getLocation().toString() : r.getLocation().toString();
properties.setProperty(XModelObjectConstants.ATTR_NAME_LOCATION, fsLoc);
properties.setProperty(XModelObjectConstants.ATTR_NAME, r.getName());
s = (FileSystemImpl)model.createModelObject(XModelObjectConstants.ENT_FILE_SYSTEM_FOLDER, properties);
fs.addChild(s);
}
IResource[] cs = null;
try {
cs = project.members();
} catch (CoreException e) {
ModelPlugin.getPluginLog().logError(e);
}
if(cs != null) for (int i = 0; i < cs.length; i++) {
if(!cs[i].isLinked()) continue;
if(!cs[i].isAccessible()) continue;
if(resources.contains(cs[i])) continue;
if(cs[i].getLocation() == null) {
continue;
}
if(cs[i].getLocation().toFile() == null || !cs[i].getLocation().toFile().isDirectory()) {
continue;
}
properties = new Properties();
fsLoc = cs[i].getLocation().toString();
properties.setProperty(XModelObjectConstants.ATTR_NAME_LOCATION, fsLoc);
properties.setProperty(XModelObjectConstants.ATTR_NAME, cs[i].getName());
s = (FileSystemImpl)model.createModelObject(XModelObjectConstants.ENT_FILE_SYSTEM_FOLDER, properties);
fs.addChild(s);
}
validateJarSystem(fs, resource);
return getObjectByResource(model, resource);
}
public static IResource getFirstWebContentResource(IProject project) {
IVirtualComponent vc = ComponentCore.createComponent(project);
if (vc == null || vc.getRootFolder() == null)
return null;
IContainer[] cs = WebUtils.getWebRootFolders(project, true);
for (IContainer c: cs) {
if(c.exists()) {
return c;
}
}
return null;
}
private static boolean isJar(IResource resource) {
return (resource instanceof IFile && isJar(resource.getName()));
}
private static void validateJarSystem(XModelObject fs, IResource resource) {
if(fs == null || !isJar(resource)) return;
String jsname = Libs.LIB_PREFIX + resource.getName().toLowerCase(); //$NON-NLS-1$
String location = resource.getLocation().toString().replace('\\', '/');
if(fs.getChildByPath(jsname) == null) {
XModelObject q = fs.getModel().createModelObject("FileSystemJar", null); //$NON-NLS-1$
q.setAttributeValue(XModelObjectConstants.ATTR_NAME, jsname);
q.setAttributeValue(XModelObjectConstants.ATTR_NAME_LOCATION, location);
fs.addChild(q);
}
}
private static void updateSrcs(IProject p, XModelObject object, Set<IResource> resources) {
if(p == null || !p.isAccessible()) return;
String[] srcs = EclipseResourceUtil.getJavaProjectSrcLocations(p);
Set<String> paths = new HashSet<String>();
for (int i = 0; i < srcs.length; i++) {
String path = EclipseResourceUtil.getRelativeLocation(object.getModel(), srcs[i]);
if(path == null) continue;
paths.add(path);
}
XModelObject[] cs = object.getChildren(XModelObjectConstants.ENT_FILE_SYSTEM_FOLDER);
for (int i = 0; i < cs.length; i++) {
if(cs[i].getAttributeValue(XModelObjectConstants.ATTR_NAME).startsWith("src")) { //$NON-NLS-1$
String loc = cs[i].getAttributeValue(XModelObjectConstants.ATTR_NAME_LOCATION);
if(!paths.contains(loc)) {
object.removeChild(cs[i]);
} else {
paths.remove(loc);
IResource r = (IResource)object.getAdapter(IResource.class);
if(r != null) resources.add(r);
}
}
}
for (String path : paths) {
String n = getNextSrcName(object);
Properties properties = new Properties();
properties.setProperty(XModelObjectConstants.ATTR_NAME_LOCATION, path);
properties.setProperty(XModelObjectConstants.ATTR_NAME, n);
FileSystemImpl s = (FileSystemImpl)object.getModel().createModelObject(XModelObjectConstants.ENT_FILE_SYSTEM_FOLDER, properties);
object.addChild(s);
IResource r = (IResource)s.getAdapter(IResource.class);
if(r != null) resources.add(r);
}
}
private static String getNextSrcName(XModelObject object) {
if(object.getChildByPath("src") == null) return "src"; //$NON-NLS-1$ //$NON-NLS-2$
int i = 1;
while(true) {
String s = "src-" + i; //$NON-NLS-1$
if(object.getChildByPath(s) == null) return s;
i++;
}
}
static String[] SYSTEM_JARS = {"rt.jar", "jsse.jar", "jce.jar", "charsets.jar"};
public static Set<String> SYSTEM_JAR_SET = new HashSet<String>();
static {
for (int i = 0; i < SYSTEM_JARS.length; i++) SYSTEM_JAR_SET.add(SYSTEM_JARS[i]);
}
private static void updateLibs(IProject project, XModelObject object) {
FileSystemsHelper.getLibs(object).update();
// List<String> paths = new ArrayList<String>();
// XModelObject[] ss = object.getChildren();
// for (int i = 0; i < ss.length; i++) {
// if(ss[i].getModelEntity().getName().equals("FileSystemJar")) {
// paths.add(ss[i].getAttributeValue(XModelObjectConstants.ATTR_NAME_LOCATION));
// }
// }
}
public static XModelObject findResourceInFileSystem(FileSystemImpl s, IResource resource) {
if(resource == null || resource.getLocation() == null) {
return null;
}
IResource sr = s.getResource();
if(sr == null) return null;
String relpath = null;
if(sr.getFullPath().isPrefixOf(resource.getFullPath())) {
String path = resource.getFullPath().toString();
String rootpath = sr.getFullPath().toString();
relpath = path.substring(rootpath.length()).replace('\\', '/');
if(relpath.length() == 0) return s;
} else if(sr.getLocation() != null && resource.getLocation() != null
&& sr.getLocation().isPrefixOf(resource.getLocation())) {
String path = resource.getLocation().toString();
String rootpath = sr.getLocation().toString();
relpath = path.substring(rootpath.length()).replace('\\', '/');
if(relpath.length() == 0) return s;
}
if(relpath == null) return null;
XModelObject o = s.getChildByPath(relpath.substring(1));
if(o == null && resource.exists()) {
s.update();
o = s.getChildByPath(relpath.substring(1));
}
if(o == null) return null;
XModelObject p = o;
while(p != null && !XModelObjectConstants.TRUE.equals(p.get("overlapped"))) p = p.getParent(); //$NON-NLS-1$
if(p == null) {
IResource r = (IResource)o.getAdapter(IResource.class);
if(r == null || (!resource.getFullPath().equals(r.getFullPath())
&& (resource.getLocation() == null || r.getLocation() == null || !resource.getLocation().equals(r.getLocation()))
)) {
//failure, more detailed file system is needed.
return null;
}
}
return (p == null) ? o : null;
}
public static boolean isOverlapped(XModelObject object) {
XModelObject p = object;
while(p != null && !XModelObjectConstants.TRUE.equals(p.get("overlapped"))) p = p.getParent(); //$NON-NLS-1$
return (p != null);
}
/**
*
* For an external location.
*/
public static XModelObject createObjectForLocation(String location) {
if(location == null) return null;
File f = new File(location);
if(!f.isFile()) return null;
Properties properties = new Properties();
properties.putAll(System.getProperties());
properties.setProperty(XModelConstants.WORKSPACE, f.getParent());
properties.put("isProjectFragment", XModelObjectConstants.TRUE); //$NON-NLS-1$
XModel model = XModelFactory.getModel(properties);
XModelObject fs = FileSystemsHelper.getFileSystems(model);
if(fs == null) {
ModelPlugin.getPluginLog().logInfo("Cannot create file systems for model at " + location); //$NON-NLS-1$
return null;
}
properties = new Properties();
String fsLoc = f.getParent();
properties.setProperty(XModelObjectConstants.ATTR_NAME_LOCATION, fsLoc);
properties.setProperty(XModelObjectConstants.ATTR_NAME, f.getParentFile().getName());
FileSystemImpl s = (FileSystemImpl)model.createModelObject(XModelObjectConstants.ENT_FILE_SYSTEM_FOLDER, properties);
fs.addChild(s);
String pp = FilePathHelper.toPathPath(f.getName());
return model.getByPath(XModelObjectConstants.SEPARATOR + pp);
}
public static String[] getJavaProjectSrcLocations(IProject project) {
IResource[] rs = getJavaSourceRoots(project);
if(rs == null || rs.length == 0) return new String[0];
List<String> result = new ArrayList<String>();
for (int i = 0; i < rs.length; i++) {
IPath p = rs[i].getLocation();
if(p != null) result.add(p.toString());
}
return result.toArray(new String[0]);
}
/**
* Returns list of canonical paths to resources of libraries (jars and class folders) included in class path.
* @throws IOException
*/
public static List<String> getClassPath(IProject project) throws CoreException, IOException {
IJavaProject javaProject = getJavaProject(project);
if(javaProject == null) {
return null;
}
ArrayList<String> l = new ArrayList<String>();
IClasspathEntry[] es = javaProject.getResolvedClasspath(true);
for (int i = 0; i < es.length; i++) {
if(es[i].getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
String s = expandPath(es[i].getPath(), project);
if(s != null) {
l.add(s);
}
}
}
return l;
}
static String expandPath(IPath ipath, IProject project) {
String s = null;
String path = ipath.toString();
//First let's check if path is defined within Eclipse work space.
if(path.startsWith(XModelObjectConstants.SEPARATOR) && path.indexOf(XModelObjectConstants.SEPARATOR, 1) > 1) {
IResource findMember = ResourcesPlugin.getWorkspace().getRoot().findMember(ipath);
if(findMember != null) {
s = findMember.getLocation().toString();
}
}
//If search in Eclipse work space has failed, this is a useless attempt, but
//let keep it just in case (this is good old code that worked for a long while).
if(s == null && path.startsWith(XModelObjectConstants.SEPARATOR + project.getName() + XModelObjectConstants.SEPARATOR)) {
IResource findMember = project.findMember(ipath.removeFirstSegments(1));
if(findMember != null) {
s = findMember.getLocation().toString();
}
}
//If we failed to find resource in Eclipse work space,
//lets try the path as absolute on disk
if(s == null && new java.io.File(path).exists()) {
s = path;
}
try {
if(s != null) {
return new java.io.File(s).getCanonicalPath();
}
} catch (IOException e) {
//ignore - we do not care about malformed URLs in classpath here.
}
return null;
}
public static List<String> getJREClassPath(IProject project) throws CoreException {
if(project == null || !project.isAccessible() || !project.hasNature(JavaCore.NATURE_ID)) return null;
ArrayList<String> l = new ArrayList<String>();
IJavaProject javaProject = JavaCore.create(project);
IClasspathEntry[] es0 = javaProject.getRawClasspath();
IClasspathEntry[] es = null;
for (int i = 0; i < es0.length && es == null; i++) {
if(es0[i].getEntryKind() == IClasspathEntry.CPE_CONTAINER &&
es0[i].getPath().toString().startsWith("org.eclipse.jdt.launching.JRE_CONTAINER")) { //$NON-NLS-1$
IClasspathContainer container = JavaCore.getClasspathContainer(es0[i].getPath(), javaProject);
if(container == null) continue;
es = container.getClasspathEntries();
}
}
if(es == null) return l;
for (int i = 0; i < es.length; i++) {
try {
String s = null;
String path = es[i].getPath().toString();
//JRE entries are not supposed to be resolved in workspace.
//However, though in Eclipse Preferences only external paths are available for selection,
//it is possible, by moving resources and creating equal paths in Eclipse and on disk,
//to make Eclipse resolve JRE entries to workspace resources.
//It is an undocumented behavior so that the following code is commented,
//though formally it is exactly how Eclipse works now.
// if(path.startsWith(XModelObjectConstants.SEPARATOR + project.getName() + XModelObjectConstants.SEPARATOR)) {
// IResource r = project.findMember(es[i].getPath().removeFirstSegments(1));
// if(r != null && r.getLocation() != null) {
// s = r.getLocation().toString();
// }
// }
if(s == null && new java.io.File(path).isFile()) {
s = path;
}
if(s != null) {
l.add(new java.io.File(s).getCanonicalPath());
}
} catch (IOException e) {
//ignore - we do not care about malformed URLs in class path here.
}
}
return l;
}
public static IJavaElement findJavaElement(XModelObject object) {
int type = object.getFileType();
IResource resource = getResource(object);
if(resource == null) return null;
IProject project = resource.getProject();
IJavaProject javaProject = getJavaProject(project);
if(javaProject == null) return null;
try {
if(type == XFileObject.SYSTEM) return javaProject.findPackageFragmentRoot(resource.getFullPath());
Path path = null;
if(type == XFileObject.FOLDER) {
String p = getJavaPackageName(object);
if(p == null) return null;
path = new Path(p.replace('.', '/'));
} else {
String p = getJavaClassQualifiedName(object);
if(p == null) return null;
path = new Path(p.replace('.', '/') + ".java"); //$NON-NLS-1$
}
return javaProject.findElement(path);
} catch (CoreException ex) {
ModelPlugin.getPluginLog().logError(ex);
}
return null;
}
public static IType getValidType(IProject project, String className) {
if (className == null || className.length() == 0) return null;
IJavaProject javaProject = getJavaProject(project);
if(javaProject == null) return null;
IFile f = null;
try {
IType t = javaProject.findType(className);
if(t == null || t.isBinary()) return t;
if(t.getParent() instanceof ICompilationUnit) {
ICompilationUnit u = (ICompilationUnit)t.getParent();
f = (IFile)u.getCorrespondingResource();
IMarker[] ms = f.findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_ZERO);
for (int i = 0; i < ms.length; i++) {
if(ms[i].getAttribute(IMarker.SEVERITY, IMarker.SEVERITY_INFO) == IMarker.SEVERITY_ERROR) return null;
}
}
return t;
} catch (JavaModelException t) {
ModelPlugin.getPluginLog().logError("Error while obtaining type " + className, t); //$NON-NLS-1$
} catch (CoreException t) {
ModelPlugin.getPluginLog().logError("Error occured while obtaining Java Problem markers for " + f.getLocation() , t); //$NON-NLS-1$
}
return null;
}
/**
* For *.java files returns qualified class name if
* resource is in located in project source folder
* @param resource
* @return
*/
public static String getJavaClassName(IResource resource) {
if(resource == null || !(resource instanceof IFile)) return null;
IResource root = getJavaSourceRoot(resource.getProject());
if(root == null) return null;
if(!root.getLocation().isPrefixOf(resource.getLocation())) return null;
String relative = resource.getLocation().toString().substring(root.getLocation().toString().length());
if(!relative.endsWith(".java")) return null; //$NON-NLS-1$
relative = relative.substring(0, relative.length() - 5);
relative = relative.replace('\\', '/');
if(relative.startsWith(XModelObjectConstants.SEPARATOR)) relative = relative.substring(1);
return relative.replace('/', '.');
}
/**
* Returns true only if project has no sources but output contains *.class file
*/
public static boolean isContainedInOutput(IProject project, String className) {
if (className == null || className.length() == 0) return false;
IJavaProject javaProject = getJavaProject(project);
if(javaProject == null) return false;
try {
IPath p = javaProject.getOutputLocation();
IResource r = project.getWorkspace().getRoot().findMember(p);
if(r == null || r.getLocation() == null) return false;
String output = r.getLocation().toString();
String f = output + XModelObjectConstants.SEPARATOR + className.replace('.', '/') + ".class"; //$NON-NLS-1$
File file = new File(f);
return file.isFile() && FileUtils.isSameFile(file);
} catch (JavaModelException t) {
ModelPlugin.getPluginLog().logError("Error checking class " + className, t); //$NON-NLS-1$
return false;
}
}
public static boolean hasSources(IJavaProject javaProject) throws JavaModelException {
IClasspathEntry[] es = javaProject.getResolvedClasspath(true);
for (int i = 0; i < es.length; i++) {
if(es[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) return true;
}
return false;
}
public static IResource getJavaSourceRoot(IProject project) {
IJavaProject javaProject = getJavaProject(project);
if(javaProject == null) return null;
try {
IClasspathEntry[] es = javaProject.getResolvedClasspath(true);
for (int i = 0; i < es.length; i++) {
if(es[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
IResource findMember = ModelPlugin.getWorkspace().getRoot().findMember(es[i].getPath());
if(findMember != null && findMember.exists()) {
return findMember;
}
}
}
} catch (JavaModelException ex) {
ModelPlugin.getPluginLog().logError(ex);
}
return null;
}
public static Set<IFolder> getSourceFolders(IProject project) {
Set<IFolder> folders = new HashSet<IFolder>();
IPackageFragmentRoot[] roots;
try {
// From source folders
IJavaProject javaProject = EclipseUtil.getJavaProject(project);
if(javaProject!=null) {
roots = javaProject.getPackageFragmentRoots();
for (int i = 0; i < roots.length; i++) {
if (roots[i].getKind() == IPackageFragmentRoot.K_SOURCE) {
IResource source = roots[i].getCorrespondingResource();
if(source instanceof IFolder) {
folders.add((IFolder)source);
}
}
}
}
} catch (JavaModelException e) {
ModelPlugin.getDefault().logError(e);
}
return folders;
}
private static class SourceFoldersCollector {
IProject project;
Set<IFolder> folders = new HashSet<IFolder>();
Set<IProject> processed = new HashSet<IProject>();
SourceFoldersCollector(IProject project) {
this.project = project;
process(project);
}
void process(IProject project) {
if(processed.contains(project)) {
return;
}
processed.add(project);
folders.addAll(getSourceFolders(project));
IJavaProject javaProject = getJavaProject(project);
if(javaProject == null) {
return;
}
IClasspathEntry[] es = null;
try {
es = javaProject.getResolvedClasspath(true);
} catch (CoreException e) {
ModelPlugin.getDefault().logError(e);
return;
}
for (int i = 0; i < es.length; i++) {
if(es[i].getEntryKind() == IClasspathEntry.CPE_PROJECT
&& (project == this.project || es[i].isExported())) {
IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject(es[i].getPath().lastSegment());
if(p != null && p.isAccessible()) {
process(p);
}
}
}
}
}
public static Set<IFolder> getAllVisibleSourceFolders(IProject project) {
return new SourceFoldersCollector(project).folders;
}
private static class LibraryCollector {
IProject project;
List<String> ordered = new ArrayList<String>();
Set<String> paths = new HashSet<String>();
Set<IProject> processed = new HashSet<IProject>();
LibraryCollector(IProject project) {
this.project = project;
process(project);
}
void process(IProject project) {
if(processed.contains(project)) {
return;
}
processed.add(project);
IJavaProject javaProject = getJavaProject(project);
if(javaProject == null) {
return;
}
IClasspathEntry[] es = null;
try {
es = javaProject.getResolvedClasspath(true);
} catch (CoreException e) {
ModelPlugin.getDefault().logError(e);
return;
}
for (int i = 0; i < es.length; i++) {
if(project == this.project || es[i].isExported()) {
if(es[i].getEntryKind() == IClasspathEntry.CPE_PROJECT) {
IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject(es[i].getPath().lastSegment());
if(p != null && p.isAccessible()) {
process(p);
}
} else if(es[i].getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
String s = expandPath(es[i].getPath(), project);
if(s != null && !paths.contains(s)) {
paths.add(s);
ordered.add(s);
}
}
}
}
}
}
public static List<String> getAllVisibleLibraries(IProject project) {
return new LibraryCollector(project).ordered;
}
public static void openResource(IResource resource) {
XModelObject o = getObjectByResource(resource);
if(o == null) o = createObjectForResource(resource);
if(o != null) XActionInvoker.invoke("Open", o, null); //$NON-NLS-1$
}
public static String getInstallPath(Plugin plugin) {
URL url = getInstallURL(plugin);
return (url == null) ? null : url.getPath();
}
public static URL getInstallURL(Plugin plugin) {
return plugin == null ? null : getInstallURL(plugin.getBundle());
}
public static String getInstallPath(Bundle bundle) {
URL url = getInstallURL(bundle);
return (url == null) ? null : url.getPath();
}
public static URL getInstallURL(Bundle bundle) {
try {
return bundle == null ? null : FileLocator.resolve(bundle.getEntry(XModelObjectConstants.SEPARATOR));
} catch (IOException e) {
//ignore and try to execute it in the other way
return bundle.getEntry(XModelObjectConstants.SEPARATOR);
}
}
/**
* Tries to find Eclipse resource by absolute path on disk.
* Uses handle methods, that is, file on disk does not need to exist.
* @location Absolute path on disk
*/
public static IFile getFile(String location) {
IPath path = new Path(location).makeAbsolute();
IFile result = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(path);
//TODO check if we need that addition
// if(result == null || !result.exists()) {
// IFile[] fs = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(path);
// if(fs != null && fs.length > 0) {
// result = fs[0];
// }
// }
return result;
}
public static IResource getFolder(String location) {
location = new java.io.File(location).getAbsolutePath();
IProject[] projects = ModelPlugin.getWorkspace().getRoot().getProjects();
for (int i = 0; projects != null && i < projects.length; i++) {
if (!projects[i].isOpen()) continue;
String l = projects[i].getLocation().toFile().getAbsolutePath();
if (!location.startsWith(l)) {
try {
IResource[] ms = projects[i].members();
for (int j = 0; j < ms.length; j++) {
if(!(ms[j] instanceof IContainer)) continue;
IContainer c = (IContainer)ms[j];
l = c.getLocation().toFile().getAbsolutePath();
if (!location.startsWith(l)) continue;
String relative = location.substring(l.length()).replace('\\', '/');
return (relative.length() == 0) ? (IResource)c : c.getFolder(new Path(relative));
}
} catch (CoreException e) {
ModelPlugin.getPluginLog().logError(e);
}
continue;
}
String relative = location.substring(l.length()).replace('\\', '/');
return (relative.length() == 0) ? (IResource)projects[i] : projects[i].getFolder(relative);
}
return null;
}
public static IPath getRelativePath(IProject project, String path) {
IPath result = null;
IPath projectPath = project.getLocation();
IPath absolutePath = new Path(path);
if (projectPath.isPrefixOf(absolutePath))
result = new Path(project.getFullPath() + absolutePath.toString().substring(projectPath.toString().length()));
else {
try {
IResource children[] = project.members(true);
for (int i = 0; i < children.length && result == null; i++) {
if (absolutePath.equals(children[i].getLocation()))
result = children[i].getFullPath();
}
for (int i = 0; i < children.length && result == null; i++) {
IPath memberPath = children[i].getLocation();
if(memberPath == null) continue;
if(memberPath.isPrefixOf(absolutePath)) {
result = children[i].getFullPath().append(absolutePath.removeFirstSegments(memberPath.segmentCount()));
}
}
} catch (CoreException ex) {
ModelPlugin.getPluginLog().logError(ex);
}
}
if (result == null) result = absolutePath;
return result;
}
public static IClasspathEntry[] getDefaultJRELibrary() {
return PreferenceConstants.getDefaultJRELibrary();
}
public static IResource[] getClasspathResources(IProject project) {
IJavaProject javaProject = getJavaProject(project);
if(javaProject == null) return new IProject[0];
ArrayList<IResource> l = new ArrayList<IResource>();
IClasspathEntry[] es = null;
try {
es = javaProject.getResolvedClasspath(true);
} catch (JavaModelException e) {
//ignore - if project cannot respond, it may not have resources of interest.
return new IProject[0];
}
if(es != null) for (int i = 0; i < es.length; i++) {
if(es[i].getEntryKind() == IClasspathEntry.CPE_PROJECT) {
IPath path = es[i].getPath();
IProject p = (IProject)project.getWorkspace().getRoot().findMember(path);
l.add(p);
} else if(es[i].getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
IPath path = es[i].getPath();
IResource r = project.getWorkspace().getRoot().findMember(path);
if(r instanceof IContainer) {
l.add(r);
} else if(r != null && !project.getFullPath().isPrefixOf(r.getFullPath())) {
l.add(r); //probably it is jar
}
}
}
return l.toArray(new IResource[0]);
}
public static String getRelativeLocation(XModel model, String path) {
if(path == null || path.startsWith("%")) return path; //$NON-NLS-1$
String workspace = XModelConstants.getWorkspace(model);
if(workspace == null) return path;
workspace = new File(workspace).getAbsolutePath().replace('\\', '/');
path = path.replace('\\', '/');
String relative = org.jboss.tools.common.util.FileUtil.getRelativePath(workspace, path);
return (relative == null) ? path : XModelConstants.WORKSPACE_REF + relative;
}
public static boolean projectExistsIgnoreCase(String name) {
return findProjectIgnoreCase(name) != null;
}
public static IProject findProjectIgnoreCase(String name) {
if(name == null || name.length() == 0) return null;
IProject[] ps = ModelPlugin.getWorkspace().getRoot().getProjects();
for (int i = 0; i < ps.length; i++) {
if(ps[i].getName().equalsIgnoreCase(name)) {
return ps[i];
}
}
return null;
}
public static boolean isJar(String path) {
path = path.toLowerCase();
return path.endsWith(".jar") || path.endsWith(".zip"); //$NON-NLS-1$ //$NON-NLS-2$
}
private static IResourceChangeListener deleteProjectListener = null;
private static class RCL implements IResourceChangeListener {
public void resourceChanged(IResourceChangeEvent event) {
if(event.getType() == IResourceChangeEvent.PRE_DELETE) {
IResource resource = event.getResource();
IProject project = (IProject)resource.getAdapter(IProject.class);
if(project != null) {
models.remove(project);
UniquePaths.getInstance().clean(project);
}
}
}
}
}