blob: 4c79d78eb9c2454b6e58dac815ebb649e5d2e544 [file] [log] [blame]
/***********************************************************************
* Copyright (c) 2008 by SAP AG, Walldorf.
* All rights reserved. This program and the accompanying materials
* are 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:
* SAP AG - initial API and implementation
***********************************************************************/
package org.eclipse.jst.jee.model.internal;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceProxy;
import org.eclipse.core.resources.IResourceProxyVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jdt.core.ICompilationUnit;
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.jst.j2ee.model.IModelProviderEvent;
import org.eclipse.jst.javaee.core.EjbLocalRef;
import org.eclipse.jst.javaee.core.JavaEEObject;
import org.eclipse.jst.javaee.core.Listener;
import org.eclipse.jst.javaee.core.ResourceRef;
import org.eclipse.jst.javaee.core.SecurityRole;
import org.eclipse.jst.javaee.core.SecurityRoleRef;
import org.eclipse.jst.javaee.ejb.MessageDrivenBean;
import org.eclipse.jst.javaee.ejb.SecurityIdentityType;
import org.eclipse.jst.javaee.ejb.SessionBean;
import org.eclipse.jst.javaee.web.Filter;
import org.eclipse.jst.javaee.web.Servlet;
import org.eclipse.jst.javaee.web.WebApp;
import org.eclipse.jst.javaee.web.WebFactory;
import org.eclipse.jst.jee.model.internal.common.AbstractAnnotationModelProvider;
import org.eclipse.jst.jee.model.internal.common.ManyToOneRelation;
import org.eclipse.jst.jee.model.internal.common.Result;
import org.eclipse.wst.common.project.facet.core.IFacetedProject;
/**
* @author Kiril Mitov k.mitov@sap.com
*
*/
public class WebAnnotationReader extends AbstractAnnotationModelProvider<WebApp> {
private static final String JAVA_EXTENSION = "java"; //$NON-NLS-1$
private ManyToOneRelation<JavaEEObject, IFile> modelToResource;
private ManyToOneRelation<JavaEEObject, IFile> modelToInterfaceResource;
private WebAnnotationFactory annotationFactory;
private WebApp ddApp;
public WebAnnotationReader(IFacetedProject facetedProject, WebApp ddApp) {
super(facetedProject);
if (ddApp == null)
throw new IllegalArgumentException("The deployment descriptor model can not be null!"); //$NON-NLS-1$
this.ddApp = ddApp;
}
@Override
protected void preLoad() {
modelObject = WebFactory.eINSTANCE.createWebApp();
annotationFactory = WebAnnotationFactory.createFactory();
}
@Override
protected void loadModel() throws CoreException {
IJavaProject javaProject = JavaCore.create(facetedProject.getProject());
final Collection<IFile> javaFiles = new HashSet<IFile>();
for (final IPackageFragmentRoot root : javaProject.getAllPackageFragmentRoots()) {
visitJavaFiles(javaFiles, root);
}
annotationFactory = WebAnnotationFactory.createFactory();
modelToInterfaceResource = new ManyToOneRelation<JavaEEObject, IFile>();
modelToResource = new ManyToOneRelation<JavaEEObject, IFile>();
for (IFile file : javaFiles) {
Result result = analyzeFile(file);
if (result == null)
continue;
processResult(file, result);
}
}
/**
* Analyze this file for a bean. If the file is not a valid java compilation
* unit or it does not contain a class the method returns <code>null</code>
*
* Only the primary type of the compilation unit is processed.
*
* @param file
* the file to be processed.
* @return result from processing the file
* @throws JavaModelException
*/
private Result analyzeFile(IFile file) throws JavaModelException {
org.eclipse.core.runtime.Assert.isTrue(JAVA_EXTENSION.equals(file.getFileExtension()),
"A file with extension different from \"java\" is analyzed for beans"); //$NON-NLS-1$
ICompilationUnit compilationUnit = JavaCore.createCompilationUnitFrom(file);
if (compilationUnit == null)
return null;
IType rootType = compilationUnit.findPrimaryType();
/*
* If the compilation unit is not valid and can not be compiled the
* rootType may be null. This can happen if a class is define as follows
* <code> @Stateless public SomeClass implements SomeInterface{}</code>.
* Here the "class" word is missed and the type is not valid.
*/
if (rootType == null || !rootType.isClass())
return null;
for (Iterator iter = ddApp.getServlets().iterator(); iter.hasNext();) {
Servlet servlet = (Servlet) iter.next();
if (rootType.getFullyQualifiedName().equals(servlet.getServletClass()))
return annotationFactory.createServlet(rootType, servlet.getServletName());
}
for (Iterator iter = ddApp.getListeners().iterator(); iter.hasNext();) {
Listener listener = (Listener) iter.next();
if (rootType.getFullyQualifiedName().equals(listener.getListenerClass()))
return annotationFactory.createListener(rootType);
}
for (Iterator iter = ddApp.getFilters().iterator(); iter.hasNext();) {
Filter filter = (Filter) iter.next();
if (rootType.getFullyQualifiedName().equals(filter.getFilterClass())) {
return annotationFactory.createFilter(rootType, filter.getFilterName());
}
}
return null;
}
/**
* Process the result from parsing the file. Depending on the result this
* might include adding a session bean, message driven bean, securityRole
* etc.
*
* @see #sessionBeanFound(IFile, SessionBean, Collection)
* @see #messageBeanFound(IFile, MessageDrivenBean, Collection)
* @see #securityRoleFound(IFile, SecurityRole)
* @param file
* @param result
* @throws JavaModelException
*/
private void processResult(IFile file, Result result) throws JavaModelException {
JavaEEObject mainObject = result.getMainObject();
if (Servlet.class.isInstance(mainObject))
servletFound(file, (Servlet) result.getMainObject(), result.getDependedTypes());
for (JavaEEObject additional : result.getAdditional()) {
if (EjbLocalRef.class.isInstance(additional)) {
ejbLocalRefFound(file, (EjbLocalRef) additional, result.getDependedTypes());
} else if (ResourceRef.class.isInstance(additional)) {
resourceRefFound(file, (ResourceRef) additional, result.getDependedTypes());
} else if (SecurityRole.class.isInstance(additional)) {
securityRoleFound(result.getMainObject(), (SecurityRole) additional);
} else if (SecurityIdentityType.class.isInstance(additional)) {
securityIdentityTypeFound(file, (SecurityIdentityType) additional);
}
}
}
private void servletFound(IFile file, Servlet servlet, Collection<IType> dependedTypes) throws JavaModelException {
modelObject.getServlets().add(servlet);
connectObjectWithFile(file, servlet, dependedTypes);
}
private void securityIdentityTypeFound(IFile file, SecurityIdentityType additional) {
}
private void resourceRefFound(IFile file, ResourceRef resourceRef, Collection<IType> dependedTypes)
throws JavaModelException {
modelObject.getResourceRefs().add(resourceRef);
connectObjectWithFile(file, resourceRef, dependedTypes);
}
private void ejbLocalRefFound(IFile file, EjbLocalRef localRef, Collection<IType> dependedTypes)
throws JavaModelException {
modelObject.getEjbLocalRefs().add(localRef);
connectObjectWithFile(file, localRef, dependedTypes);
}
private void connectObjectWithFile(IFile file, JavaEEObject localRef, Collection<IType> dependedTypes)
throws JavaModelException {
modelToResource.connect(localRef, file);
Collection<IFile> files = new HashSet<IFile>(dependedTypes.size());
for (IType type : dependedTypes) {
if (type.isBinary() || type.isInterface() == false)
continue;
IResource resource = type.getCompilationUnit().getCorrespondingResource();
if (resource != null && resource.exists())
modelToInterfaceResource.connect(localRef, (IFile) resource);
}
}
private void visitJavaFiles(final Collection<IFile> javaFiles, final IPackageFragmentRoot root)
throws CoreException {
if (root.getKind() != IPackageFragmentRoot.K_SOURCE)
return;
root.getCorrespondingResource().accept(new IResourceProxyVisitor() {
public boolean visit(IResourceProxy proxy) throws CoreException {
if (proxy.getType() == IResource.FILE) {
if (proxy.getName().endsWith("." + JAVA_EXTENSION)) { //$NON-NLS-1$
IFile file = (IFile) proxy.requestResource();
if (root.getJavaProject().isOnClasspath(file))
javaFiles.add(file);
}
return false;
}
return true;
}
}, IContainer.NONE);
}
@Override
protected boolean isProjectRelative(IProject project) {
if (project == null)
return false;
else if (project.equals(facetedProject.getProject()))
return true;
return false;
}
@Override
public void dispose() {
// Job disposeJob = new Job(Messages.getString("WebAnnotationReader.DisposeWebAnnotationReader")) { //$NON-NLS-1$
// @Override
// protected IStatus run(IProgressMonitor monitor) {
IModelProviderEvent modelEvent = createModelProviderEvent();
modelEvent.addResource(facetedProject.getProject());
modelEvent.setEventCode(modelEvent.getEventCode() | IModelProviderEvent.PRE_DISPOSE);
ResourcesPlugin.getWorkspace().removeResourceChangeListener(WebAnnotationReader.this);
modelToResource = null;
modelObject = null;
notifyListeners(modelEvent);
clearListeners();
// return Status.OK_STATUS;
// }
// };
// disposeJob.schedule();
}
@Override
protected synchronized void processAddedFile(IModelProviderEvent modelEvent, IFile file) throws CoreException {
Result result = analyzeFile(file);
if (result == null)
return;
processResult(file, result);
modelEvent.addResource(file);
}
@Override
protected synchronized void processChangedFile(IModelProviderEvent modelEvent, IFile file) throws CoreException {
if (modelToResource.containsTarget(file))
processChangedModelFile(modelEvent, file);
else
processAddedFile(modelEvent, file);
}
private void processChangedModelFile(IModelProviderEvent modelEvent, IFile file) throws CoreException {
processRemovedFile(modelEvent, file);
processAddedFile(modelEvent, file);
}
@Override
protected synchronized void processRemovedFile(IModelProviderEvent modelEvent, IFile file) throws CoreException {
if (modelToResource.containsTarget(file))
processRemovedModelResource(modelEvent, file);
else if (modelToInterfaceResource.containsTarget(file))
processRemoveInterface(modelEvent, file);
}
private void processRemoveInterface(IModelProviderEvent event, IFile file) {
}
private void processRemovedModelResource(IModelProviderEvent event, IFile file) {
Collection<JavaEEObject> modelObjects = modelToResource.getSources(file);
for (JavaEEObject o : modelObjects) {
if (Servlet.class.isInstance(o))
disconnectFromRoles(o);
EcoreUtil.remove((EObject) o);
}
modelToResource.disconnect(file);
event.setEventCode(event.getEventCode() | IModelProviderEvent.REMOVED_RESOURCE);
event.addResource(file);
}
public void modify(Runnable runnable, IPath modelPath) {
}
public IStatus validateEdit(IPath modelPath, Object context) {
return null;
}
@Override
protected Collection<SecurityRoleRef> getSecurityRoleRefs(JavaEEObject target) {
if (Servlet.class.isInstance(target))
return ((Servlet) target).getSecurityRoleRefs();
return null;
}
@Override
protected Collection<SecurityRole> getSecurityRoles() {
return modelObject.getSecurityRoles();
}
}