org.eclipse.recommenders.codesearch.rcp.index.ui.ProjectIndexerRunnable.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.recommenders.codesearch.rcp.index.ui.ProjectIndexerRunnable.java

Source

/**
 * Copyright (c) 2012 Tobias Boehm.
 * 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:
 *    Marcel Bruch - initial API and implementation.
 *    Tobias Boehm - implementation.
 */

package org.eclipse.recommenders.codesearch.rcp.index.ui;

import static com.google.common.collect.Ordering.usingToString;
import static java.util.Arrays.asList;
import static org.eclipse.recommenders.codesearch.rcp.index.indexer.CodeIndexer.addFieldToDocument;
import static org.eclipse.recommenders.codesearch.rcp.index.indexer.ResourcePathIndexer.getFile;
import static org.eclipse.recommenders.utils.Checks.cast;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

import org.apache.lucene.document.Document;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.IClassFile;
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.dom.CompilationUnit;
import org.eclipse.jdt.internal.core.JarPackageFragmentRoot;
import org.eclipse.jdt.internal.core.SourceMapper;
import org.eclipse.jdt.ui.SharedASTProvider;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.recommenders.codesearch.rcp.index.Fields;
import org.eclipse.recommenders.codesearch.rcp.index.indexer.CodeIndexer;
import org.eclipse.recommenders.codesearch.rcp.index.indexer.CodeIndexerConfigBean;
import org.eclipse.recommenders.codesearch.rcp.index.indexer.ResourcePathIndexer;
import org.eclipse.recommenders.codesearch.rcp.index.indexer.TimestampIndexer;
import org.eclipse.recommenders.rcp.RecommendersPlugin;
import org.eclipse.recommenders.utils.rcp.internal.RecommendersUtilsPlugin;

public class ProjectIndexerRunnable implements IRunnableWithProgress {

    private final IJavaProject project;
    private final CodeIndexer indexer;
    private IPackageFragmentRoot[] roots;
    private IProgressMonitor monitor;

    //
    IPackageFragmentRoot root;
    private File rootLocation;
    private SourceMapper sourceMapper;

    public ProjectIndexerRunnable(final IJavaProject project, final CodeIndexer indexer) {
        this.project = project;
        this.indexer = indexer;
    }

    @Override
    public void run(final IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {

        try {
            this.roots = project.getPackageFragmentRoots();
            this.monitor = monitor;
            openMonitor();

            for (final IPackageFragmentRoot root : roots) {
                analyzeRoot(root);
            }
        } catch (final Exception e) {
            RecommendersPlugin.logError(e, "Error during code search indexing");
        } finally {
            closeMonitor();
        }
    }

    private void openMonitor() {
        monitor.beginTask("", roots.length + 1);
        monitor.subTask("About to begin...");
        monitor.worked(1);
    }

    private void analyzeRoot(final IPackageFragmentRoot root) throws Exception {
        this.root = root;
        monitor.subTask("Analyzing " + root.getElementName());

        rootLocation = getFile(root);
        if (monitor.isCanceled()) {
            return;
        }
        if (rootLocation == null) {
            return;
        }
        if (hasNotChanged(rootLocation)) {
            return;
        }
        if (root.isArchive()) {
            indexer.delete(rootLocation);
            if (!findSourceMapper()) {
                return;
            }
        }

        analyzePackageFragments();

        monitor.subTask("Checkpointing...");
        indexer.commit();
        monitor.worked(1);
        root.close();
    }

    private void analyzePackageFragments() throws Exception {
        for (final IJavaElement child : usingToString().sortedCopy(asList(root.getChildren()))) {
            final IPackageFragment fragment = cast(child);
            monitor.subTask("Analyzing " + fragment.getElementName());

            if (fragment.getElementName().startsWith("sun.")) {
                continue;
            }
            if (fragment.getElementName().startsWith("com.sun.")) {
                continue;
            }
            if (fragment.getElementName().startsWith("com.oracle.")) {
                continue;
            }
            if (fragment.getElementName().startsWith("sunw.")) {
                continue;
            }

            for (final IClassFile clazz : usingToString().sortedCopy(asList(fragment.getClassFiles()))) {
                analyzeClassFile(clazz);
            }
            for (final ICompilationUnit cu : fragment.getCompilationUnits()) {
                analyzeCompilationUnit(cu);
            }
            fragment.close();
        }
        addArchiveVisitedMarker();
    }

    private void analyzeCompilationUnit(final ICompilationUnit cu) {
        try {
            final File cuLocation = getFile(cu);
            if (hasNotChanged(cuLocation)) {
                return;
            }
            final CompilationUnit ast = SharedASTProvider.getAST(cu, SharedASTProvider.WAIT_YES, monitor);
            if (ast == null) {
                return;
            }

            indexer.delete(cuLocation);
            indexer.index(ast, new CodeIndexerConfigBean(true, 1.5f));
        } catch (final Exception e) {
            RecommendersUtilsPlugin.logError(e, "Failed to index '%s'", cu.getResource().getFullPath());
        }
    }

    private boolean hasNotChanged(final File file) {
        final long lastModified = file.lastModified();
        final long lastIndexed = indexer.lastIndexed(file);
        return lastModified < lastIndexed;
    }

    @SuppressWarnings("restriction")
    private boolean findSourceMapper() {
        final JarPackageFragmentRoot jarRoot = (JarPackageFragmentRoot) root;
        sourceMapper = jarRoot.getSourceMapper();
        return sourceMapper != null;
    }

    private void analyzeClassFile(final IClassFile clazz) throws IOException {
        if (monitor.isCanceled()) {
            return;
        }
        if (clazz.getElementName().contains("$")) {
            return;
        }

        final IType type = clazz.getType();
        if (type == null) {
            return;
        }
        final CompilationUnit ast = SharedASTProvider.getAST(clazz, SharedASTProvider.WAIT_YES, monitor);
        if (ast == null) {
            return;
        }

        // final String sourceFileName = type.getElementName() + ".java";
        // final char[] source = sourceMapper.findSource(type, sourceFileName);
        // if (source == null) {
        // return;
        // }
        // final IJavaProject javaProject = root.getJavaProject();
        final String unitName = root.getPath() + "!" + type.getFullyQualifiedName();
        // final CompilationUnit ast = CompilationUnitHelper.parse(source,
        // unitName, javaProject);
        // ast.setProperty("location", rootLocation);
        // ast.setProperty("project", javaProject);
        monitor.subTask(unitName);

        indexer.index(ast, new CodeIndexerConfigBean(false, 1.0f));
    }

    private void addArchiveVisitedMarker() throws IOException {
        final Document visited = new Document();
        addFieldToDocument(visited, Fields.RESOURCE_PATH, ResourcePathIndexer.getPath(rootLocation));
        addFieldToDocument(visited, Fields.TIMESTAMP, TimestampIndexer.getTimeString());
        indexer.addDocument(visited);
    }

    private void closeMonitor() {
        monitor.done();
    }
}