/******************************************************************************* * 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.scanner.java; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.jdt.core.Flags; 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.IType; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTParser; import org.eclipse.jdt.core.dom.ASTRequestor; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.osgi.util.NLS; import org.jboss.tools.common.model.util.EclipseJavaUtil; import org.jboss.tools.common.model.util.EclipseResourceUtil; import org.jboss.tools.common.util.FileUtil; import org.jboss.tools.seam.core.ISeamProject; import org.jboss.tools.seam.core.SeamCoreMessages; 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; /** * This object collects changes in target that should be fired to listeners. * * @author Viacheslav Kabanovich */ public class JavaScanner implements IFileScanner { public JavaScanner() {} /** * Returns true if file is java source - has *.java mask. * @param resource * @return */ public boolean isRelevant(IFile resource) { return resource.getName().endsWith(".java"); } /** * This method should be called only if isRelevant returns true; * Makes simple check if this java file contains annotation Name. * @param resource * @return */ public boolean isLikelyComponentSource(IFile f) { if(!f.isSynchronized(IFile.DEPTH_ZERO) || !f.exists()) return false; String content = FileUtil.readFile(f.getLocation().toFile()); if(content == null) return false; int a = content.indexOf("org.jboss.seam.annotations."); //$NON-NLS-1$ if(a < 0) { a = content.indexOf("javax.ejb."); if(a < 0) return false; } int i = content.indexOf("@"); //$NON-NLS-1$ if(i < 0) return false; return true; } private ASTParser p = ASTParser.newParser(AST.JLS3); /** * Returns component or list of component * TODO change return type * @param f * @return * @throws ScannerException */ public LoadedDeclarations parse(IFile f, ISeamProject sp) throws ScannerException { ICompilationUnit u = null; try { u = getCompilationUnit(f); } catch (CoreException e) { throw new ScannerException( NLS.bind(SeamCoreMessages.JAVA_SCANNER_CANNOT_GET_COMPILATION_UNIT_FOR,f), e); } if(u == null) return null; ICompilationUnit[] us = new ICompilationUnit[]{u}; p.setSource(u); p.setResolveBindings(true); if("package-info.java".equals(f.getFullPath().lastSegment())) { PackageInfoRequestor requestor = new PackageInfoRequestor(f); p.createASTs(us, new String[0], requestor, null); return requestor.getDeclarations(); } ASTRequestorImpl requestor = new ASTRequestorImpl(f); p.createASTs(us, new String[0], requestor, null); return requestor.getDeclarations(); } private ICompilationUnit getCompilationUnit(IFile f) throws CoreException { IProject project = f.getProject(); IJavaProject javaProject = (IJavaProject)project.getNature(JavaCore.NATURE_ID); IResource[] rs = EclipseResourceUtil.getJavaSourceRoots(project); for (int i = 0; i < rs.length; i++) { if(rs[i].getFullPath().isPrefixOf(f.getFullPath())) { IPath path = f.getFullPath().removeFirstSegments(rs[i].getFullPath().segmentCount()); IJavaElement e = javaProject.findElement(path); if(e == null && path.lastSegment().equals("package-info.java")) { //strange but sometimes only this works IJavaElement ep = javaProject.findElement(path.removeLastSegments(1)); if(ep instanceof IPackageFragment) { e = ((IPackageFragment)ep).getCompilationUnit("package-info.java"); } } if(e instanceof ICompilationUnit) { return (ICompilationUnit)e; } } } return null; } class ASTRequestorImpl extends ASTRequestor { private ASTVisitorImpl visitor = new ASTVisitorImpl(); LoadedDeclarations ds = new LoadedDeclarations(); IResource resource; IPath sourcePath; public ASTRequestorImpl(IResource resource) { this.resource = resource; this.sourcePath = resource.getFullPath(); } public LoadedDeclarations getDeclarations() { return ds; } public void acceptAST(ICompilationUnit source, CompilationUnit ast) { IType[] ts = null; try { ts = source.getTypes(); } catch (JavaModelException e) { SeamCorePlugin.getPluginLog().logError(e); } if(ts == null || ts.length == 0) return; for (int i = 0; i < ts.length; i++) { visitor.setType(null); int f = 0; try { f = ts[i].getFlags(); } catch (JavaModelException e) { SeamCorePlugin.getPluginLog().logError(e); continue; } if(Flags.isPublic(f)) { visitor.setType(ts[i]); ast.accept(visitor); if(!visitor.hasSeamComponent()) continue; processTypeData(visitor.root); } } } private void processTypeData(ASTVisitorImpl.TypeData data) { if(data.hasSeamComponentItself()) { ComponentBuilder b = new ComponentBuilder(ds, data); b.component.setSourcePath(sourcePath); b.component.setResource(resource); b.process(); } for (ASTVisitorImpl.TypeData c: data.children) { processTypeData(c); } } } static String getResolvedType(IType type, String n) { String result = EclipseJavaUtil.resolveType(type, n); return result == null ? n : result; } } //:Pserver:anonymous@anoncvs.forge.jboss.com:/cvsroot/jboss