org.eclipse.jst.jee.model.internal.WebAnnotationReader.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.jst.jee.model.internal.WebAnnotationReader.java

Source

/***********************************************************************
 * 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.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

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.IAnnotation;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElementDelta;
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.j2ee.web.project.facet.WebFacetUtils;
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.SecurityIdentityType;
import org.eclipse.jst.javaee.web.Filter;
import org.eclipse.jst.javaee.web.FilterMapping;
import org.eclipse.jst.javaee.web.Servlet;
import org.eclipse.jst.javaee.web.ServletMapping;
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 WEB_SERVLET = "WebServlet"; //$NON-NLS-1$
    private static final String WEB_SERVLET_FQ = "javax.servlet.annotation.WebServlet"; //$NON-NLS-1$

    private static final String WEB_LISTENER = "WebListener"; //$NON-NLS-1$
    private static final String WEB_LISTENER_FQ = "javax.servlet.annotation.WebListener"; //$NON-NLS-1$

    private static final String WEB_FILTER = "WebFilter"; //$NON-NLS-1$
    private static final String WEB_FILTER_FQ = "javax.servlet.annotation.WebFilter"; //$NON-NLS-1$

    private ManyToOneRelation<JavaEEObject, ICompilationUnit> modelToUnit;

    private ManyToOneRelation<JavaEEObject, ICompilationUnit> modelToInterfaceUnit;

    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<ICompilationUnit> javaUnits = new HashSet<ICompilationUnit>();
        for (final IPackageFragmentRoot root : javaProject.getAllPackageFragmentRoots()) {
            visitJavaFiles(javaUnits, root);
        }
        annotationFactory = WebAnnotationFactory.createFactory();

        modelToInterfaceUnit = new ManyToOneRelation<JavaEEObject, ICompilationUnit>();
        modelToUnit = new ManyToOneRelation<JavaEEObject, ICompilationUnit>();
        for (ICompilationUnit unit : javaUnits) {
            Result result = analyzeCompilationUnit(unit);
            if (result == null)
                continue;
            processResult(unit, result);
        }
    }

    /**
     * Analyze this unit for a web artifact. 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 unit
     *            the unit to be processed.
     * @return result from processing the file
     * @throws JavaModelException
     */
    private Result analyzeCompilationUnit(ICompilationUnit unit) throws JavaModelException {
        IType rootType = unit.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());
            }
        }
        if (Float.parseFloat(
                facetedProject.getProjectFacetVersion(WebFacetUtils.WEB_FACET).getVersionString()) > 2.5) {
            return createJavaeeObject(rootType);
        }
        return null;
    }

    public Result createJavaeeObject(IType type) throws JavaModelException {
        Result result = null;
        for (IAnnotation annotation : type.getAnnotations()) {
            String annotationName = annotation.getElementName();
            if (WEB_SERVLET.equals(annotationName) || WEB_SERVLET_FQ.equals(annotationName)) {
                result = annotationFactory.createServlet(type, null);
                break;
            } else if (WEB_FILTER.equals(annotationName) || WEB_FILTER_FQ.equals(annotationName)) {
                result = annotationFactory.createFilter(type, null);
                break;
            } else if (WEB_LISTENER.equals(annotationName) || WEB_LISTENER_FQ.equals(annotationName)) {
                result = annotationFactory.createListener(type);
                break;
            }
        }
        return result;
    }

    /**
     * Process the result from parsing the unit. Depending on the result this
     * might include adding a session bean, message driven bean, securityRole
     * etc.
     * 
     * @param unit
     * @param result
     * @throws JavaModelException
     */
    private void processResult(ICompilationUnit unit, Result result) throws JavaModelException {
        JavaEEObject mainObject = result.getMainObject();
        if (Servlet.class.isInstance(mainObject))
            servletFound(unit, (Servlet) result.getMainObject(), result.getDependedTypes());
        if (Listener.class.isInstance(mainObject))
            listenerFound(unit, (Listener) result.getMainObject(), result.getDependedTypes());
        if (Filter.class.isInstance(mainObject))
            filterFound(unit, (Filter) result.getMainObject(), result.getDependedTypes());
        for (JavaEEObject additional : result.getAdditional()) {
            if (EjbLocalRef.class.isInstance(additional)) {
                ejbLocalRefFound(unit, (EjbLocalRef) additional, result.getDependedTypes());
            } else if (ResourceRef.class.isInstance(additional)) {
                resourceRefFound(unit, (ResourceRef) additional, result.getDependedTypes());
            } else if (SecurityRole.class.isInstance(additional)) {
                securityRoleFound(result.getMainObject(), (SecurityRole) additional);
            } else if (SecurityIdentityType.class.isInstance(additional)) {
                securityIdentityTypeFound(unit, (SecurityIdentityType) additional);
            } else if (ServletMapping.class.isInstance(additional)) {
                servletMappingFound(unit, (ServletMapping) additional, result.getDependedTypes());
            } else if (FilterMapping.class.isInstance(additional)) {
                filterMappingFound(unit, (FilterMapping) additional, result.getDependedTypes());
            }
        }
    }

    private void filterMappingFound(ICompilationUnit unit, FilterMapping additional,
            Collection<IType> dependedTypes) throws JavaModelException {
        modelObject.getFilterMappings().add(additional);
        connectObjectWithFile(unit, additional, dependedTypes);
    }

    private void servletMappingFound(ICompilationUnit unit, ServletMapping additional,
            Collection<IType> dependedTypes) throws JavaModelException {
        modelObject.getServletMappings().add(additional);
        connectObjectWithFile(unit, additional, dependedTypes);
    }

    private void servletFound(ICompilationUnit unit, Servlet servlet, Collection<IType> dependedTypes)
            throws JavaModelException {
        modelObject.getServlets().add(servlet);
        connectObjectWithFile(unit, servlet, dependedTypes);
    }

    private void listenerFound(ICompilationUnit unit, Listener listener, Collection<IType> dependedTypes)
            throws JavaModelException {
        modelObject.getListeners().add(listener);
        connectObjectWithFile(unit, listener, dependedTypes);
    }

    private void filterFound(ICompilationUnit unit, Filter filter, Collection<IType> dependedTypes)
            throws JavaModelException {
        modelObject.getFilters().add(filter);
        connectObjectWithFile(unit, filter, dependedTypes);
    }

    private void securityIdentityTypeFound(ICompilationUnit file, SecurityIdentityType additional) {
    }

    private void resourceRefFound(ICompilationUnit unit, ResourceRef resourceRef, Collection<IType> dependedTypes)
            throws JavaModelException {
        modelObject.getResourceRefs().add(resourceRef);
        connectObjectWithFile(unit, resourceRef, dependedTypes);
    }

    private void ejbLocalRefFound(ICompilationUnit unit, EjbLocalRef localRef, Collection<IType> dependedTypes)
            throws JavaModelException {
        modelObject.getEjbLocalRefs().add(localRef);
        connectObjectWithFile(unit, localRef, dependedTypes);
    }

    private void connectObjectWithFile(ICompilationUnit unit, JavaEEObject localRef,
            Collection<IType> dependedTypes) throws JavaModelException {
        modelToUnit.connect(localRef, unit);
        for (IType type : dependedTypes) {
            if (type.isBinary() || type.isInterface() == false)
                continue;
            modelToInterfaceUnit.connect(localRef, type.getCompilationUnit());
        }
    }

    @Override
    protected void processAddedCompilationUnit(IModelProviderEvent modelEvent, ICompilationUnit unit)
            throws CoreException {
        Result result = analyzeCompilationUnit(unit);
        if (result == null || result.isEmpty())
            return;
        processResult(unit, result);
        modelEvent.addResource(unit);
    }

    @Override
    protected void processChangedCompilationUnit(IModelProviderEvent modelEvent, ICompilationUnit unit)
            throws CoreException {
        if (modelToUnit.containsTarget(unit))
            processChangedModelUnit(modelEvent, unit);
        else
            processAddedCompilationUnit(modelEvent, unit);
    }

    private void processChangedModelUnit(IModelProviderEvent modelEvent, ICompilationUnit unit)
            throws CoreException {
        processRemovedCompilationUnit(modelEvent, unit);
        processAddedCompilationUnit(modelEvent, unit);
    }

    @Override
    protected void processRemovedCompilationUnit(IModelProviderEvent modelEvent, ICompilationUnit unit)
            throws CoreException {
        if (modelToUnit.containsTarget(unit))
            processRemovedModelResource(modelEvent, unit);
        else if (modelToInterfaceUnit.containsTarget(unit))
            processRemoveInterface(modelEvent, unit);
    }

    private void processRemoveInterface(IModelProviderEvent event, ICompilationUnit unit) {
    }

    @Override
    protected void processRemovedPackage(IModelProviderEvent modelEvent, IJavaElementDelta delta)
            throws CoreException {
        Collection<ICompilationUnit> clonedCollection = cloneCollection(modelToUnit.getTargets());
        for (ICompilationUnit unit : clonedCollection) {
            if (unit.getParent().getElementName().equals(delta.getElement().getElementName())) {
                processRemovedCompilationUnit(modelEvent, unit);
            }
        }
    }

    private Collection<ICompilationUnit> cloneCollection(Collection<ICompilationUnit> targets) {
        Collection<ICompilationUnit> result = new ArrayList<ICompilationUnit>();
        for (ICompilationUnit iCompilationUnit : targets) {
            result.add(iCompilationUnit);
        }
        return result;
    }

    private void processRemovedModelResource(IModelProviderEvent event, ICompilationUnit file) {
        Collection<JavaEEObject> modelObjects = modelToUnit.getSources(file);
        for (JavaEEObject o : modelObjects) {
            if (Servlet.class.isInstance(o))
                disconnectFromRoles(o);
            EcoreUtil.remove((EObject) o);
        }
        modelToUnit.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();
    }

}