Using only one Lucene index to keep data for whole project rather than several indices for each source root in order to improve performance. Currently requires that the indexing creates indices from scratch.
authorJan Lahoda <jlahoda@netbeans.org>
Fri, 01 Jul 2011 18:38:14 +0200
changeset 61938223639f3b1
parent 618 4e5f7288c74f
child 620 49f2dba8cb19
Using only one Lucene index to keep data for whole project rather than several indices for each source root in order to improve performance. Currently requires that the indexing creates indices from scratch.
remoting/server/indexer/impl/nbproject/genfiles.properties
remoting/server/indexer/impl/nbproject/project.xml
remoting/server/indexer/impl/src/org/netbeans/modules/jackpot30/backend/impl/OptionProcessorImpl.java
remoting/server/indexer/impl/src/org/netbeans/modules/jackpot30/backend/impl/spi/IndexAccessor.java
remoting/server/indexer/source/nbproject/genfiles.properties
remoting/server/indexer/source/nbproject/project.xml
remoting/server/indexer/source/src/org/netbeans/modules/jackpot30/indexer/source/SourceIndexer.java
remoting/server/indexer/usages/nbproject/genfiles.properties
remoting/server/indexer/usages/nbproject/project.xml
remoting/server/indexer/usages/src/org/netbeans/modules/jackpot30/indexer/usages/IndexerImpl.java
remoting/server/tests/run-declarative-tests
remoting/server/web/base.web.api/nbproject/project.properties
remoting/server/web/base.web.api/src/org/netbeans/modules/jackpot30/backend/base/CategoryStorage.java
remoting/server/web/base.web.api/src/org/netbeans/modules/jackpot30/backend/base/api/API.java
remoting/server/web/source.web.api/nbproject/project.properties
remoting/server/web/source.web.api/src/org/netbeans/modules/jackpot30/source/api/API.java
remoting/server/web/type.web.api/src/org/netbeans/modules/jackpot30/backend/type/api/API.java
remoting/server/web/usages.web.api/src/org/netbeans/modules/jackpot30/backend/usages/api/API.java
     1.1 --- a/remoting/server/indexer/impl/nbproject/genfiles.properties	Thu Jun 30 13:54:51 2011 +0200
     1.2 +++ b/remoting/server/indexer/impl/nbproject/genfiles.properties	Fri Jul 01 18:38:14 2011 +0200
     1.3 @@ -1,8 +1,8 @@
     1.4 -build.xml.data.CRC32=f3e356a3
     1.5 +build.xml.data.CRC32=73a66b48
     1.6  build.xml.script.CRC32=c32e03a8
     1.7  build.xml.stylesheet.CRC32=a56c6a5b@1.47
     1.8  # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
     1.9  # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
    1.10 -nbproject/build-impl.xml.data.CRC32=f3e356a3
    1.11 +nbproject/build-impl.xml.data.CRC32=73a66b48
    1.12  nbproject/build-impl.xml.script.CRC32=87e6e497
    1.13  nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.47
     2.1 --- a/remoting/server/indexer/impl/nbproject/project.xml	Thu Jun 30 13:54:51 2011 +0200
     2.2 +++ b/remoting/server/indexer/impl/nbproject/project.xml	Fri Jul 01 18:38:14 2011 +0200
     2.3 @@ -216,7 +216,9 @@
     2.4                      </test-dependency>
     2.5                  </test-type>
     2.6              </test-dependencies>
     2.7 -            <public-packages/>
     2.8 +            <public-packages>
     2.9 +                <package>org.netbeans.modules.jackpot30.backend.impl.spi</package>
    2.10 +            </public-packages>
    2.11          </data>
    2.12      </configuration>
    2.13  </project>
     3.1 --- a/remoting/server/indexer/impl/src/org/netbeans/modules/jackpot30/backend/impl/OptionProcessorImpl.java	Thu Jun 30 13:54:51 2011 +0200
     3.2 +++ b/remoting/server/indexer/impl/src/org/netbeans/modules/jackpot30/backend/impl/OptionProcessorImpl.java	Fri Jul 01 18:38:14 2011 +0200
     3.3 @@ -47,13 +47,16 @@
     3.4  import java.io.IOException;
     3.5  import java.io.InputStream;
     3.6  import java.util.Arrays;
     3.7 -import java.util.HashMap;
     3.8  import java.util.HashSet;
     3.9  import java.util.Map;
    3.10  import java.util.Properties;
    3.11  import java.util.Set;
    3.12  import java.util.jar.JarOutputStream;
    3.13  import java.util.zip.ZipEntry;
    3.14 +import org.apache.lucene.analysis.KeywordAnalyzer;
    3.15 +import org.apache.lucene.index.CorruptIndexException;
    3.16 +import org.apache.lucene.index.IndexWriter;
    3.17 +import org.apache.lucene.store.FSDirectory;
    3.18  import org.netbeans.api.java.classpath.ClassPath;
    3.19  import org.netbeans.api.java.classpath.GlobalPathRegistry;
    3.20  import org.netbeans.api.java.source.SourceUtils;
    3.21 @@ -63,6 +66,7 @@
    3.22  import org.netbeans.api.project.SourceGroup;
    3.23  import org.netbeans.api.project.ui.OpenProjects;
    3.24  import org.netbeans.api.sendopts.CommandException;
    3.25 +import org.netbeans.modules.jackpot30.backend.impl.spi.IndexAccessor;
    3.26  import org.netbeans.modules.parsing.impl.indexing.CacheFolder;
    3.27  import org.netbeans.spi.java.classpath.support.ClassPathSupport;
    3.28  import org.netbeans.spi.project.support.ant.PropertyUtils;
    3.29 @@ -129,7 +133,20 @@
    3.30              return;
    3.31          }
    3.32  
    3.33 +        File baseDirFile = new File(optionValues.get(CATEGORY_ROOT_DIR)[0]);
    3.34 +        FileObject baseDir = FileUtil.toFileObject(baseDirFile);
    3.35 +        IndexWriter w = null;
    3.36 +
    3.37 +        FileObject cacheFolder = CacheFolder.getCacheFolder();
    3.38 +        FileObject cacheTemp = cacheFolder.getFileObject("index");
    3.39 +
    3.40          try {
    3.41 +            if (cacheTemp != null) cacheTemp.delete();
    3.42 +
    3.43 +            cacheTemp = cacheFolder.createFolder("index");
    3.44 +            w = new IndexWriter(FSDirectory.open(FileUtil.toFile(cacheTemp)), new KeywordAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED);
    3.45 +
    3.46 +            IndexAccessor.current = new IndexAccessor(w, baseDir);
    3.47              Set<FileObject> roots = getRoots(optionValues.get(CATEGORY_PROJECTS), env);
    3.48  
    3.49              indexProjects(roots, env);
    3.50 @@ -137,16 +154,24 @@
    3.51              throw (CommandException) new CommandException(0).initCause(ex);
    3.52          } catch (IOException ex) {
    3.53              throw (CommandException) new CommandException(0).initCause(ex);
    3.54 +        } finally {
    3.55 +            if (w != null) {
    3.56 +                try {
    3.57 +                    w.close(true);
    3.58 +                } catch (CorruptIndexException ex) {
    3.59 +                    Exceptions.printStackTrace(ex);
    3.60 +                } catch (IOException ex) {
    3.61 +                    Exceptions.printStackTrace(ex);
    3.62 +                }
    3.63 +            }
    3.64          }
    3.65  
    3.66          JarOutputStream out = null;
    3.67          InputStream segments = null;
    3.68  
    3.69          try {
    3.70 -            FileObject cacheFolder = CacheFolder.getCacheFolder();
    3.71 -
    3.72              out = new JarOutputStream(new FileOutputStream(cache));
    3.73 -            pack(out, cacheFolder, categoryId, new StringBuilder());
    3.74 +            pack(out, cacheTemp, "index", new StringBuilder(categoryId));
    3.75  
    3.76              segments = cacheFolder.getFileObject("segments").getInputStream();
    3.77              Properties in = new Properties();
    3.78 @@ -155,14 +180,13 @@
    3.79  
    3.80              segments.close();//XXX: should be in finally!
    3.81  
    3.82 -            File baseDirFile = new File(optionValues.get(CATEGORY_ROOT_DIR)[0]);
    3.83 -            String baseDir = baseDirFile.toURI().toString();
    3.84 +            String baseDirPath = baseDirFile.toURI().toString();
    3.85  
    3.86              Properties outSegments = new Properties();
    3.87  
    3.88              for (String segment : in.stringPropertyNames()) {
    3.89                  String url = in.getProperty(segment);
    3.90 -                String rel = url.startsWith(baseDir) ? "rel:/" + url.substring(baseDir.length()) : url;
    3.91 +                String rel = url.startsWith(baseDirPath) ? "rel:/" + url.substring(baseDirPath.length()) : url;
    3.92  
    3.93                  outSegments.setProperty(segment, rel);
    3.94              }
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/remoting/server/indexer/impl/src/org/netbeans/modules/jackpot30/backend/impl/spi/IndexAccessor.java	Fri Jul 01 18:38:14 2011 +0200
     4.3 @@ -0,0 +1,37 @@
     4.4 +/*
     4.5 + * To change this template, choose Tools | Templates
     4.6 + * and open the template in the editor.
     4.7 + */
     4.8 +package org.netbeans.modules.jackpot30.backend.impl.spi;
     4.9 +
    4.10 +import org.apache.lucene.index.IndexWriter;
    4.11 +import org.openide.filesystems.FileObject;
    4.12 +import org.openide.filesystems.FileUtil;
    4.13 +
    4.14 +/**
    4.15 + *
    4.16 + * @author lahvac
    4.17 + */
    4.18 +public class IndexAccessor {
    4.19 +
    4.20 +    private final FileObject root;
    4.21 +    private final IndexWriter w;
    4.22 +
    4.23 +    public IndexAccessor(IndexWriter w, FileObject root) {
    4.24 +        this.w = w;
    4.25 +        this.root = root;
    4.26 +    }
    4.27 +
    4.28 +    public IndexWriter getIndexWriter() {
    4.29 +        return w;
    4.30 +    }
    4.31 +
    4.32 +    public String getPath(FileObject file) {
    4.33 +        return FileUtil.getRelativePath(root, file);
    4.34 +    }
    4.35 +
    4.36 +    public static IndexAccessor current;
    4.37 +    public static IndexAccessor getCurrent() {
    4.38 +        return current;
    4.39 +    }
    4.40 +}
     5.1 --- a/remoting/server/indexer/source/nbproject/genfiles.properties	Thu Jun 30 13:54:51 2011 +0200
     5.2 +++ b/remoting/server/indexer/source/nbproject/genfiles.properties	Fri Jul 01 18:38:14 2011 +0200
     5.3 @@ -1,8 +1,8 @@
     5.4 -build.xml.data.CRC32=b606330f
     5.5 +build.xml.data.CRC32=f5dffe4b
     5.6  build.xml.script.CRC32=aab17f8c
     5.7  build.xml.stylesheet.CRC32=a56c6a5b@1.47
     5.8  # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
     5.9  # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
    5.10 -nbproject/build-impl.xml.data.CRC32=b606330f
    5.11 +nbproject/build-impl.xml.data.CRC32=f5dffe4b
    5.12  nbproject/build-impl.xml.script.CRC32=279e9fd9
    5.13  nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.47
     6.1 --- a/remoting/server/indexer/source/nbproject/project.xml	Thu Jun 30 13:54:51 2011 +0200
     6.2 +++ b/remoting/server/indexer/source/nbproject/project.xml	Fri Jul 01 18:38:14 2011 +0200
     6.3 @@ -25,6 +25,14 @@
     6.4                      </run-dependency>
     6.5                  </dependency>
     6.6                  <dependency>
     6.7 +                    <code-name-base>org.netbeans.modules.jackpot30.backend.impl</code-name-base>
     6.8 +                    <build-prerequisite/>
     6.9 +                    <compile-dependency/>
    6.10 +                    <run-dependency>
    6.11 +                        <specification-version>1.0</specification-version>
    6.12 +                    </run-dependency>
    6.13 +                </dependency>
    6.14 +                <dependency>
    6.15                      <code-name-base>org.netbeans.modules.parsing.api</code-name-base>
    6.16                      <build-prerequisite/>
    6.17                      <compile-dependency/>
     7.1 --- a/remoting/server/indexer/source/src/org/netbeans/modules/jackpot30/indexer/source/SourceIndexer.java	Thu Jun 30 13:54:51 2011 +0200
     7.2 +++ b/remoting/server/indexer/source/src/org/netbeans/modules/jackpot30/indexer/source/SourceIndexer.java	Fri Jul 01 18:38:14 2011 +0200
     7.3 @@ -48,15 +48,21 @@
     7.4  import java.net.URL;
     7.5  import java.util.logging.Level;
     7.6  import java.util.logging.Logger;
     7.7 +import org.apache.lucene.document.Document;
     7.8 +import org.apache.lucene.document.Field;
     7.9 +import org.apache.lucene.document.Field.Index;
    7.10 +import org.apache.lucene.document.Field.Store;
    7.11  import org.netbeans.api.editor.mimelookup.MimeRegistration;
    7.12 +import org.netbeans.modules.jackpot30.backend.impl.spi.IndexAccessor;
    7.13  import org.netbeans.modules.parsing.lucene.support.DocumentIndex;
    7.14 -import org.netbeans.modules.parsing.lucene.support.IndexDocument;
    7.15  import org.netbeans.modules.parsing.lucene.support.IndexManager;
    7.16  import org.netbeans.modules.parsing.spi.indexing.Context;
    7.17  import org.netbeans.modules.parsing.spi.indexing.CustomIndexer;
    7.18  import org.netbeans.modules.parsing.spi.indexing.CustomIndexerFactory;
    7.19  import org.netbeans.modules.parsing.spi.indexing.Indexable;
    7.20 +import org.openide.filesystems.FileObject;
    7.21  import org.openide.filesystems.FileUtil;
    7.22 +import org.openide.filesystems.URLMapper;
    7.23  
    7.24  /**
    7.25   *
    7.26 @@ -69,18 +75,22 @@
    7.27      @Override
    7.28      protected void index(Iterable<? extends Indexable> files, Context context) {
    7.29          try {
    7.30 -            DocumentIndex idx = IndexManager.createDocumentIndex(FileUtil.toFile(context.getIndexFolder()));
    7.31 -            
    7.32              for (Indexable i : files) {
    7.33 -                IndexDocument doc = IndexManager.createDocument(i.getRelativePath());
    7.34 +                FileObject f = URLMapper.findFileObject(i.getURL());
    7.35  
    7.36 -                doc.addPair(KEY_CONTENT, readFully(i.getURL()), false, true);
    7.37 +                if (f == null) continue;
    7.38  
    7.39 -                idx.addDocument(doc);
    7.40 +                String relPath = IndexAccessor.getCurrent().getPath(f);
    7.41 +
    7.42 +                if (relPath == null) continue;
    7.43 +                
    7.44 +                Document doc = new Document();
    7.45 +
    7.46 +                doc.add(new Field("relativePath", relPath, Store.YES, Index.NOT_ANALYZED));
    7.47 +                doc.add(new Field(KEY_CONTENT, readFully(i.getURL()), Store.YES, Index.NO));
    7.48 +
    7.49 +                IndexAccessor.getCurrent().getIndexWriter().addDocument(doc);
    7.50              }
    7.51 -
    7.52 -            idx.store(true);
    7.53 -            idx.close();
    7.54          } catch (IOException ex) {
    7.55              Logger.getLogger(SourceIndexer.class.getName()).log(Level.SEVERE, null, ex);
    7.56          }
     8.1 --- a/remoting/server/indexer/usages/nbproject/genfiles.properties	Thu Jun 30 13:54:51 2011 +0200
     8.2 +++ b/remoting/server/indexer/usages/nbproject/genfiles.properties	Fri Jul 01 18:38:14 2011 +0200
     8.3 @@ -1,8 +1,8 @@
     8.4 -build.xml.data.CRC32=15fd41e2
     8.5 +build.xml.data.CRC32=5ee97dea
     8.6  build.xml.script.CRC32=4ae79e41
     8.7  build.xml.stylesheet.CRC32=a56c6a5b@1.47
     8.8  # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
     8.9  # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
    8.10 -nbproject/build-impl.xml.data.CRC32=15fd41e2
    8.11 +nbproject/build-impl.xml.data.CRC32=5ee97dea
    8.12  nbproject/build-impl.xml.script.CRC32=16d3b827
    8.13  nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.47
     9.1 --- a/remoting/server/indexer/usages/nbproject/project.xml	Thu Jun 30 13:54:51 2011 +0200
     9.2 +++ b/remoting/server/indexer/usages/nbproject/project.xml	Fri Jul 01 18:38:14 2011 +0200
     9.3 @@ -42,6 +42,14 @@
     9.4                      </run-dependency>
     9.5                  </dependency>
     9.6                  <dependency>
     9.7 +                    <code-name-base>org.netbeans.modules.jackpot30.backend.impl</code-name-base>
     9.8 +                    <build-prerequisite/>
     9.9 +                    <compile-dependency/>
    9.10 +                    <run-dependency>
    9.11 +                        <specification-version>1.0</specification-version>
    9.12 +                    </run-dependency>
    9.13 +                </dependency>
    9.14 +                <dependency>
    9.15                      <code-name-base>org.netbeans.modules.java.source</code-name-base>
    9.16                      <build-prerequisite/>
    9.17                      <compile-dependency/>
    10.1 --- a/remoting/server/indexer/usages/src/org/netbeans/modules/jackpot30/indexer/usages/IndexerImpl.java	Thu Jun 30 13:54:51 2011 +0200
    10.2 +++ b/remoting/server/indexer/usages/src/org/netbeans/modules/jackpot30/indexer/usages/IndexerImpl.java	Fri Jul 01 18:38:14 2011 +0200
    10.3 @@ -41,8 +41,11 @@
    10.4   */
    10.5  package org.netbeans.modules.jackpot30.indexer.usages;
    10.6  
    10.7 +import com.sun.source.tree.ClassTree;
    10.8  import com.sun.source.tree.IdentifierTree;
    10.9  import com.sun.source.tree.MemberSelectTree;
   10.10 +import com.sun.source.tree.MethodTree;
   10.11 +import com.sun.source.tree.VariableTree;
   10.12  import com.sun.source.util.TreePathScanner;
   10.13  import java.io.IOException;
   10.14  import java.util.Collection;
   10.15 @@ -53,6 +56,12 @@
   10.16  import javax.lang.model.element.Element;
   10.17  import javax.lang.model.element.ElementKind;
   10.18  import javax.lang.model.element.ExecutableElement;
   10.19 +import javax.lang.model.element.TypeElement;
   10.20 +import org.apache.lucene.document.Document;
   10.21 +import org.apache.lucene.document.Field;
   10.22 +import org.apache.lucene.document.Field.Index;
   10.23 +import org.apache.lucene.document.Field.Store;
   10.24 +import org.apache.lucene.index.CorruptIndexException;
   10.25  import org.netbeans.api.editor.mimelookup.MimeRegistration;
   10.26  import org.netbeans.api.java.source.ClasspathInfo;
   10.27  import org.netbeans.api.java.source.CompilationController;
   10.28 @@ -60,15 +69,12 @@
   10.29  import org.netbeans.api.java.source.JavaSource;
   10.30  import org.netbeans.api.java.source.JavaSource.Phase;
   10.31  import org.netbeans.api.java.source.Task;
   10.32 -import org.netbeans.modules.parsing.lucene.support.DocumentIndex;
   10.33 -import org.netbeans.modules.parsing.lucene.support.IndexDocument;
   10.34 -import org.netbeans.modules.parsing.lucene.support.IndexManager;
   10.35 +import org.netbeans.modules.jackpot30.backend.impl.spi.IndexAccessor;
   10.36  import org.netbeans.modules.parsing.spi.indexing.Context;
   10.37  import org.netbeans.modules.parsing.spi.indexing.CustomIndexer;
   10.38  import org.netbeans.modules.parsing.spi.indexing.CustomIndexerFactory;
   10.39  import org.netbeans.modules.parsing.spi.indexing.Indexable;
   10.40  import org.openide.filesystems.FileObject;
   10.41 -import org.openide.filesystems.FileUtil;
   10.42  import org.openide.filesystems.URLMapper;
   10.43  import org.openide.util.Exceptions;
   10.44  
   10.45 @@ -104,15 +110,11 @@
   10.46              return ;
   10.47          }
   10.48  
   10.49 -        final DocumentIndex[] idx = new DocumentIndex[1];
   10.50 -
   10.51          try {
   10.52 -            idx[0] = IndexManager.createDocumentIndex(FileUtil.toFile(context.getIndexFolder()));
   10.53 -            
   10.54              ClasspathInfo cpInfo = ClasspathInfo.create(context.getRoot());
   10.55  
   10.56              for (String path : deleted) {
   10.57 -                idx[0].removeDocument(path);
   10.58 +                assert false;
   10.59              }
   10.60  
   10.61              if (!toIndex.isEmpty()) {
   10.62 @@ -121,8 +123,11 @@
   10.63                          if (cc.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0)
   10.64                              return ;
   10.65  
   10.66 -                        final IndexDocument doc = IndexManager.createDocument(FileUtil.getRelativePath(context.getRoot(), cc.getFileObject()));
   10.67 +                        final String file = IndexAccessor.getCurrent().getPath(cc.getFileObject());
   10.68 +                        final Document usages = new Document();
   10.69  
   10.70 +                        usages.add(new Field("file", file, Store.YES, Index.NO));
   10.71 +                        
   10.72                          new TreePathScanner<Void, Void>() {
   10.73                              private final Set<String> SEEN_SIGNATURES = new HashSet<String>();
   10.74                              @Override public Void visitIdentifier(IdentifierTree node, Void p) {
   10.75 @@ -140,7 +145,7 @@
   10.76                                      String serialized = Common.serialize(ElementHandle.create(el));
   10.77  
   10.78                                      if (SEEN_SIGNATURES.add(serialized)) {
   10.79 -                                        doc.addPair(KEY_SIGNATURES, serialized, true, true);
   10.80 +                                        usages.add(new Field(KEY_SIGNATURES, serialized, Store.YES, Index.NOT_ANALYZED));
   10.81                                      }
   10.82  
   10.83                                      if (el.getKind() == ElementKind.METHOD) {
   10.84 @@ -148,29 +153,95 @@
   10.85                                              serialized = Common.serialize(ElementHandle.create(el));
   10.86  
   10.87                                              if (SEEN_SIGNATURES.add(serialized)) {
   10.88 -                                                doc.addPair(KEY_SIGNATURES, serialized, true, true);
   10.89 +                                                usages.add(new Field(KEY_SIGNATURES, serialized, Store.YES, Index.NOT_ANALYZED));
   10.90                                              }
   10.91                                          }
   10.92                                      }
   10.93                                  }
   10.94                              }
   10.95 +
   10.96 +                            private String currentClassFQN;
   10.97 +                            @Override public Void visitClass(ClassTree node, Void p) {
   10.98 +                                String oldClassFQN = currentClassFQN;
   10.99 +                                boolean oldInMethod = inMethod;
  10.100 +
  10.101 +                                try {
  10.102 +                                    Element el = cc.getTrees().getElement(getCurrentPath());
  10.103 +
  10.104 +                                    if (el != null) {
  10.105 +                                        try {
  10.106 +                                            currentClassFQN = cc.getElements().getBinaryName((TypeElement) el).toString();
  10.107 +                                            Document currentClassDocument = new Document();
  10.108 +
  10.109 +                                            currentClassDocument.add(new Field("classFQN", currentClassFQN, Store.YES, Index.NO));
  10.110 +                                            currentClassDocument.add(new Field("classSimpleName", node.getSimpleName().toString(), Store.YES, Index.NOT_ANALYZED));
  10.111 +                                            currentClassDocument.add(new Field("classSimpleNameLower", node.getSimpleName().toString().toLowerCase(), Store.YES, Index.NOT_ANALYZED));
  10.112 +                                            currentClassDocument.add(new Field("file", file, Store.YES, Index.NO));
  10.113 +
  10.114 +                                            IndexAccessor.getCurrent().getIndexWriter().addDocument(currentClassDocument);
  10.115 +                                        } catch (CorruptIndexException ex) {
  10.116 +                                            Exceptions.printStackTrace(ex);
  10.117 +                                        } catch (IOException ex) {
  10.118 +                                            Exceptions.printStackTrace(ex);
  10.119 +                                        }
  10.120 +                                    }
  10.121 +
  10.122 +                                    inMethod = false;
  10.123 +
  10.124 +                                    return super.visitClass(node, p);
  10.125 +                                } finally {
  10.126 +                                    currentClassFQN = oldClassFQN;
  10.127 +                                    inMethod = oldInMethod;
  10.128 +                                }
  10.129 +                            }
  10.130 +
  10.131 +                            private boolean inMethod;
  10.132 +                            @Override public Void visitMethod(MethodTree node, Void p) {
  10.133 +                                boolean oldInMethod = inMethod;
  10.134 +
  10.135 +                                try {
  10.136 +                                    handleFeature();
  10.137 +                                    inMethod = true;
  10.138 +                                    return super.visitMethod(node, p);
  10.139 +                                } finally {
  10.140 +                                    inMethod = oldInMethod;
  10.141 +                                }
  10.142 +                            }
  10.143 +
  10.144 +                            @Override public Void visitVariable(VariableTree node, Void p) {
  10.145 +                                handleFeature();
  10.146 +                                return super.visitVariable(node, p);
  10.147 +                            }
  10.148 +
  10.149 +                            public void handleFeature() {
  10.150 +                                Element el = cc.getTrees().getElement(getCurrentPath());
  10.151 +
  10.152 +                                if (el != null) {
  10.153 +                                    try {
  10.154 +                                        Document currentFeatureDocument = new Document();
  10.155 +
  10.156 +                                        currentFeatureDocument.add(new Field("featureClassFQN", currentClassFQN, Store.YES, Index.NO));
  10.157 +                                        currentFeatureDocument.add(new Field("featureSimpleName", el.getSimpleName().toString(), Store.YES, Index.NOT_ANALYZED));
  10.158 +                                        currentFeatureDocument.add(new Field("featureSimpleNameLower", el.getSimpleName().toString().toLowerCase(), Store.YES, Index.NOT_ANALYZED));
  10.159 +                                        currentFeatureDocument.add(new Field("featureKind", el.getKind().name(), Store.YES, Index.NO));
  10.160 +                                        currentFeatureDocument.add(new Field("file", file, Store.YES, Index.NO));
  10.161 +
  10.162 +                                        IndexAccessor.getCurrent().getIndexWriter().addDocument(currentFeatureDocument);
  10.163 +                                    } catch (CorruptIndexException ex) {
  10.164 +                                        Exceptions.printStackTrace(ex);
  10.165 +                                    } catch (IOException ex) {
  10.166 +                                        Exceptions.printStackTrace(ex);
  10.167 +                                    }
  10.168 +                                }
  10.169 +                            }
  10.170                          }.scan(cc.getCompilationUnit(), null);
  10.171  
  10.172 -                        idx[0].addDocument(doc);
  10.173 +                        IndexAccessor.getCurrent().getIndexWriter().addDocument(usages);
  10.174                      }
  10.175                  }, true);
  10.176              }
  10.177          } catch (IOException ex) {
  10.178              Exceptions.printStackTrace(ex);
  10.179 -        } finally {
  10.180 -            if (idx[0] != null) {
  10.181 -                try {
  10.182 -                    idx[0].store(true);
  10.183 -                    idx[0].close();
  10.184 -                } catch (IOException ex) {
  10.185 -                    Exceptions.printStackTrace(ex);
  10.186 -                }
  10.187 -            }
  10.188          }
  10.189      }
  10.190  
  10.191 @@ -189,6 +260,7 @@
  10.192  
  10.193          @Override
  10.194          public void filesDeleted(Iterable<? extends Indexable> deleted, Context context) {
  10.195 +            assert false;
  10.196              Collection<String> deletedPaths = new LinkedList<String>();
  10.197  
  10.198              for (Indexable i : deleted) {
    11.1 --- a/remoting/server/tests/run-declarative-tests	Thu Jun 30 13:54:51 2011 +0200
    11.2 +++ b/remoting/server/tests/run-declarative-tests	Fri Jul 01 18:38:14 2011 +0200
    11.3 @@ -41,7 +41,7 @@
    11.4  (cd ../web/web.main; ant jar)
    11.5  java -jar ../web/web.main/dist/web.main.jar cache >/dev/null 2>/dev/null &
    11.6  
    11.7 -#trap "kill %1" EXIT
    11.8 +trap "kill %1" EXIT
    11.9  
   11.10  sleep 1s; #XXX
   11.11  
    12.1 --- a/remoting/server/web/base.web.api/nbproject/project.properties	Thu Jun 30 13:54:51 2011 +0200
    12.2 +++ b/remoting/server/web/base.web.api/nbproject/project.properties	Fri Jul 01 18:38:14 2011 +0200
    12.3 @@ -28,6 +28,7 @@
    12.4  excludes=
    12.5  file.reference.org-netbeans-modules-java-source.jar=../../../../server/lib/org-netbeans-modules-java-source.jar
    12.6  file.reference.org-netbeans-modules-parsing-api.jar=../../../../server/lib/org-netbeans-modules-parsing-api.jar
    12.7 +file.reference.org-netbeans-modules-parsing-lucene.jar=../../../../server/lib/org-netbeans-modules-parsing-lucene.jar
    12.8  file.reference.org-openide-filesystems.jar=../../../../server/lib/org-openide-filesystems.jar
    12.9  file.reference.org-openide-util-lookup.jar=../../../../server/lib/org-openide-util-lookup.jar
   12.10  file.reference.util-commons.jar=../../../ide/api/external/util-commons.jar
   12.11 @@ -42,7 +43,9 @@
   12.12      ${file.reference.org-openide-filesystems.jar}:\
   12.13      ${file.reference.org-openide-util-lookup.jar}:\
   12.14      ${file.reference.util-commons.jar}:\
   12.15 -    ${file.reference.util-pojson.jar}
   12.16 +    ${file.reference.util-pojson.jar}:\
   12.17 +    ${libs.lucene.classpath}:\
   12.18 +    ${file.reference.org-netbeans-modules-parsing-lucene.jar}
   12.19  # Space-separated list of extra javac options
   12.20  javac.compilerargs=
   12.21  javac.deprecation=false
    13.1 --- a/remoting/server/web/base.web.api/src/org/netbeans/modules/jackpot30/backend/base/CategoryStorage.java	Thu Jun 30 13:54:51 2011 +0200
    13.2 +++ b/remoting/server/web/base.web.api/src/org/netbeans/modules/jackpot30/backend/base/CategoryStorage.java	Fri Jul 01 18:38:14 2011 +0200
    13.3 @@ -44,6 +44,8 @@
    13.4  import java.io.File;
    13.5  import java.io.FileNotFoundException;
    13.6  import java.io.IOException;
    13.7 +import java.lang.ref.Reference;
    13.8 +import java.lang.ref.SoftReference;
    13.9  import java.lang.reflect.Field;
   13.10  import java.net.URL;
   13.11  import java.util.ArrayList;
   13.12 @@ -55,8 +57,11 @@
   13.13  import java.util.Set;
   13.14  import java.util.logging.Level;
   13.15  import java.util.logging.Logger;
   13.16 +import org.apache.lucene.analysis.KeywordAnalyzer;
   13.17  import org.codeviation.pojson.Pojson;
   13.18  import org.netbeans.modules.parsing.impl.indexing.CacheFolder;
   13.19 +import org.netbeans.modules.parsing.lucene.support.Index;
   13.20 +import org.netbeans.modules.parsing.lucene.support.IndexManager;
   13.21  import org.openide.filesystems.FileObject;
   13.22  import org.openide.filesystems.FileUtil;
   13.23  
   13.24 @@ -66,13 +71,23 @@
   13.25   */
   13.26  public class CategoryStorage {
   13.27  
   13.28 -    public static void setCacheRoot(File cacheRoot) {
   13.29 +    public static synchronized void setCacheRoot(File cacheRoot) {
   13.30          CategoryStorage.cacheRoot = cacheRoot;
   13.31 +        categoryCache = null;
   13.32 +    }
   13.33 +
   13.34 +    public static void internalReset() {
   13.35 +        setCacheRoot(cacheRoot);
   13.36      }
   13.37  
   13.38      private static File cacheRoot;
   13.39 +    private static Reference<Iterable<? extends CategoryStorage>> categoryCache;
   13.40  
   13.41 -    public static Iterable<? extends CategoryStorage> listCategories() {
   13.42 +    public static synchronized Iterable<? extends CategoryStorage> listCategories() {
   13.43 +        Iterable<? extends CategoryStorage> cached = categoryCache != null ? categoryCache.get() : null;
   13.44 +
   13.45 +        if (cached != null) return cached;
   13.46 +
   13.47          List<CategoryStorage> result = new ArrayList<CategoryStorage>();
   13.48  
   13.49          for (File cat : cacheRoot.listFiles()) {
   13.50 @@ -94,6 +109,8 @@
   13.51              result.add(new CategoryStorage(cat.getName(), displayName));
   13.52          }
   13.53  
   13.54 +        categoryCache = new SoftReference<Iterable<? extends CategoryStorage>>(result);
   13.55 +        
   13.56          return result;
   13.57      }
   13.58  
   13.59 @@ -113,7 +130,7 @@
   13.60          this.displayName = displayName;
   13.61      }
   13.62  
   13.63 -    public Iterable<? extends URL> getCategoryIndexFolders() {
   13.64 +    private Iterable<? extends URL> getCategoryIndexFolders() {
   13.65          try {
   13.66              FileObject root = getCacheRoot();
   13.67              CacheFolder.setCacheFolder(root);
   13.68 @@ -148,6 +165,17 @@
   13.69          return Collections.emptyList();
   13.70      }
   13.71  
   13.72 +    public Iterable<? extends String> getSourceRoots() {
   13.73 +        List<String> result = new ArrayList<String>();
   13.74 +
   13.75 +        for (URL srcRoot : getCategoryIndexFolders()) {
   13.76 +            if (!"rel".equals(srcRoot.getProtocol())) continue;
   13.77 +            result.add(srcRoot.getPath().substring(1));
   13.78 +        }
   13.79 +
   13.80 +        return result;
   13.81 +    }
   13.82 +
   13.83      public String getId() {
   13.84          return id;
   13.85      }
   13.86 @@ -156,7 +184,31 @@
   13.87          return displayName;
   13.88      }
   13.89  
   13.90 -    public FileObject getCacheRoot() {
   13.91 +    private FileObject getCacheRoot() {
   13.92          return FileUtil.toFileObject(FileUtil.normalizeFile(new File(cacheRoot, id)));
   13.93      }
   13.94 +
   13.95 +    private File getIndexFile() {
   13.96 +        return new File(new File(cacheRoot, id), "index");
   13.97 +    }
   13.98 +
   13.99 +    private Reference<Index> cachedIndex;
  13.100 +
  13.101 +    public synchronized Index getIndex() {
  13.102 +        Index cached = cachedIndex != null ? cachedIndex.get() : null;
  13.103 +
  13.104 +        if (cached != null) return cached;
  13.105 +
  13.106 +        try {
  13.107 +            Index index = IndexManager.createIndex(getIndexFile(), new KeywordAnalyzer());
  13.108 +
  13.109 +            index.getStatus(true);
  13.110 +
  13.111 +            cachedIndex = new SoftReference<Index>(index);
  13.112 +
  13.113 +            return index;
  13.114 +        } catch (IOException ex) {
  13.115 +            throw new IllegalStateException(ex);
  13.116 +        }
  13.117 +    }
  13.118  }
    14.1 --- a/remoting/server/web/base.web.api/src/org/netbeans/modules/jackpot30/backend/base/api/API.java	Thu Jun 30 13:54:51 2011 +0200
    14.2 +++ b/remoting/server/web/base.web.api/src/org/netbeans/modules/jackpot30/backend/base/api/API.java	Fri Jul 01 18:38:14 2011 +0200
    14.3 @@ -40,19 +40,10 @@
    14.4  package org.netbeans.modules.jackpot30.backend.base.api;
    14.5  
    14.6  import java.io.IOException;
    14.7 -import java.lang.reflect.Field;
    14.8 -import java.lang.reflect.InvocationTargetException;
    14.9 -import java.lang.reflect.Method;
   14.10 -import java.util.Arrays;
   14.11 -import java.util.Map;
   14.12 -import java.util.logging.Level;
   14.13 -import java.util.logging.Logger;
   14.14  import javax.ws.rs.GET;
   14.15  import javax.ws.rs.Path;
   14.16  import javax.ws.rs.Produces;
   14.17  import org.netbeans.modules.jackpot30.backend.base.CategoryStorage;
   14.18 -import org.netbeans.modules.java.source.usages.ClassIndexImpl;
   14.19 -import org.netbeans.modules.java.source.usages.ClassIndexManager;
   14.20  
   14.21  /**
   14.22   *
   14.23 @@ -82,39 +73,8 @@
   14.24      @Produces("test/plain")
   14.25      public String indexUpdated() throws IOException {
   14.26          //XXX: should allow individual providers to do their own cleanup:
   14.27 -        //XXX: synchronize with the queries!
   14.28 -        //XXX: well, still does not work!
   14.29 -
   14.30 -        try {
   14.31 -            for (String name : Arrays.asList("instances", "transientInstances")) {
   14.32 -                Field instances = ClassIndexManager.class.getDeclaredField(name);
   14.33 -
   14.34 -                instances.setAccessible(true);
   14.35 -
   14.36 -                Map<?, ClassIndexImpl> toClear = (Map<?, ClassIndexImpl>) instances.get(ClassIndexManager.getDefault());
   14.37 -
   14.38 -                for (ClassIndexImpl impl : toClear.values()) {
   14.39 -                    Method close = ClassIndexImpl.class.getDeclaredMethod("close");
   14.40 -
   14.41 -                    close.setAccessible(true);
   14.42 -                    close.invoke(impl);
   14.43 -                }
   14.44 -
   14.45 -                toClear.clear();
   14.46 -            }
   14.47 -        } catch (InvocationTargetException ex) {
   14.48 -            Logger.getLogger(API.class.getName()).log(Level.SEVERE, null, ex);
   14.49 -        } catch (NoSuchMethodException ex) {
   14.50 -            Logger.getLogger(API.class.getName()).log(Level.SEVERE, null, ex);
   14.51 -        } catch (IllegalArgumentException ex) {
   14.52 -            Logger.getLogger(API.class.getName()).log(Level.SEVERE, null, ex);
   14.53 -        } catch (IllegalAccessException ex) {
   14.54 -            Logger.getLogger(API.class.getName()).log(Level.SEVERE, null, ex);
   14.55 -        } catch (NoSuchFieldException ex) {
   14.56 -            Logger.getLogger(API.class.getName()).log(Level.SEVERE, null, ex);
   14.57 -        } catch (SecurityException ex) {
   14.58 -            Logger.getLogger(API.class.getName()).log(Level.SEVERE, null, ex);
   14.59 -        }
   14.60 +        
   14.61 +        CategoryStorage.internalReset();
   14.62          
   14.63          return "Done";
   14.64      }
    15.1 --- a/remoting/server/web/source.web.api/nbproject/project.properties	Thu Jun 30 13:54:51 2011 +0200
    15.2 +++ b/remoting/server/web/source.web.api/nbproject/project.properties	Fri Jul 01 18:38:14 2011 +0200
    15.3 @@ -35,7 +35,8 @@
    15.4      ${reference.base_web_api.jar}:\
    15.5      ${libs.jersey.classpath}:\
    15.6      ${file.reference.org-netbeans-modules-parsing-api.jar}:\
    15.7 -    ${file.reference.org-openide-filesystems.jar}
    15.8 +    ${file.reference.org-openide-filesystems.jar}:\
    15.9 +    ${libs.lucene.classpath}
   15.10  # Space-separated list of extra javac options
   15.11  javac.compilerargs=
   15.12  javac.deprecation=false
    16.1 --- a/remoting/server/web/source.web.api/src/org/netbeans/modules/jackpot30/source/api/API.java	Thu Jun 30 13:54:51 2011 +0200
    16.2 +++ b/remoting/server/web/source.web.api/src/org/netbeans/modules/jackpot30/source/api/API.java	Fri Jul 01 18:38:14 2011 +0200
    16.3 @@ -42,21 +42,20 @@
    16.4  package org.netbeans.modules.jackpot30.source.api;
    16.5  
    16.6  import java.io.IOException;
    16.7 -import java.net.URL;
    16.8 -import java.util.logging.Level;
    16.9 -import java.util.logging.Logger;
   16.10 +import java.util.ArrayList;
   16.11 +import java.util.List;
   16.12 +import java.util.concurrent.atomic.AtomicBoolean;
   16.13  import javax.ws.rs.GET;
   16.14  import javax.ws.rs.Path;
   16.15  import javax.ws.rs.Produces;
   16.16  import javax.ws.rs.QueryParam;
   16.17 +import org.apache.lucene.document.Document;
   16.18 +import org.apache.lucene.search.Query;
   16.19  import org.netbeans.modules.jackpot30.backend.base.CategoryStorage;
   16.20 -import org.netbeans.modules.parsing.impl.indexing.CacheFolder;
   16.21 -import org.netbeans.modules.parsing.lucene.support.DocumentIndex;
   16.22 -import org.netbeans.modules.parsing.lucene.support.IndexDocument;
   16.23 -import org.netbeans.modules.parsing.lucene.support.IndexManager;
   16.24 +import org.netbeans.modules.parsing.lucene.support.Convertor;
   16.25 +import org.netbeans.modules.parsing.lucene.support.Index;
   16.26 +import org.netbeans.modules.parsing.lucene.support.Queries;
   16.27  import org.netbeans.modules.parsing.lucene.support.Queries.QueryKind;
   16.28 -import org.openide.filesystems.FileObject;
   16.29 -import org.openide.filesystems.FileUtil;
   16.30  
   16.31  /**
   16.32   *
   16.33 @@ -70,36 +69,21 @@
   16.34      @GET
   16.35      @Path("/cat")
   16.36      @Produces("text/plain")
   16.37 -    public String cat(@QueryParam("path") String segment, @QueryParam("relative") String relative) throws IOException {
   16.38 -        CategoryStorage srcRoots = CategoryStorage.forId(segment);
   16.39 +    public String cat(@QueryParam("path") String segment, @QueryParam("relative") String relative) throws IOException, InterruptedException {
   16.40 +        CategoryStorage category = CategoryStorage.forId(segment);
   16.41 +        Index idx = category.getIndex();
   16.42 +        Query query = Queries.createQuery("relativePath", "does-not-exist", relative, QueryKind.EXACT);
   16.43 +        List<String> found = new ArrayList<String>();
   16.44  
   16.45 -        for (URL srcRoot : srcRoots.getCategoryIndexFolders()) {
   16.46 -            DocumentIndex idx = null;
   16.47 +        //TODO: field selector:
   16.48 +        idx.query(found, new ConvertorImpl(), null, new AtomicBoolean(), query);
   16.49  
   16.50 -            try {
   16.51 -                if (!"rel".equals(srcRoot.getProtocol())) continue;
   16.52 +        return !found.isEmpty() ? found.get(0) : null;
   16.53 +    }
   16.54  
   16.55 -                if (!relative.startsWith(srcRoot.toString().substring("rel:/".length()))) continue;
   16.56 -
   16.57 -                String stripped = relative.substring(srcRoot.toString().substring("rel:/".length()).length());
   16.58 -                FileObject dataFolder = CacheFolder.getDataFolder(srcRoot);
   16.59 -
   16.60 -                idx = IndexManager.createDocumentIndex(FileUtil.toFile(dataFolder.getFileObject("fullsource/1")));//XXX: don't hardcode the constants!
   16.61 -
   16.62 -                idx.getStatus(); //XXX: to initialize the index
   16.63 -                
   16.64 -                for (IndexDocument d : idx.findByPrimaryKey(stripped, QueryKind.EXACT, KEY_CONTENT)) {
   16.65 -                    return d.getValue(KEY_CONTENT);
   16.66 -                }
   16.67 -            } catch (InterruptedException ex) {
   16.68 -                Logger.getLogger(API.class.getName()).log(Level.SEVERE, null, ex);
   16.69 -            } finally {
   16.70 -                if (idx != null) {
   16.71 -                    idx.close();
   16.72 -                }
   16.73 -            }
   16.74 +    private static class ConvertorImpl implements Convertor<Document, String> {
   16.75 +        @Override public String convert(Document p) {
   16.76 +            return p.get(KEY_CONTENT);
   16.77          }
   16.78 -
   16.79 -        return null;
   16.80      }
   16.81  }
    17.1 --- a/remoting/server/web/type.web.api/src/org/netbeans/modules/jackpot30/backend/type/api/API.java	Thu Jun 30 13:54:51 2011 +0200
    17.2 +++ b/remoting/server/web/type.web.api/src/org/netbeans/modules/jackpot30/backend/type/api/API.java	Fri Jul 01 18:38:14 2011 +0200
    17.3 @@ -40,30 +40,27 @@
    17.4  package org.netbeans.modules.jackpot30.backend.type.api;
    17.5  
    17.6  import java.io.IOException;
    17.7 -import java.net.URL;
    17.8 +import java.util.AbstractMap.SimpleEntry;
    17.9  import java.util.ArrayList;
   17.10 -import java.util.EnumSet;
   17.11 -import java.util.HashSet;
   17.12  import java.util.LinkedHashMap;
   17.13  import java.util.List;
   17.14  import java.util.Map;
   17.15 -import java.util.Set;
   17.16 -import javax.lang.model.element.TypeElement;
   17.17 +import java.util.Map.Entry;
   17.18 +import java.util.concurrent.atomic.AtomicBoolean;
   17.19  import javax.ws.rs.DefaultValue;
   17.20  import javax.ws.rs.GET;
   17.21  import javax.ws.rs.Path;
   17.22  import javax.ws.rs.Produces;
   17.23  import javax.ws.rs.QueryParam;
   17.24 +import org.apache.lucene.document.Document;
   17.25 +import org.apache.lucene.search.Query;
   17.26  import org.codeviation.pojson.Pojson;
   17.27 -import org.netbeans.api.java.classpath.ClassPath;
   17.28 -import org.netbeans.api.java.source.ClassIndex.NameKind;
   17.29 -import org.netbeans.api.java.source.ClassIndex.SearchScope;
   17.30 -import org.netbeans.api.java.source.ClasspathInfo;
   17.31 -import org.netbeans.api.java.source.ElementHandle;
   17.32  import org.netbeans.modules.jackpot30.backend.base.CategoryStorage;
   17.33 -import org.netbeans.modules.java.source.usages.ClassIndexManager;
   17.34  import org.netbeans.modules.jumpto.type.GoToTypeAction;
   17.35 -import org.netbeans.spi.java.classpath.support.ClassPathSupport;
   17.36 +import org.netbeans.modules.parsing.lucene.support.Convertor;
   17.37 +import org.netbeans.modules.parsing.lucene.support.Index;
   17.38 +import org.netbeans.modules.parsing.lucene.support.Queries;
   17.39 +import org.netbeans.modules.parsing.lucene.support.Queries.QueryKind;
   17.40  
   17.41  /**
   17.42   *
   17.43 @@ -75,7 +72,7 @@
   17.44      @GET
   17.45      @Path("/search")
   17.46      @Produces("text/plain")
   17.47 -    public String findType(@QueryParam("path") String segment, @QueryParam("prefix") String prefix, @QueryParam("casesensitive") @DefaultValue("false") boolean casesensitive, @QueryParam("asynchronous") @DefaultValue(value="false") boolean asynchronous) throws IOException {
   17.48 +    public String findType(@QueryParam("path") String segment, @QueryParam("prefix") String prefix, @QueryParam("casesensitive") @DefaultValue("false") boolean casesensitive, @QueryParam("asynchronous") @DefaultValue(value="false") boolean asynchronous) throws IOException, InterruptedException {
   17.49          assert !asynchronous;
   17.50  
   17.51          //copied (and converted to NameKind) from jumpto's GoToTypeAction:
   17.52 @@ -87,47 +84,61 @@
   17.53              return "";
   17.54          }
   17.55  
   17.56 -        NameKind nameKind;
   17.57 +        QueryKind queryKind;
   17.58          int wildcard = GoToTypeAction.containsWildCard(prefix);
   17.59  
   17.60          if (exact) {
   17.61              //nameKind = panel.isCaseSensitive() ? SearchType.EXACT_NAME : SearchType.CASE_INSENSITIVE_EXACT_NAME;
   17.62 -            nameKind = NameKind.SIMPLE_NAME;
   17.63 +            queryKind = QueryKind.EXACT;
   17.64          }
   17.65          else if ((GoToTypeAction.isAllUpper(prefix) && prefix.length() > 1) || GoToTypeAction.isCamelCase(prefix)) {
   17.66 -            nameKind = NameKind.CAMEL_CASE;
   17.67 +            queryKind = QueryKind.CAMEL_CASE;
   17.68          }
   17.69          else if (wildcard != -1) {
   17.70 -            nameKind = casesensitive ? NameKind.REGEXP : NameKind.CASE_INSENSITIVE_REGEXP;
   17.71 +            queryKind = casesensitive ? QueryKind.REGEXP : QueryKind.CASE_INSENSITIVE_REGEXP;
   17.72          }
   17.73          else {
   17.74 -            nameKind = casesensitive ? NameKind.PREFIX : NameKind.CASE_INSENSITIVE_PREFIX;
   17.75 +            queryKind = casesensitive ? QueryKind.PREFIX : QueryKind.CASE_INSENSITIVE_PREFIX;
   17.76          }
   17.77  
   17.78          Map<String, List<String>> result = new LinkedHashMap<String, List<String>>();
   17.79 -        CategoryStorage srcRoots = CategoryStorage.forId(segment);
   17.80 +        CategoryStorage category = CategoryStorage.forId(segment);
   17.81 +        Index index = category.getIndex();
   17.82  
   17.83 -        for (URL srcRoot : srcRoots.getCategoryIndexFolders()) {
   17.84 -            if (!"rel".equals(srcRoot.getProtocol())) continue;
   17.85 -            String rootId = srcRoot.getPath().substring(1);
   17.86 -            List<String> currentResult = new ArrayList<String>();
   17.87 +        List<Query> queries = new ArrayList<Query>(2);
   17.88  
   17.89 -            result.put(rootId, currentResult);
   17.90 +        queries.add(Queries.createQuery("classSimpleName", "classSimpleNameLower", prefix, queryKind));
   17.91  
   17.92 -            ClassIndexManager.getDefault().createUsagesQuery(srcRoot, true).isValid();
   17.93 -            ClasspathInfo cpInfo = ClasspathInfo.create(ClassPath.EMPTY, ClassPath.EMPTY, ClassPathSupport.createClassPath(srcRoot));
   17.94 -            Set<ElementHandle<TypeElement>> names = new HashSet<ElementHandle<TypeElement>>(cpInfo.getClassIndex().getDeclaredTypes(prefix, nameKind, EnumSet.of(SearchScope.SOURCE)));
   17.95 +        if (queryKind == QueryKind.CAMEL_CASE) {
   17.96 +            queries.add(Queries.createQuery("classSimpleName", "classSimpleNameLower", prefix, QueryKind.CASE_INSENSITIVE_PREFIX));
   17.97 +        }
   17.98  
   17.99 -            if (nameKind == NameKind.CAMEL_CASE) {
  17.100 -                names.addAll(cpInfo.getClassIndex().getDeclaredTypes(prefix, NameKind.CASE_INSENSITIVE_PREFIX, EnumSet.of(SearchScope.SOURCE)));
  17.101 -            }
  17.102 +        List<Entry<String, String>> found = new ArrayList<Entry<String, String>>();
  17.103  
  17.104 -            for (ElementHandle<TypeElement> d : names) {
  17.105 -                currentResult.add(d.getBinaryName());
  17.106 +        //TODO: field selector:
  17.107 +        index.query(found, new ConvertorImpl(), null, new AtomicBoolean(), queries.toArray(new Query[queries.size()]));
  17.108 +
  17.109 +        for (Entry<String, String> e : found) {
  17.110 +            for (String rel : category.getSourceRoots()) {
  17.111 +                if (e.getKey().startsWith(rel)) {
  17.112 +                    List<String> current = result.get(rel);
  17.113 +
  17.114 +                    if (current == null) {
  17.115 +                        result.put(rel, current = new ArrayList<String>());
  17.116 +                    }
  17.117 +
  17.118 +                    current.add(e.getValue());
  17.119 +                }
  17.120              }
  17.121          }
  17.122  
  17.123          return Pojson.save(result);
  17.124      }
  17.125  
  17.126 +    private static class ConvertorImpl implements Convertor<Document, Entry<String, String>> {
  17.127 +        @Override public Entry<String, String> convert(Document p) {
  17.128 +            return new SimpleEntry<String, String>(p.get("file"), p.get("classFQN"));
  17.129 +        }
  17.130 +    }
  17.131 +
  17.132  }
    18.1 --- a/remoting/server/web/usages.web.api/src/org/netbeans/modules/jackpot30/backend/usages/api/API.java	Thu Jun 30 13:54:51 2011 +0200
    18.2 +++ b/remoting/server/web/usages.web.api/src/org/netbeans/modules/jackpot30/backend/usages/api/API.java	Fri Jul 01 18:38:14 2011 +0200
    18.3 @@ -42,21 +42,20 @@
    18.4  package org.netbeans.modules.jackpot30.backend.usages.api;
    18.5  
    18.6  import java.io.IOException;
    18.7 -import java.net.URL;
    18.8 -import java.util.logging.Level;
    18.9 -import java.util.logging.Logger;
   18.10 +import java.util.ArrayList;
   18.11 +import java.util.List;
   18.12 +import java.util.concurrent.atomic.AtomicBoolean;
   18.13  import javax.ws.rs.GET;
   18.14  import javax.ws.rs.Path;
   18.15  import javax.ws.rs.Produces;
   18.16  import javax.ws.rs.QueryParam;
   18.17 +import org.apache.lucene.document.Document;
   18.18 +import org.apache.lucene.search.Query;
   18.19  import org.netbeans.modules.jackpot30.backend.base.CategoryStorage;
   18.20 -import org.netbeans.modules.parsing.impl.indexing.CacheFolder;
   18.21 -import org.netbeans.modules.parsing.lucene.support.DocumentIndex;
   18.22 -import org.netbeans.modules.parsing.lucene.support.IndexDocument;
   18.23 -import org.netbeans.modules.parsing.lucene.support.IndexManager;
   18.24 +import org.netbeans.modules.parsing.lucene.support.Convertor;
   18.25 +import org.netbeans.modules.parsing.lucene.support.Index;
   18.26 +import org.netbeans.modules.parsing.lucene.support.Queries;
   18.27  import org.netbeans.modules.parsing.lucene.support.Queries.QueryKind;
   18.28 -import org.openide.filesystems.FileObject;
   18.29 -import org.openide.filesystems.FileUtil;
   18.30  
   18.31  /**
   18.32   *
   18.33 @@ -70,38 +69,27 @@
   18.34      @GET
   18.35      @Path("/search")
   18.36      @Produces("text/plain")
   18.37 -    public String search(@QueryParam("path") String segment, @QueryParam("signatures") String signatures) throws IOException {
   18.38 +    public String search(@QueryParam("path") String segment, @QueryParam("signatures") String signatures) throws IOException, InterruptedException {
   18.39          StringBuilder result = new StringBuilder();
   18.40 -        CategoryStorage srcRoots = CategoryStorage.forId(segment);
   18.41 +        CategoryStorage category = CategoryStorage.forId(segment);
   18.42 +        Index idx = category.getIndex();
   18.43 +        Query query = Queries.createQuery(KEY_SIGNATURES, "does-not-exist", signatures, QueryKind.EXACT);
   18.44 +        List<String> found = new ArrayList<String>();
   18.45  
   18.46 -        for (URL srcRoot : srcRoots.getCategoryIndexFolders()) {
   18.47 -            DocumentIndex idx = null;
   18.48 +        //TODO: field selector:
   18.49 +        idx.query(found, new ConvertorImpl(), null, new AtomicBoolean(), query);
   18.50  
   18.51 -            try {
   18.52 -                if (!"rel".equals(srcRoot.getProtocol())) continue;
   18.53 -
   18.54 -                FileObject dataFolder = CacheFolder.getDataFolder(srcRoot).getFileObject("javausages/1");//XXX: don't hardcode the constants!
   18.55 -
   18.56 -                if (dataFolder == null) continue;
   18.57 -
   18.58 -                idx = IndexManager.createDocumentIndex(FileUtil.toFile(dataFolder));
   18.59 -
   18.60 -                idx.getStatus(); //XXX: to initialize the index
   18.61 -
   18.62 -                for (IndexDocument d : idx.query(KEY_SIGNATURES, signatures, QueryKind.EXACT)) {
   18.63 -                    result.append(srcRoot.toString().substring("rel:/".length()));
   18.64 -                    result.append(d.getPrimaryKey());
   18.65 -                    result.append("\n");
   18.66 -                }
   18.67 -            } catch (InterruptedException ex) {
   18.68 -                Logger.getLogger(API.class.getName()).log(Level.SEVERE, null, ex);
   18.69 -            } finally {
   18.70 -                if (idx != null) {
   18.71 -                    idx.close();
   18.72 -                }
   18.73 -            }
   18.74 +        for (String foundFile : found) {
   18.75 +            result.append(foundFile);
   18.76 +            result.append("\n");
   18.77          }
   18.78  
   18.79          return result.toString();
   18.80      }
   18.81 +
   18.82 +    private static class ConvertorImpl implements Convertor<Document, String> {
   18.83 +        @Override public String convert(Document p) {
   18.84 +            return p.get("file");
   18.85 +        }
   18.86 +    }
   18.87  }