in.software.analytics.parichayana.core.internal.builder.ParichayanaBuilder.java Source code

Java tutorial

Introduction

Here is the source code for in.software.analytics.parichayana.core.internal.builder.ParichayanaBuilder.java

Source

/*******************************************************************************
 * Copyright (c) 2014 Software Analytics and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU General Public License, version 2 
 * (GPL-2.0) which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl-2.0.txt
 *
 * Contributors:
 *     Haris Peco - initial API and implementation
 *******************************************************************************/
package in.software.analytics.parichayana.core.internal.builder;

import in.software.analytics.parichayana.core.Constants;
import in.software.analytics.parichayana.core.ParichayanaActivator;
import in.software.analytics.parichayana.core.internal.nature.ParichayanaNature;
import in.software.analytics.parichayana.engine.CatchAntiPatterns;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

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.IWorkspaceRoot;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.IClasspathEntry;
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.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.util.IClassFileReader;
import org.eclipse.jdt.internal.core.ClasspathEntry;
import org.eclipse.jdt.internal.core.ExternalFoldersManager;
import org.eclipse.jdt.internal.core.JavaModelManager;
import org.eclipse.jdt.internal.core.JavaProject;

public class ParichayanaBuilder extends IncrementalProjectBuilder {

    public static final String ID = "in.software.analytics.parichayana.core.parichayanaBuilder";

    private IProject project;
    static final IProject[] ZERO_PROJECT = new IProject[0];

    /* (non-Javadoc)
     * @see org.eclipse.core.resources.IncrementalProjectBuilder#build(int, java.util.Map, org.eclipse.core.runtime.IProgressMonitor)
     */
    @Override
    protected IProject[] build(int kind, Map<String, String> args, IProgressMonitor monitor) throws CoreException {
        project = getProject();
        if (project == null || !project.isAccessible()) {
            return ZERO_PROJECT;
        }
        if (!project.hasNature(ParichayanaNature.NATURE_ID)
                || !ParichayanaActivator.isParichayanaEnabled(project)) {
            cleanupMarkers(project);
            return ZERO_PROJECT;
        }
        try {
            if (kind == FULL_BUILD) {
                buildAll(monitor);
            } else {
                IResourceDelta delta = getDelta(project);
                if (delta == null) {
                    buildAll(monitor);
                } else {
                    buildDelta(delta, monitor);
                }
            }
        } catch (CoreException e) {
            ParichayanaActivator.log(e);
        } finally {
            if (monitor != null) {
                monitor.done();
            }
        }
        IProject[] requiredProjects = getRequiredProjects(true);
        return requiredProjects;
    }

    /**
     * @param delta
     * @param monitor
     * @throws CoreException 
     */
    private void buildDelta(IResourceDelta delta, IProgressMonitor monitor) throws CoreException {
        final List<ICompilationUnit> units = new ArrayList<ICompilationUnit>();
        delta.accept(new IResourceDeltaVisitor() {

            @Override
            public boolean visit(IResourceDelta delta) throws CoreException {
                IResource res = delta.getResource();
                switch (res.getType()) {
                case IResource.ROOT:
                    return true;
                case IResource.PROJECT:
                    return true;
                case IResource.FOLDER:
                    return true;
                case IResource.FILE:
                    IJavaElement element = JavaCore.create(res);
                    ICompilationUnit cu = null;
                    if (element instanceof IClassFile) {
                        cu = getCompilationUnit((IClassFile) element);
                    }
                    if (element instanceof ICompilationUnit) {
                        cu = (ICompilationUnit) element;
                    }
                    if (cu != null) {
                        cleanupMarkers(cu.getUnderlyingResource());
                        if (units.contains(cu)) {
                            return false;
                        }
                        units.add(cu);
                    }
                    return false;
                default:
                    return false;
                }
            }

            public ICompilationUnit getCompilationUnit(IClassFile classFile) {
                IClassFileReader classFileReader = ToolFactory.createDefaultClassFileReader(classFile,
                        IClassFileReader.CLASSFILE_ATTRIBUTES);
                if (classFileReader != null) {
                    char[] className = classFileReader.getClassName();
                    if (className != null) {
                        String fqn = new String(classFileReader.getClassName()).replace("/", "."); //$NON-NLS-1$ //$NON-NLS-2$
                        IJavaProject javaProject = classFile.getJavaProject();
                        IType sourceType = null;
                        try {
                            sourceType = javaProject.findType(fqn);
                            if (sourceType != null) {
                                return sourceType.getCompilationUnit();
                            }
                        } catch (JavaModelException e) {
                            // ignore
                        }
                    }
                }
                return null;
            }
        });
        build(units, monitor);
    }

    /**
     * @param units
     * @param monitor 
     */
    private void build(List<ICompilationUnit> units, IProgressMonitor monitor) {
        Iterator<ICompilationUnit> iter = units.iterator();
        while (iter.hasNext()) {
            ICompilationUnit unit = iter.next();
            String name = getFullyQualifiedName(unit);
            String include = ParichayanaActivator.getPreference(Constants.INCLUDE_EXPRESSION, project);
            if (!match(include, name, true)) {
                iter.remove();
                continue;
            }
            String exclude = ParichayanaActivator.getPreference(Constants.EXCLUDE_EXPRESSION, project);
            if (match(exclude, name, false)) {
                iter.remove();
            }
        }
        monitor.beginTask("Parichayana builder", units.size());
        new CatchAntiPatterns(units, project, monitor);
    }

    /**
     * @param unit
     * @return
     */
    private String getFullyQualifiedName(ICompilationUnit unit) {
        String name = unit.getElementName();
        IJavaElement parent = unit.getParent();
        if (parent instanceof IPackageFragment) {
            String n = parent.getElementName();
            if (n != null && !n.isEmpty()) {
                name = n + "." + name;
            }
        }
        if (name.endsWith(".java")) {
            name = name.substring(0, name.length() - 5);
        }
        return name;
    }

    private boolean match(String expression, String name, boolean defaultValue) {
        if (expression != null && !expression.isEmpty()) {
            try {
                Pattern pattern = Pattern.compile(expression);
                Matcher matcher = pattern.matcher(name);
                boolean f = matcher.find();
                return f;
            } catch (PatternSyntaxException e) {
                ParichayanaActivator.logWarning(e.getMessage() + ", expession=" + expression);
                return defaultValue;
            }
        }
        return defaultValue;
    }

    /**
     * @param monitor
     */
    private void buildAll(IProgressMonitor monitor) throws CoreException {
        checkCancel(monitor);
        List<ICompilationUnit> units = getCompilationUnits();
        build(units, monitor);
    }

    public void checkCancel(IProgressMonitor monitor) {
        if (monitor != null && monitor.isCanceled())
            throw new OperationCanceledException();
    }

    private void cleanupMarkers(IResource resource) {
        if (resource == null) {
            return;
        }
        try {
            resource.deleteMarkers(Constants.BASE_MARKER_ID, true, IResource.DEPTH_INFINITE);
        } catch (CoreException e) {
            ParichayanaActivator.log(e);
        }
    }

    private IProject[] getRequiredProjects(boolean includeBinaryPrerequisites) {
        JavaProject javaProject = (JavaProject) JavaCore.create(this.project);
        IWorkspaceRoot workspaceRoot = this.project.getWorkspace().getRoot();
        if (javaProject == null || workspaceRoot == null) {
            return ZERO_PROJECT;
        }

        List<IProject> projects = new ArrayList<IProject>();
        ExternalFoldersManager externalFoldersManager = JavaModelManager.getExternalManager();
        try {
            IClasspathEntry[] entries = javaProject.getExpandedClasspath();
            for (int i = 0, l = entries.length; i < l; i++) {
                IClasspathEntry entry = entries[i];
                IPath path = entry.getPath();
                IProject p = null;
                switch (entry.getEntryKind()) {
                case IClasspathEntry.CPE_PROJECT:
                    p = workspaceRoot.getProject(path.lastSegment()); // missing projects are considered too
                    if (((ClasspathEntry) entry).isOptional() && !JavaProject.hasJavaNature(p)) // except if entry is optional
                        p = null;
                    break;
                case IClasspathEntry.CPE_LIBRARY:
                    if (includeBinaryPrerequisites && path.segmentCount() > 0) {
                        // some binary resources on the class path can come from projects that are not included in the project references
                        IResource resource = workspaceRoot.findMember(path.segment(0));
                        if (resource instanceof IProject) {
                            p = (IProject) resource;
                        } else {
                            resource = externalFoldersManager.getFolder(path);
                            if (resource != null)
                                p = resource.getProject();
                        }
                    }
                }
                if (p != null && !projects.contains(p))
                    projects.add(p);
            }
        } catch (JavaModelException e) {
            return ZERO_PROJECT;
        }
        IProject[] result = new IProject[projects.size()];
        projects.toArray(result);
        return result;
    }

    @Override
    protected void clean(IProgressMonitor monitor) throws CoreException {
        project = getProject();
        if (project == null || !project.isAccessible()) {
            return;
        }
        cleanupMarkers(project);
    }

    private List<ICompilationUnit> getCompilationUnits() throws JavaModelException {
        List<ICompilationUnit> compilationUnits = new ArrayList<ICompilationUnit>();
        IJavaProject javaProject = JavaCore.create(project);
        IClasspathEntry[] entries = javaProject.getRawClasspath();
        for (IClasspathEntry entry : entries) {
            if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
                IPackageFragmentRoot[] roots = javaProject.findPackageFragmentRoots(entry);
                for (IPackageFragmentRoot root : roots) {
                    if (root.isArchive()) {
                        continue;
                    }
                    IJavaElement[] children = root.getChildren();
                    for (IJavaElement child : children) {
                        if (child instanceof IPackageFragment) {
                            IPackageFragment packageFragment = (IPackageFragment) child;
                            ICompilationUnit[] cus = packageFragment.getCompilationUnits();
                            for (ICompilationUnit cu : cus) {
                                cleanupMarkers(cu.getUnderlyingResource());
                                compilationUnits.add(cu);
                            }
                        }
                    }
                }
            }
        }

        return compilationUnits;
    }

}