/*******************************************************************************
* Copyright (c) 2007 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.seam.internal.core;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.jboss.tools.common.model.XModel;
import org.jboss.tools.common.model.plugin.ModelPlugin;
import org.jboss.tools.common.model.util.EclipseResourceUtil;
import org.jboss.tools.jst.web.WebUtils;
import org.jboss.tools.jst.web.model.helpers.InnerModelHelper;
import org.jboss.tools.seam.core.SeamCorePlugin;
import org.jboss.tools.seam.internal.core.scanner.IFileScanner;
import org.jboss.tools.seam.internal.core.scanner.LoadedDeclarations;
import org.jboss.tools.seam.internal.core.scanner.ScannerException;
import org.jboss.tools.seam.internal.core.scanner.java.JavaScanner;
import org.jboss.tools.seam.internal.core.scanner.xml.PropertiesScanner;
import org.jboss.tools.seam.internal.core.scanner.xml.XMLScanner;
/**
* @author Viacheslav Kabanovich
*/
public class SeamResourceVisitor implements IResourceVisitor, IResourceDeltaVisitor {
static IFileScanner[] FILE_SCANNERS = {
new JavaScanner(),
new XMLScanner(),
new PropertiesScanner(),
};
SeamProject p;
IPath[] outs = new IPath[0];
IPath[] srcs = new IPath[0];
IPath[] webinfs = new IPath[0];
public SeamResourceVisitor(SeamProject p) {
this.p = p;
if(p.getProject() != null && p.getProject().isOpen()) {
getJavaSourceRoots(p.getProject());
XModel model = InnerModelHelper.createXModel(p.getProject());
IContainer[] cs = WebUtils.getWebRootFolders(p.getProject());
List<IPath> ws = new ArrayList<IPath>();
if(model != null && cs.length > 0) {
for (IContainer c: cs) {
IFolder f = c.getFolder(new Path("WEB-INF"));
if(f.exists()) {
ws.add(f.getFullPath());
}
}
webinfs = ws.toArray(new IPath[0]);
}
}
}
public boolean visit(IResource resource) {
if(resource instanceof IFile) {
IFile f = (IFile)resource;
if(!shouldVisitFile(f)) return false;
for (int i = 0; i < FILE_SCANNERS.length; i++) {
IFileScanner scanner = FILE_SCANNERS[i];
if(scanner.isRelevant(f)) {
long t = System.currentTimeMillis();
if(!scanner.isLikelyComponentSource(f)) {
p.pathRemoved(f.getFullPath());
return false;
}
LoadedDeclarations c = null;
try {
c = scanner.parse(f, p);
} catch (ScannerException e) {
SeamCorePlugin.getDefault().logError(e);
}
if(c != null) componentsLoaded(c, f);
long dt = System.currentTimeMillis() - t;
timeUsed += dt;
// System.out.println("Time=" + timeUsed);
}
}
return true;
}
return shouldVisitFolder(resource);
}
static long timeUsed = 0;
void componentsLoaded(LoadedDeclarations c, IFile resource) {
if(c == null || c.getComponents().size() + c.getFactories().size() + c.getNamespaces().size() + c.getImports().size() == 0) return;
p.registerComponents(c, resource.getFullPath());
}
void getJavaSourceRoots(IProject project) {
IJavaProject javaProject = EclipseResourceUtil.getJavaProject(project);
if(javaProject == null) return;
List<IPath> ps = new ArrayList<IPath>();
List<IPath> os = new ArrayList<IPath>();
try {
IPath output = javaProject.getOutputLocation();
if(output != null) os.add(output);
IClasspathEntry[] es = javaProject.getResolvedClasspath(true);
for (int i = 0; i < es.length; i++) {
if(es[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
IResource findMember = ResourcesPlugin.getWorkspace().getRoot().findMember(es[i].getPath());
if(findMember != null && findMember.exists()) {
ps.add(findMember.getFullPath());
}
IPath out = es[i].getOutputLocation();
if(out != null && !os.contains(out)) {
os.add(out);
}
}
}
srcs = ps.toArray(new IPath[ps.size()]);
outs = os.toArray(new IPath[os.size()]);
} catch(CoreException ce) {
ModelPlugin.getPluginLog().logError("Error while locating java source roots for " + project, ce);
}
}
public boolean visit(IResourceDelta delta) throws CoreException {
IResource resource = delta.getResource();
switch (delta.getKind()) {
case IResourceDelta.ADDED:
case IResourceDelta.CHANGED:
if(resource instanceof IFile) {
IFile f = (IFile)resource;
if(!shouldVisitFile(f)) return false;
for (int i = 0; i < FILE_SCANNERS.length; i++) {
IFileScanner scanner = FILE_SCANNERS[i];
if(scanner.isRelevant(f)) {
long t = System.currentTimeMillis();
if(!scanner.isLikelyComponentSource(f)) {
p.pathRemoved(f.getFullPath());
return false;
}
LoadedDeclarations c = null;
try {
c = scanner.parse(f, p);
} catch (ScannerException e) {
SeamCorePlugin.getDefault().logError(e);
}
if(c != null) componentsLoaded(c, f);
long dt = System.currentTimeMillis() - t;
timeUsed += dt;
// System.out.println("Time=" + timeUsed);
}
}
}
if(resource instanceof IFolder) {
return shouldVisitFolder(resource);
}
//return true to continue visiting children.
return true;
case IResourceDelta.REMOVED:
p.pathRemoved(resource.getFullPath());
break;
}
return true;
}
boolean shouldVisitFile(IResource resource) {
for (int i = 0; i < outs.length; i++) {
if(outs[i].isPrefixOf(resource.getFullPath())) {
return false;
}
}
return true;
}
boolean shouldVisitFolder(IResource resource) {
IPath path = resource.getFullPath();
for (int i = 0; i < outs.length; i++) {
if(outs[i].isPrefixOf(path)) {
return false;
}
}
for (int i = 0; i < srcs.length; i++) {
if(srcs[i].isPrefixOf(path) || path.isPrefixOf(srcs[i])) {
return true;
}
}
for (IPath webinf: webinfs) {
if(webinf.isPrefixOf(path) || path.isPrefixOf(webinf)) {
return true;
}
}
if(resource == resource.getProject()) {
return true;
}
return false;
}
}