Author: scabanovich
Date: 2007-07-05 11:10:20 -0400 (Thu, 05 Jul 2007)
New Revision: 2328
Added:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/scanner/lib/ClassPath.java
Modified:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/core/SeamCoreBuilder.java
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/SeamProject.java
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/scanner/lib/LibraryScanner.java
Log:
EXIN-217 Added class path monitoring; added class loader for classes defined in jars.
Modified:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/core/SeamCoreBuilder.java
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/core/SeamCoreBuilder.java 2007-07-05
15:06:43 UTC (rev 2327)
+++
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/core/SeamCoreBuilder.java 2007-07-05
15:10:20 UTC (rev 2328)
@@ -42,7 +42,7 @@
static IFileScanner[] FILE_SCANNERS = {
new JavaScanner(),
new XMLScanner(),
- new LibraryScanner()
+// new LibraryScanner()
};
SampleResourceVisitor RESOURCE_VISITOR = new SampleResourceVisitor();
@@ -161,7 +161,12 @@
* java.util.Map, org.eclipse.core.runtime.IProgressMonitor)
*/
protected IProject[] build(int kind, Map args, IProgressMonitor monitor)
- throws CoreException {
+ throws CoreException {
+ if(getSeamProject().getClassPath().update()) {
+ System.out.println("update from class path");
+ getSeamProject().getClassPath().process();
+ }
+
if (kind == FULL_BUILD) {
fullBuild(monitor);
} else {
Modified:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/SeamProject.java
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/SeamProject.java 2007-07-05
15:06:43 UTC (rev 2327)
+++
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/SeamProject.java 2007-07-05
15:10:20 UTC (rev 2328)
@@ -33,12 +33,14 @@
import org.jboss.tools.seam.core.event.ISeamProjectChangeListener;
import org.jboss.tools.seam.core.event.SeamProjectChangeEvent;
import org.jboss.tools.seam.internal.core.scanner.LoadedDeclarations;
+import org.jboss.tools.seam.internal.core.scanner.lib.ClassPath;
/**
* @author Viacheslav Kabanovich
*/
public class SeamProject implements ISeamProject {
IProject project;
+ ClassPath classPath = new ClassPath(this);
Map<String, SeamComponent> allComponents = new HashMap<String,
SeamComponent>();
protected Set<ISeamFactory> allFactories = new HashSet<ISeamFactory>();
Set<ISeamContextVariable> allVariables = new
HashSet<ISeamContextVariable>();
@@ -60,8 +62,13 @@
public void setProject(IProject project) {
this.project = project;
+ classPath.init();
load();
}
+
+ public ClassPath getClassPath() {
+ return classPath;
+ }
/**
* Loads results of last build, which are considered
@@ -104,6 +111,7 @@
Map<Object,ISeamComponentDeclaration> currentComponents =
findComponentDeclarations(source);
+ List<Change> addedComponents = null;
for (int i = 0; i < components.length; i++) {
SeamComponentDeclaration loaded = (SeamComponentDeclaration)components[i];
SeamComponentDeclaration current =
(SeamComponentDeclaration)currentComponents.remove(loaded.getId());
@@ -129,10 +137,9 @@
c = newComponent(name);
allComponents.put(name, c);
allVariables.add(c);
+ addedComponents = Change.addChange(addedComponents, new Change(this, null, null,
c));
}
c.addDeclaration(components[i]);
- List<Change> changes = Change.addChange(null, new Change(this, null, null, c));
- fireChanges(changes);
if(loaded instanceof ISeamJavaComponentDeclaration) {
javaDeclarations.put(c.getClassName(), (SeamJavaComponentDeclaration)components[i]);
@@ -141,7 +148,7 @@
if(ci == c) continue;
SeamComponent cii = (SeamComponent)ci;
cii.addDeclaration(loaded);
- changes = Change.addChange(null, new Change(ci, null, null, loaded));
+ List<Change> changes = Change.addChange(null, new Change(ci, null, null,
loaded));
fireChanges(changes);
}
} else if(loaded instanceof ISeamXmlComponentDeclaration) {
@@ -150,15 +157,17 @@
SeamJavaComponentDeclaration j = javaDeclarations.get(className);
if(j != null) {
c.addDeclaration(j);
- changes = Change.addChange(null, new Change(c, null, null, j));
+ List<Change> changes = Change.addChange(null, new Change(c, null, null, j));
fireChanges(changes);
}
}
}
+ fireChanges(addedComponents);
componentDeclarationsRemoved(currentComponents);
Map<Object, ISeamFactory> currentFactories = findFactoryDeclarations(source);
+ List<Change> addedFactories = null;
for (int i = 0; i < factories.length; i++) {
SeamFactory loaded = factories[i];
SeamFactory current = (SeamFactory)currentFactories.remove(loaded.getId());
@@ -166,26 +175,19 @@
List<Change> changes = current.merge(loaded);
fireChanges(changes);
continue;
-
}
+ allFactories.add(loaded);
+ allVariables.add(loaded);
+ addedFactories = Change.addChange(addedFactories, new Change(this, null, null,
loaded));
}
+ fireChanges(addedFactories);
factoryDeclarationsRemoved(currentFactories);
-
}
/**
* Package local method called by builder.
- * @param component
* @param source
- */
- public void registerFactories(ISeamFactory[] list, IPath source) {
-
- }
-
- /**
- * Package local method called by builder.
- * @param source
*/
public void pathRemoved(IPath source) {
Iterator<SeamComponent> iterator = allComponents.values().iterator();
@@ -283,14 +285,6 @@
fireChanges(changes);
}
- //deprecated
- public Set<ISeamComponent> getComponentsByName(String name) {
- Set<ISeamComponent> result = new HashSet<ISeamComponent>();
- ISeamComponent c = getComponentByName(name);
- if(c != null) result.add(c);
- return result;
- }
-
/**
* @see org.jboss.tools.seam.core.ISeamProject#getComponentsByClass(java.lang.String)
*/
@@ -401,7 +395,7 @@
allVariables.remove(factory);
}
- SeamComponent getComponent(String name) {
+ public SeamComponent getComponent(String name) {
return allComponents.get(name);
}
Added:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/scanner/lib/ClassPath.java
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/scanner/lib/ClassPath.java
(rev 0)
+++
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/scanner/lib/ClassPath.java 2007-07-05
15:10:20 UTC (rev 2328)
@@ -0,0 +1,250 @@
+/*******************************************************************************
+ * 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.seam.internal.core.scanner.lib;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.IClasspathContainer;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.jboss.tools.common.model.XModel;
+import org.jboss.tools.common.model.XModelObject;
+import org.jboss.tools.common.model.filesystems.impl.FileSystemsLoader;
+import org.jboss.tools.common.model.filesystems.impl.JarSystemImpl;
+import org.jboss.tools.common.model.project.IModelNature;
+import org.jboss.tools.common.model.util.EclipseResourceUtil;
+import org.jboss.tools.common.model.util.XModelObjectUtil;
+import org.jboss.tools.seam.core.SeamCorePlugin;
+import org.jboss.tools.seam.internal.core.SeamProject;
+import org.jboss.tools.seam.internal.core.scanner.LoadedDeclarations;
+
+/**
+ * Monitors class path of project and loads seam components of it.
+ *
+ * @author Viacheslav Kabanovich
+ */
+public class ClassPath {
+ SeamProject project;
+ XModel model = null;
+ ClassLoader classLoader = null;
+
+ List<String> paths = null;
+
+ Set<String> processedPaths = new HashSet<String>();
+
+ /**
+ * Creates instance of class path for seam project
+ * @param project
+ */
+ public ClassPath(SeamProject project) {
+ this.project = project;
+ }
+
+ /**
+ * Returns seam project
+ * @return
+ */
+ public SeamProject getProject() {
+ return project;
+ }
+
+ /**
+ * Initialization of inner model.
+ */
+ public void init() {
+ IModelNature n = EclipseResourceUtil.getModelNature(project.getProject());
+ model = n == null ?
EclipseResourceUtil.createObjectForResource(project.getProject()).getModel() :
n.getModel();
+ }
+
+ static String[] SYSTEM_JARS = {"rt.jar", "jsse.jar",
"jce.jar", "charsets.jar"};
+ 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]);
+ }
+
+ /**
+ * Returns true if class path was up-to-date.
+ * Otherwise, updates inner model and disables class loader.
+ * @return
+ */
+ public boolean update() {
+ List<String> newPaths = null;
+ try {
+ newPaths = EclipseResourceUtil.getClassPath(project.getProject());
+ List<String> jre = getJREClassPath(project.getProject());
+ if(jre != null) newPaths.removeAll(jre);
+ } catch (Exception e) {
+ //TODO
+ }
+ if(paths == null && newPaths == null) return false;
+ if((newPaths == null || paths == null) || (paths.size() != newPaths.size())) {
+ paths = newPaths;
+ } else {
+ boolean b = false;
+ for (int i = 0; i < paths.size() && !b; i++) {
+ if(!paths.get(i).equals(newPaths.get(i))) b = true;
+ }
+ if(!b) return false;
+ paths = newPaths;
+ }
+ XModelObject object = model.getByPath("FileSystems");
+ XModelObject[] fs = object.getChildren("FileSystemJar");
+ Set<XModelObject> fss = new HashSet<XModelObject>();
+ for (int i = 0; i < fs.length; i++) fss.add(fs[i]);
+
+ for (int i = 0; i < paths.size(); i++) {
+ String path = paths.get(i);
+ if(!path.endsWith(".jar")) continue;
+ String fileName = new File(path).getName();
+ if(SYSTEM_JAR_SET.contains(fileName)) continue;
+ String jsname = "lib-" + fileName;
+ XModelObject o = model.getByPath("FileSystems").getChildByPath(jsname);
+ if(o != null) {
+ fss.remove(o);
+ } else {
+ o = object.getModel().createModelObject("FileSystemJar", null);
+ o.setAttributeValue("name", jsname);
+ o.setAttributeValue("location", path);
+ o.set(FileSystemsLoader.IS_ADDED_TO_CLASSPATH, "true");
+ object.addChild(o);
+// object.setModified(true);
+ }
+ }
+
+ for (XModelObject o: fss) {
+ String path = XModelObjectUtil.expand(o.getAttributeValue("location"),
o.getModel(), null);
+ if("true".equals(o.get(FileSystemsLoader.IS_ADDED_TO_CLASSPATH))) {
+ o.removeFromParent();
+ } else if(!new File(path).exists()) {
+ o.removeFromParent();
+ }
+ }
+
+ classLoader = null;
+
+ return true;
+ }
+
+ /**
+ * Loads seam components from items recently added to class path.
+ */
+ public void process() {
+ Iterator<String> it = processedPaths.iterator();
+ while(it.hasNext()) {
+ String p = it.next();
+ if(paths.contains(p)) continue;
+ project.pathRemoved(new Path(p));
+ it.remove();
+ }
+ for (int i = 0; i < paths.size(); i++) {
+ String p = paths.get(i);
+ if(processedPaths.contains(p)) continue;
+ processedPaths.add(p);
+
+ LibraryScanner scanner = new LibraryScanner();
+ scanner.setClassPath(this);
+
+ String fileName = new File(p).getName();
+ if(SYSTEM_JAR_SET.contains(fileName)) continue;
+ String jsname = "lib-" + fileName;
+ XModelObject o = model.getByPath("FileSystems").getChildByPath(jsname);
+ if(!scanner.isLikelyComponentSource(o)) continue;
+
+ LoadedDeclarations c = null;
+ try {
+ c = scanner.parse(o, new Path(p));
+ } catch (Exception e) {
+ SeamCorePlugin.getDefault().logError(e);
+ }
+ if(c != null) componentsLoaded(c, new Path(p));
+ }
+ }
+
+ void componentsLoaded(LoadedDeclarations c, IPath path) {
+ if(c == null || c.getComponents().size() + c.getFactories().size() == 0) return;
+ project.registerComponents(c, path);
+ }
+
+ public ClassLoader getClassLoader() {
+ if(classLoader != null) return classLoader;
+
+ XModelObject object = model.getByPath("FileSystems");
+ XModelObject[] fs = object.getChildren("FileSystemJar");
+
+ List<URL> urls = new ArrayList<URL>();
+ for (int i = 0; i < fs.length; i++) {
+ JarSystemImpl jar = (JarSystemImpl)fs[i];
+ String tempLocation = jar.getTempLocation();
+ File f = new File(tempLocation);
+ if(f.isFile()) {
+ try {
+ URL u = new File(tempLocation).toURL();
+ if(u != null) urls.add(u);
+ } catch (MalformedURLException e) {
+ //ignore
+ }
+ }
+ }
+
+ classLoader = new URLClassLoader(urls.toArray(new URL[0]),
Class.class.getClassLoader());
+
+ return classLoader;
+ }
+
+ public static List<String> getJREClassPath(IProject project) throws Exception {
+ if(!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().equals("org.eclipse.jdt.launching.JRE_CONTAINER"))
{
+ 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();
+ if(path.startsWith("/" + project.getName() + "/")) {
+ s =
project.findMember(es[i].getPath().removeFirstSegments(1)).getLocation().toString();
+ } else if(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;
+ }
+
+}
Modified:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/scanner/lib/LibraryScanner.java
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/scanner/lib/LibraryScanner.java 2007-07-05
15:06:43 UTC (rev 2327)
+++
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/scanner/lib/LibraryScanner.java 2007-07-05
15:10:20 UTC (rev 2328)
@@ -14,9 +14,24 @@
import java.util.Map;
import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.IClassFile;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.IParent;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.ITypeRoot;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
import org.jboss.tools.common.model.XModelObject;
import org.jboss.tools.common.model.filesystems.impl.FileSystemsImpl;
+import org.jboss.tools.common.model.plugin.ModelPlugin;
import org.jboss.tools.common.model.util.EclipseResourceUtil;
+import org.jboss.tools.common.model.util.XModelObjectUtil;
import org.jboss.tools.seam.internal.core.SeamPropertiesDeclaration;
import org.jboss.tools.seam.internal.core.scanner.IFileScanner;
import org.jboss.tools.seam.internal.core.scanner.LoadedDeclarations;
@@ -26,6 +41,16 @@
* @author Viacheslav Kabanovich
*/
public class LibraryScanner implements IFileScanner {
+ ClassPath classPath = null;
+
+ //Now it is absolute file on disk
+ IPath sourcePath = null;
+
+ public LibraryScanner() {}
+
+ public void setClassPath(ClassPath classPath) {
+ this.classPath = classPath;
+ }
public boolean isRelevant(IFile f) {
if(f.getName().endsWith(".jar")) return true;
@@ -40,9 +65,7 @@
o = EclipseResourceUtil.getObjectByResource(f);
if(o == null || !o.getModelEntity().getName().equals("FileSystemJar"))
return false;
}
- if(o.getChildByPath("META-INF/seam.properties") != null) return true;
- if(o.getChildByPath("META-INF/components.xml") != null) return true;
- return false;
+ return isLikelyComponentSource(o);
}
public LoadedDeclarations parse(IFile f) throws Exception {
@@ -53,6 +76,19 @@
o = EclipseResourceUtil.getObjectByResource(f);
if(o == null || !o.getModelEntity().getName().equals("FileSystemJar"))
return null;
}
+ return parse(o, f.getFullPath());
+ }
+
+ public boolean isLikelyComponentSource(XModelObject o) {
+ if(o == null) return false;
+ if(o.getChildByPath("META-INF/seam.properties") != null) return true;
+ if(o.getChildByPath("META-INF/components.xml") != null) return true;
+ return false;
+ }
+
+ public LoadedDeclarations parse(XModelObject o, IPath path) throws Exception {
+ if(o == null) return null;
+ sourcePath = path;
XModelObject seamProperties = o.getChildByPath("META-INF/seam.properties");
XModelObject componentsXML = o.getChildByPath("META-INF/components.xml");
if(componentsXML == null && seamProperties == null) return null;
@@ -62,7 +98,7 @@
processJavaClasses(o, ds);
if(componentsXML != null) {
- LoadedDeclarations ds1 = new XMLScanner().parse(componentsXML, f.getFullPath());
+ LoadedDeclarations ds1 = new XMLScanner().parse(componentsXML, path);
if(ds1 != null) {
ds.getComponents().addAll(ds1.getComponents());
ds.getFactories().addAll(ds1.getFactories());
@@ -82,7 +118,7 @@
if(d == null) {
d = new SeamPropertiesDeclaration();
d.setId(properties[i]);
- d.setSourcePath(f.getFullPath());
+ d.setSourcePath(path);
d.setName(componentName);
ds1.put(componentName, d);
}
@@ -94,8 +130,47 @@
return ds;
}
- protected void processJavaClasses(XModelObject o, LoadedDeclarations ds) {
- //TODO
+ protected void processJavaClasses(XModelObject o, LoadedDeclarations ds) throws
JavaModelException {
+ IJavaProject javaProject = JavaCore.create(classPath.getProject().getProject());
+ String location = o.getAttributeValue("location");
+ location = XModelObjectUtil.expand(location, o.getModel(), null);
+
+ IFile[] fs = ModelPlugin.getWorkspace().getRoot().findFilesForLocation(new
Path(location));
+ IPackageFragmentRoot root = null;
+ if(fs != null) for (int i = 0; i < fs.length && root == null; i++) {
+ root = javaProject.findPackageFragmentRoot(fs[i].getFullPath());
+ }
+ if(root == null) {
+ root = javaProject.findPackageFragmentRoot(new Path(location));
+ }
+ if(root == null) return;
+ process(root, ds);
+
}
+
+ protected void process(IParent element, LoadedDeclarations ds) throws JavaModelException
{
+ if(element == null) return;
+ IJavaElement[] es = element.getChildren();
+ for (int i = 0; i < es.length; i++) {
+ if(es[i] instanceof IPackageFragment) {
+ process((IPackageFragment)es[i], ds);
+ } else if(es[i] instanceof IClassFile) {
+ IClassFile typeRoot = (IClassFile)es[i];
+ IType type = typeRoot.getType();
+ String className = type.getFullyQualifiedName();
+
+ Class<?> cls = null;
+ try {
+ cls = classPath.getClassLoader().loadClass(className);
+ } catch (NoClassDefFoundError e) {
+ //ignore
+ } catch (ClassNotFoundException e) {
+ //ignore
+ }
+ String result = cls == null ? "not found " + className : className;
+ System.out.println(result);
+ }
+ }
+ }
}