Package it.unibz.instasearch.indexing

Source Code of it.unibz.instasearch.indexing.WorkspaceIndexerJDT$ClassFileSourceStorage

/*
* Copyright (c) 2009 Andrejs Jermakovics.
*
* 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:
*     Andrejs Jermakovics - initial implementation
*/
package it.unibz.instasearch.indexing;

import it.unibz.instasearch.InstaSearchPlugin;
import it.unibz.instasearch.prefs.PreferenceConstants;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeSet;

import org.apache.lucene.index.IndexWriter;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.IJarEntryResource;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
import org.eclipse.ui.IEditorInput;

/**
* Workspace indexer which also indexes JAR source attachments
*/


@SuppressWarnings("restriction")
public class WorkspaceIndexerJDT extends WorkspaceIndexer {

  /**
   * @throws Exception
   * @throws IOException
   */
  public WorkspaceIndexerJDT() throws Exception {
    super();
   
    if( JavaCore.getJavaCore() == null ) // check that we have JDT. throws exception if we don't have JavaCore
      throw new RuntimeException("JDT not detected");
  }

  @Override
  protected void indexContainers(IndexWriter indexWriter, IWorkspaceRoot workspaceRoot, IProgressMonitor monitor) throws Exception {
   
    super.indexContainers(indexWriter, workspaceRoot, monitor);
   
    boolean indexArchives = InstaSearchPlugin.getBoolPref(PreferenceConstants.P_INDEX_ARCHIVES);
    if( ! indexArchives )
      return;
   
    try {
      IJavaModel javaModel = JavaCore.create(workspaceRoot);
     
      List<IPackageFragmentRoot> jars = getJars(javaModel);

      monitor.beginTask("Indexing JAR Source Attachements (" + jars.size() + ")", jars.size());

      for(IPackageFragmentRoot jar: jars) {
        monitor.worked(1);

        indexClassFiles(indexWriter, jar, monitor);
        indexNonJavaResources(indexWriter, jar, monitor);
       
        if( monitor.isCanceled() )
          break;
      }
    } catch(Exception e) {
      InstaSearchPlugin.log(e);
    }
   
    if( monitor.isCanceled() ) {
      // if user canceled, disable jar indexing in preferences. next time don't index
      InstaSearchPlugin.setBoolPref(PreferenceConstants.P_INDEX_ARCHIVES, false);
    }
   
    monitor.done();
  }
 
  /**
   * Index non .class files
   *
   * @param indexWriter
   * @param jar
   * @param monitor
   * @throws CoreException
   * @throws IOException
   */
  private void indexNonJavaResources(IndexWriter indexWriter, IPackageFragmentRoot jar, IProgressMonitor monitor) throws Exception {
   
    Object[] resources = jar.getNonJavaResources();
   
    if( resources == null || resources.length == 0 )
      return;
   
    IJarEntryResource[] jarEntries = new IJarEntryResource[resources.length];
    System.arraycopy(resources, 0, jarEntries, 0, resources.length);
   
    indexNonJavaResources(indexWriter, jar, jarEntries, monitor);
  }
 
  /**
   * @param indexWriter
   * @param jar
   * @param resources
   * @param monitor
   * @throws IOException
   * @throws CoreException
   */
  private void indexNonJavaResources(IndexWriter indexWriter, IPackageFragmentRoot jar, IJarEntryResource[] resources, IProgressMonitor monitor) throws Exception {
   
    String jarName = getJarName(jar);
    String projectPath = getProjectPath(jar);
   
    for(IJarEntryResource resource: resources)
    {
      if( monitor.isCanceled() )
        return;
     
      if( resource.isFile() )
      {
        if( isIndexable(resource) )
          indexStorageWithRetry(indexWriter, resource, projectPath, IResource.NULL_STAMP, jarName);
      }
      else
      {
        indexNonJavaResources(indexWriter, jar, resource.getChildren(), monitor);
      }
    }
   
  }

  /**
   * @param jarRes
   * @return
   */
  private boolean isIndexable(IJarEntryResource jarRes) {
    String ext = jarRes.getFullPath().getFileExtension();
   
    return isIndexableExtension(ext);
  }

  /**
   * @param jar
   * @return
   */
  private String getProjectPath(IPackageFragmentRoot jar) {
    return jar.getJavaProject().getElementName() + "/" + getJarName(jar);
  }

  /**
   * @param jar
   * @return
   */
  private String getJarName(IPackageFragmentRoot jar) {
    return jar.getElementName();
  }

  private void indexClassFiles(IndexWriter indexWriter, IPackageFragmentRoot jar, IProgressMonitor monitor) throws Exception {
   
    String jarName = getJarName(jar);
    String projectPath = getProjectPath(jar);
   
    for(IJavaElement pkgRootChild: jar.getChildren()) {
     
      IPackageFragment pkg = (IPackageFragment) pkgRootChild;
      monitor.setTaskName("Indexing JAR Source Attachements: " + jar.getElementName() + " - " + pkg.getElementName());
     
      for(IClassFile classFile: pkg.getClassFiles()) {
        if( classFile.getElementName().contains("$") ) continue; // not type root
       
        ClassFileSourceStorage classFileSourceStorage = new ClassFileSourceStorage(classFile);
       
        if( classFileSourceStorage.hasSource() )
          indexStorageWithRetry(indexWriter, classFileSourceStorage, projectPath, IResource.NULL_STAMP, jarName);
       
        if( monitor.isCanceled() ) return;
      }
     
    }

  }
 
  private List<IPackageFragmentRoot> getJars(IJavaModel javaModel) throws JavaModelException {
   
    IJavaProject[] projects = javaModel.getJavaProjects();
    TreeSet<String> jarNames = new TreeSet<String>();
    LinkedList<IPackageFragmentRoot> jars = new LinkedList<IPackageFragmentRoot>();
   
    for(IJavaProject javaProj: projects) {
     
      IPackageFragmentRoot[] roots = javaProj.getPackageFragmentRoots();
     
      for(IPackageFragmentRoot root: roots) {
        if( root.isArchive() && root.getSourceAttachmentPath() != null ) {
         
          String name = root.getElementName();
         
          if( !jarNames.contains(name) ) {
            jarNames.add(name);
            jars.add(root);
          }
        }
      }
    }
   
    return jars;
  }

  @Override
  public IEditorInput getEditorInput(SearchResultDoc doc) throws Exception {
   
    if( ! doc.isInJar() )
      return super.getEditorInput(doc);
 
    if( "class".equals(doc.getFileExtension()) ) {
      IClassFile classFile = getClassFile(doc);

      if( classFile == null )
        return null;

      return EditorUtility.getEditorInput(classFile);
    }
   
    IStorage storage = getNonJavaResource(doc);
   
    if( storage == null )
      return null;
   
    return EditorUtility.getEditorInput(storage);
  }

  @Override
  public IStorage getStorage(SearchResultDoc doc) throws Exception {
    if( !doc.isInJar() )
      return super.getStorage(doc); // return file
   
    if( "class".equals(doc.getFileExtension())) {
      IClassFile classFile = getClassFile(doc);

      if( classFile == null )
        return null;

      ClassFileSourceStorage storage = new ClassFileSourceStorage(classFile);

      return storage;
    }
   
    return getNonJavaResource(doc);
  }
 
  /**
   * @param doc
   * @return
   * @throws JavaModelException
   */
  private IStorage getNonJavaResource(SearchResultDoc doc) throws JavaModelException {
   
    IWorkspaceRoot workspaceRoot = InstaSearchPlugin.getWorkspaceRoot();
    IJavaModel javaModel = JavaCore.create(workspaceRoot);
   
    String javaProjectName = doc.getProject().segment(0);
    IJavaProject javaProj = javaModel.getJavaProject(javaProjectName);
   
    if( !javaProj.isOpen() )
      javaProj.open(new NullProgressMonitor());
   
    javaModel.refreshExternalArchives(new IJavaElement[]{javaProj}, new NullProgressMonitor());
   
    String jarName = doc.getJarName();
   
    IPackageFragmentRoot[] roots = javaProj.getPackageFragmentRoots();
    IPackageFragmentRoot jar = null;
   
    for(IPackageFragmentRoot root: roots) {
      if( root.isArchive() && root.getSourceAttachmentPath() != null ) {
       
        String name = root.getElementName();
        if( name.equals(jarName)) {
          jar = root;
          break;
        }
      }
    }
   
    if( jar == null )
      return null;
   
    String filePath = doc.getFilePath();
    IPath path = new Path(filePath);
   
    IJarEntryResource res  = null;
    for(String segment: path.segments())
    {
      if( res == null )
        res = findJarEntry(jar, segment);
      else
        res = findJarEntry(res.getChildren(), segment);
    }
   
    return res;
  }

  /**
   * @param jar
   * @param filePath
   * @return
   * @throws JavaModelException
   */
  private IJarEntryResource findJarEntry(IPackageFragmentRoot jar, String filePath) throws JavaModelException {
   
    Object[] resources = jar.getNonJavaResources();
   
    if( resources == null || resources.length == 0 )
      return null;
   
    IJarEntryResource[] jarEntries = new IJarEntryResource[resources.length];
    System.arraycopy(resources, 0, jarEntries, 0, resources.length);
   
    return findJarEntry(jarEntries, filePath);
  }

  /**
   * @param jarEntries
   * @param filePath
   * @return
   */
  private IJarEntryResource findJarEntry(IJarEntryResource[] jarEntries,
      String filePath) {
   
    for(IJarEntryResource entry: jarEntries)
    {
      if( filePath.equals(entry.getName()) )
        return entry;
    }
   
    return null;
  }

  /**
   * @param doc
   * @return
   * @throws JavaModelException
   */
  private IClassFile getClassFile(SearchResultDoc doc) throws Exception {
   
    IWorkspaceRoot workspaceRoot = InstaSearchPlugin.getWorkspaceRoot();
    IJavaModel javaModel = JavaCore.create(workspaceRoot);
   
    String javaProjectName = doc.getProject().segment(0);
    IJavaProject proj = javaModel.getJavaProject(javaProjectName);
   
    if( proj == null )
      throw new Exception("Project " + javaProjectName + " not found");
   
    if( !proj.isOpen() )
      proj.open(new NullProgressMonitor());
   
    javaModel.refreshExternalArchives(new IJavaElement[]{proj}, new NullProgressMonitor());
   
    IPath filePath = new Path(doc.getFilePath());
    String fileName = filePath.lastSegment();
   
    IPath jarPath = filePath.removeLastSegments(2); // remove pkg and filename
    IPackageFragmentRoot jar = null;
    IResource jarFile = workspaceRoot.findMember(jarPath);
   
    if( jarFile != null )
      jar = proj.getPackageFragmentRoot(jarFile);
    else
      jar = proj.getPackageFragmentRoot(jarPath.toString()); // external archive
   
    if( jar == null )
      throw new Exception("Jar " + jarPath + " not found in project " + doc.getProjectName());
   
    IPath pkgPath = filePath.removeLastSegments(1); // remove filename
    String pkgName = pkgPath.lastSegment();
   
    IPackageFragment pkg = jar.getPackageFragment(pkgName);
   
    if( pkg == null )
      throw new Exception("Package " + pkgName + " not found  in " + doc.getProjectName());
   
    IClassFile classFile = pkg.getClassFile(fileName);
   
    return classFile;
  }
 
  /**
   * Stores the attached source of a .class file
   */
  private class ClassFileSourceStorage implements IStorage {

    private IClassFile classFile;
    private String source;

    /**
     * @param classFileWithSource
     * @throws JavaModelException
     *
     */
    public ClassFileSourceStorage(IClassFile classFileWithSource) throws JavaModelException {
      this.classFile = classFileWithSource;
      this.source = classFile.getSource();
    }
   
    public InputStream getContents() throws CoreException {
      if( !hasSource() ) return null;
     
      return new ByteArrayInputStream(source.getBytes());
    }

    public boolean hasSource() {
      return source != null;
    }
   
    /**
     * <jar path>/<package name>/<file name>
     */
    public IPath getFullPath() {
      IPackageFragment pkg = (IPackageFragment)classFile.getParent();

      IPackageFragmentRoot jar = (IPackageFragmentRoot)pkg.getParent();
     
      String pkgName = pkg.getElementName();
      IPath jarPath = jar.getPath();
     
      IPath filePath = jarPath.append(pkgName).append(getName());
     
      return filePath;
    }

    public String getName() {
      return classFile.getElementName(); // ClassName.class
    }

    public boolean isReadOnly() {
      return true;
    }

    @SuppressWarnings("rawtypes")
    public Object getAdapter(Class adapter) {
      return classFile.getAdapter(adapter);
    }
   
  }
}
TOP

Related Classes of it.unibz.instasearch.indexing.WorkspaceIndexerJDT$ClassFileSourceStorage

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.