org.hammurapi.eclipse.plugin.HammurapiBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.hammurapi.eclipse.plugin.HammurapiBuilder.java

Source

/*
 * Hammurapi
 * Automated Java code review system. 
 * Copyright (C) 2004  Hammurapi Group
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * URL: http://www.hammurapi.org
 * e-Mail: support@hammurapi.biz
    
 */
package org.hammurapi.eclipse.plugin;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.PluginVersionIdentifier;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.hammurapi.HammurapiException;
import org.hammurapi.InspectorSource;
import org.hammurapi.ReviewRequestBase;
import org.hammurapi.Reviewer;
import org.hammurapi.Violation;

/**
 * Builder class for hammurapi code review system.
 * @author zorror8080
 * @version $Revision: 1.5 $
 */
public class HammurapiBuilder extends IncrementalProjectBuilder {
    private void performBuild(IProgressMonitor progressMonitor) throws CoreException {
        final IProject project = getProject();
        HammurapiPlugin.report2LogInfo("project: " + project, null);

        if (project != null) {
            HammurapiPlugin.report2LogInfo("proj.name: " + project.getName(), null);
            HammurapiPlugin.report2LogInfo("proj.isOpen(): " + project.isOpen(), null);
            HammurapiPlugin.report2LogInfo("project.hasNature: " + project.hasNature("HammurapiNature"), null);
            Collection files = null;
            IResourceDelta rDelta = getDelta(project);
            HammurapiPlugin.report2LogInfo("rDelta: " + rDelta, null);
            if (rDelta != null) {
                files = getFiles(rDelta);
            } else {
                files = getFiles(project);
            }
            HammurapiPlugin.report2LogInfo("files: " + files, null);
            HammurapiPlugin.report2LogInfo("files.size(): " + files.size(), null);
            if (files.size() > 0) {
                progressMonitor.beginTask("Hammurapi", 100); //files.size());
                try {
                    Reviewer reviewer = null;
                    try {
                        reviewer = new Reviewer(null, true, (InspectorSource) null, null);
                    } catch (HammurapiException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                    ClassLoader classLoader = null;
                    IJavaProject javaProject = (IJavaProject) project.getAdapter(IJavaElement.class);
                    try {
                        List urls = getClasspathURLs(javaProject, false);
                        URL[] urlArray = (URL[]) urls.toArray(new URL[urls.size()]);
                        classLoader = new URLClassLoader(urlArray);
                    } catch (CoreException e) {
                        throw e;
                    } catch (Throwable e) {
                        HammurapiPlugin.report2LogError("Unable to create a classloader for the project", e);
                        classLoader = null;
                    }

                    IFile file;
                    IMarker marker;
                    HammurapiPlugin.clearAllMarkers(project);
                    HammurapiPlugin.report2LogInfo("markers deleted.", null);
                    HammurapiChecker hChecker;
                    final List fileRef = new ArrayList();
                    for (Iterator it = files.iterator(); it.hasNext();) {
                        file = (IFile) it.next();
                        fileRef.add(file);
                        progressMonitor.subTask(file.getName());
                        // test...
                        /*
                                    HammurapiPlugin.createProblemMarker(
                                      file,
                                      9,
                                      IMarker.SEVERITY_ERROR,
                                      "hello!");
                                    */
                        // kick Hammurapi code check...and collect result.
                        try {
                            HammurapiPlugin.report2LogInfo("reviewer: " + reviewer, null);

                            reviewer.process(new ReviewRequestBase(null) {
                                public Reader getSource() {
                                    Reader res = null;
                                    try {
                                        res = new BufferedReader(
                                                new InputStreamReader(((IFile) fileRef.get(0)).getContents()));
                                    } catch (CoreException e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                    }
                                    HammurapiPlugin.report2LogInfo("getSource: " + res, null);

                                    return res;
                                }

                                public String getName() {
                                    return ((IFile) fileRef.get(0)).getFullPath().toString();
                                }

                                public void onViolation(Violation violation) {
                                    try {
                                        HammurapiPlugin.createProblemMarker((IResource) fileRef.get(0),
                                                (violation.getSource() == null ? 0
                                                        : violation.getSource().getLine()),
                                                IMarker.SEVERITY_ERROR, violation.getMessage());
                                    } catch (CoreException ex) {
                                    }
                                }

                                public void onWarning(Violation warning) {
                                    try {
                                        HammurapiPlugin.createProblemMarker((IResource) fileRef.get(0),
                                                (warning.getSource() == null ? 0 : warning.getSource().getLine()),
                                                IMarker.SEVERITY_WARNING, warning.getMessage());
                                    } catch (CoreException ex) {
                                    }
                                }

                                public File getRootDir() {
                                    // TODO Auto-generated method stub
                                    return null;
                                }
                            });
                        } catch (HammurapiException e1) {
                            // TODO Auto-generated catch block
                            e1.printStackTrace();
                        }
                        if (progressMonitor.isCanceled()) {
                            forgetLastBuiltState();
                            throw new OperationCanceledException();
                        }
                        /*
                        hChecker = new HammurapiChecker(reviewer);
                        new Thread(hChecker).start();
                        while (!hChecker.isCompleted())
                        {
                            
                          //HammurapiPlugin.createProblemMarker(file, 9, IMarker.SEVERITY_ERROR, "hello!");
                          if (progressMonitor.isCanceled())
                          {
                            hChecker.stop(); // stop checker...
                            forgetLastBuiltState();
                            throw new OperationCanceledException();
                          }
                        }
                        */
                        /*
                        if (i > 100)
                        {
                          throw new CoreException(new Status(IStatus.INFO,"hammurapi plugin",0,"reached 100", null));
                        }
                        */
                        progressMonitor.worked(1);
                    }
                } finally {
                    progressMonitor.done();
                }
            }
        }
    }

    /**
     *  Determine if running eclipse 2.1 or newer.
     *
     *  The ability for source folders to have different output folders
     *  was introduced in Eclipse 2.1.  Check the version of the
     *  org.eclipse.jdt.core plug-in to determine if it's safe to
     *  call the getOutputLocation() method, which was introduced
     *  in Eclipse v2.1.
     */
    private boolean isEclipse_2_1_Safe() {
        boolean res = false;
        //if (!mEclipseVersionDetermined)
        {
            Plugin jdtCorePlugin = Platform.getPlugin("org.eclipse.jdt.core");
            if (jdtCorePlugin != null) {
                PluginVersionIdentifier version = jdtCorePlugin.getDescriptor().getVersionIdentifier();
                res = version.isGreaterOrEqualTo(new PluginVersionIdentifier("2.1"));
            }
            //mEclipseVersionDetermined = true;
        }

        return res;
    }

    /**
     * @author Daniel Berg jdt-dev@eclipse.org.
     * @param javaProject
     * @return
     */
    private List getClasspathURLs(IJavaProject javaProject, boolean exportedOnly)
            throws JavaModelException, MalformedURLException, CoreException {
        HashSet urls = new HashSet();

        IClasspathEntry[] entries = javaProject.getResolvedClasspath(true);
        boolean defaultOutputAdded = false;

        for (int i = 0; i < entries.length; i++) {
            // Source entries are apparently always assumed to be exported - but don't
            // report themselves as such.
            if (!exportedOnly || entries[i].isExported()
                    || entries[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
                switch (entries[i].getEntryKind()) {
                case IClasspathEntry.CPE_SOURCE: {
                    IPath outputLocation = null;

                    if (isEclipse_2_1_Safe()) {
                        outputLocation = entries[i].getOutputLocation();
                    }
                    if (outputLocation == null) {
                        //
                        //  If the output location is null then the project's
                        //  default output location is being used.
                        //
                        if (!defaultOutputAdded) {
                            defaultOutputAdded = true;
                            outputLocation = javaProject.getOutputLocation();
                        }
                    }

                    if (outputLocation != null) {

                        // When the output location is the project itself, the project
                        // can't resolve the file - therefore just get the project's
                        // location. 

                        if (outputLocation.segmentCount() == 1) {
                            outputLocation = javaProject.getProject().getLocation();
                        } else {
                            // Output locations are always workspace relative. Do this mess
                            // to get a fully qualified location.
                            outputLocation = javaProject.getProject().getParent().getFile(outputLocation)
                                    .getLocation();
                        }

                        urls.add(outputLocation.addTrailingSeparator().toFile().toURL());
                    }

                    break;
                }
                case IClasspathEntry.CPE_LIBRARY: {
                    // Jars always come with a nice fully specified path.
                    urls.add(new URL("file:/" + entries[i].getPath().toOSString()));

                    break;
                }
                case IClasspathEntry.CPE_PROJECT: {
                    IJavaProject dependentProject = (IJavaProject) (ResourcesPlugin.getWorkspace().getRoot()
                            .getProject(entries[i].getPath().segment(0))).getAdapter(IJavaElement.class);

                    urls.addAll(getClasspathURLs(dependentProject, true));

                    break;
                }
                default: {
                    String msg = "Encountered unexpected classpath entry : " + entries[i].getEntryKind();
                    HammurapiPlugin.report2LogError(msg, null);
                    Status status = new Status(IStatus.ERROR, "HammurapiPlugin", IStatus.ERROR, msg, null);
                    throw new CoreException(status);
                }
                }
            }
        }

        return new ArrayList(urls);
    }

    private Collection getFiles(final IResourceDelta rDelta) throws CoreException {
        List files = new ArrayList();
        List folders = new ArrayList();
        IResourceDelta rDeltas[] = rDelta.getAffectedChildren();
        //HammurapiPlugin.report2LogInfo("rDeltas: "+rDeltas, null);
        //HammurapiPlugin.report2LogInfo("rDeltas.size: "+rDeltas.length, null);
        IResourceDelta currDelta;
        IResource currResource;
        int deltaKind;
        int resourceType;
        for (int i = 0; i < rDeltas.length; i++) {
            currDelta = rDeltas[i];
            currResource = currDelta.getResource();
            resourceType = currResource.getType();
            //HammurapiPlugin.report2LogInfo("resourceType: "+resourceType, null);
            //HammurapiPlugin.report2LogInfo("currResource.getName(): "+currResource.getName(), null);
            if (resourceType == IResource.FILE) {
                deltaKind = currDelta.getKind();
                if ((deltaKind == IResourceDelta.ADDED || deltaKind == IResourceDelta.CHANGED)
                        && currResource.getName() != null && currResource.getName().endsWith(".java")) {
                    files.add(currResource);
                }
            } else {
                if (resourceType == IResource.FOLDER) {
                    folders.add(currDelta);
                }
            }
        }
        for (Iterator it = folders.iterator(); it.hasNext();) {
            files.addAll(getFiles((IResourceDelta) it.next()));
        }
        return files;
    }

    private Collection getFiles(IContainer container) throws CoreException {
        List files = new ArrayList();
        List folders = new ArrayList();
        int rType;
        IResource resource;
        IResource[] resources = container.members();
        for (int i = 0; i < resources.length; i++) {
            resource = resources[i];
            rType = resource.getType();
            if (rType == IResource.FILE && resource.getName() != null && resource.getName().endsWith(".java")) {
                files.add(resource);
            } else {
                if (rType == IResource.FOLDER) {
                    folders.add(resource);
                }
            }
        }

        for (Iterator it = folders.iterator(); it.hasNext();) {
            files.addAll(getFiles((IContainer) it.next()));
        }
        return files;
    }

    protected IProject[] build(int buildType, Map map, IProgressMonitor progressMonitor) throws CoreException {
        HammurapiPlugin.report2LogInfo(
                "@@@prop: " + getProject().getPersistentProperty(
                        new QualifiedName(HammurapiPlugin.HAMMURAPI_PROPERTY, HammurapiPlugin.ENABLED_PROPERTY)),
                null);
        if ((true + "").equals(getProject().getPersistentProperty(
                new QualifiedName(HammurapiPlugin.HAMMURAPI_PROPERTY, HammurapiPlugin.ENABLED_PROPERTY)))) {
            switch (buildType) {
            case IncrementalProjectBuilder.AUTO_BUILD:
                HammurapiPlugin.report2LogInfo("doAutoBuild", null);
                performBuild(progressMonitor);
                break;

            case IncrementalProjectBuilder.INCREMENTAL_BUILD:
                HammurapiPlugin.report2LogInfo("doIncrementalBuild", null);
                performBuild(progressMonitor);
                break;

            default:
                HammurapiPlugin.report2LogInfo("doFullBuild", null);
                performBuild(progressMonitor);
                break;
            }
        }
        return null;
    }

    public static class BuildRunnable implements IRunnableWithProgress {
        private List projects2Build;

        private BuildRunnable() {
            projects2Build = new ArrayList();
        }

        void addProject(IProject iproject) {
            projects2Build.add(iproject);
        }

        public void run(org.eclipse.core.runtime.IProgressMonitor mon)
                throws java.lang.reflect.InvocationTargetException, java.lang.InterruptedException {
            IProject aProject;
            for (Iterator iterator = projects2Build.iterator(); iterator.hasNext();) {
                aProject = (org.eclipse.core.resources.IProject) iterator.next();
                try {
                    aProject.build(6, HammurapiBuilder.class.getName(), null, mon);
                } catch (CoreException e) {
                    throw new InvocationTargetException(e);
                }
            }
        }
    }

    private static class HammurapiChecker implements Runnable {
        private boolean stopRequested = false;
        private boolean completed = false;
        private int severity;
        private int lineNo;
        private String reviewMessage;
        private Reviewer reviewer;

        private HammurapiChecker(Reviewer reviewer) {
            this.reviewer = reviewer;
        }

        void stop() {
            stopRequested = true;
        }

        boolean isCompleted() {
            return completed;
        }

        int getSeverity() {
            return severity;
        }

        int getLineNo() {
            return lineNo;
        }

        String getReviewMessage() {
            return reviewMessage;
        }

        public void run() {
            try {
                while (!stopRequested) {
                    //reviewer.process(null);
                }
            } finally {
                completed = true;
            }
        }
    }
}