Merging recent trunk/default changes to marks branch marks
authorJan Lahoda <jlahoda@netbeans.org>
Fri, 18 Feb 2011 20:16:26 +0100
branchmarks
changeset 5501b17e3ff36e6
parent 527 a19f2108d439
parent 549 c0ac67a767d4
child 553 c34ac1f0e220
Merging recent trunk/default changes to marks branch
api/test/unit/src/org/netbeans/modules/jackpot30/impl/UtilitiesTest.java
file/src/org/netbeans/modules/jackpot30/file/DeclarativeHintRegistry.java
file/src/org/netbeans/modules/jackpot30/file/conditionapi/Context.java
     1.1 --- a/api/nbproject/genfiles.properties	Sat Jan 22 21:51:05 2011 +0100
     1.2 +++ b/api/nbproject/genfiles.properties	Fri Feb 18 20:16:26 2011 +0100
     1.3 @@ -3,6 +3,6 @@
     1.4  build.xml.stylesheet.CRC32=79c3b980@1.28.0.7
     1.5  # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
     1.6  # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
     1.7 -nbproject/build-impl.xml.data.CRC32=d6395e19
     1.8 +nbproject/build-impl.xml.data.CRC32=a7e51eed
     1.9  nbproject/build-impl.xml.script.CRC32=c4574e66
    1.10  nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.44
     2.1 --- a/api/nbproject/project.xml	Sat Jan 22 21:51:05 2011 +0100
     2.2 +++ b/api/nbproject/project.xml	Fri Feb 18 20:16:26 2011 +0100
     2.3 @@ -64,8 +64,8 @@
     2.4                      <build-prerequisite/>
     2.5                      <compile-dependency/>
     2.6                      <run-dependency>
     2.7 -                        <release-version>1</release-version>
     2.8 -                        <specification-version>2.6.0.232</specification-version>
     2.9 +                        <release-version>1-3</release-version>
    2.10 +                        <specification-version>2.13</specification-version>
    2.11                      </run-dependency>
    2.12                  </dependency>
    2.13                  <dependency>
     3.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/Utilities.java	Sat Jan 22 21:51:05 2011 +0100
     3.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/Utilities.java	Fri Feb 18 20:16:26 2011 +0100
     3.3 @@ -327,6 +327,10 @@
     3.4          return parseAndAttribute(null, jti, pattern, null, errors);
     3.5      }
     3.6  
     3.7 +    public static Tree parseAndAttribute(JavacTaskImpl jti, String pattern, SourcePositions[] sourcePositions, Collection<Diagnostic<? extends JavaFileObject>> errors) {
     3.8 +        return parseAndAttribute(null, jti, pattern, null, sourcePositions, errors);
     3.9 +    }
    3.10 +
    3.11      private static Tree parseAndAttribute(CompilationInfo info, JavacTaskImpl jti, String pattern, Scope scope, Collection<Diagnostic<? extends JavaFileObject>> errors) {
    3.12          return parseAndAttribute(info, jti, pattern, scope, new SourcePositions[1], errors);
    3.13      }
    3.14 @@ -1263,6 +1267,25 @@
    3.15              return super.switchBlockStatementGroup();
    3.16          }
    3.17  
    3.18 +
    3.19 +        @Override
    3.20 +        protected JCTree resource() {
    3.21 +            if (S.token() == Token.IDENTIFIER && S.stringVal().startsWith("$")) {
    3.22 +                //XXX: should inspect the next token, not next character:
    3.23 +                char[] maybeSemicolon = S.getRawCharacters(S.endPos(), S.endPos() + 1);
    3.24 +
    3.25 +                if (maybeSemicolon[0] == ';' || maybeSemicolon[0] == ')') {
    3.26 +                    int pos = S.pos();
    3.27 +                    com.sun.tools.javac.util.Name name = S.name();
    3.28 +
    3.29 +                    S.nextToken();
    3.30 +
    3.31 +                    return F.at(pos).Ident(name);
    3.32 +                }
    3.33 +            }
    3.34 +            return super.resource();
    3.35 +        }
    3.36 +
    3.37      }
    3.38  
    3.39      private static final class PushbackLexer implements Lexer {
     4.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/batch/BatchSearch.java	Sat Jan 22 21:51:05 2011 +0100
     4.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/batch/BatchSearch.java	Fri Feb 18 20:16:26 2011 +0100
     4.3 @@ -133,7 +133,7 @@
     4.4              private Set<FileObject> KNOWN_SOURCE_ROOTS = new HashSet<FileObject>(GlobalPathRegistry.getDefault().getSourceRoots());
     4.5              public Index findIndex(FileObject root, ProgressHandleWrapper progress) {
     4.6                  progress.startNextPart(1);
     4.7 -                if (KNOWN_SOURCE_ROOTS.contains(root)) {
     4.8 +                if (KNOWN_SOURCE_ROOTS.contains(root) || scope.forceIndicesUpToDate) {
     4.9                      try {
    4.10                          return FileBasedIndex.get(root.getURL());
    4.11                      } catch (IOException ex) {
    4.12 @@ -424,6 +424,10 @@
    4.13      }
    4.14      
    4.15      public static void getVerifiedSpans(BatchResult candidates, @NonNull ProgressHandleWrapper progress, final VerifiedSpansCallBack callback, final Collection<? super MessageImpl> problems) {
    4.16 +        getVerifiedSpans(candidates, progress, callback, false, problems);
    4.17 +    }
    4.18 +
    4.19 +    public static void getVerifiedSpans(BatchResult candidates, @NonNull ProgressHandleWrapper progress, final VerifiedSpansCallBack callback, boolean doNotRegisterClassPath, final Collection<? super MessageImpl> problems) {
    4.20          int[] parts = new int[candidates.projectId2Resources.size()];
    4.21          int   index = 0;
    4.22  
    4.23 @@ -436,11 +440,11 @@
    4.24          for (Collection<? extends Resource> it :candidates.projectId2Resources.values()) {
    4.25              inner.startNextPart(it.size());
    4.26  
    4.27 -            getVerifiedSpans(it, inner, callback, problems);
    4.28 +            getVerifiedSpans(it, inner, callback, doNotRegisterClassPath, problems);
    4.29          }
    4.30      }
    4.31  
    4.32 -    private static void getVerifiedSpans(Collection<? extends Resource> resources, @NonNull final ProgressHandleWrapper progress, final VerifiedSpansCallBack callback, final Collection<? super MessageImpl> problems) {
    4.33 +    private static void getVerifiedSpans(Collection<? extends Resource> resources, @NonNull final ProgressHandleWrapper progress, final VerifiedSpansCallBack callback, boolean doNotRegisterClassPath, final Collection<? super MessageImpl> problems) {
    4.34          Collection<FileObject> files = new LinkedList<FileObject>();
    4.35          final Map<FileObject, Resource> file2Resource = new HashMap<FileObject, Resource>();
    4.36  
    4.37 @@ -457,20 +461,24 @@
    4.38          }
    4.39  
    4.40          Map<ClasspathInfo, Collection<FileObject>> cp2Files = BatchUtilities.sortFiles(files);
    4.41 -        Set<ClassPath> toRegisterSet = new HashSet<ClassPath>();
    4.42 +        ClassPath[] toRegister = null;
    4.43  
    4.44 -        for (ClasspathInfo cpInfo : cp2Files.keySet()) {
    4.45 -            toRegisterSet.add(cpInfo.getClassPath(PathKind.SOURCE));
    4.46 -        }
    4.47 +        if (!doNotRegisterClassPath) {
    4.48 +            Set<ClassPath> toRegisterSet = new HashSet<ClassPath>();
    4.49  
    4.50 -        ClassPath[] toRegister = !toRegisterSet.isEmpty() ? toRegisterSet.toArray(new ClassPath[0]) : null;
    4.51 +            for (ClasspathInfo cpInfo : cp2Files.keySet()) {
    4.52 +                toRegisterSet.add(cpInfo.getClassPath(PathKind.SOURCE));
    4.53 +            }
    4.54  
    4.55 -        if (toRegister != null) {
    4.56 -            GlobalPathRegistry.getDefault().register(ClassPath.SOURCE, toRegister);
    4.57 -            try {
    4.58 -                Utilities.waitScanFinished();
    4.59 -            } catch (InterruptedException ex) {
    4.60 -                Exceptions.printStackTrace(ex);
    4.61 +            toRegister = !toRegisterSet.isEmpty() ? toRegisterSet.toArray(new ClassPath[0]) : null;
    4.62 +
    4.63 +            if (toRegister != null) {
    4.64 +                GlobalPathRegistry.getDefault().register(ClassPath.SOURCE, toRegister);
    4.65 +                try {
    4.66 +                    Utilities.waitScanFinished();
    4.67 +                } catch (InterruptedException ex) {
    4.68 +                    Exceptions.printStackTrace(ex);
    4.69 +                }
    4.70              }
    4.71          }
    4.72  
    4.73 @@ -495,27 +503,38 @@
    4.74                                  if (parameter.toPhase(Phase.PARSED).compareTo(Phase.PARSED) < 0)
    4.75                                      return ;
    4.76  
    4.77 -                                Context ctx = JavaSourceAccessor.getINSTANCE().getJavacTask(parameter).getContext();
    4.78 -                                ClassReader reader = ClassReader.instance(ctx);
    4.79 -                                Field attributeReaders = ClassReader.class.getDeclaredField("attributeReaders");
    4.80 +                                boolean cont = true;
    4.81  
    4.82 -                                attributeReaders.setAccessible(true);
    4.83 -                                ((Map) attributeReaders.get(reader)).remove(Names.instance(ctx)._org_netbeans_ParameterNames);
    4.84 -                                //workaround for #192481 end
    4.85 +                                try {
    4.86 +                                    Context ctx = JavaSourceAccessor.getINSTANCE().getJavacTask(parameter).getContext();
    4.87 +                                    ClassReader reader = ClassReader.instance(ctx);
    4.88 +                                    Field attributeReaders = ClassReader.class.getDeclaredField("attributeReaders");
    4.89  
    4.90 -                                if (parameter.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0)
    4.91 -                                    return ;
    4.92 +                                    attributeReaders.setAccessible(true);
    4.93 +                                    ((Map) attributeReaders.get(reader)).remove(Names.instance(ctx)._org_netbeans_ParameterNames);
    4.94 +                                    //workaround for #192481 end
    4.95  
    4.96 -                                progress.setMessage("processing: " + FileUtil.getFileDisplayName(parameter.getFileObject()));
    4.97 -                                Resource r = file2Resource.get(parameter.getFileObject());
    4.98 -                                Map<PatternDescription, List<HintDescription>> sortedHintsPatterns = new HashMap<PatternDescription, List<HintDescription>>();
    4.99 -                                Map<Kind, List<HintDescription>> sortedHintsKinds = new HashMap<Kind, List<HintDescription>>();
   4.100 +                                    if (parameter.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0)
   4.101 +                                        return ;
   4.102  
   4.103 -                                RulesManager.sortOut(r.hints, sortedHintsKinds, sortedHintsPatterns);
   4.104 +                                    progress.setMessage("processing: " + FileUtil.getFileDisplayName(parameter.getFileObject()));
   4.105 +                                    Resource r = file2Resource.get(parameter.getFileObject());
   4.106 +                                    Map<PatternDescription, List<HintDescription>> sortedHintsPatterns = new HashMap<PatternDescription, List<HintDescription>>();
   4.107 +                                    Map<Kind, List<HintDescription>> sortedHintsKinds = new HashMap<Kind, List<HintDescription>>();
   4.108  
   4.109 -                                List<ErrorDescription> hints = new HintsInvoker(parameter, new AtomicBoolean()).computeHints(parameter, sortedHintsKinds, sortedHintsPatterns, problems);
   4.110 +                                    RulesManager.sortOut(r.hints, sortedHintsKinds, sortedHintsPatterns);
   4.111  
   4.112 -                                if (callback.spansVerified(parameter, r, hints)) {
   4.113 +                                    List<ErrorDescription> hints = new HintsInvoker(parameter, new AtomicBoolean()).computeHints(parameter, sortedHintsKinds, sortedHintsPatterns, problems);
   4.114 +
   4.115 +                                    cont = callback.spansVerified(parameter, r, hints);
   4.116 +                                } catch (ThreadDeath td) {
   4.117 +                                    throw td;
   4.118 +                                } catch (Throwable t) {
   4.119 +                                    LOG.log(Level.INFO, "Exception while performing batch processing in " + FileUtil.getFileDisplayName(parameter.getFileObject()), t);
   4.120 +                                    problems.add(new MessageImpl(MessageKind.WARNING, "An exception occurred while processing file: " + FileUtil.getFileDisplayName(parameter.getFileObject()) + " (" + t.getLocalizedMessage() + ")."));
   4.121 +                                }
   4.122 +                                
   4.123 +                                if (cont) {
   4.124                                      progress.tick();
   4.125                                      currentPointer.incrementAndGet();
   4.126                                  } else {
   4.127 @@ -552,18 +571,20 @@
   4.128          public  final String subIndex; //public only for AddScopePanel
   4.129          public  final boolean update; //public only for AddScopePanel
   4.130          private final Collection<? extends FileObject> sourceRoots;
   4.131 +        private final boolean forceIndicesUpToDate;
   4.132  
   4.133          private Scope() {
   4.134 -            this(null, null, null, null, true, null);
   4.135 +            this(null, null, null, null, true, null, false);
   4.136          }
   4.137  
   4.138 -        private Scope(ScopeType scopeType, String folder, String indexURL, String subIndex, boolean update, Collection<? extends FileObject> sourceRoots) {
   4.139 +        private Scope(ScopeType scopeType, String folder, String indexURL, String subIndex, boolean update, Collection<? extends FileObject> sourceRoots, boolean forceIndicesUpToDate) {
   4.140              this.scopeType = scopeType;
   4.141              this.folder = folder;
   4.142              this.indexURL = indexURL;
   4.143              this.subIndex = subIndex;
   4.144              this.update = update;
   4.145              this.sourceRoots = sourceRoots;
   4.146 +            this.forceIndicesUpToDate = forceIndicesUpToDate;
   4.147          }
   4.148  
   4.149          public String serialize() {
   4.150 @@ -580,27 +601,31 @@
   4.151          }
   4.152  
   4.153          public static Scope createAllOpenedProjectsScope() {
   4.154 -            return new Scope(ScopeType.ALL_OPENED_PROJECTS, null, null, null, false, null);
   4.155 +            return new Scope(ScopeType.ALL_OPENED_PROJECTS, null, null, null, false, null, false);
   4.156          }
   4.157  
   4.158          public static Scope createAllDependentOpenedSourceRoots(FileObject from) {
   4.159 -            return new Scope(ScopeType.ALL_DEPENDENT_OPENED_SOURCE_ROOTS, null, null, null, false, Collections.singletonList(from));
   4.160 +            return new Scope(ScopeType.ALL_DEPENDENT_OPENED_SOURCE_ROOTS, null, null, null, false, Collections.singletonList(from), false);
   4.161          }
   4.162  
   4.163          public static Scope createGivenFolderNoIndex(String folder) {
   4.164 -            return new Scope(ScopeType.GIVEN_FOLDER, folder, null, null, false, null);
   4.165 +            return new Scope(ScopeType.GIVEN_FOLDER, folder, null, null, false, null, false);
   4.166          }
   4.167  
   4.168          public static Scope createGivenFolderLocalIndex(String folder, File indexFolder, boolean update) {
   4.169 -            return new Scope(ScopeType.GIVEN_FOLDER, folder, indexFolder.getAbsolutePath(), null, update, null);
   4.170 +            return new Scope(ScopeType.GIVEN_FOLDER, folder, indexFolder.getAbsolutePath(), null, update, null, false);
   4.171          }
   4.172  
   4.173          public static Scope createGivenFolderRemoteIndex(String folder, String urlIndex, String subIndex) {
   4.174 -            return new Scope(ScopeType.GIVEN_FOLDER, folder, urlIndex, subIndex, false, null);
   4.175 +            return new Scope(ScopeType.GIVEN_FOLDER, folder, urlIndex, subIndex, false, null, false);
   4.176          }
   4.177  
   4.178          public static Scope createGivenSourceRoots(FileObject... sourceRoots) {
   4.179 -            return new Scope(ScopeType.GIVEN_SOURCE_ROOTS, null, null, null, false, Arrays.asList(sourceRoots));
   4.180 +            return createGivenSourceRoots(false, sourceRoots);
   4.181 +        }
   4.182 +
   4.183 +        public static Scope createGivenSourceRoots(boolean forceIndicesUpToDate, FileObject... sourceRoots) {
   4.184 +            return new Scope(ScopeType.GIVEN_SOURCE_ROOTS, null, null, null, false, Arrays.asList(sourceRoots), forceIndicesUpToDate);
   4.185          }
   4.186  
   4.187          public String getDisplayName() {
     5.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/batch/BatchUtilities.java	Sat Jan 22 21:51:05 2011 +0100
     5.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/batch/BatchUtilities.java	Fri Feb 18 20:16:26 2011 +0100
     5.3 @@ -44,13 +44,10 @@
     5.4  import com.sun.source.util.TreePath;
     5.5  import com.sun.tools.javac.api.JavacTaskImpl;
     5.6  import com.sun.tools.javac.util.Log;
     5.7 -import java.io.ByteArrayInputStream;
     5.8 -import java.io.File;
     5.9  import java.io.IOException;
    5.10 -import java.io.InputStream;
    5.11 -import java.io.OutputStream;
    5.12  import java.io.Reader;
    5.13  import java.io.StringReader;
    5.14 +import java.io.Writer;
    5.15  import java.lang.reflect.Constructor;
    5.16  import java.lang.reflect.Method;
    5.17  import java.nio.charset.Charset;
    5.18 @@ -71,6 +68,7 @@
    5.19  import java.util.logging.Logger;
    5.20  import javax.swing.text.Document;
    5.21  import org.netbeans.api.annotations.common.NonNull;
    5.22 +import org.netbeans.api.annotations.common.NullAllowed;
    5.23  import org.netbeans.api.java.classpath.ClassPath;
    5.24  import org.netbeans.api.java.source.ClasspathInfo;
    5.25  import org.netbeans.api.java.source.CompilationController;
    5.26 @@ -327,7 +325,7 @@
    5.27  //        }
    5.28      }
    5.29  
    5.30 -    public static void exportDiff(ModificationResult result, OutputStream out) throws IOException {
    5.31 +    public static void exportDiff(ModificationResult result, @NullAllowed FileObject relativeTo, Writer out) throws IOException {
    5.32          for (FileObject f : result.getModifiedFileObjects()) {
    5.33              Charset c = FileEncodingQuery.getEncoding(f);
    5.34              String orig = new String(f.asBytes(), c);
    5.35 @@ -336,15 +334,15 @@
    5.36              if (orig.equals(nue)) {
    5.37                  continue;
    5.38              }
    5.39 +
    5.40 +            String name = relativeTo != null ? FileUtil.getRelativePath(relativeTo, f) : FileUtil.toFile(f).getAbsolutePath();
    5.41              
    5.42 -            File jiFile = FileUtil.toFile(f);
    5.43 -            
    5.44 -            doExportDiff(jiFile.getAbsolutePath(), orig, nue, out);
    5.45 +            doExportDiff(name, orig, nue, out);
    5.46          }
    5.47      }
    5.48  
    5.49      //copied from the diff module:
    5.50 -    private static void doExportDiff(String name, String original, String modified, OutputStream out) throws IOException {
    5.51 +    private static void doExportDiff(String name, String original, String modified, Writer out) throws IOException {
    5.52          DiffProvider diff = new BuiltInDiffProvider();//(DiffProvider) Lookup.getDefault().lookup(DiffProvider.class);
    5.53  
    5.54          Reader r1 = null;
    5.55 @@ -361,7 +359,6 @@
    5.56          }
    5.57  
    5.58          try {
    5.59 -            InputStream is;
    5.60              r1 = new StringReader(original);
    5.61              r2 = new StringReader(modified);
    5.62              TextDiffVisualizer.TextDiffInfo info = new TextDiffVisualizer.TextDiffInfo(
    5.63 @@ -380,12 +377,7 @@
    5.64  //            } else {
    5.65  //                diffText = TextDiffVisualizer.differenceToNormalDiffText(info);
    5.66  //            }
    5.67 -            is = new ByteArrayInputStream(diffText.getBytes("utf8"));  // NOI18N
    5.68 -            while(true) {
    5.69 -                int i = is.read();
    5.70 -                if (i == -1) break;
    5.71 -                out.write(i);
    5.72 -            }
    5.73 +            out.write(diffText);
    5.74          } finally {
    5.75              if (r1 != null) try { r1.close(); } catch (Exception e) {}
    5.76              if (r2 != null) try { r2.close(); } catch (Exception e) {}
     6.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/duplicates/Bundle.properties	Sat Jan 22 21:51:05 2011 +0100
     6.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/duplicates/Bundle.properties	Fri Feb 18 20:16:26 2011 +0100
     6.3 @@ -1,1 +1,3 @@
     6.4  CTL_GlobalFindDuplicates=Global Find Duplicates
     6.5 +DuplicatesListPanel.findMore.text=<html><body><a href="">Look for More</a>
     6.6 +DuplicatesListPanel.progressLabel.text=
     7.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/duplicates/ComputeDuplicates.java	Sat Jan 22 21:51:05 2011 +0100
     7.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/duplicates/ComputeDuplicates.java	Fri Feb 18 20:16:26 2011 +0100
     7.3 @@ -44,7 +44,6 @@
     7.4  import java.util.ArrayList;
     7.5  import java.util.Arrays;
     7.6  import java.util.BitSet;
     7.7 -import java.util.Collection;
     7.8  import java.util.Collections;
     7.9  import java.util.Comparator;
    7.10  import java.util.HashSet;
    7.11 @@ -54,6 +53,7 @@
    7.12  import java.util.List;
    7.13  import java.util.Map;
    7.14  import java.util.Map.Entry;
    7.15 +import java.util.NoSuchElementException;
    7.16  import java.util.Set;
    7.17  import java.util.concurrent.atomic.AtomicBoolean;
    7.18  import org.apache.lucene.document.Document;
    7.19 @@ -86,7 +86,7 @@
    7.20   */
    7.21  public class ComputeDuplicates {
    7.22  
    7.23 -    public Collection<? extends DuplicateDescription> computeDuplicatesForAllOpenedProjects(ProgressHandle progress, AtomicBoolean cancel) throws IOException {
    7.24 +    public Iterator<? extends DuplicateDescription> computeDuplicatesForAllOpenedProjects(ProgressHandle progress, AtomicBoolean cancel) throws IOException {
    7.25          Set<URL> urls = new HashSet<URL>();
    7.26  
    7.27          for (ClassPath cp : GlobalPathRegistry.getDefault().getPaths(ClassPath.SOURCE)) {
    7.28 @@ -103,7 +103,7 @@
    7.29          }
    7.30      }
    7.31  
    7.32 -    public Collection<? extends DuplicateDescription> computeDuplicates(Set<URL> forURLs, ProgressHandle progress, AtomicBoolean cancel) throws IOException {
    7.33 +    public Iterator<? extends DuplicateDescription> computeDuplicates(Set<URL> forURLs, ProgressHandle progress, AtomicBoolean cancel) throws IOException {
    7.34          Map<IndexReader, FileObject> readers2Roots = new LinkedHashMap<IndexReader, FileObject>();
    7.35  
    7.36          progress.progress("Updating indices");
    7.37 @@ -142,19 +142,27 @@
    7.38          //TODO: only show valuable duplicates?:
    7.39  //        dd = dd.subList(0, dd.size() / 10 + 1);
    7.40  
    7.41 -        progress.switchToDeterminate(dd.size());
    7.42 -        
    7.43 -        List<DuplicateDescription> result = new LinkedList<DuplicateDescription>();
    7.44 -        int done = 0;
    7.45 +        return new DuplicatesIterator(readers2Roots, dd);
    7.46 +    }
    7.47  
    7.48 -        for (String longest : dd) {
    7.49 +    private static final class DuplicatesIterator implements Iterator<DuplicateDescription> {
    7.50 +        private final Map<IndexReader, FileObject> readers2Roots;
    7.51 +        private final Iterator<String> duplicateCandidates;
    7.52 +        private final List<DuplicateDescription> result = new LinkedList<DuplicateDescription>();
    7.53 +
    7.54 +        public DuplicatesIterator(Map<IndexReader, FileObject> readers2Roots, Iterable<String> duplicateCandidates) {
    7.55 +            this.readers2Roots = readers2Roots;
    7.56 +            this.duplicateCandidates = duplicateCandidates.iterator();
    7.57 +        }
    7.58 +
    7.59 +        private DuplicateDescription nextDescription() throws IOException {
    7.60 +        while (duplicateCandidates.hasNext()) {
    7.61 +            String longest = duplicateCandidates.next();
    7.62              List<Span> foundDuplicates = new LinkedList<Span>();
    7.63  
    7.64              Query query = new TermQuery(new Term("generalized", longest));
    7.65  
    7.66              for (Entry<IndexReader, FileObject> e : readers2Roots.entrySet()) {
    7.67 -                if (cancel.get()) return Collections.emptyList();
    7.68 -
    7.69                  Searcher s = new IndexSearcher(e.getKey());
    7.70                  BitSet matchingDocuments = new BitSet(e.getKey().maxDoc());
    7.71                  Collector c = new BitSetCollector(matchingDocuments);
    7.72 @@ -201,16 +209,45 @@
    7.73                      }
    7.74                  }
    7.75  
    7.76 -                if (add)
    7.77 +                if (add) {
    7.78                      result.add(current);
    7.79 +                    return current;
    7.80 +                }
    7.81              }
    7.82  
    7.83 -            progress.progress(++done);
    7.84 +        }
    7.85 +        return null;
    7.86          }
    7.87  
    7.88 -        progress.finish();
    7.89 +        private DuplicateDescription next;
    7.90  
    7.91 -        return result;
    7.92 +        public boolean hasNext() {
    7.93 +            if (next == null) {
    7.94 +                try {
    7.95 +                    next = nextDescription();
    7.96 +                } catch (IOException ex) {
    7.97 +                    Exceptions.printStackTrace(ex);
    7.98 +                }
    7.99 +            }
   7.100 +
   7.101 +            return next != null;
   7.102 +        }
   7.103 +
   7.104 +        public DuplicateDescription next() {
   7.105 +            if (!hasNext()) {
   7.106 +                throw new NoSuchElementException();
   7.107 +            }
   7.108 +
   7.109 +            DuplicateDescription r = next;
   7.110 +
   7.111 +            next = null;
   7.112 +            return r;
   7.113 +        }
   7.114 +
   7.115 +        public void remove() {
   7.116 +            throw new UnsupportedOperationException("Not supported.");
   7.117 +        }
   7.118 +
   7.119      }
   7.120  
   7.121      private static List<String> getDuplicatedValues(IndexReader ir, String field, AtomicBoolean cancel) throws IOException {
     8.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/duplicates/DuplicatesListPanel.form	Sat Jan 22 21:51:05 2011 +0100
     8.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/duplicates/DuplicatesListPanel.form	Fri Feb 18 20:16:26 2011 +0100
     8.3 @@ -1,9 +1,6 @@
     8.4 -<?xml version="1.0" encoding="UTF-8" ?>
     8.5 +<?xml version="1.1" encoding="UTF-8" ?>
     8.6  
     8.7  <Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
     8.8 -  <SyntheticProperties>
     8.9 -    <SyntheticProperty name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,56,0,0,1,-98"/>
    8.10 -  </SyntheticProperties>
    8.11    <AuxValues>
    8.12      <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
    8.13      <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
    8.14 @@ -19,11 +16,12 @@
    8.15    <Layout>
    8.16      <DimensionLayout dim="0">
    8.17        <Group type="103" groupAlignment="0" attributes="0">
    8.18 -          <Group type="102" alignment="0" attributes="0">
    8.19 +          <Group type="102" alignment="1" attributes="0">
    8.20                <EmptySpace max="-2" attributes="0"/>
    8.21 -              <Group type="103" groupAlignment="0" attributes="0">
    8.22 -                  <Component id="jSplitPane1" alignment="1" pref="390" max="32767" attributes="0"/>
    8.23 -                  <Component id="jScrollPane4" alignment="1" pref="390" max="32767" attributes="0"/>
    8.24 +              <Group type="103" groupAlignment="1" attributes="0">
    8.25 +                  <Component id="mainSplit2" alignment="0" pref="906" max="32767" attributes="0"/>
    8.26 +                  <Component id="jScrollPane1" alignment="0" pref="906" max="32767" attributes="0"/>
    8.27 +                  <Component id="jPanel1" alignment="1" min="-2" max="-2" attributes="0"/>
    8.28                </Group>
    8.29                <EmptySpace max="-2" attributes="0"/>
    8.30            </Group>
    8.31 @@ -32,99 +30,118 @@
    8.32      <DimensionLayout dim="1">
    8.33        <Group type="103" groupAlignment="0" attributes="0">
    8.34            <Group type="102" attributes="0">
    8.35 -              <EmptySpace max="-2" attributes="0"/>
    8.36 -              <Component id="jScrollPane4" min="-2" pref="76" max="-2" attributes="0"/>
    8.37 -              <EmptySpace max="-2" attributes="0"/>
    8.38 -              <Component id="jSplitPane1" pref="206" max="32767" attributes="0"/>
    8.39 -              <EmptySpace max="-2" attributes="0"/>
    8.40 +              <EmptySpace min="-2" max="-2" attributes="0"/>
    8.41 +              <Component id="jScrollPane1" min="-2" pref="67" max="-2" attributes="0"/>
    8.42 +              <EmptySpace min="-2" max="-2" attributes="0"/>
    8.43 +              <Component id="mainSplit2" pref="467" max="32767" attributes="0"/>
    8.44 +              <EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
    8.45 +              <Component id="jPanel1" min="-2" max="-2" attributes="0"/>
    8.46 +              <EmptySpace min="-2" max="-2" attributes="0"/>
    8.47            </Group>
    8.48        </Group>
    8.49      </DimensionLayout>
    8.50    </Layout>
    8.51    <SubComponents>
    8.52 -    <Container class="javax.swing.JSplitPane" name="jSplitPane1">
    8.53 +    <Container class="javax.swing.JScrollPane" name="jScrollPane1">
    8.54 +
    8.55 +      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
    8.56 +      <SubComponents>
    8.57 +        <Component class="javax.swing.JList" name="duplicatesList">
    8.58 +          <Properties>
    8.59 +            <Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor">
    8.60 +              <StringArray count="0"/>
    8.61 +            </Property>
    8.62 +            <Property name="prototypeCellValue" type="java.lang.Object" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
    8.63 +              <Connection code="&quot;9999999999999999999999999999999999999999999999999999999999999999999999&quot;" type="code"/>
    8.64 +            </Property>
    8.65 +            <Property name="visibleRowCount" type="int" value="4"/>
    8.66 +          </Properties>
    8.67 +        </Component>
    8.68 +      </SubComponents>
    8.69 +    </Container>
    8.70 +    <Container class="javax.swing.JSplitPane" name="mainSplit2">
    8.71 +      <Properties>
    8.72 +        <Property name="dividerLocation" type="int" value="400"/>
    8.73 +      </Properties>
    8.74        <AuxValues>
    8.75          <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new BalancedSplitPane()"/>
    8.76        </AuxValues>
    8.77  
    8.78        <Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
    8.79        <SubComponents>
    8.80 -        <Container class="javax.swing.JScrollPane" name="jScrollPane2">
    8.81 -          <AuxValues>
    8.82 -            <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
    8.83 -          </AuxValues>
    8.84 +        <Container class="javax.swing.JPanel" name="rightPanel">
    8.85 +          <Constraints>
    8.86 +            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
    8.87 +              <JSplitPaneConstraints position="right"/>
    8.88 +            </Constraint>
    8.89 +          </Constraints>
    8.90 +
    8.91 +          <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
    8.92 +          <SubComponents>
    8.93 +            <Component class="javax.swing.JComboBox" name="rightFileList">
    8.94 +              <Properties>
    8.95 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
    8.96 +                  <StringArray count="0"/>
    8.97 +                </Property>
    8.98 +              </Properties>
    8.99 +              <Constraints>
   8.100 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
   8.101 +                  <GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="324" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
   8.102 +                </Constraint>
   8.103 +              </Constraints>
   8.104 +            </Component>
   8.105 +            <Container class="javax.swing.JScrollPane" name="jScrollPane3">
   8.106 +              <AuxValues>
   8.107 +                <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
   8.108 +              </AuxValues>
   8.109 +              <Constraints>
   8.110 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
   8.111 +                  <GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="6" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
   8.112 +                </Constraint>
   8.113 +              </Constraints>
   8.114 +
   8.115 +              <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
   8.116 +              <SubComponents>
   8.117 +                <Component class="javax.swing.JEditorPane" name="right">
   8.118 +                </Component>
   8.119 +              </SubComponents>
   8.120 +            </Container>
   8.121 +          </SubComponents>
   8.122 +        </Container>
   8.123 +        <Container class="javax.swing.JPanel" name="leftPanel">
   8.124            <Constraints>
   8.125              <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
   8.126                <JSplitPaneConstraints position="left"/>
   8.127              </Constraint>
   8.128            </Constraints>
   8.129  
   8.130 -          <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
   8.131 +          <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
   8.132            <SubComponents>
   8.133 -            <Component class="javax.swing.JEditorPane" name="left">
   8.134 -            </Component>
   8.135 -          </SubComponents>
   8.136 -        </Container>
   8.137 -        <Container class="javax.swing.JScrollPane" name="jScrollPane3">
   8.138 -          <AuxValues>
   8.139 -            <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
   8.140 -          </AuxValues>
   8.141 -          <Constraints>
   8.142 -            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
   8.143 -              <JSplitPaneConstraints position="right"/>
   8.144 -            </Constraint>
   8.145 -          </Constraints>
   8.146 +            <Container class="javax.swing.JScrollPane" name="jScrollPane2">
   8.147 +              <AuxValues>
   8.148 +                <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
   8.149 +              </AuxValues>
   8.150 +              <Constraints>
   8.151 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
   8.152 +                  <GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="6" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
   8.153 +                </Constraint>
   8.154 +              </Constraints>
   8.155  
   8.156 -          <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
   8.157 -          <SubComponents>
   8.158 -            <Component class="javax.swing.JEditorPane" name="right">
   8.159 -            </Component>
   8.160 -          </SubComponents>
   8.161 -        </Container>
   8.162 -      </SubComponents>
   8.163 -    </Container>
   8.164 -    <Container class="javax.swing.JScrollPane" name="jScrollPane4">
   8.165 -
   8.166 -      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
   8.167 -      <SubComponents>
   8.168 -        <Container class="javax.swing.JSplitPane" name="jSplitPane2">
   8.169 -          <Properties>
   8.170 -            <Property name="dividerLocation" type="int" value="250"/>
   8.171 -            <Property name="dividerSize" type="int" value="1"/>
   8.172 -          </Properties>
   8.173 -          <AuxValues>
   8.174 -            <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new BalancedSplitPane()"/>
   8.175 -          </AuxValues>
   8.176 -
   8.177 -          <Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
   8.178 -          <SubComponents>
   8.179 -            <Component class="javax.swing.JList" name="rightList">
   8.180 +              <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
   8.181 +              <SubComponents>
   8.182 +                <Component class="javax.swing.JEditorPane" name="left">
   8.183 +                </Component>
   8.184 +              </SubComponents>
   8.185 +            </Container>
   8.186 +            <Component class="javax.swing.JComboBox" name="leftFileList">
   8.187                <Properties>
   8.188 -                <Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
   8.189 -                  <Connection code="createListModel()" type="code"/>
   8.190 -                </Property>
   8.191 -                <Property name="cellRenderer" type="javax.swing.ListCellRenderer" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
   8.192 -                  <Connection code="new RendererImpl(false)" type="code"/>
   8.193 +                <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
   8.194 +                  <StringArray count="0"/>
   8.195                  </Property>
   8.196                </Properties>
   8.197                <Constraints>
   8.198 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
   8.199 -                  <JSplitPaneConstraints position="right"/>
   8.200 -                </Constraint>
   8.201 -              </Constraints>
   8.202 -            </Component>
   8.203 -            <Component class="javax.swing.JList" name="leftList">
   8.204 -              <Properties>
   8.205 -                <Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
   8.206 -                  <Connection code="createListModel()" type="code"/>
   8.207 -                </Property>
   8.208 -                <Property name="cellRenderer" type="javax.swing.ListCellRenderer" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
   8.209 -                  <Connection code="new RendererImpl(true)" type="code"/>
   8.210 -                </Property>
   8.211 -              </Properties>
   8.212 -              <Constraints>
   8.213 -                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
   8.214 -                  <JSplitPaneConstraints position="left"/>
   8.215 +                <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
   8.216 +                  <GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
   8.217                  </Constraint>
   8.218                </Constraints>
   8.219              </Component>
   8.220 @@ -132,5 +149,41 @@
   8.221          </Container>
   8.222        </SubComponents>
   8.223      </Container>
   8.224 +    <Container class="javax.swing.JPanel" name="jPanel1">
   8.225 +
   8.226 +      <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
   8.227 +      <SubComponents>
   8.228 +        <Component class="javax.swing.JLabel" name="progressLabel">
   8.229 +          <Properties>
   8.230 +            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   8.231 +              <ResourceString bundle="org/netbeans/modules/jackpot30/impl/duplicates/Bundle.properties" key="DuplicatesListPanel.progressLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   8.232 +            </Property>
   8.233 +          </Properties>
   8.234 +          <Constraints>
   8.235 +            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
   8.236 +              <GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
   8.237 +            </Constraint>
   8.238 +          </Constraints>
   8.239 +        </Component>
   8.240 +        <Component class="javax.swing.JLabel" name="findMore">
   8.241 +          <Properties>
   8.242 +            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   8.243 +              <ResourceString bundle="org/netbeans/modules/jackpot30/impl/duplicates/Bundle.properties" key="DuplicatesListPanel.findMore.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   8.244 +            </Property>
   8.245 +            <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
   8.246 +              <Color id="Hand Cursor"/>
   8.247 +            </Property>
   8.248 +          </Properties>
   8.249 +          <Events>
   8.250 +            <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="findMoreMouseClicked"/>
   8.251 +          </Events>
   8.252 +          <Constraints>
   8.253 +            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
   8.254 +              <GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
   8.255 +            </Constraint>
   8.256 +          </Constraints>
   8.257 +        </Component>
   8.258 +      </SubComponents>
   8.259 +    </Container>
   8.260    </SubComponents>
   8.261  </Form>
     9.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/duplicates/DuplicatesListPanel.java	Sat Jan 22 21:51:05 2011 +0100
     9.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/duplicates/DuplicatesListPanel.java	Fri Feb 18 20:16:26 2011 +0100
     9.3 @@ -41,14 +41,19 @@
     9.4  import java.awt.Color;
     9.5  import java.awt.Component;
     9.6  import java.awt.Rectangle;
     9.7 +import java.awt.event.ActionEvent;
     9.8 +import java.awt.event.ActionListener;
     9.9  import java.io.IOException;
    9.10  import java.util.Collection;
    9.11 +import java.util.Iterator;
    9.12 +import java.util.LinkedHashSet;
    9.13 +import java.util.Set;
    9.14 +import javax.swing.DefaultComboBoxModel;
    9.15  import javax.swing.DefaultListCellRenderer;
    9.16  import javax.swing.DefaultListModel;
    9.17  import javax.swing.JEditorPane;
    9.18  import javax.swing.JList;
    9.19  import javax.swing.JSplitPane;
    9.20 -import javax.swing.ListModel;
    9.21  import javax.swing.SwingUtilities;
    9.22  import javax.swing.event.ListSelectionEvent;
    9.23  import javax.swing.event.ListSelectionListener;
    9.24 @@ -68,6 +73,8 @@
    9.25  import org.openide.filesystems.FileUtil;
    9.26  import org.openide.util.Exceptions;
    9.27  import org.openide.util.Lookup;
    9.28 +import org.openide.util.RequestProcessor;
    9.29 +import org.openide.util.RequestProcessor.Task;
    9.30  import org.openide.util.lookup.Lookups;
    9.31  import org.openide.util.lookup.ServiceProvider;
    9.32  
    9.33 @@ -76,12 +83,14 @@
    9.34   * @author lahvac
    9.35   */
    9.36  public class DuplicatesListPanel extends javax.swing.JPanel {
    9.37 -    private final Collection<? extends DuplicateDescription> dupes;
    9.38 -    private final int commonPrefixLength;
    9.39 +    private final Collection<String> sourceRoots;
    9.40 +    private final Iterator<? extends DuplicateDescription> dupes;
    9.41  
    9.42 -    public DuplicatesListPanel(Collection<? extends DuplicateDescription> dupes) {
    9.43 +    private int targetCount;
    9.44 +
    9.45 +    public DuplicatesListPanel(Collection<String> sourceRoots, final Iterator<? extends DuplicateDescription> dupes) {
    9.46 +        this.sourceRoots = sourceRoots;
    9.47          this.dupes = dupes;
    9.48 -        this.commonPrefixLength = computeCommonPrefixLen(dupes);
    9.49          
    9.50          initComponents();
    9.51  
    9.52 @@ -91,20 +100,44 @@
    9.53          right.setContentType("text/x-java");
    9.54          right.putClientProperty(DuplicatesListPanel.class, new OffsetsBag(right.getDocument()));
    9.55  
    9.56 -        leftList.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
    9.57 +        duplicatesList.setModel(new DefaultListModel());
    9.58 +        duplicatesList.setCellRenderer(new DuplicatesRendererImpl());
    9.59 +        duplicatesList.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
    9.60              public void valueChanged(ListSelectionEvent arg0) {
    9.61 -                setDiff((DuplicateDescription) leftList.getSelectedValue());
    9.62 -                rightList.setSelectedValue(leftList.getSelectedValue(), false);
    9.63 +                DuplicateDescription dd = (DuplicateDescription) duplicatesList.getSelectedValue();
    9.64 +                DefaultComboBoxModel l = new DefaultComboBoxModel();
    9.65 +                DefaultComboBoxModel r = new DefaultComboBoxModel();
    9.66 +
    9.67 +                for (Span s : dd.dupes) {
    9.68 +                    l.addElement(s);
    9.69 +                    r.addElement(s);
    9.70 +                }
    9.71 +
    9.72 +                leftFileList.setModel(l);
    9.73 +                rightFileList.setModel(r);
    9.74 +
    9.75 +                leftFileList.setSelectedIndex(0);
    9.76 +                rightFileList.setSelectedIndex(1);
    9.77              }
    9.78          });
    9.79  
    9.80 -        rightList.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
    9.81 -            public void valueChanged(ListSelectionEvent arg0) {
    9.82 -                leftList.setSelectedValue(rightList.getSelectedValue(), false);
    9.83 +        leftFileList.setRenderer(new SpanRendererImpl());
    9.84 +        leftFileList.addActionListener(new ActionListener() {
    9.85 +
    9.86 +            public void actionPerformed(ActionEvent e) {
    9.87 +                setSpan(left, (Span) leftFileList.getSelectedItem());
    9.88 +            }
    9.89 +        });
    9.90 +        rightFileList.setRenderer(new SpanRendererImpl());
    9.91 +        rightFileList.addActionListener(new ActionListener() {
    9.92 +            public void actionPerformed(ActionEvent e) {
    9.93 +                setSpan(right, (Span) rightFileList.getSelectedItem());
    9.94              }
    9.95          });
    9.96  
    9.97 -        leftList.setSelectedIndex(0);
    9.98 +        progressLabel.setText("Looking for duplicates...");
    9.99 +
   9.100 +        findMore();
   9.101      }
   9.102  
   9.103      /** This method is called from within the constructor to
   9.104 @@ -115,81 +148,136 @@
   9.105      @SuppressWarnings("unchecked")
   9.106      // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
   9.107      private void initComponents() {
   9.108 +        java.awt.GridBagConstraints gridBagConstraints;
   9.109  
   9.110 -        jSplitPane1 = new BalancedSplitPane();
   9.111 +        jScrollPane1 = new javax.swing.JScrollPane();
   9.112 +        duplicatesList = new javax.swing.JList();
   9.113 +        mainSplit2 = new BalancedSplitPane();
   9.114 +        rightPanel = new javax.swing.JPanel();
   9.115 +        rightFileList = new javax.swing.JComboBox();
   9.116 +        jScrollPane3 = new javax.swing.JScrollPane();
   9.117 +        right = new javax.swing.JEditorPane();
   9.118 +        leftPanel = new javax.swing.JPanel();
   9.119          jScrollPane2 = new javax.swing.JScrollPane();
   9.120          left = new javax.swing.JEditorPane();
   9.121 -        jScrollPane3 = new javax.swing.JScrollPane();
   9.122 -        right = new javax.swing.JEditorPane();
   9.123 -        jScrollPane4 = new javax.swing.JScrollPane();
   9.124 -        jSplitPane2 = new BalancedSplitPane();
   9.125 -        rightList = new javax.swing.JList();
   9.126 -        leftList = new javax.swing.JList();
   9.127 +        leftFileList = new javax.swing.JComboBox();
   9.128 +        jPanel1 = new javax.swing.JPanel();
   9.129 +        progressLabel = new javax.swing.JLabel();
   9.130 +        findMore = new javax.swing.JLabel();
   9.131 +
   9.132 +        duplicatesList.setPrototypeCellValue("9999999999999999999999999999999999999999999999999999999999999999999999");
   9.133 +        duplicatesList.setVisibleRowCount(4);
   9.134 +        jScrollPane1.setViewportView(duplicatesList);
   9.135 +
   9.136 +        mainSplit2.setDividerLocation(400);
   9.137 +
   9.138 +        rightPanel.setLayout(new java.awt.GridBagLayout());
   9.139 +
   9.140 +        gridBagConstraints = new java.awt.GridBagConstraints();
   9.141 +        gridBagConstraints.gridx = 0;
   9.142 +        gridBagConstraints.gridy = 0;
   9.143 +        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
   9.144 +        gridBagConstraints.ipadx = 324;
   9.145 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
   9.146 +        gridBagConstraints.weightx = 1.0;
   9.147 +        rightPanel.add(rightFileList, gridBagConstraints);
   9.148 +
   9.149 +        jScrollPane3.setViewportView(right);
   9.150 +
   9.151 +        gridBagConstraints = new java.awt.GridBagConstraints();
   9.152 +        gridBagConstraints.gridx = 0;
   9.153 +        gridBagConstraints.gridy = 1;
   9.154 +        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
   9.155 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
   9.156 +        gridBagConstraints.weightx = 1.0;
   9.157 +        gridBagConstraints.weighty = 1.0;
   9.158 +        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
   9.159 +        rightPanel.add(jScrollPane3, gridBagConstraints);
   9.160 +
   9.161 +        mainSplit2.setRightComponent(rightPanel);
   9.162 +
   9.163 +        leftPanel.setLayout(new java.awt.GridBagLayout());
   9.164  
   9.165          jScrollPane2.setViewportView(left);
   9.166  
   9.167 -        jSplitPane1.setLeftComponent(jScrollPane2);
   9.168 +        gridBagConstraints = new java.awt.GridBagConstraints();
   9.169 +        gridBagConstraints.gridx = 0;
   9.170 +        gridBagConstraints.gridy = 1;
   9.171 +        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
   9.172 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
   9.173 +        gridBagConstraints.weightx = 1.0;
   9.174 +        gridBagConstraints.weighty = 1.0;
   9.175 +        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
   9.176 +        leftPanel.add(jScrollPane2, gridBagConstraints);
   9.177  
   9.178 -        jScrollPane3.setViewportView(right);
   9.179 +        gridBagConstraints = new java.awt.GridBagConstraints();
   9.180 +        gridBagConstraints.gridx = 0;
   9.181 +        gridBagConstraints.gridy = 0;
   9.182 +        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
   9.183 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
   9.184 +        gridBagConstraints.weightx = 1.0;
   9.185 +        leftPanel.add(leftFileList, gridBagConstraints);
   9.186  
   9.187 -        jSplitPane1.setRightComponent(jScrollPane3);
   9.188 +        mainSplit2.setLeftComponent(leftPanel);
   9.189  
   9.190 -        jSplitPane2.setDividerLocation(250);
   9.191 -        jSplitPane2.setDividerSize(1);
   9.192 +        jPanel1.setLayout(new java.awt.GridBagLayout());
   9.193  
   9.194 -        rightList.setModel(createListModel());
   9.195 -        rightList.setCellRenderer(new RendererImpl(false));
   9.196 -        jSplitPane2.setRightComponent(rightList);
   9.197 +        progressLabel.setText(org.openide.util.NbBundle.getMessage(DuplicatesListPanel.class, "DuplicatesListPanel.progressLabel.text")); // NOI18N
   9.198 +        gridBagConstraints = new java.awt.GridBagConstraints();
   9.199 +        gridBagConstraints.gridx = 0;
   9.200 +        gridBagConstraints.gridy = 0;
   9.201 +        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
   9.202 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
   9.203 +        gridBagConstraints.weightx = 1.0;
   9.204 +        jPanel1.add(progressLabel, gridBagConstraints);
   9.205  
   9.206 -        leftList.setModel(createListModel());
   9.207 -        leftList.setCellRenderer(new RendererImpl(true));
   9.208 -        jSplitPane2.setLeftComponent(leftList);
   9.209 -
   9.210 -        jScrollPane4.setViewportView(jSplitPane2);
   9.211 +        findMore.setText(org.openide.util.NbBundle.getMessage(DuplicatesListPanel.class, "DuplicatesListPanel.findMore.text")); // NOI18N
   9.212 +        findMore.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
   9.213 +        findMore.addMouseListener(new java.awt.event.MouseAdapter() {
   9.214 +            public void mouseClicked(java.awt.event.MouseEvent evt) {
   9.215 +                findMoreMouseClicked(evt);
   9.216 +            }
   9.217 +        });
   9.218 +        gridBagConstraints = new java.awt.GridBagConstraints();
   9.219 +        gridBagConstraints.gridx = 1;
   9.220 +        gridBagConstraints.gridy = 0;
   9.221 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
   9.222 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 0);
   9.223 +        jPanel1.add(findMore, gridBagConstraints);
   9.224  
   9.225          javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
   9.226          this.setLayout(layout);
   9.227          layout.setHorizontalGroup(
   9.228              layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
   9.229 -            .addGroup(layout.createSequentialGroup()
   9.230 +            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
   9.231                  .addContainerGap()
   9.232 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
   9.233 -                    .addComponent(jSplitPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 390, Short.MAX_VALUE)
   9.234 -                    .addComponent(jScrollPane4, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 390, Short.MAX_VALUE))
   9.235 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
   9.236 +                    .addComponent(mainSplit2, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 906, Short.MAX_VALUE)
   9.237 +                    .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 906, Short.MAX_VALUE)
   9.238 +                    .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
   9.239                  .addContainerGap())
   9.240          );
   9.241          layout.setVerticalGroup(
   9.242              layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
   9.243              .addGroup(layout.createSequentialGroup()
   9.244                  .addContainerGap()
   9.245 -                .addComponent(jScrollPane4, javax.swing.GroupLayout.PREFERRED_SIZE, 76, javax.swing.GroupLayout.PREFERRED_SIZE)
   9.246 +                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 67, javax.swing.GroupLayout.PREFERRED_SIZE)
   9.247                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
   9.248 -                .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 206, Short.MAX_VALUE)
   9.249 +                .addComponent(mainSplit2, javax.swing.GroupLayout.DEFAULT_SIZE, 467, Short.MAX_VALUE)
   9.250 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
   9.251 +                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
   9.252                  .addContainerGap())
   9.253          );
   9.254      }// </editor-fold>//GEN-END:initComponents
   9.255  
   9.256 +    private void findMoreMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_findMoreMouseClicked
   9.257 +        findMore();
   9.258 +    }//GEN-LAST:event_findMoreMouseClicked
   9.259  
   9.260 -    private ListModel createListModel() {
   9.261 -        DefaultListModel dlm = new DefaultListModel();
   9.262 -
   9.263 -        for (DuplicateDescription dd : dupes) {
   9.264 -            dlm.addElement(dd);
   9.265 -        }
   9.266 -
   9.267 -        return dlm;
   9.268 -    }
   9.269 -
   9.270 -    private static int computeCommonPrefixLen(Collection<? extends DuplicateDescription> dupes) {
   9.271 -        String commonPrefix = null;
   9.272 -
   9.273 -        for (DuplicateDescription dd : dupes) {
   9.274 -            for (Span s : dd.dupes) {
   9.275 -                commonPrefix = computeCommonPrefix(commonPrefix, s.file);
   9.276 -            }
   9.277 -        }
   9.278 -
   9.279 -        return commonPrefix != null ? commonPrefix.length() : 0;
   9.280 +    private void findMore() {
   9.281 +        targetCount = duplicatesList.getModel().getSize() + 100;
   9.282 +        findMore.setVisible(false);
   9.283 +        WORKER.schedule(0);
   9.284      }
   9.285  
   9.286      private static String computeCommonPrefix(String origCommonPrefix, FileObject file) {
   9.287 @@ -208,11 +296,6 @@
   9.288          return origCommonPrefix;
   9.289      }
   9.290      
   9.291 -    private void setDiff(DuplicateDescription dd) {
   9.292 -        setSpan(left, dd.dupes.get(0));
   9.293 -        setSpan(right, dd.dupes.get(1));
   9.294 -    }
   9.295 -
   9.296      private static void setSpan(JEditorPane pane, Span s) {
   9.297          try {
   9.298              pane.setText(s.file.asText());
   9.299 @@ -241,17 +324,49 @@
   9.300  
   9.301      private static final AttributeSet HIGHLIGHT = AttributesUtilities.createImmutable(StyleConstants.Background, new Color(0xDF, 0xDF, 0xDF, 0xff));
   9.302  
   9.303 -    private final class RendererImpl extends DefaultListCellRenderer {
   9.304 -        private final boolean left;
   9.305 -        public RendererImpl(boolean left) {
   9.306 -            this.left = left;
   9.307 -        }
   9.308 +    private final class DuplicatesRendererImpl extends DefaultListCellRenderer {
   9.309          @Override
   9.310          public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
   9.311 +            if (!(value instanceof DuplicateDescription)) return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
   9.312              DuplicateDescription dd = (DuplicateDescription) value;
   9.313 -            String name = left ? FileUtil.getFileDisplayName(dd.dupes.get(0).file).substring(commonPrefixLength) : FileUtil.getFileDisplayName(dd.dupes.get(1).file).substring(commonPrefixLength);
   9.314 +            Set<FileObject> files = new LinkedHashSet<FileObject>();
   9.315 +            String commonPrefix = null;
   9.316  
   9.317 -            return super.getListCellRendererComponent(list, name, index, isSelected, cellHasFocus);
   9.318 +            for (Span s : dd.dupes) {
   9.319 +                commonPrefix = computeCommonPrefix(commonPrefix, s.file);
   9.320 +                files.add(s.file);
   9.321 +            }
   9.322 +
   9.323 +            StringBuilder cap = new StringBuilder();
   9.324 +
   9.325 +            OUTER: for (FileObject file : files) {
   9.326 +                String name = FileUtil.getFileDisplayName(file);
   9.327 +
   9.328 +                if (cap.length() > 0) {
   9.329 +                    cap.append("    ");
   9.330 +                }
   9.331 +                
   9.332 +                for (String sr : sourceRoots) {
   9.333 +                    if (name.startsWith(sr)) {
   9.334 +                        cap.append(name.substring(Math.max(0, sr.lastIndexOf('/') + 1)));
   9.335 +                        continue OUTER;
   9.336 +                    }
   9.337 +                }
   9.338 +            }
   9.339 +
   9.340 +            return super.getListCellRendererComponent(list, cap.toString(), index, isSelected, cellHasFocus);
   9.341 +        }
   9.342 +    }
   9.343 +
   9.344 +    private final class SpanRendererImpl extends DefaultListCellRenderer {
   9.345 +        @Override
   9.346 +        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
   9.347 +            if (!(value instanceof Span)) {
   9.348 +                return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
   9.349 +            }
   9.350 +            Span span = (Span) value;
   9.351 +
   9.352 +            return super.getListCellRendererComponent(list, FileUtil.getFileDisplayName(span.file), index, isSelected, cellHasFocus);
   9.353          }
   9.354      }
   9.355  
   9.356 @@ -287,6 +402,7 @@
   9.357      private static final class BalancedSplitPane extends JSplitPane {
   9.358  
   9.359          @Override
   9.360 +        @SuppressWarnings("deprecation")
   9.361          public void reshape(int x, int y, int w, int h) {
   9.362              super.reshape(x, y, w, h);
   9.363              SwingUtilities.invokeLater(new Runnable() {
   9.364 @@ -299,15 +415,50 @@
   9.365      }
   9.366  
   9.367      // Variables declaration - do not modify//GEN-BEGIN:variables
   9.368 +    private javax.swing.JList duplicatesList;
   9.369 +    private javax.swing.JLabel findMore;
   9.370 +    private javax.swing.JPanel jPanel1;
   9.371 +    private javax.swing.JScrollPane jScrollPane1;
   9.372      private javax.swing.JScrollPane jScrollPane2;
   9.373      private javax.swing.JScrollPane jScrollPane3;
   9.374 -    private javax.swing.JScrollPane jScrollPane4;
   9.375 -    private javax.swing.JSplitPane jSplitPane1;
   9.376 -    private javax.swing.JSplitPane jSplitPane2;
   9.377      private javax.swing.JEditorPane left;
   9.378 -    private javax.swing.JList leftList;
   9.379 +    private javax.swing.JComboBox leftFileList;
   9.380 +    private javax.swing.JPanel leftPanel;
   9.381 +    private javax.swing.JSplitPane mainSplit2;
   9.382 +    private javax.swing.JLabel progressLabel;
   9.383      private javax.swing.JEditorPane right;
   9.384 -    private javax.swing.JList rightList;
   9.385 +    private javax.swing.JComboBox rightFileList;
   9.386 +    private javax.swing.JPanel rightPanel;
   9.387      // End of variables declaration//GEN-END:variables
   9.388  
   9.389 +    private static final RequestProcessor DEFAULT_WORKER = new RequestProcessor(DuplicatesListPanel.class.getName(), 1, false, false);
   9.390 +    private final Task WORKER = DEFAULT_WORKER.create(new Runnable() {
   9.391 +        public void run() {
   9.392 +            if (dupes.hasNext()) {
   9.393 +                final DuplicateDescription dd = dupes.next();
   9.394 +
   9.395 +                SwingUtilities.invokeLater(new Runnable() {
   9.396 +
   9.397 +                    public void run() {
   9.398 +                        ((DefaultListModel)duplicatesList.getModel()).addElement(dd);
   9.399 +
   9.400 +                        int size = duplicatesList.getModel().getSize();
   9.401 +
   9.402 +                        if (size == 1) {
   9.403 +                            duplicatesList.setSelectedIndex(0);
   9.404 +                        }
   9.405 +                        
   9.406 +                        if (size >= targetCount) {
   9.407 +                            findMore.setVisible(true);
   9.408 +                            progressLabel.setText("Found " + size + " duplicated snippets.");
   9.409 +                        } else {
   9.410 +                            progressLabel.setText("Found " + size + " duplicated snippets and searching...");
   9.411 +                            WORKER.schedule(0);
   9.412 +                        }
   9.413 +                    }
   9.414 +                });
   9.415 +            }
   9.416 +        }
   9.417 +    });
   9.418 +
   9.419  }
    10.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/duplicates/GlobalFindDuplicates.java	Sat Jan 22 21:51:05 2011 +0100
    10.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/duplicates/GlobalFindDuplicates.java	Fri Feb 18 20:16:26 2011 +0100
    10.3 @@ -46,18 +46,22 @@
    10.4  import java.awt.event.ActionListener;
    10.5  import java.io.IOException;
    10.6  import java.util.Collection;
    10.7 -import java.util.Collections;
    10.8 +import java.util.Iterator;
    10.9  import java.util.LinkedList;
   10.10  import java.util.concurrent.atomic.AtomicBoolean;
   10.11  import javax.swing.JLabel;
   10.12  import javax.swing.JPanel;
   10.13  import javax.swing.SwingUtilities;
   10.14 +import org.netbeans.api.java.classpath.ClassPath;
   10.15 +import org.netbeans.api.java.classpath.GlobalPathRegistry;
   10.16  import org.netbeans.api.progress.ProgressHandle;
   10.17  import org.netbeans.api.progress.ProgressHandleFactory;
   10.18  import org.netbeans.modules.jackpot30.impl.duplicates.ComputeDuplicates.DuplicateDescription;
   10.19  import org.openide.DialogDescriptor;
   10.20  import org.openide.DialogDisplayer;
   10.21  import org.openide.NotifyDescriptor;
   10.22 +import org.openide.filesystems.FileObject;
   10.23 +import org.openide.filesystems.FileUtil;
   10.24  import org.openide.util.Exceptions;
   10.25  import org.openide.util.HelpCtx;
   10.26  import org.openide.util.RequestProcessor;
   10.27 @@ -65,7 +69,7 @@
   10.28  public final class GlobalFindDuplicates implements ActionListener {
   10.29  
   10.30      public void actionPerformed(ActionEvent e) {
   10.31 -        final Collection<DuplicateDescription> dupes = Collections.synchronizedList(new LinkedList<DuplicateDescription>());
   10.32 +        final Iterator<? extends DuplicateDescription>[] dupes = new Iterator[1];
   10.33          final ProgressHandle handle = ProgressHandleFactory.createHandle("Compute Duplicates");
   10.34          JPanel panel = createPanel(handle);
   10.35          final AtomicBoolean cancel = new AtomicBoolean();
   10.36 @@ -79,11 +83,22 @@
   10.37  
   10.38          final Dialog d = DialogDisplayer.getDefault().createDialog(w);
   10.39          final AtomicBoolean done = new AtomicBoolean();
   10.40 +        final Collection<String> sourceRoots = new LinkedList<String>();
   10.41  
   10.42          WORKER.post(new Runnable() {
   10.43              public void run() {
   10.44                  try {
   10.45 -                    dupes.addAll(new ComputeDuplicates().computeDuplicatesForAllOpenedProjects(handle, cancel));
   10.46 +                    for (ClassPath cp : GlobalPathRegistry.getDefault().getPaths(ClassPath.SOURCE)) {
   10.47 +                        for (ClassPath.Entry e : cp.entries()) {
   10.48 +                            FileObject root = e.getRoot();
   10.49 +
   10.50 +                            if (root == null) continue;
   10.51 +
   10.52 +                            sourceRoots.add(FileUtil.getFileDisplayName(root));
   10.53 +                        }
   10.54 +                    }
   10.55 +
   10.56 +                    dupes[0] = new ComputeDuplicates().computeDuplicatesForAllOpenedProjects(handle, cancel);
   10.57                      done.set(true);
   10.58                  } catch (IOException ex) {
   10.59                      Exceptions.printStackTrace(ex);
   10.60 @@ -111,7 +126,7 @@
   10.61          
   10.62          if (cancel.get()) return;
   10.63  
   10.64 -        NotifyDescriptor nd = new NotifyDescriptor.Message(new DuplicatesListPanel(dupes));
   10.65 +        NotifyDescriptor nd = new NotifyDescriptor.Message(new DuplicatesListPanel(sourceRoots, dupes[0]));
   10.66  
   10.67          DialogDisplayer.getDefault().notifyLater(nd);
   10.68      }
    11.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/indexing/AbstractLuceneIndex.java	Sat Jan 22 21:51:05 2011 +0100
    11.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/indexing/AbstractLuceneIndex.java	Fri Feb 18 20:16:26 2011 +0100
    11.3 @@ -50,9 +50,11 @@
    11.4  import java.util.BitSet;
    11.5  import java.util.Collection;
    11.6  import java.util.Collections;
    11.7 +import java.util.HashMap;
    11.8  import java.util.HashSet;
    11.9  import java.util.Iterator;
   11.10  import java.util.List;
   11.11 +import java.util.Map;
   11.12  import java.util.Set;
   11.13  import java.util.logging.Level;
   11.14  import java.util.logging.Logger;
   11.15 @@ -60,8 +62,8 @@
   11.16  import javax.lang.model.type.ArrayType;
   11.17  import javax.lang.model.type.TypeKind;
   11.18  import javax.lang.model.type.TypeMirror;
   11.19 -import org.apache.lucene.analysis.Token;
   11.20  import org.apache.lucene.analysis.TokenStream;
   11.21 +import org.apache.lucene.analysis.tokenattributes.TermAttribute;
   11.22  import org.apache.lucene.document.CompressionTools;
   11.23  import org.apache.lucene.document.Document;
   11.24  import org.apache.lucene.document.Field;
   11.25 @@ -81,6 +83,7 @@
   11.26  import org.apache.lucene.search.TermQuery;
   11.27  import org.apache.lucene.search.TopDocs;
   11.28  import org.netbeans.api.annotations.common.NonNull;
   11.29 +import org.netbeans.api.annotations.common.NullAllowed;
   11.30  import org.netbeans.modules.jackpot30.impl.pm.BulkSearch;
   11.31  import org.netbeans.modules.jackpot30.impl.pm.BulkSearch.BulkPattern;
   11.32  import org.netbeans.modules.jackpot30.impl.pm.BulkSearch.EncodingContext;
   11.33 @@ -117,10 +120,19 @@
   11.34  
   11.35      @Override
   11.36      public Collection<? extends String> findCandidates(BulkPattern pattern) throws IOException {
   11.37 +        return findCandidates(pattern, false).keySet();
   11.38 +    }
   11.39 +
   11.40 +    @Override
   11.41 +    public Map<String, Map<String, Integer>> findCandidatesWithFrequencies(BulkPattern pattern) throws IOException {
   11.42 +        return findCandidates(pattern, true);
   11.43 +    }
   11.44 +
   11.45 +    private Map<String, Map<String, Integer>> findCandidates(BulkPattern pattern, boolean withFrequencies) throws IOException {
   11.46          IndexReader reader = createReader();
   11.47  
   11.48          if (reader == null) {
   11.49 -             return Collections.emptyList();
   11.50 +             return Collections.emptyMap();
   11.51           }
   11.52  
   11.53          Searcher s = new IndexSearcher(reader);
   11.54 @@ -133,7 +145,7 @@
   11.55              throw new IOException(ex);
   11.56          }
   11.57  
   11.58 -        Collection<String> result = new HashSet<String>();
   11.59 +        Map<String, Map<String, Integer>> result = new HashMap<String, Map<String, Integer>>();
   11.60  
   11.61          for (int docNum = matchingDocuments.nextSetBit(0); docNum >= 0; docNum = matchingDocuments.nextSetBit(docNum+1)) {
   11.62              try {
   11.63 @@ -146,14 +158,24 @@
   11.64                  ByteArrayInputStream in = new ByteArrayInputStream(CompressionTools.decompress(doc.getField("encoded").getBinaryValue()));
   11.65  
   11.66                  try {
   11.67 -                    if (!BulkSearch.getDefault().matches(in, pattern)) {
   11.68 +                    Map<String, Integer> freqs;
   11.69 +                    boolean matches;
   11.70 +
   11.71 +                    if (withFrequencies) {
   11.72 +                        freqs = BulkSearch.getDefault().matchesWithFrequencies(in, pattern);
   11.73 +                        matches = !freqs.isEmpty();
   11.74 +                    } else {
   11.75 +                        freqs = null;
   11.76 +                        matches = BulkSearch.getDefault().matches(in, pattern);
   11.77 +                    }
   11.78 +
   11.79 +                    if (matches) {
   11.80 +                        result.put(doc.getField("path").stringValue(), freqs);
   11.81                          continue;
   11.82                      }
   11.83                  } finally {
   11.84                      in.close();
   11.85                  }
   11.86 -
   11.87 -                result.add(doc.getField("path").stringValue());
   11.88              } catch (DataFormatException ex) {
   11.89                  throw new IOException(ex);
   11.90              }
   11.91 @@ -224,7 +246,7 @@
   11.92                  }
   11.93              });
   11.94              
   11.95 -            return CompressionTools.decompressString(doc.getField("sourceCode").getBinaryValue());
   11.96 +            return CompressionTools.decompressString(doc.getField("sourceCode").getBinaryValue()).replaceAll("\r\n", "\n")/*XXX*/;
   11.97          } catch (DataFormatException ex) {
   11.98              Exceptions.printStackTrace(ex);
   11.99              return "";
  11.100 @@ -249,7 +271,7 @@
  11.101          }
  11.102  
  11.103          @Override
  11.104 -        public void record(URL source, final CompilationUnitTree cut, final AttributionWrapper attributed) throws IOException {
  11.105 +        public void record(URL source, final CompilationUnitTree cut, final @NullAllowed AttributionWrapper attributed) throws IOException {
  11.106              String relative = source.getPath().substring(stripLength);
  11.107              ByteArrayOutputStream out = null;
  11.108              EncodingContext ec = null;
  11.109 @@ -351,19 +373,23 @@
  11.110      public static final class TokenStreamImpl extends TokenStream {
  11.111  
  11.112          private final Iterator<? extends String> tokens;
  11.113 +        private final TermAttribute termAtt;
  11.114  
  11.115          public TokenStreamImpl(Iterable<? extends String> tokens) {
  11.116              this.tokens = tokens != null ? tokens.iterator() : /*???*/Collections.<String>emptyList().iterator();
  11.117 +            this.termAtt = addAttribute(TermAttribute.class);
  11.118          }
  11.119  
  11.120          @Override
  11.121 -        public Token next() throws IOException {
  11.122 +        public boolean incrementToken() throws IOException {
  11.123              if (!tokens.hasNext())
  11.124 -                return null;
  11.125 +                return false;
  11.126  
  11.127              String t = tokens.next();
  11.128  
  11.129 -            return new Token(t, 0, t.length());
  11.130 +            termAtt.setTermBuffer(t);
  11.131 +            
  11.132 +            return true;
  11.133          }
  11.134      }
  11.135  
    12.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/indexing/CustomIndexerImpl.java	Sat Jan 22 21:51:05 2011 +0100
    12.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/indexing/CustomIndexerImpl.java	Fri Feb 18 20:16:26 2011 +0100
    12.3 @@ -102,13 +102,20 @@
    12.4                  w[0].remove(path);
    12.5              }
    12.6  
    12.7 +            final boolean attributed = Boolean.getBoolean(CustomIndexerImpl.class.getName() + "-attributed");
    12.8 +
    12.9              if (!toIndex.isEmpty()) {
   12.10                  JavaSource.create(cpInfo, toIndex).runUserActionTask(new Task<CompilationController>() {
   12.11                      public void run(final CompilationController cc) throws Exception {
   12.12 -                        if (cc.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0)
   12.13 +                        if (attributed) {
   12.14 +                            if (cc.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0)
   12.15 +                                return ;
   12.16 +                        } else {
   12.17 +                        if (cc.toPhase(Phase.PARSED).compareTo(Phase.PARSED) < 0)
   12.18                              return ;
   12.19 +                        }
   12.20  
   12.21 -                        w[0].record(cc.getFileObject().getURL(), cc.getCompilationUnit(), new AttributionWrapper(cc));
   12.22 +                        w[0].record(cc.getFileObject().getURL(), cc.getCompilationUnit(), attributed ? new AttributionWrapper(cc) : null);
   12.23                      }
   12.24                  }, true);
   12.25              }
    13.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/indexing/Index.java	Sat Jan 22 21:51:05 2011 +0100
    13.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/indexing/Index.java	Fri Feb 18 20:16:26 2011 +0100
    13.3 @@ -39,7 +39,7 @@
    13.4  
    13.5  package org.netbeans.modules.jackpot30.impl.indexing;
    13.6  
    13.7 -import org.netbeans.modules.jackpot30.spi.HintDescription.AdditionalQueryConstraints;
    13.8 +import java.util.Map;
    13.9  import com.sun.source.util.Trees;
   13.10  import javax.lang.model.util.Types;
   13.11  import org.netbeans.modules.jackpot30.impl.WebUtilities;
   13.12 @@ -53,6 +53,7 @@
   13.13  import java.util.Collections;
   13.14  import org.codeviation.pojson.Pojson;
   13.15  import org.netbeans.api.annotations.common.NonNull;
   13.16 +import org.netbeans.api.annotations.common.NullAllowed;
   13.17  import org.netbeans.api.java.source.CompilationInfo;
   13.18  import org.netbeans.modules.jackpot30.impl.pm.BulkSearch.BulkPattern;
   13.19  import org.openide.util.Exceptions;
   13.20 @@ -92,6 +93,10 @@
   13.21                  }
   13.22              }
   13.23              @Override
   13.24 +            public Map<String, Map<String, Integer>> findCandidatesWithFrequencies(BulkPattern pattern) throws IOException {
   13.25 +                throw new UnsupportedOperationException("Not supported yet.");
   13.26 +            }
   13.27 +            @Override
   13.28              public @NonNull IndexInfo getIndexInfo() {
   13.29                  IndexInfo result = IndexInfo.empty();
   13.30  
   13.31 @@ -109,7 +114,7 @@
   13.32              @Override
   13.33              public CharSequence getSourceCode(String relativePath) {
   13.34                  try {
   13.35 -                    URI u = new URI(indexURL + "?path=" + escapeForQuery(subIndex) + "&relative=" + escapeForQuery(relativePath));
   13.36 +                    URI u = new URI(indexURL + "/cat?path=" + escapeForQuery(subIndex) + "&relative=" + escapeForQuery(relativePath));
   13.37  
   13.38                      return WebUtilities.requestStringResponse(u);
   13.39                  } catch (URISyntaxException ex) {
   13.40 @@ -124,6 +129,7 @@
   13.41      public abstract IndexWriter openForWriting() throws IOException;
   13.42  
   13.43      public abstract Collection<? extends String> findCandidates(BulkPattern pattern) throws IOException;
   13.44 +    public abstract Map<String, Map<String, Integer>> findCandidatesWithFrequencies(BulkPattern pattern) throws IOException;
   13.45  
   13.46      public abstract CharSequence getSourceCode(String relativePath);
   13.47  
   13.48 @@ -133,7 +139,7 @@
   13.49  
   13.50          protected IndexWriter() throws IOException {}
   13.51  
   13.52 -        public abstract void record(URL source, final CompilationUnitTree cut, AttributionWrapper attributed) throws IOException;
   13.53 +        public abstract void record(URL source, final CompilationUnitTree cut, @NullAllowed AttributionWrapper attributed) throws IOException;
   13.54  
   13.55          public abstract void remove(String relativePath) throws IOException;
   13.56  
    14.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/pm/BulkSearch.java	Sat Jan 22 21:51:05 2011 +0100
    14.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/pm/BulkSearch.java	Fri Feb 18 20:16:26 2011 +0100
    14.3 @@ -83,6 +83,7 @@
    14.4      public abstract Map<String, Collection<TreePath>> match(CompilationInfo info, TreePath toSearch, BulkPattern pattern, Map<String, Long> timeLog);
    14.5  
    14.6      public abstract boolean matches(InputStream encoded, BulkPattern pattern);
    14.7 +    public abstract Map<String, Integer> matchesWithFrequencies(InputStream encoded, BulkPattern pattern);
    14.8      
    14.9      public abstract boolean matches(CompilationInfo info, TreePath toSearch, BulkPattern pattern);
   14.10  
    15.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/pm/CopyFinder.java	Sat Jan 22 21:51:05 2011 +0100
    15.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/pm/CopyFinder.java	Fri Feb 18 20:16:26 2011 +0100
    15.3 @@ -332,8 +332,13 @@
    15.4              return false;
    15.5          }
    15.6  
    15.7 -        if (node == null)
    15.8 -            return p == null;
    15.9 +        if (node == null) {
   15.10 +            if (p == null) return true;
   15.11 +            if (Utilities.isMultistatementWildcardTree(p.getLeaf())) {
   15.12 +                return true;
   15.13 +            }
   15.14 +            return false;
   15.15 +        }
   15.16  
   15.17          if (p != null && p.getLeaf().getKind() == Kind.IDENTIFIER) {
   15.18              String ident = ((IdentifierTree) p.getLeaf()).getName().toString();
   15.19 @@ -358,6 +363,8 @@
   15.20                          bind = info.getTypes().isAssignable(real, designed);
   15.21                      else
   15.22                          bind = false;
   15.23 +                } else {
   15.24 +                    bind = designed == null;
   15.25                  }
   15.26  
   15.27                  if (bind) {
   15.28 @@ -555,9 +562,12 @@
   15.29      }
   15.30  
   15.31      private Boolean scan(Tree node, Tree p, TreePath pOrigin) {
   15.32 -        if (node == null || p == null)
   15.33 -            return node == p;
   15.34 +        if (node == null && p == null)
   15.35 +            return true;
   15.36  
   15.37 +        if (node != null && p == null)
   15.38 +            return false;
   15.39 +        
   15.40          return scan(node, new TreePath(pOrigin, p));
   15.41      }
   15.42  
    16.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/pm/CopyFinderBasedBulkSearch.java	Sat Jan 22 21:51:05 2011 +0100
    16.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/pm/CopyFinderBasedBulkSearch.java	Fri Feb 18 20:16:26 2011 +0100
    16.3 @@ -117,6 +117,11 @@
    16.4          throw new UnsupportedOperationException("Not supported yet.");
    16.5      }
    16.6  
    16.7 +    @Override
    16.8 +    public Map<String, Integer> matchesWithFrequencies(InputStream encoded, BulkPattern pattern) {
    16.9 +        throw new UnsupportedOperationException("Not supported yet.");
   16.10 +    }
   16.11 +
   16.12      private static final class BulkPatternImpl extends BulkPattern {
   16.13  
   16.14          private final Map<Tree, String> pattern2Code;
    17.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/pm/NFABasedBulkSearch.java	Sat Jan 22 21:51:05 2011 +0100
    17.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/pm/NFABasedBulkSearch.java	Fri Feb 18 20:16:26 2011 +0100
    17.3 @@ -56,6 +56,7 @@
    17.4  import java.io.UnsupportedEncodingException;
    17.5  import java.util.ArrayList;
    17.6  import java.util.Collection;
    17.7 +import java.util.Collections;
    17.8  import java.util.EnumMap;
    17.9  import java.util.EnumSet;
   17.10  import java.util.HashMap;
   17.11 @@ -473,14 +474,23 @@
   17.12      @Override
   17.13      public boolean matches(InputStream encoded, BulkPattern patternIn) {
   17.14          try {
   17.15 -            return matchesImpl(encoded, patternIn);
   17.16 +            return !matchesImpl(encoded, patternIn, false).isEmpty();
   17.17          } catch (IOException ex) {
   17.18              Exceptions.printStackTrace(ex);
   17.19              return false;
   17.20          }
   17.21      }
   17.22  
   17.23 -    private boolean matchesImpl(InputStream encoded, BulkPattern patternIn) throws IOException {
   17.24 +    public Map<String, Integer> matchesWithFrequencies(InputStream encoded, BulkPattern patternIn) {
   17.25 +        try {
   17.26 +            return matchesImpl(encoded, patternIn, true);
   17.27 +        } catch (IOException ex) {
   17.28 +            Exceptions.printStackTrace(ex);
   17.29 +            return Collections.emptyMap();
   17.30 +        }
   17.31 +    }
   17.32 +
   17.33 +    public Map<String, Integer> matchesImpl(InputStream encoded, BulkPattern patternIn, boolean withFrequencies) throws IOException {
   17.34          BulkPatternImpl pattern = (BulkPatternImpl) patternIn;
   17.35          final NFA<Input, Res> nfa = pattern.toNFA();
   17.36          Stack<NFA.State> skips = new Stack<NFA.State>();
   17.37 @@ -508,6 +518,7 @@
   17.38              identifiers.add(new String(baos.toByteArray(), "UTF-8"));
   17.39          }
   17.40  
   17.41 +        Map<String, Integer> patternsAndFrequencies = new HashMap<String, Integer>();
   17.42          int read = encoded.read();
   17.43          
   17.44          while (read != (-1)) {
   17.45 @@ -560,7 +571,16 @@
   17.46                  
   17.47                  for (Res res : nfa.getResults(active)) {
   17.48                      if (identifiers.containsAll(pattern.getIdentifiers().get(res.patternIndex))) {
   17.49 -                        return true;
   17.50 +                        if (!withFrequencies) {
   17.51 +                            patternsAndFrequencies.put(res.pattern, 1);
   17.52 +                            return patternsAndFrequencies;
   17.53 +                        }
   17.54 +                        
   17.55 +                        Integer freqs = patternsAndFrequencies.get(res.pattern);
   17.56 +
   17.57 +                        if (freqs == null) freqs = 0;
   17.58 +
   17.59 +                        patternsAndFrequencies.put(res.pattern, freqs + 1);
   17.60                      }
   17.61                  }
   17.62  
   17.63 @@ -568,7 +588,7 @@
   17.64              }
   17.65          }
   17.66  
   17.67 -        return false;
   17.68 +        return patternsAndFrequencies;
   17.69      }
   17.70  
   17.71      private static final Map<Kind, byte[]> kind2Encoded;
    18.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/refactoring/Bundle.properties	Sat Jan 22 21:51:05 2011 +0100
    18.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/refactoring/Bundle.properties	Fri Feb 18 20:16:26 2011 +0100
    18.3 @@ -69,4 +69,6 @@
    18.4  FindDuplicatesRefactoringPanel.knowPatterns.text=&Known patterns
    18.5  FindDuplicatesRefactoringPanel.examplesButton.text=
    18.6  BTN_Examples=Examples
    18.7 -ExamplesList.jLabel1.text=Examples:
    18.8 +FindDuplicatesRefactoringPanel.recentButton.toolTipText=Recent Rules
    18.9 +FindDuplicatesRefactoringPanel.recentButton.text=
   18.10 +ExamplesList.pattern.contentType=text/x-javahints
    19.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/refactoring/ExamplesList.form	Sat Jan 22 21:51:05 2011 +0100
    19.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/refactoring/ExamplesList.form	Fri Feb 18 20:16:26 2011 +0100
    19.3 @@ -16,9 +16,10 @@
    19.4    <Layout>
    19.5      <DimensionLayout dim="0">
    19.6        <Group type="103" groupAlignment="0" attributes="0">
    19.7 -          <Group type="102" alignment="0" attributes="0">
    19.8 +          <Group type="102" alignment="1" attributes="0">
    19.9                <EmptySpace max="-2" attributes="0"/>
   19.10 -              <Group type="103" groupAlignment="0" attributes="0">
   19.11 +              <Group type="103" groupAlignment="1" attributes="0">
   19.12 +                  <Component id="jScrollPane2" alignment="0" pref="376" max="32767" attributes="0"/>
   19.13                    <Component id="jScrollPane1" alignment="0" pref="376" max="32767" attributes="0"/>
   19.14                    <Component id="jLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
   19.15                </Group>
   19.16 @@ -32,7 +33,9 @@
   19.17                <EmptySpace max="-2" attributes="0"/>
   19.18                <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
   19.19                <EmptySpace max="-2" attributes="0"/>
   19.20 -              <Component id="jScrollPane1" pref="255" max="32767" attributes="0"/>
   19.21 +              <Component id="jScrollPane1" pref="130" max="32767" attributes="0"/>
   19.22 +              <EmptySpace max="-2" attributes="0"/>
   19.23 +              <Component id="jScrollPane2" min="-2" pref="119" max="-2" attributes="0"/>
   19.24                <EmptySpace max="-2" attributes="0"/>
   19.25            </Group>
   19.26        </Group>
   19.27 @@ -41,8 +44,8 @@
   19.28    <SubComponents>
   19.29      <Component class="javax.swing.JLabel" name="jLabel1">
   19.30        <Properties>
   19.31 -        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   19.32 -          <ResourceString bundle="org/netbeans/modules/jackpot30/impl/refactoring/Bundle.properties" key="ExamplesList.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   19.33 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
   19.34 +          <Connection code="convertor.getHeader()" type="code"/>
   19.35          </Property>
   19.36        </Properties>
   19.37      </Component>
   19.38 @@ -67,9 +70,26 @@
   19.39            </Properties>
   19.40            <Events>
   19.41              <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="listMouseClicked"/>
   19.42 +            <EventHandler event="valueChanged" listener="javax.swing.event.ListSelectionListener" parameters="javax.swing.event.ListSelectionEvent" handler="listValueChanged"/>
   19.43            </Events>
   19.44          </Component>
   19.45        </SubComponents>
   19.46      </Container>
   19.47 +    <Container class="javax.swing.JScrollPane" name="jScrollPane2">
   19.48 +      <AuxValues>
   19.49 +        <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
   19.50 +      </AuxValues>
   19.51 +
   19.52 +      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
   19.53 +      <SubComponents>
   19.54 +        <Component class="javax.swing.JEditorPane" name="pattern">
   19.55 +          <Properties>
   19.56 +            <Property name="contentType" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   19.57 +              <ResourceString bundle="org/netbeans/modules/jackpot30/impl/refactoring/Bundle.properties" key="ExamplesList.pattern.contentType" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   19.58 +            </Property>
   19.59 +          </Properties>
   19.60 +        </Component>
   19.61 +      </SubComponents>
   19.62 +    </Container>
   19.63    </SubComponents>
   19.64  </Form>
    20.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/refactoring/ExamplesList.java	Sat Jan 22 21:51:05 2011 +0100
    20.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/refactoring/ExamplesList.java	Fri Feb 18 20:16:26 2011 +0100
    20.3 @@ -43,33 +43,41 @@
    20.4  
    20.5  import java.awt.Component;
    20.6  import java.awt.Dialog;
    20.7 +import java.awt.Rectangle;
    20.8  import java.util.Collections;
    20.9  import java.util.Set;
   20.10  import javax.swing.DefaultListCellRenderer;
   20.11  import javax.swing.DefaultListModel;
   20.12  import javax.swing.JList;
   20.13 -import org.netbeans.modules.jackpot30.impl.examples.Example;
   20.14 +import javax.swing.text.BadLocationException;
   20.15  import org.netbeans.modules.jackpot30.impl.examples.Example.Option;
   20.16 -import org.netbeans.modules.jackpot30.impl.examples.LoadExamples;
   20.17  import org.openide.DialogDescriptor;
   20.18  import org.openide.DialogDisplayer;
   20.19 +import org.openide.util.Exceptions;
   20.20  
   20.21  /**
   20.22   *
   20.23   * @author lahvac
   20.24   */
   20.25 -public class ExamplesList extends javax.swing.JPanel {
   20.26 +public class ExamplesList<T> extends javax.swing.JPanel {
   20.27  
   20.28 -    public ExamplesList(Set<Option> require, Set<Option> forbidden) {
   20.29 +    private final DialogDescription<T> convertor;
   20.30 +    private final Class<T> dataClass;
   20.31 +
   20.32 +    public ExamplesList(Iterable<? extends T> data, DialogDescription<T> convertor, Class<T> dataClass, Set<Option> require, Set<Option> forbidden) {
   20.33 +        this.convertor = convertor;
   20.34 +        this.dataClass = dataClass;
   20.35 +        
   20.36          initComponents();
   20.37  
   20.38          DefaultListModel listModel = new DefaultListModel();
   20.39  
   20.40 -        for (Example e : LoadExamples.loadExamples()) {
   20.41 -            if (!e.getOptions().containsAll(require)) continue;
   20.42 -            if (!Collections.disjoint(e.getOptions(), forbidden)) continue;
   20.43 +        for (T t : data) {
   20.44 +            Set<Option> options = convertor.getOptions(t);
   20.45 +            if (!options.containsAll(require)) continue;
   20.46 +            if (!Collections.disjoint(options, forbidden)) continue;
   20.47              
   20.48 -            listModel.addElement(e);
   20.49 +            listModel.addElement(t);
   20.50          }
   20.51  
   20.52          list.setModel(listModel);
   20.53 @@ -89,8 +97,10 @@
   20.54          jLabel1 = new javax.swing.JLabel();
   20.55          jScrollPane1 = new javax.swing.JScrollPane();
   20.56          list = new javax.swing.JList();
   20.57 +        jScrollPane2 = new javax.swing.JScrollPane();
   20.58 +        pattern = new javax.swing.JEditorPane();
   20.59  
   20.60 -        jLabel1.setText(org.openide.util.NbBundle.getMessage(ExamplesList.class, "ExamplesList.jLabel1.text")); // NOI18N
   20.61 +        jLabel1.setText(convertor.getHeader());
   20.62  
   20.63          list.setModel(new javax.swing.AbstractListModel() {
   20.64              String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
   20.65 @@ -102,17 +112,26 @@
   20.66                  listMouseClicked(evt);
   20.67              }
   20.68          });
   20.69 +        list.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
   20.70 +            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
   20.71 +                listValueChanged(evt);
   20.72 +            }
   20.73 +        });
   20.74          jScrollPane1.setViewportView(list);
   20.75  
   20.76 +        pattern.setContentType(org.openide.util.NbBundle.getMessage(ExamplesList.class, "ExamplesList.pattern.contentType")); // NOI18N
   20.77 +        jScrollPane2.setViewportView(pattern);
   20.78 +
   20.79          javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
   20.80          this.setLayout(layout);
   20.81          layout.setHorizontalGroup(
   20.82              layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
   20.83 -            .addGroup(layout.createSequentialGroup()
   20.84 +            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
   20.85                  .addContainerGap()
   20.86 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
   20.87 -                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE)
   20.88 -                    .addComponent(jLabel1))
   20.89 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
   20.90 +                    .addComponent(jScrollPane2, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE)
   20.91 +                    .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE)
   20.92 +                    .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.LEADING))
   20.93                  .addContainerGap())
   20.94          );
   20.95          layout.setVerticalGroup(
   20.96 @@ -121,7 +140,9 @@
   20.97                  .addContainerGap()
   20.98                  .addComponent(jLabel1)
   20.99                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  20.100 -                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 255, Short.MAX_VALUE)
  20.101 +                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 130, Short.MAX_VALUE)
  20.102 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  20.103 +                .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 119, javax.swing.GroupLayout.PREFERRED_SIZE)
  20.104                  .addContainerGap())
  20.105          );
  20.106      }// </editor-fold>//GEN-END:initComponents
  20.107 @@ -133,10 +154,28 @@
  20.108          }
  20.109      }//GEN-LAST:event_listMouseClicked
  20.110  
  20.111 +    private void listValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_listValueChanged
  20.112 +        T ex = dataClass.cast(list.getSelectedValue());
  20.113 +
  20.114 +        pattern.setText(convertor.getCode(ex));
  20.115 +        
  20.116 +        try {
  20.117 +            Rectangle rect = pattern.modelToView(0);
  20.118 +
  20.119 +            if (rect != null) {
  20.120 +                pattern.scrollRectToVisible(rect);
  20.121 +            }
  20.122 +        } catch (BadLocationException ex1) {
  20.123 +            Exceptions.printStackTrace(ex1);
  20.124 +        }
  20.125 +    }//GEN-LAST:event_listValueChanged
  20.126 +
  20.127      // Variables declaration - do not modify//GEN-BEGIN:variables
  20.128      private javax.swing.JLabel jLabel1;
  20.129      private javax.swing.JScrollPane jScrollPane1;
  20.130 +    private javax.swing.JScrollPane jScrollPane2;
  20.131      private javax.swing.JList list;
  20.132 +    private javax.swing.JEditorPane pattern;
  20.133      // End of variables declaration//GEN-END:variables
  20.134  
  20.135      private DialogDescriptor desc;
  20.136 @@ -147,23 +186,21 @@
  20.137          this.dialog = dialog;
  20.138      }
  20.139  
  20.140 -    public Example getSelectedExample() {
  20.141 -        return (Example) list.getSelectedValue();
  20.142 +    public T getSelectedExample() {
  20.143 +        return dataClass.cast(list.getSelectedValue());
  20.144      }
  20.145      
  20.146 -    private static class ExamplesRenderer extends DefaultListCellRenderer {
  20.147 +    private class ExamplesRenderer extends DefaultListCellRenderer {
  20.148          @Override
  20.149          public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
  20.150 -            if (value instanceof Example) {
  20.151 -                value = ((Example) value).getDisplayName();
  20.152 -            }
  20.153 +            value = convertor.getDisplayName(dataClass.cast(value));
  20.154              return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
  20.155          }
  20.156      }
  20.157  
  20.158 -    public static Example chooseExample(Set<Option> require, Set<Option> forbidden) {
  20.159 -        ExamplesList examples = new ExamplesList(require, forbidden);
  20.160 -        DialogDescriptor dd = new DialogDescriptor(examples, "Choose Example", true, DialogDescriptor.OK_CANCEL_OPTION, DialogDescriptor.OK_OPTION, null);
  20.161 +    public static <T> T chooseExample(Iterable<? extends T> examplesList, DialogDescription<T> convertor, Class<T> dataClass, Set<Option> require, Set<Option> forbidden) {
  20.162 +        ExamplesList<T> examples = new ExamplesList<T>(examplesList, convertor, dataClass, require, forbidden);
  20.163 +        DialogDescriptor dd = new DialogDescriptor(examples, convertor.getCaption(), true, DialogDescriptor.OK_CANCEL_OPTION, DialogDescriptor.OK_OPTION, null);
  20.164          Dialog dialog = DialogDisplayer.getDefault().createDialog(dd);
  20.165  
  20.166          examples.setDialog(dd, dialog);
  20.167 @@ -175,4 +212,12 @@
  20.168  
  20.169          return null;
  20.170      }
  20.171 +
  20.172 +    public interface DialogDescription<T> {
  20.173 +        public String getCaption();
  20.174 +        public String getHeader();
  20.175 +        public String getDisplayName(T t);
  20.176 +        public String getCode(T t);
  20.177 +        public Set<Option> getOptions(T t);
  20.178 +    }
  20.179  }
    21.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/refactoring/FindDuplicatesRefactoringPanel.form	Sat Jan 22 21:51:05 2011 +0100
    21.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/refactoring/FindDuplicatesRefactoringPanel.form	Fri Feb 18 20:16:26 2011 +0100
    21.3 @@ -248,6 +248,24 @@
    21.4                  <Property name="horizontalGap" type="int" value="0"/>
    21.5                </Layout>
    21.6                <SubComponents>
    21.7 +                <Component class="javax.swing.JButton" name="recentButton">
    21.8 +                  <Properties>
    21.9 +                    <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
   21.10 +                      <Image iconType="3" name="/org/netbeans/modules/jackpot30/impl/resources/recent_icon.png"/>
   21.11 +                    </Property>
   21.12 +                    <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   21.13 +                      <ResourceString bundle="org/netbeans/modules/jackpot30/impl/refactoring/Bundle.properties" key="FindDuplicatesRefactoringPanel.recentButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   21.14 +                    </Property>
   21.15 +                    <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   21.16 +                      <ResourceString bundle="org/netbeans/modules/jackpot30/impl/refactoring/Bundle.properties" key="FindDuplicatesRefactoringPanel.recentButton.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   21.17 +                    </Property>
   21.18 +                    <Property name="borderPainted" type="boolean" value="false"/>
   21.19 +                    <Property name="contentAreaFilled" type="boolean" value="false"/>
   21.20 +                  </Properties>
   21.21 +                  <Events>
   21.22 +                    <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="recentButtonActionPerformed"/>
   21.23 +                  </Events>
   21.24 +                </Component>
   21.25                  <Component class="javax.swing.JButton" name="examplesButton">
   21.26                    <Properties>
   21.27                      <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
    22.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/refactoring/FindDuplicatesRefactoringPanel.java	Sat Jan 22 21:51:05 2011 +0100
    22.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/refactoring/FindDuplicatesRefactoringPanel.java	Fri Feb 18 20:16:26 2011 +0100
    22.3 @@ -41,6 +41,7 @@
    22.4  
    22.5  import java.awt.CardLayout;
    22.6  import java.util.Collection;
    22.7 +import java.util.Collections;
    22.8  import java.util.EnumSet;
    22.9  import java.util.HashSet;
   22.10  import java.util.LinkedList;
   22.11 @@ -48,6 +49,8 @@
   22.12  import java.util.Map;
   22.13  import java.util.Set;
   22.14  import java.util.TreeMap;
   22.15 +import java.util.prefs.BackingStoreException;
   22.16 +import java.util.prefs.Preferences;
   22.17  import javax.swing.DefaultListModel;
   22.18  import javax.swing.SwingUtilities;
   22.19  import javax.swing.event.ChangeEvent;
   22.20 @@ -60,7 +63,11 @@
   22.21  import org.netbeans.modules.jackpot30.impl.batch.BatchSearch.Scope;
   22.22  import org.netbeans.modules.jackpot30.impl.examples.Example;
   22.23  import org.netbeans.modules.jackpot30.impl.examples.Example.Option;
   22.24 +import org.netbeans.modules.jackpot30.impl.examples.LoadExamples;
   22.25 +import org.netbeans.modules.jackpot30.impl.refactoring.ExamplesList.DialogDescription;
   22.26  import org.netbeans.modules.jackpot30.spi.HintDescription;
   22.27 +import org.openide.util.Exceptions;
   22.28 +import org.openide.util.NbPreferences;
   22.29  import org.openide.util.Union2;
   22.30  
   22.31  /**
   22.32 @@ -147,6 +154,7 @@
   22.33          jScrollPane1 = new javax.swing.JScrollPane();
   22.34          pattern = new javax.swing.JTextPane();
   22.35          jPanel3 = new javax.swing.JPanel();
   22.36 +        recentButton = new javax.swing.JButton();
   22.37          examplesButton = new javax.swing.JButton();
   22.38          patternTypeSelectionPanel = new javax.swing.JPanel();
   22.39          knowPatterns = new javax.swing.JRadioButton();
   22.40 @@ -299,6 +307,18 @@
   22.41  
   22.42          jPanel3.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.CENTER, 0, 5));
   22.43  
   22.44 +        recentButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/netbeans/modules/jackpot30/impl/resources/recent_icon.png"))); // NOI18N
   22.45 +        org.openide.awt.Mnemonics.setLocalizedText(recentButton, org.openide.util.NbBundle.getMessage(FindDuplicatesRefactoringPanel.class, "FindDuplicatesRefactoringPanel.recentButton.text")); // NOI18N
   22.46 +        recentButton.setToolTipText(org.openide.util.NbBundle.getMessage(FindDuplicatesRefactoringPanel.class, "FindDuplicatesRefactoringPanel.recentButton.toolTipText")); // NOI18N
   22.47 +        recentButton.setBorderPainted(false);
   22.48 +        recentButton.setContentAreaFilled(false);
   22.49 +        recentButton.addActionListener(new java.awt.event.ActionListener() {
   22.50 +            public void actionPerformed(java.awt.event.ActionEvent evt) {
   22.51 +                recentButtonActionPerformed(evt);
   22.52 +            }
   22.53 +        });
   22.54 +        jPanel3.add(recentButton);
   22.55 +
   22.56          examplesButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/netbeans/modules/jackpot30/impl/resources/examples_icon.png"))); // NOI18N
   22.57          org.openide.awt.Mnemonics.setLocalizedText(examplesButton, org.openide.util.NbBundle.getMessage(FindDuplicatesRefactoringPanel.class, "FindDuplicatesRefactoringPanel.examplesButton.text")); // NOI18N
   22.58          examplesButton.setToolTipText(org.openide.util.NbBundle.getMessage(FindDuplicatesRefactoringPanel.class, "BTN_Examples")); // NOI18N
   22.59 @@ -419,13 +439,40 @@
   22.60      }//GEN-LAST:event_knowPatternsActionPerformed
   22.61  
   22.62      private void examplesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_examplesButtonActionPerformed
   22.63 -        Example ex = ExamplesList.chooseExample(query ? EnumSet.noneOf(Option.class) : EnumSet.of(Option.FIX), query ? EnumSet.of(Option.FIX) : EnumSet.noneOf(Option.class));
   22.64 +        Example ex = ExamplesList.chooseExample(LoadExamples.loadExamples(), new ExamplesConvertor(), Example.class, query ? EnumSet.noneOf(Option.class) : EnumSet.of(Option.FIX), query ? EnumSet.of(Option.FIX) : EnumSet.noneOf(Option.class));
   22.65  
   22.66          if (ex != null) {
   22.67              pattern.setText(ex.getCode());
   22.68          }
   22.69      }//GEN-LAST:event_examplesButtonActionPerformed
   22.70  
   22.71 +    private void recentButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_recentButtonActionPerformed
   22.72 +        String cod = ExamplesList.chooseExample(loadRecent(),
   22.73 +                                                new DialogDescription<String>() {
   22.74 +                                                    public String getDisplayName(String t) {
   22.75 +                                                        return t;
   22.76 +                                                    }
   22.77 +                                                    public String getCode(String t) {
   22.78 +                                                        return t;
   22.79 +                                                    }
   22.80 +                                                    public Set<Option> getOptions(String t) {
   22.81 +                                                        return query ? EnumSet.noneOf(Option.class) : EnumSet.of(Option.FIX);
   22.82 +                                                    }
   22.83 +                                                    public String getCaption() {
   22.84 +                                                        return "Recent patterns";
   22.85 +                                                    }
   22.86 +                                                    public String getHeader() {
   22.87 +                                                        return "Patterns:";
   22.88 +                                                    }
   22.89 +                                                },
   22.90 +                                                String.class,
   22.91 +                                                query ? EnumSet.noneOf(Option.class) : EnumSet.of(Option.FIX), query ? EnumSet.of(Option.FIX) : EnumSet.noneOf(Option.class));
   22.92 +
   22.93 +        if (cod != null) {
   22.94 +            pattern.setText(cod);
   22.95 +        }
   22.96 +    }//GEN-LAST:event_recentButtonActionPerformed
   22.97 +
   22.98      private void stateChanged() {
   22.99          if (SwingUtilities.isEventDispatchThread()) {
  22.100              changeListener.stateChanged(new ChangeEvent(this));
  22.101 @@ -508,10 +555,61 @@
  22.102  
  22.103      void fillInFromSettings() {
  22.104          scopesPanel.fillInFromSettings();
  22.105 +
  22.106 +        List<String> recent = loadRecent();
  22.107 +
  22.108 +        if (!recent.isEmpty()) {
  22.109 +            pattern.setText(recent.get(0));
  22.110 +        }
  22.111      }
  22.112  
  22.113      void saveScopesCombo() {
  22.114          scopesPanel.saveScopesCombo();
  22.115 +
  22.116 +        String currentPattern = pattern.getText().trim();
  22.117 +        List<String> recent = loadRecent();
  22.118 +
  22.119 +        recent.remove(currentPattern);
  22.120 +        recent.add(0, currentPattern);
  22.121 +
  22.122 +        while (recent.size() > MAX_RECENT) {
  22.123 +            recent.remove(recent.size() - 1);
  22.124 +        }
  22.125 +
  22.126 +        Preferences prefs = NbPreferences.forModule(FindDuplicatesRefactoringPanel.class);
  22.127 +        Preferences recentPatterns = prefs.node(query ? RECENT_PATTERNS_QUERY : RECENT_PATTERNS_APPLY);
  22.128 +        int i = 0;
  22.129 +
  22.130 +        for (String r : recent) {
  22.131 +            recentPatterns.put("pattern_" + i++, r);
  22.132 +        }
  22.133 +    }
  22.134 +
  22.135 +    private static final int MAX_RECENT = 50;
  22.136 +    private static final String RECENT_PATTERNS_QUERY = "recentPatternsQuery";
  22.137 +    private static final String RECENT_PATTERNS_APPLY = "recentPatternsApply";
  22.138 +
  22.139 +    private List<String> loadRecent() {
  22.140 +        Preferences prefs = NbPreferences.forModule(FindDuplicatesRefactoringPanel.class);
  22.141 +
  22.142 +        if (prefs == null) return Collections.emptyList();
  22.143 +
  22.144 +        List<String> recent = new LinkedList<String>();
  22.145 +        Preferences recentPatterns = prefs.node(query ? RECENT_PATTERNS_QUERY : RECENT_PATTERNS_APPLY);
  22.146 +
  22.147 +        if (recentPatterns != null) {
  22.148 +            try {
  22.149 +                for (String k : recentPatterns.keys()) {
  22.150 +                    if (k.startsWith("pattern_")) {
  22.151 +                        recent.add(recentPatterns.get(k, null));
  22.152 +                    }
  22.153 +                }
  22.154 +            } catch (BackingStoreException ex) {
  22.155 +                Exceptions.printStackTrace(ex);
  22.156 +            }
  22.157 +        }
  22.158 +
  22.159 +        return recent;
  22.160      }
  22.161  
  22.162      // Variables declaration - do not modify//GEN-BEGIN:variables
  22.163 @@ -534,6 +632,7 @@
  22.164      private javax.swing.JTextPane pattern;
  22.165      private javax.swing.JPanel patternSelection;
  22.166      private javax.swing.JPanel patternTypeSelectionPanel;
  22.167 +    private javax.swing.JButton recentButton;
  22.168      private javax.swing.JButton removeAllHints;
  22.169      private javax.swing.JButton removeHint;
  22.170      private org.netbeans.modules.jackpot30.impl.refactoring.ScopesPanel scopesPanel;
  22.171 @@ -543,4 +642,28 @@
  22.172      // End of variables declaration//GEN-END:variables
  22.173  
  22.174      private static final String HINTS_LIST_PROTOTYPE  = "012345678901234567890123456789";
  22.175 +
  22.176 +    private static final class ExamplesConvertor implements DialogDescription<Example> {
  22.177 +
  22.178 +        public String getDisplayName(Example t) {
  22.179 +            return t.getDisplayName();
  22.180 +        }
  22.181 +
  22.182 +        public String getCode(Example t) {
  22.183 +            return t.getCode();
  22.184 +        }
  22.185 +
  22.186 +        public Set<Option> getOptions(Example t) {
  22.187 +            return t.getOptions();
  22.188 +        }
  22.189 +
  22.190 +        public String getCaption() {
  22.191 +            return "Choose Example";
  22.192 +        }
  22.193 +
  22.194 +        public String getHeader() {
  22.195 +            return "Examples:";
  22.196 +        }
  22.197 +
  22.198 +    }
  22.199  }
    23.1 Binary file api/src/org/netbeans/modules/jackpot30/impl/resources/examples_icon.png has changed
    24.1 Binary file api/src/org/netbeans/modules/jackpot30/impl/resources/recent_icon.png has changed
    25.1 --- a/api/src/org/netbeans/modules/jackpot30/spi/JavaFix.java	Sat Jan 22 21:51:05 2011 +0100
    25.2 +++ b/api/src/org/netbeans/modules/jackpot30/spi/JavaFix.java	Fri Feb 18 20:16:26 2011 +0100
    25.3 @@ -41,6 +41,7 @@
    25.4  
    25.5  import com.sun.javadoc.Doc;
    25.6  import com.sun.javadoc.Tag;
    25.7 +import com.sun.source.tree.AnnotationTree;
    25.8  import com.sun.source.tree.AssignmentTree;
    25.9  import com.sun.source.tree.BinaryTree;
   25.10  import com.sun.source.tree.BlockTree;
   25.11 @@ -48,6 +49,7 @@
   25.12  import com.sun.source.tree.CatchTree;
   25.13  import com.sun.source.tree.ClassTree;
   25.14  import com.sun.source.tree.CompoundAssignmentTree;
   25.15 +import com.sun.source.tree.DisjunctiveTypeTree;
   25.16  import com.sun.source.tree.ExpressionStatementTree;
   25.17  import com.sun.source.tree.ExpressionTree;
   25.18  import com.sun.source.tree.LiteralTree;
   25.19 @@ -62,10 +64,13 @@
   25.20  import java.util.regex.Matcher;
   25.21  import com.sun.source.tree.IdentifierTree;
   25.22  import com.sun.source.tree.MemberSelectTree;
   25.23 +import com.sun.source.tree.MethodTree;
   25.24 +import com.sun.source.tree.ModifiersTree;
   25.25  import com.sun.source.tree.Scope;
   25.26  import com.sun.source.tree.StatementTree;
   25.27  import com.sun.source.tree.Tree;
   25.28  import com.sun.source.tree.Tree.Kind;
   25.29 +import com.sun.source.tree.TypeParameterTree;
   25.30  import com.sun.source.util.SourcePositions;
   25.31  import com.sun.source.util.TreePath;
   25.32  import com.sun.source.util.TreePathScanner;
   25.33 @@ -92,6 +97,7 @@
   25.34  import org.netbeans.api.java.source.ClasspathInfo;
   25.35  import org.netbeans.api.java.source.CompilationInfo;
   25.36  import org.netbeans.api.java.source.SourceUtils;
   25.37 +import org.netbeans.api.java.source.TreeMaker;
   25.38  import org.netbeans.api.java.source.TreePathHandle;
   25.39  import org.netbeans.api.java.source.TypeMirrorHandle;
   25.40  import org.netbeans.api.java.source.WorkingCopy;
   25.41 @@ -106,6 +112,7 @@
   25.42  import org.openide.filesystems.FileObject;
   25.43  import org.openide.modules.SpecificationVersion;
   25.44  import org.openide.util.Lookup;
   25.45 +import org.openide.util.NbBundle.Messages;
   25.46  
   25.47  /**
   25.48   *
   25.49 @@ -525,7 +532,17 @@
   25.50                  wc.rewrite(tp.getLeaf(), parsed);
   25.51              }
   25.52  
   25.53 -            new ReplaceParameters(wc, canShowUI, parameters, parametersMulti, parameterNames).scan(new TreePath(tp.getParentPath(), parsed), null);
   25.54 +            //prevent generating QualIdents inside import clauses - might be better to solve that inside ImportAnalysis2,
   25.55 +            //but that seems not to be straightforward:
   25.56 +            boolean inImport = parsed.getKind() == Kind.IMPORT;
   25.57 +            TreePath w = tp.getParentPath();
   25.58 +
   25.59 +            while (!inImport && w != null) {
   25.60 +                inImport |= w.getLeaf().getKind() == Kind.IMPORT;
   25.61 +                w = w.getParentPath();
   25.62 +            }
   25.63 +
   25.64 +            new ReplaceParameters(wc, canShowUI, inImport, parameters, parametersMulti, parameterNames).scan(new TreePath(tp.getParentPath(), parsed), null);
   25.65          }
   25.66      }
   25.67  
   25.68 @@ -535,14 +552,16 @@
   25.69  
   25.70          private final WorkingCopy wc;
   25.71          private final boolean canShowUI;
   25.72 +        private final boolean inImport;
   25.73          private final Map<String, TreePath> parameters;
   25.74          private final Map<String, Collection<TreePath>> parametersMulti;
   25.75          private final Map<String, String> parameterNames;
   25.76  
   25.77 -        public ReplaceParameters(WorkingCopy wc, boolean canShowUI, Map<String, TreePath> parameters, Map<String, Collection<TreePath>> parametersMulti, Map<String, String> parameterNames) {
   25.78 +        public ReplaceParameters(WorkingCopy wc, boolean canShowUI, boolean inImport, Map<String, TreePath> parameters, Map<String, Collection<TreePath>> parametersMulti, Map<String, String> parameterNames) {
   25.79              this.parameters = parameters;
   25.80              this.wc = wc;
   25.81              this.canShowUI = canShowUI;
   25.82 +            this.inImport = inImport;
   25.83              this.parametersMulti = parametersMulti;
   25.84              this.parameterNames = parameterNames;
   25.85          }
   25.86 @@ -589,7 +608,7 @@
   25.87  
   25.88              Element e = wc.getTrees().getElement(getCurrentPath());
   25.89  
   25.90 -            if (e != null && isStaticElement(e)) {
   25.91 +            if (e != null && isStaticElement(e) && !inImport) {
   25.92                  wc.rewrite(node, wc.getTreeMaker().QualIdent(e));
   25.93              }
   25.94  
   25.95 @@ -626,7 +645,7 @@
   25.96              //check correct dependency:
   25.97              checkDependency(wc, e, canShowUI);
   25.98  
   25.99 -            if (isStaticElement(e)) {
  25.100 +            if (isStaticElement(e) && !inImport) {
  25.101                  wc.rewrite(node, wc.getTreeMaker().QualIdent(e));
  25.102  
  25.103                  return null;
  25.104 @@ -1091,5 +1110,167 @@
  25.105              }
  25.106          };
  25.107      }
  25.108 -    
  25.109 +
  25.110 +    @Messages("FIX_RemoveFromParent=Remove {0} from parent")
  25.111 +    public static Fix removeFromParent(HintContext ctx, TreePath what) {
  25.112 +        return removeFromParent(ctx, Bundle.FIX_RemoveFromParent(/*TODO: better short name:*/what.getLeaf().toString()), what);
  25.113 +    }
  25.114 +
  25.115 +    public static Fix removeFromParent(HintContext ctx, String displayName, TreePath what) {
  25.116 +        return toEditorFix(new RemoveFromParent(displayName, ctx.getInfo(), what));
  25.117 +    }
  25.118 +
  25.119 +    private static final class RemoveFromParent extends JavaFix {
  25.120 +
  25.121 +        private final String displayName;
  25.122 +
  25.123 +        public RemoveFromParent(String displayName, CompilationInfo info, TreePath toRemove) {
  25.124 +            super(info, toRemove);
  25.125 +            this.displayName = displayName;
  25.126 +        }
  25.127 +
  25.128 +        @Override
  25.129 +        protected String getText() {
  25.130 +            return displayName;
  25.131 +        }
  25.132 +
  25.133 +        @Override
  25.134 +        protected void performRewrite(WorkingCopy wc, TreePath tp, boolean canShowUI) {
  25.135 +            TreeMaker make = wc.getTreeMaker();
  25.136 +            Tree leaf = tp.getLeaf();
  25.137 +            Tree parentLeaf = tp.getParentPath().getLeaf();
  25.138 +
  25.139 +            switch (parentLeaf.getKind()) {
  25.140 +                case ANNOTATION:
  25.141 +                    AnnotationTree at = (AnnotationTree) parentLeaf;
  25.142 +                    AnnotationTree newAnnot;
  25.143 +
  25.144 +                    newAnnot = make.removeAnnotationAttrValue(at, (ExpressionTree) leaf);
  25.145 +
  25.146 +                    wc.rewrite(at, newAnnot);
  25.147 +                    break;
  25.148 +                case BLOCK:
  25.149 +                    BlockTree bt = (BlockTree) parentLeaf;
  25.150 +
  25.151 +                    wc.rewrite(bt, make.removeBlockStatement(bt, (StatementTree) leaf));
  25.152 +                    break;
  25.153 +                case CASE:
  25.154 +                    CaseTree caseTree = (CaseTree) parentLeaf;
  25.155 +                    
  25.156 +                    wc.rewrite(caseTree, make.removeCaseStatement(caseTree, (StatementTree) leaf));
  25.157 +                    break;
  25.158 +                case CLASS:
  25.159 +                    ClassTree classTree = (ClassTree) parentLeaf;
  25.160 +                    ClassTree nueClassTree;
  25.161 +
  25.162 +                    if (classTree.getTypeParameters().contains(leaf)) {
  25.163 +                        nueClassTree = make.removeClassTypeParameter(classTree, (TypeParameterTree) leaf);
  25.164 +                    } else if (classTree.getExtendsClause() == leaf) {
  25.165 +                        nueClassTree = make.Class(classTree.getModifiers(), classTree.getSimpleName(), classTree.getTypeParameters(), null, classTree.getImplementsClause(), classTree.getMembers());
  25.166 +                    } else if (classTree.getImplementsClause().contains(leaf)) {
  25.167 +                        nueClassTree = make.removeClassImplementsClause(classTree, leaf);
  25.168 +                    } else if (classTree.getMembers().contains(leaf)) {
  25.169 +                        nueClassTree = make.removeClassMember(classTree, leaf);
  25.170 +                    } else {
  25.171 +                        throw new UnsupportedOperationException();
  25.172 +                    }
  25.173 +
  25.174 +                    wc.rewrite(classTree, nueClassTree);
  25.175 +                    break;
  25.176 +                case DISJUNCTIVE_TYPE:
  25.177 +                    DisjunctiveTypeTree disjunct = (DisjunctiveTypeTree) parentLeaf;
  25.178 +                    List<? extends Tree> alternatives = new LinkedList<Tree>(disjunct.getTypeAlternatives());
  25.179 +
  25.180 +                    alternatives.remove(leaf);
  25.181 +
  25.182 +                    wc.rewrite(disjunct, make.DisjunctiveType(alternatives));
  25.183 +                    break;
  25.184 +                case METHOD:
  25.185 +                    MethodTree mTree = (MethodTree) parentLeaf;
  25.186 +                    MethodTree newMethod;
  25.187 +
  25.188 +                    if (mTree.getTypeParameters().contains(leaf)) {
  25.189 +                        newMethod = make.removeMethodTypeParameter(mTree, (TypeParameterTree) leaf);
  25.190 +                    } else if (mTree.getParameters().contains(leaf)) {
  25.191 +                        newMethod = make.removeMethodParameter(mTree, (VariableTree) leaf);
  25.192 +                    } else if (mTree.getThrows().contains(leaf)) {
  25.193 +                        newMethod = make.removeMethodThrows(mTree, (ExpressionTree) leaf);
  25.194 +                    } else {
  25.195 +                        throw new UnsupportedOperationException();
  25.196 +                    }
  25.197 +
  25.198 +                    wc.rewrite(mTree, newMethod);
  25.199 +                    break;
  25.200 +                case METHOD_INVOCATION:
  25.201 +                    MethodInvocationTree iTree = (MethodInvocationTree) parentLeaf;
  25.202 +                    MethodInvocationTree newInvocation;
  25.203 +
  25.204 +                    if (iTree.getTypeArguments().contains(leaf)) {
  25.205 +                        newInvocation = make.removeMethodInvocationTypeArgument(iTree, (ExpressionTree) leaf);
  25.206 +                    } else if (iTree.getArguments().contains(leaf)) {
  25.207 +                        newInvocation = make.removeMethodInvocationArgument(iTree, (ExpressionTree) leaf);
  25.208 +                    } else {
  25.209 +                        throw new UnsupportedOperationException();
  25.210 +                    }
  25.211 +
  25.212 +                    wc.rewrite(iTree, newInvocation);
  25.213 +                    break;
  25.214 +                case MODIFIERS:
  25.215 +                    ModifiersTree modsTree = (ModifiersTree) parentLeaf;
  25.216 +
  25.217 +                    wc.rewrite(modsTree, make.removeModifiersAnnotation(modsTree, (AnnotationTree) leaf));
  25.218 +                    break;
  25.219 +                case NEW_CLASS:
  25.220 +                    NewClassTree newCTree = (NewClassTree) parentLeaf;
  25.221 +                    NewClassTree newNCT;
  25.222 +
  25.223 +                    if (newCTree.getTypeArguments().contains(leaf)) {
  25.224 +                        newNCT = make.removeNewClassTypeArgument(newCTree, (ExpressionTree) leaf);
  25.225 +                    } else if (newCTree.getArguments().contains(leaf)) {
  25.226 +                        newNCT = make.removeNewClassArgument(newCTree, (ExpressionTree) leaf);
  25.227 +                    } else {
  25.228 +                        throw new UnsupportedOperationException();
  25.229 +                    }
  25.230 +
  25.231 +                    wc.rewrite(newCTree, newNCT);
  25.232 +                    break;
  25.233 +                case PARAMETERIZED_TYPE:
  25.234 +                    ParameterizedTypeTree parTree = (ParameterizedTypeTree) parentLeaf;
  25.235 +
  25.236 +                    wc.rewrite(parTree, make.removeParameterizedTypeTypeArgument(parTree, (ExpressionTree) leaf));
  25.237 +                    break;
  25.238 +                case SWITCH:
  25.239 +                    SwitchTree switchTree = (SwitchTree) parentLeaf;
  25.240 +                    SwitchTree newSwitch;
  25.241 +
  25.242 +                    if (switchTree.getCases().contains(leaf)) {
  25.243 +                        newSwitch = make.removeSwitchCase(switchTree, (CaseTree) leaf);
  25.244 +                    } else {
  25.245 +                        throw new UnsupportedOperationException();
  25.246 +                    }
  25.247 +
  25.248 +                    wc.rewrite(switchTree, newSwitch);
  25.249 +                    break;
  25.250 +                case TRY:
  25.251 +                    TryTree tryTree = (TryTree) parentLeaf;
  25.252 +                    TryTree newTry;
  25.253 +
  25.254 +                    if (tryTree.getResources().contains(leaf)) {
  25.255 +                        LinkedList<Tree> resources = new LinkedList<Tree>(tryTree.getResources());
  25.256 +
  25.257 +                        resources.remove(leaf);
  25.258 +
  25.259 +                        newTry = make.Try(resources, tryTree.getBlock(), tryTree.getCatches(), tryTree.getFinallyBlock());
  25.260 +                    } else if (tryTree.getCatches().contains(leaf)) {
  25.261 +                        newTry = make.removeTryCatch(tryTree, (CatchTree) leaf);
  25.262 +                    } else {
  25.263 +                        throw new UnsupportedOperationException();
  25.264 +                    }
  25.265 +
  25.266 +                    wc.rewrite(tryTree, newTry);
  25.267 +                    break;
  25.268 +            }
  25.269 +        }
  25.270 +
  25.271 +    }
  25.272  }
    26.1 --- a/api/test/unit/src/org/netbeans/modules/jackpot30/impl/UtilitiesTest.java	Sat Jan 22 21:51:05 2011 +0100
    26.2 +++ b/api/test/unit/src/org/netbeans/modules/jackpot30/impl/UtilitiesTest.java	Fri Feb 18 20:16:26 2011 +0100
    26.3 @@ -222,6 +222,42 @@
    26.4          String golden = "$1.isDirectory()";
    26.5          assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " "));
    26.6      }
    26.7 +    
    26.8 +    public void testARMResourceVariable1() throws Exception {
    26.9 +        prepareTest("test/Test.java", "package test; public class Test{}");
   26.10 +
   26.11 +        Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
   26.12 +        Tree result = Utilities.parseAndAttribute(info, "try ($t$) { $stmts$; } catch $catches$", s);
   26.13 +
   26.14 +        assertTrue(result.getKind().name(), result.getKind() == Kind.TRY);
   26.15 +
   26.16 +        String golden = "try ($t$) { $stmts$; }$catches$";
   26.17 +        assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " "));
   26.18 +    }
   26.19 +    
   26.20 +    public void testARMResourceVariable2() throws Exception {
   26.21 +        prepareTest("test/Test.java", "package test; public class Test{}");
   26.22 +
   26.23 +        Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
   26.24 +        Tree result = Utilities.parseAndAttribute(info, "try ($t$; $type $name = $init) { $stmts$; } catch $catches$", s);
   26.25 +
   26.26 +        assertTrue(result.getKind().name(), result.getKind() == Kind.TRY);
   26.27 +
   26.28 +        String golden = "try ($t$ final $type $name = $init;) { $stmts$; }$catches$";
   26.29 +        assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " "));
   26.30 +    }
   26.31 +    
   26.32 +    public void testARMResourceNotVariable() throws Exception {
   26.33 +        prepareTest("test/Test.java", "package test; public class Test{}");
   26.34 +
   26.35 +        Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
   26.36 +        Tree result = Utilities.parseAndAttribute(info, "try ($t $n = $init$) { $stmts$; } catch $catches$", s);
   26.37 +
   26.38 +        assertTrue(result.getKind().name(), result.getKind() == Kind.TRY);
   26.39 +
   26.40 +        String golden = "try (final $t $n = $init$;) { $stmts$; }$catches$";
   26.41 +        assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " "));
   26.42 +    }
   26.43  
   26.44      public void testParseAndAttributeType() throws Exception {
   26.45          prepareTest("test/Test.java", "package test; public class Test{}");
    27.1 --- a/api/test/unit/src/org/netbeans/modules/jackpot30/impl/batch/BatchSearchTest.java	Sat Jan 22 21:51:05 2011 +0100
    27.2 +++ b/api/test/unit/src/org/netbeans/modules/jackpot30/impl/batch/BatchSearchTest.java	Fri Feb 18 20:16:26 2011 +0100
    27.3 @@ -39,6 +39,8 @@
    27.4  
    27.5  package org.netbeans.modules.jackpot30.impl.batch;
    27.6  
    27.7 +import org.netbeans.modules.jackpot30.impl.indexing.CustomIndexerImpl;
    27.8 +import org.netbeans.api.java.source.SourceUtils;
    27.9  import java.net.URLStreamHandlerFactory;
   27.10  import junit.framework.Assert;
   27.11  import java.io.ByteArrayInputStream;
   27.12 @@ -90,6 +92,7 @@
   27.13  
   27.14  import org.openide.util.Exceptions;
   27.15  import org.openide.util.lookup.ServiceProvider;
   27.16 +import static org.netbeans.modules.jackpot30.impl.indexing.IndexingTestUtils.writeFiles;
   27.17  import static org.netbeans.modules.jackpot30.impl.indexing.IndexingTestUtils.writeFilesAndWaitForScan;
   27.18  
   27.19  /**
   27.20 @@ -215,7 +218,7 @@
   27.21          assertEquals(golden, output);
   27.22  
   27.23          //check verification:
   27.24 -        Map<String, Map<String, Iterable<String>>> verifiedOutput = verifiedSpans(result);
   27.25 +        Map<String, Map<String, Iterable<String>>> verifiedOutput = verifiedSpans(result, false);
   27.26          Map<String, Map<String, Iterable<String>>> verifiedGolden = new HashMap<String, Map<String, Iterable<String>>>();
   27.27  
   27.28          verifiedGolden.put(src1.getURL().toExternalForm(), Collections.<String, Iterable<String>>singletonMap("test/Test1.java", Arrays.<String>asList()));
   27.29 @@ -275,7 +278,7 @@
   27.30          });
   27.31  
   27.32  //        verifiedGolden.put(data.getURL().toExternalForm(), Arrays.asList("0:75-0:86:verifier:TODO: No display name"));
   27.33 -        Map<String, Map<String, Iterable<String>>> verifiedOutput = verifiedSpans(result);
   27.34 +        Map<String, Map<String, Iterable<String>>> verifiedOutput = verifiedSpans(result, false);
   27.35          Map<String, Map<String, Iterable<String>>> verifiedGolden = new HashMap<String, Map<String, Iterable<String>>>();
   27.36  
   27.37          Map<String, Iterable<String>> verifiedGoldenPart = new HashMap<String, Iterable<String>>();
   27.38 @@ -367,6 +370,88 @@
   27.39          assertEquals(golden, output);
   27.40      }
   27.41  
   27.42 +    public void testEfficientIndexQuery() throws Exception {
   27.43 +        String orig = System.getProperty(CustomIndexerImpl.class.getName() + "-attributed", "false");
   27.44 +
   27.45 +        try {
   27.46 +            System.setProperty(CustomIndexerImpl.class.getName() + "-attributed", "true");
   27.47 +            FileObject data = FileUtil.createFolder(workdir, "data");
   27.48 +            FileObject extrasrc = FileUtil.createFolder(data, "extrasrc");
   27.49 +            writeFilesAndWaitForScan(extrasrc,
   27.50 +                                     new File("test/Test1.java", "package test; public class Test1 { private void test() { java.io.File f = null; f.isDirectory(); } }"),
   27.51 +                                     new File("test/Test2.java", "package test; public class Test2 { private boolean isDirectory() { return this.isDirectory(); } }"));
   27.52 +
   27.53 +            ClassPath extraCP = ClassPathSupport.createClassPath(extrasrc);
   27.54 +
   27.55 +            GlobalPathRegistry.getDefault().register(ClassPath.SOURCE, new ClassPath[] {extraCP});
   27.56 +
   27.57 +            SourceUtils.waitScanFinished();
   27.58 +
   27.59 +            GlobalPathRegistry.getDefault().unregister(ClassPath.SOURCE, new ClassPath[] {extraCP});
   27.60 +
   27.61 +            //delete the source files, to verify that the index and just the index is used the get the results:
   27.62 +            extrasrc.getFileObject("test/Test1.java").delete();
   27.63 +            extrasrc.getFileObject("test/Test2.java").delete();
   27.64 +
   27.65 +            Iterable<? extends HintDescription> hints = PatternConvertor.create("$1.isDirectory();;");
   27.66 +            Map<String, Iterable<String>> golden = new HashMap<String, Iterable<String>>();
   27.67 +
   27.68 +            golden.put(extrasrc.getURL().toExternalForm(), new HashSet<String>(Arrays.asList("test/Test1.java", "test/Test2.java")));
   27.69 +
   27.70 +            BatchResult result = BatchSearch.findOccurrences(hints, Scope.createGivenSourceRoots(true, extrasrc));
   27.71 +            Map<String, Iterable<String>> output = toDebugOutput(result);
   27.72 +
   27.73 +            assertEquals(golden, output);
   27.74 +
   27.75 +            Iterable<? extends HintDescription> hints2 = PatternConvertor.create("$1.isDirectory() :: $1 instanceof java.io.File;;");
   27.76 +            Map<String, Iterable<String>> golden2 = new HashMap<String, Iterable<String>>();
   27.77 +
   27.78 +            golden2.put(extrasrc.getURL().toExternalForm(), new HashSet<String>(Arrays.asList("test/Test1.java")));
   27.79 +
   27.80 +            BatchResult result2 = BatchSearch.findOccurrences(hints2, Scope.createGivenSourceRoots(true, extrasrc));
   27.81 +            Map<String, Iterable<String>> output2 = toDebugOutput(result2);
   27.82 +
   27.83 +            assertEquals(golden2, output2);
   27.84 +
   27.85 +            //add the content back, so that the spans can be verified:
   27.86 +            writeFiles(extrasrc,
   27.87 +                       new File("test/Test1.java", "package test; public class Test1 { private void test() { java.io.File f = null; f.isDirectory(); } }"),
   27.88 +                       new File("test/Test2.java", "package test; public class Test2 { private boolean isDirectory() { return this.isDirectory(); } }"));
   27.89 +
   27.90 +            //check verification:
   27.91 +            final Set<FileObject> added = new HashSet<FileObject>();
   27.92 +            final Set<FileObject> removed = new HashSet<FileObject>();
   27.93 +
   27.94 +            GlobalPathRegistry.getDefault().addGlobalPathRegistryListener(new GlobalPathRegistryListener() {
   27.95 +                public void pathsAdded(GlobalPathRegistryEvent event) {
   27.96 +                    for (ClassPath cp : event.getChangedPaths()) {
   27.97 +                        added.addAll(Arrays.asList(cp.getRoots()));
   27.98 +                    }
   27.99 +                }
  27.100 +                public void pathsRemoved(GlobalPathRegistryEvent event) {
  27.101 +                    for (ClassPath cp : event.getChangedPaths()) {
  27.102 +                        removed.addAll(Arrays.asList(cp.getRoots()));
  27.103 +                    }
  27.104 +                }
  27.105 +            });
  27.106 +
  27.107 +            Map<String, Map<String, Iterable<String>>> verifiedOutput = verifiedSpans(result2, true);
  27.108 +            Map<String, Map<String, Iterable<String>>> verifiedGolden = new HashMap<String, Map<String, Iterable<String>>>();
  27.109 +
  27.110 +            Map<String, Iterable<String>> verifiedGoldenPart = new HashMap<String, Iterable<String>>();
  27.111 +
  27.112 +            verifiedGoldenPart.put("test/Test1.java", Arrays.<String>asList("0:82-0:93:verifier:TODO: No display name"));
  27.113 +
  27.114 +            verifiedGolden.put(extrasrc.getURL().toExternalForm(), verifiedGoldenPart);
  27.115 +
  27.116 +            assertEquals(verifiedGolden, verifiedOutput);
  27.117 +            assertEquals(Collections.emptySet(), added);
  27.118 +            assertEquals(Collections.emptySet(), removed);
  27.119 +        } finally {
  27.120 +            System.setProperty(CustomIndexerImpl.class.getName() + "-attributed", orig);
  27.121 +        }
  27.122 +    }
  27.123 +
  27.124      public void testScopeDeSerialization() throws Exception {
  27.125          serializeDeserialize(Scope.createAllOpenedProjectsScope());
  27.126          serializeDeserialize(Scope.createGivenFolderLocalIndex(new java.io.File("/tmp/src").getAbsolutePath(), new java.io.File("/tmp/index"), true));
  27.127 @@ -424,7 +509,7 @@
  27.128          return output;
  27.129      }
  27.130  
  27.131 -    private Map<String, Map<String, Iterable<String>>> verifiedSpans(BatchResult candidates) throws Exception {
  27.132 +    private Map<String, Map<String, Iterable<String>>> verifiedSpans(BatchResult candidates, boolean doNotRegisterClassPath) throws Exception {
  27.133          final Map<String, Map<String, Iterable<String>>> result = new HashMap<String, Map<String, Iterable<String>>>();
  27.134          List<MessageImpl> errors = new LinkedList<MessageImpl>();
  27.135          BatchSearch.getVerifiedSpans(candidates, new ProgressHandleWrapper(1), new BatchSearch.VerifiedSpansCallBack() {
  27.136 @@ -450,7 +535,7 @@
  27.137              public void cannotVerifySpan(Resource r) {
  27.138                  fail("Cannot verify: " +r.getRelativePath());
  27.139              }
  27.140 -        }, errors);
  27.141 +        }, doNotRegisterClassPath, errors);
  27.142  
  27.143          return result;
  27.144      }
    28.1 --- a/api/test/unit/src/org/netbeans/modules/jackpot30/impl/duplicates/ComputeDuplicatesTest.java	Sat Jan 22 21:51:05 2011 +0100
    28.2 +++ b/api/test/unit/src/org/netbeans/modules/jackpot30/impl/duplicates/ComputeDuplicatesTest.java	Fri Feb 18 20:16:26 2011 +0100
    28.3 @@ -42,6 +42,7 @@
    28.4  import org.netbeans.api.progress.ProgressHandle;
    28.5  import org.openide.filesystems.FileObject;
    28.6  import java.util.HashMap;
    28.7 +import java.util.LinkedList;
    28.8  import java.util.Map;
    28.9  import java.util.concurrent.atomic.AtomicBoolean;
   28.10  import org.netbeans.api.java.source.TestUtilities;
   28.11 @@ -51,6 +52,7 @@
   28.12  import org.netbeans.modules.jackpot30.impl.indexing.IndexTestBase;
   28.13  import org.netbeans.modules.jackpot30.impl.indexing.IndexingTestUtils.File;
   28.14  import org.openide.filesystems.FileUtil;
   28.15 +import org.openide.util.NbCollections;
   28.16  import static org.junit.Assert.*;
   28.17  
   28.18  import static org.netbeans.modules.jackpot30.impl.indexing.IndexingTestUtils.writeFilesAndWaitForScan;
   28.19 @@ -101,7 +103,7 @@
   28.20  
   28.21          handle.start();
   28.22          
   28.23 -        for (DuplicateDescription dd : new ComputeDuplicates().computeDuplicatesForAllOpenedProjects(handle, new AtomicBoolean())) {
   28.24 +        for (DuplicateDescription dd : NbCollections.iterable(new ComputeDuplicates().computeDuplicatesForAllOpenedProjects(handle, new AtomicBoolean()))) {
   28.25              for (Span s : dd.dupes) {
   28.26                  duplicatesReal.put(relativePath(s.file), TestUtilities.copyFileToString(FileUtil.toFile(s.file)).substring(s.startOff, s.endOff));
   28.27              }
    29.1 --- a/api/test/unit/src/org/netbeans/modules/jackpot30/impl/indexing/IndexTest.java	Sat Jan 22 21:51:05 2011 +0100
    29.2 +++ b/api/test/unit/src/org/netbeans/modules/jackpot30/impl/indexing/IndexTest.java	Fri Feb 18 20:16:26 2011 +0100
    29.3 @@ -39,10 +39,12 @@
    29.4  
    29.5  package org.netbeans.modules.jackpot30.impl.indexing;
    29.6  
    29.7 +import java.util.Map;
    29.8  import org.netbeans.modules.jackpot30.impl.Utilities;
    29.9  import java.util.Collections;
   29.10  import java.net.URL;
   29.11  import java.util.Arrays;
   29.12 +import java.util.HashMap;
   29.13  import java.util.HashSet;
   29.14  import java.util.Set;
   29.15  import org.netbeans.api.java.classpath.ClassPath;
   29.16 @@ -149,6 +151,33 @@
   29.17          verifyIndex("$1.length()", new AdditionalQueryConstraints(Collections.singleton("java.lang.CharSequence")), "test/Test1.java");
   29.18      }
   29.19  
   29.20 +    public void testFrequencies() throws Exception {
   29.21 +        writeFilesAndWaitForScan(src,
   29.22 +                                 new File("test/Test1.java", "package test; public class Test1 { private void test() { java.io.File f = null; f.isDirectory(); f.isDirectory(); } }"),
   29.23 +                                 new File("test/Test2.java", "package test; public class Test2 { private void test() { new javax.swing.ImageIcon(null); java.io.File f = null; f.isDirectory(); } }"),
   29.24 +                                 new File("test/Test3.java", "package test; public class Test3 { private void test() { new javax.swing.ImageIcon(null); new javax.swing.ImageIcon(null); } }")
   29.25 +                                );
   29.26 +
   29.27 +        String[] patterns = new String[] {
   29.28 +            "$1.isDirectory()",
   29.29 +            "new ImageIcon($1)"
   29.30 +        };
   29.31 +
   29.32 +        Map<String, Map<String, Integer>> golden = new HashMap<String, Map<String, Integer>>();
   29.33 +        
   29.34 +        golden.put("test/Test3.java", Collections.singletonMap("new ImageIcon($1)", 2));
   29.35 +        golden.put("test/Test1.java", Collections.singletonMap("$1.isDirectory()", 2));
   29.36 +        
   29.37 +        Map<String, Integer> freqsTest2 = new HashMap<String, Integer>();
   29.38 +        
   29.39 +        freqsTest2.put("$1.isDirectory()", 1);
   29.40 +        freqsTest2.put("new ImageIcon($1)", 1);
   29.41 +        
   29.42 +        golden.put("test/Test2.java", freqsTest2);
   29.43 +        
   29.44 +        verifyIndexWithFrequencies(patterns, golden);
   29.45 +    }
   29.46 +
   29.47      private void verifyIndex(final String[] patterns, String... containedIn) throws Exception {
   29.48          ClassPath EMPTY = ClassPathSupport.createClassPath(new FileObject[0]);
   29.49          ClasspathInfo cpInfo = ClasspathInfo.create(ClassPathSupport.createClassPath(SourceUtilsTestUtil.getBootClassPath().toArray(new URL[0])),
   29.50 @@ -191,4 +220,21 @@
   29.51          assertEquals(golden, real);
   29.52      }
   29.53  
   29.54 +    private void verifyIndexWithFrequencies(final String[] patterns, Map<String, Map<String, Integer>> golden) throws Exception {
   29.55 +        ClassPath EMPTY = ClassPathSupport.createClassPath(new FileObject[0]);
   29.56 +        ClasspathInfo cpInfo = ClasspathInfo.create(ClassPathSupport.createClassPath(SourceUtilsTestUtil.getBootClassPath().toArray(new URL[0])),
   29.57 +                                                    EMPTY,
   29.58 +                                                    EMPTY);
   29.59 +
   29.60 +        final Map<String, Map<String, Integer>> real = new HashMap<String, Map<String, Integer>>();
   29.61 +
   29.62 +        JavaSource.create(cpInfo).runUserActionTask(new Task<CompilationController>() {
   29.63 +            public void run(CompilationController parameter) throws Exception {
   29.64 +                real.putAll(FileBasedIndex.get(src.getURL()).findCandidatesWithFrequencies(BulkSearch.getDefault().create(parameter, patterns)));
   29.65 +            }
   29.66 +        }, true);
   29.67 +
   29.68 +        assertEquals(golden, real);
   29.69 +    }
   29.70 +
   29.71  }
   29.72 \ No newline at end of file
    30.1 --- a/api/test/unit/src/org/netbeans/modules/jackpot30/impl/indexing/IndexingTestUtils.java	Sat Jan 22 21:51:05 2011 +0100
    30.2 +++ b/api/test/unit/src/org/netbeans/modules/jackpot30/impl/indexing/IndexingTestUtils.java	Fri Feb 18 20:16:26 2011 +0100
    30.3 @@ -72,7 +72,7 @@
    30.4  
    30.5  public class IndexingTestUtils {
    30.6      
    30.7 -    public static void writeFilesAndWaitForScan(FileObject sourceRoot, File... files) throws Exception {
    30.8 +    public static void writeFiles(FileObject sourceRoot, File... files) throws Exception {
    30.9          for (FileObject c : sourceRoot.getChildren()) {
   30.10              c.delete();
   30.11          }
   30.12 @@ -81,7 +81,10 @@
   30.13              FileObject fo = FileUtil.createData(sourceRoot, f.filename);
   30.14              TestUtilities.copyStringToFile(fo, f.content);
   30.15          }
   30.16 +    }
   30.17  
   30.18 +    public static void writeFilesAndWaitForScan(FileObject sourceRoot, File... files) throws Exception {
   30.19 +        writeFiles(sourceRoot, files);
   30.20          SourceUtils.waitScanFinished();
   30.21      }
   30.22  
    31.1 --- a/api/test/unit/src/org/netbeans/modules/jackpot30/impl/pm/BulkSearchTestPerformer.java	Sat Jan 22 21:51:05 2011 +0100
    31.2 +++ b/api/test/unit/src/org/netbeans/modules/jackpot30/impl/pm/BulkSearchTestPerformer.java	Fri Feb 18 20:16:26 2011 +0100
    31.3 @@ -505,6 +505,25 @@
    31.4          assertTrue(matches);
    31.5      }
    31.6  
    31.7 +    public void testFrequencies() throws Exception {
    31.8 +        String text = "package test; public class Test { public void test1(boolean b) { java.io.File f = null; f.isDirectory(); f.isDirectory(); new javax.swing.ImageIcon(null); } }";
    31.9 +
   31.10 +        prepareTest("test/Test.java", text);
   31.11 +
   31.12 +        ByteArrayOutputStream out = new ByteArrayOutputStream();
   31.13 +        EncodingContext ec = new EncodingContext(out, false);
   31.14 +
   31.15 +        createSearch().encode(info.getCompilationUnit(), ec);
   31.16 +        
   31.17 +        Map<String, Integer> actual = createSearch().matchesWithFrequencies(new ByteArrayInputStream(out.toByteArray()), createSearch().create(info, "$1.isDirectory()", "new ImageIcon($1)"));
   31.18 +        Map<String, Integer> golden = new HashMap<String, Integer>();
   31.19 +
   31.20 +        golden.put("$1.isDirectory()", 2);
   31.21 +        golden.put("new ImageIcon($1)", 1);
   31.22 +
   31.23 +        assertEquals(golden, actual);
   31.24 +    }
   31.25 +
   31.26      public void testPatternEncodingAndIdentifiers() throws Exception {
   31.27          String text = "package test; public class Test { }";
   31.28  
    32.1 --- a/api/test/unit/src/org/netbeans/modules/jackpot30/impl/pm/CopyFinderBasedBulkSearchTest.java	Sat Jan 22 21:51:05 2011 +0100
    32.2 +++ b/api/test/unit/src/org/netbeans/modules/jackpot30/impl/pm/CopyFinderBasedBulkSearchTest.java	Fri Feb 18 20:16:26 2011 +0100
    32.3 @@ -65,6 +65,11 @@
    32.4      }
    32.5  
    32.6      @Override
    32.7 +    public void testFrequencies() throws Exception {
    32.8 +        //XXX: serialization is a prerequisite
    32.9 +    }
   32.10 +
   32.11 +    @Override
   32.12      public void testPatternEncodingAndIdentifiers() throws Exception {
   32.13          //XXX
   32.14      }
    33.1 --- a/api/test/unit/src/org/netbeans/modules/jackpot30/impl/pm/CopyFinderTest.java	Sat Jan 22 21:51:05 2011 +0100
    33.2 +++ b/api/test/unit/src/org/netbeans/modules/jackpot30/impl/pm/CopyFinderTest.java	Fri Feb 18 20:16:26 2011 +0100
    33.3 @@ -265,4 +265,47 @@
    33.4          performTest("package test; import java.util.*; public class Test { public void test() { |List<? super String>| l1; |List<? super String>| l2;} }");
    33.5      }
    33.6  
    33.7 +    public void testSingleVariableStrict() throws Exception {
    33.8 +        performVariablesTest("package test; public class Test { public void test() { if (true) System.err.println(1); } }",
    33.9 +                             "if ($c) $then; else $else;",
   33.10 +                             new Pair[0],
   33.11 +                             new Pair[0],
   33.12 +                             new Pair[0],
   33.13 +                             true,
   33.14 +                             true);
   33.15 +    }
   33.16 +
   33.17 +    public void testMultiVariableZeroOrOne1() throws Exception {
   33.18 +        performVariablesTest("package test; public class Test { public void test() { if (true) System.err.println(1); } }",
   33.19 +                             "if ($c) $then; else $else$;",
   33.20 +                             new Pair[] {new Pair<String, int[]>("$c", new int[] {59, 63}),
   33.21 +                                         new Pair<String, int[]>("$then", new int[] {65, 87})},
   33.22 +                             new Pair[0],
   33.23 +                             new Pair[0],
   33.24 +                             false,
   33.25 +                             true);
   33.26 +    }
   33.27 +
   33.28 +    public void testMultiVariableZeroOrOne2() throws Exception {
   33.29 +        performVariablesTest("package test; public class Test { public void test() { if (true) System.err.println(1); else System.err.println(2); } }",
   33.30 +                             "if ($c) $then; else $else$;",
   33.31 +                             new Pair[] {new Pair<String, int[]>("$c", new int[] {59, 63}),
   33.32 +                                         new Pair<String, int[]>("$then", new int[] {65, 87}),
   33.33 +                                         new Pair<String, int[]>("$else$", new int[] {93, 115})},
   33.34 +                             new Pair[0],
   33.35 +                             new Pair[0],
   33.36 +                             false,
   33.37 +                             true);
   33.38 +    }
   33.39 +
   33.40 +    public void testNonResolvableType() throws Exception {
   33.41 +        performVariablesTest("package test; public class Test { { java.io.File f = null; boolean b = f.isDirectory(); } }",
   33.42 +                             "$1{can.not.Resolve}.$m($args$)",
   33.43 +                             new Pair[0],
   33.44 +                             new Pair[0],
   33.45 +                             new Pair[0],
   33.46 +                             true,
   33.47 +                             true);
   33.48 +    }
   33.49 +
   33.50  }
    34.1 --- a/api/test/unit/src/org/netbeans/modules/jackpot30/impl/pm/NFABasedBulkSearchTest.java	Sat Jan 22 21:51:05 2011 +0100
    34.2 +++ b/api/test/unit/src/org/netbeans/modules/jackpot30/impl/pm/NFABasedBulkSearchTest.java	Fri Feb 18 20:16:26 2011 +0100
    34.3 @@ -128,6 +128,11 @@
    34.4          public BulkPattern create(Collection<? extends String> code, Collection<? extends Tree> patterns, Collection<? extends AdditionalQueryConstraints> additionalConstraints) {
    34.5              return new NFABasedBulkSearch().create(code, patterns, additionalConstraints);
    34.6          }
    34.7 +
    34.8 +        @Override
    34.9 +        public Map<String, Integer> matchesWithFrequencies(InputStream encoded, BulkPattern pattern) {
   34.10 +            return new NFABasedBulkSearch().matchesWithFrequencies(encoded, pattern);
   34.11 +        }
   34.12      }
   34.13  
   34.14      private static final class IndexImpl extends AbstractLuceneIndex {
    35.1 --- a/api/test/unit/src/org/netbeans/modules/jackpot30/spi/JavaFixTest.java	Sat Jan 22 21:51:05 2011 +0100
    35.2 +++ b/api/test/unit/src/org/netbeans/modules/jackpot30/spi/JavaFixTest.java	Fri Feb 18 20:16:26 2011 +0100
    35.3 @@ -423,6 +423,39 @@
    35.4  		           "}\n");
    35.5      }
    35.6  
    35.7 +    public void testCarefulRewriteInImports() throws Exception {
    35.8 +        performRewriteTest("package test;\n" +
    35.9 +                           "import javax.swing.text.AbstractDocument;\n" +
   35.10 +                           "public class Test {\n" +
   35.11 +                           "}\n",
   35.12 +                           "javax.swing.text.AbstractDocument => javax.swing.text.Document",
   35.13 +                           "package test;\n" +
   35.14 +                           "import javax.swing.text.Document;\n" +
   35.15 +                           "public class Test {\n" +
   35.16 +		           "}\n");
   35.17 +    }
   35.18 +
   35.19 +    public void testRemoveFromParent1() throws Exception {
   35.20 +        performRemoveFromParentTest("package test;\n" +
   35.21 +                                    "public class Test {\n" +
   35.22 +                                    "    private int I;" +
   35.23 +                                    "}\n",
   35.24 +                                    "$mods$ int $f;",
   35.25 +                                    "package test;\n" +
   35.26 +                                    "public class Test {\n" +
   35.27 +                                    "}\n");
   35.28 +    }
   35.29 +
   35.30 +    public void testRemoveFromParent2() throws Exception {
   35.31 +        performRemoveFromParentTest("package test;\n" +
   35.32 +                                    "public class Test extends java.util.ArrayList {\n" +
   35.33 +                                    "}\n",
   35.34 +                                    "java.util.ArrayList",
   35.35 +                                    "package test;\n" +
   35.36 +                                    "public class Test {\n" +
   35.37 +                                    "}\n");
   35.38 +    }
   35.39 +
   35.40      public void performRewriteTest(String code, String rule, String golden) throws Exception {
   35.41  	prepareTest("test/Test.java", code);
   35.42  
   35.43 @@ -450,4 +483,30 @@
   35.44  
   35.45          assertEquals(golden, doc.getText(0, doc.getLength()));
   35.46      }
   35.47 +
   35.48 +    public void performRemoveFromParentTest(String code, String rule, String golden) throws Exception {
   35.49 +	prepareTest("test/Test.java", code);
   35.50 +
   35.51 +        HintDescription hd = HintDescriptionFactory.create()
   35.52 +                                                   .setTriggerPattern(PatternDescription.create(rule, Collections.<String, String>emptyMap()))
   35.53 +                                                   .setWorker(new HintDescription.Worker() {
   35.54 +            @Override public Collection<? extends ErrorDescription> createErrors(HintContext ctx) {
   35.55 +                return Collections.singletonList(ErrorDescriptionFactory.forName(ctx, ctx.getPath(), "", JavaFix.removeFromParent(ctx, "", ctx.getPath())));
   35.56 +            }
   35.57 +        }).produce();
   35.58 +
   35.59 +        Map<PatternDescription, List<HintDescription>> patternHints = new HashMap<PatternDescription, List<HintDescription>>();
   35.60 +        HashMap<Kind, List<HintDescription>> kindHints = new HashMap<Kind, List<HintDescription>>();
   35.61 +
   35.62 +        RulesManager.sortOut(Collections.singleton(hd), kindHints, patternHints);
   35.63 +        List<ErrorDescription> computeHints = new HintsInvoker(info, new AtomicBoolean()).computeHints(info, kindHints, patternHints);
   35.64 +
   35.65 +        assertEquals(computeHints.toString(), 1, computeHints.size());
   35.66 +
   35.67 +        Fix fix = computeHints.get(0).getFixes().getFixes().get(0);
   35.68 +
   35.69 +	fix.implement();
   35.70 +
   35.71 +        assertEquals(golden, doc.getText(0, doc.getLength()));
   35.72 +    }
   35.73  }
    36.1 --- a/borrowedtests/nbproject/genfiles.properties	Sat Jan 22 21:51:05 2011 +0100
    36.2 +++ b/borrowedtests/nbproject/genfiles.properties	Fri Feb 18 20:16:26 2011 +0100
    36.3 @@ -3,6 +3,6 @@
    36.4  build.xml.stylesheet.CRC32=79c3b980@1.28.0.7
    36.5  # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
    36.6  # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
    36.7 -nbproject/build-impl.xml.data.CRC32=71327745
    36.8 +nbproject/build-impl.xml.data.CRC32=4bf510a9
    36.9  nbproject/build-impl.xml.script.CRC32=c6833bcb
   36.10  nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.44
    37.1 --- a/borrowedtests/nbproject/platform.properties	Sat Jan 22 21:51:05 2011 +0100
    37.2 +++ b/borrowedtests/nbproject/platform.properties	Fri Feb 18 20:16:26 2011 +0100
    37.3 @@ -16,5 +16,6 @@
    37.4      ${nbplatform.active.dir}/java:\
    37.5      ${nbplatform.active.dir}/groovy:\
    37.6      ${nbplatform.active.dir}/ruby:\
    37.7 +    ${nbplatform.active.dir}/extra:\
    37.8      ${nbplatform.active.dir}/ide
    37.9  nbplatform.active=default
    38.1 --- a/borrowedtests/nbproject/project.xml	Sat Jan 22 21:51:05 2011 +0100
    38.2 +++ b/borrowedtests/nbproject/project.xml	Fri Feb 18 20:16:26 2011 +0100
    38.3 @@ -72,8 +72,8 @@
    38.4                      <build-prerequisite/>
    38.5                      <compile-dependency/>
    38.6                      <run-dependency>
    38.7 -                        <release-version>1</release-version>
    38.8 -                        <specification-version>2.13.0.232</specification-version>
    38.9 +                        <release-version>1-3</release-version>
   38.10 +                        <specification-version>2.13</specification-version>
   38.11                      </run-dependency>
   38.12                  </dependency>
   38.13                  <dependency>
    39.1 --- a/borrowedtests/src/org/netbeans/api/java/source/SourceUtilsTestUtil2.java	Sat Jan 22 21:51:05 2011 +0100
    39.2 +++ b/borrowedtests/src/org/netbeans/api/java/source/SourceUtilsTestUtil2.java	Fri Feb 18 20:16:26 2011 +0100
    39.3 @@ -74,7 +74,7 @@
    39.4      }
    39.5      
    39.6      public static void disableLocks() {
    39.7 -        FSDirectory.setDisableLocks(true);
    39.8 +//        FSDirectory.setDisableLocks(true);
    39.9      }
   39.10      
   39.11  }
    40.1 --- a/bridges/refactoring/src/org/netbeans/modules/jackpot30/refactoring/invertboolean/InvertBooleanRefactoringPluginImpl.java	Sat Jan 22 21:51:05 2011 +0100
    40.2 +++ b/bridges/refactoring/src/org/netbeans/modules/jackpot30/refactoring/invertboolean/InvertBooleanRefactoringPluginImpl.java	Fri Feb 18 20:16:26 2011 +0100
    40.3 @@ -52,6 +52,7 @@
    40.4  import java.util.Map;
    40.5  import javax.lang.model.element.Modifier;
    40.6  import javax.lang.model.element.TypeElement;
    40.7 +import javax.lang.model.type.TypeMirror;
    40.8  import org.netbeans.api.java.source.JavaSource;
    40.9  import org.netbeans.api.java.source.JavaSource.Phase;
   40.10  import org.netbeans.api.java.source.ModificationResult;
   40.11 @@ -200,7 +201,9 @@
   40.12                                  constraints.append(" && ");
   40.13                              }
   40.14                              parameters.append("$").append(count);
   40.15 -                            constraints.append("$").append(count).append(" instanceof ").append(parameter.getTrees().getTypeMirror(new TreePath(new TreePath(path, vt), vt.getType())));
   40.16 +                            TypeMirror type = parameter.getTrees().getTypeMirror(new TreePath(new TreePath(path, vt), vt.getType()));
   40.17 +                            type = parameter.getTypes().erasure(type);
   40.18 +                            constraints.append("$").append(count).append(" instanceof ").append(type);
   40.19                              count++;
   40.20                          }
   40.21  
    41.1 --- a/cmdline/compiler/src/org/netbeans/modules/jackpot30/compiler/HintsAnnotationProcessing.java	Sat Jan 22 21:51:05 2011 +0100
    41.2 +++ b/cmdline/compiler/src/org/netbeans/modules/jackpot30/compiler/HintsAnnotationProcessing.java	Fri Feb 18 20:16:26 2011 +0100
    41.3 @@ -40,7 +40,8 @@
    41.4  
    41.5  import java.io.File;
    41.6  import java.io.IOException;
    41.7 -import java.io.OutputStream;
    41.8 +import java.io.OutputStreamWriter;
    41.9 +import java.io.Writer;
   41.10  import java.util.Arrays;
   41.11  import java.util.Collection;
   41.12  import java.util.Collections;
   41.13 @@ -98,7 +99,7 @@
   41.14          EXTRA_HINTS
   41.15      )));
   41.16  
   41.17 -    private OutputStream diff;
   41.18 +    private Writer diff;
   41.19  
   41.20      @Override
   41.21      protected boolean initialize(ProcessingEnvironment processingEnv) {
   41.22 @@ -199,10 +200,10 @@
   41.23                  if (diff == null) {
   41.24                      FileObject upgradeDiffFO = processingEnv.getFiler().createResource(StandardLocation.SOURCE_OUTPUT, "", "META-INF/upgrade/upgrade.diff");
   41.25  
   41.26 -                    diff = upgradeDiffFO.openOutputStream();
   41.27 +                    diff = new OutputStreamWriter(upgradeDiffFO.openOutputStream());
   41.28                  }
   41.29  
   41.30 -                BatchUtilities.exportDiff(mr, diff);
   41.31 +                BatchUtilities.exportDiff(mr, null, diff);
   41.32              }
   41.33          } catch (IOException ex) {
   41.34              Exceptions.printStackTrace(ex);
    42.1 --- a/cmdline/lib/test/unit/src/org/netbeans/modules/jackpot30/cmdline/lib/CreateStandaloneJar.java	Sat Jan 22 21:51:05 2011 +0100
    42.2 +++ b/cmdline/lib/test/unit/src/org/netbeans/modules/jackpot30/cmdline/lib/CreateStandaloneJar.java	Fri Feb 18 20:16:26 2011 +0100
    42.3 @@ -64,6 +64,9 @@
    42.4  import java.util.Set;
    42.5  import java.util.jar.JarOutputStream;
    42.6  import java.util.zip.ZipEntry;
    42.7 +import org.apache.lucene.analysis.tokenattributes.OffsetAttributeImpl;
    42.8 +import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttributeImpl;
    42.9 +import org.apache.lucene.analysis.tokenattributes.TermAttributeImpl;
   42.10  import org.netbeans.api.java.source.JavaSource;
   42.11  import org.netbeans.junit.NbTestCase;
   42.12  import org.netbeans.modules.classfile.ClassFile;
   42.13 @@ -401,7 +404,10 @@
   42.14              "org.netbeans.modules.java.platform.DefaultJavaPlatformProvider",
   42.15              
   42.16              "com.sun.tools.javac.resources.compiler",
   42.17 -            "com.sun.tools.javac.resources.javac"
   42.18 +            "com.sun.tools.javac.resources.javac",
   42.19 +            TermAttributeImpl.class.getName(),
   42.20 +            OffsetAttributeImpl.class.getName(),
   42.21 +            PositionIncrementAttributeImpl.class.getName()
   42.22  
   42.23  
   42.24              , "org.netbeans.modules.java.hints.infrastructure.RulesManager$HintProviderImpl"
    43.1 --- a/cmdline/nbproject/platform.properties	Sat Jan 22 21:51:05 2011 +0100
    43.2 +++ b/cmdline/nbproject/platform.properties	Fri Feb 18 20:16:26 2011 +0100
    43.3 @@ -10,6 +10,7 @@
    43.4      ${nbplatform.active.dir}/platform:\
    43.5      ${nbplatform.active.dir}/profiler:\
    43.6      ${nbplatform.active.dir}/websvccommon:\
    43.7 +    ${nbplatform.active.dir}/extra:\
    43.8      ../build/cluster:\
    43.9      ../borrowedtests/build/cluster
   43.10  nbplatform.active=default
    44.1 --- a/cmdline/tool/src/org/netbeans/modules/jackpot30/cmdline/Main.java	Sat Jan 22 21:51:05 2011 +0100
    44.2 +++ b/cmdline/tool/src/org/netbeans/modules/jackpot30/cmdline/Main.java	Fri Feb 18 20:16:26 2011 +0100
    44.3 @@ -40,11 +40,14 @@
    44.4  package org.netbeans.modules.jackpot30.cmdline;
    44.5  
    44.6  import java.io.BufferedOutputStream;
    44.7 +import java.io.BufferedWriter;
    44.8  import java.io.File;
    44.9  import java.io.FileOutputStream;
   44.10  import java.io.IOException;
   44.11  import java.io.OutputStream;
   44.12 +import java.io.OutputStreamWriter;
   44.13  import java.io.PrintStream;
   44.14 +import java.io.Writer;
   44.15  import java.net.URL;
   44.16  import java.util.ArrayList;
   44.17  import java.util.Collection;
   44.18 @@ -343,13 +346,13 @@
   44.19          Collection<ModificationResult> diffs = BatchUtilities.applyFixes(occurrences, w, new AtomicBoolean(), problems);
   44.20  
   44.21          if (out != null) {
   44.22 -            OutputStream outS = null;
   44.23 +            Writer outS = null;
   44.24  
   44.25              try {
   44.26 -                outS = new BufferedOutputStream(new FileOutputStream(out));
   44.27 +                outS = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(out)));
   44.28  
   44.29                  for (ModificationResult mr : diffs) {
   44.30 -                    BatchUtilities.exportDiff(mr, outS);
   44.31 +                    BatchUtilities.exportDiff(mr, null, outS);
   44.32                  }
   44.33              } finally {
   44.34                  try {
    45.1 --- a/file/src/org/netbeans/modules/jackpot30/file/APIAccessor.java	Sat Jan 22 21:51:05 2011 +0100
    45.2 +++ b/file/src/org/netbeans/modules/jackpot30/file/APIAccessor.java	Fri Feb 18 20:16:26 2011 +0100
    45.3 @@ -72,4 +72,6 @@
    45.4      public abstract Map<String, Collection<? extends TreePath>> getMultiVariables(Context ctx);
    45.5      public abstract Map<String, String> getVariableNames(Context ctx);
    45.6  
    45.7 +    public abstract Variable enterAuxiliaryVariable(Context ctx, TreePath source);
    45.8 +
    45.9  }
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/file/src/org/netbeans/modules/jackpot30/file/ConditionAPIHacks.java	Fri Feb 18 20:16:26 2011 +0100
    46.3 @@ -0,0 +1,74 @@
    46.4 +/*
    46.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    46.6 + *
    46.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
    46.8 + *
    46.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   46.10 + * Other names may be trademarks of their respective owners.
   46.11 + *
   46.12 + * The contents of this file are subject to the terms of either the GNU
   46.13 + * General Public License Version 2 only ("GPL") or the Common
   46.14 + * Development and Distribution License("CDDL") (collectively, the
   46.15 + * "License"). You may not use this file except in compliance with the
   46.16 + * License. You can obtain a copy of the License at
   46.17 + * http://www.netbeans.org/cddl-gplv2.html
   46.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   46.19 + * specific language governing permissions and limitations under the
   46.20 + * License.  When distributing the software, include this License Header
   46.21 + * Notice in each file and include the License file at
   46.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   46.23 + * particular file as subject to the "Classpath" exception as provided
   46.24 + * by Oracle in the GPL Version 2 section of the License file that
   46.25 + * accompanied this code. If applicable, add the following below the
   46.26 + * License Header, with the fields enclosed by brackets [] replaced by
   46.27 + * your own identifying information:
   46.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   46.29 + *
   46.30 + * If you wish your version of this file to be governed by only the CDDL
   46.31 + * or only the GPL Version 2, indicate your decision by adding
   46.32 + * "[Contributor] elects to include this software in this distribution
   46.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   46.34 + * single choice of license, a recipient has the option to distribute
   46.35 + * your version of this file under either the CDDL, the GPL Version 2 or
   46.36 + * to extend the choice of license to its licensees as provided above.
   46.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   46.38 + * Version 2 license, then the option applies only if the new code is
   46.39 + * made subject to such option by the copyright holder.
   46.40 + *
   46.41 + * Contributor(s):
   46.42 + *
   46.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
   46.44 + */
   46.45 +
   46.46 +package org.netbeans.modules.jackpot30.file;
   46.47 +
   46.48 +import com.sun.source.util.TreePath;
   46.49 +import javax.lang.model.element.Element;
   46.50 +import org.netbeans.api.annotations.common.CheckForNull;
   46.51 +import org.netbeans.api.annotations.common.NonNull;
   46.52 +import org.netbeans.api.annotations.common.NullAllowed;
   46.53 +import org.netbeans.api.java.source.CompilationInfo;
   46.54 +import org.netbeans.modules.jackpot30.file.conditionapi.Context;
   46.55 +import org.netbeans.modules.jackpot30.file.conditionapi.Variable;
   46.56 +
   46.57 +/**Methods that can be used from declarative hints' conditions, but that are not
   46.58 + * a good solution for the problem they solve.
   46.59 + *
   46.60 + * @author lahvac
   46.61 + */
   46.62 +public class ConditionAPIHacks {
   46.63 +
   46.64 +    public @CheckForNull Variable getDeclaration(@NonNull Context ctx, @NonNull Variable forVar) {
   46.65 +        CompilationInfo info = APIAccessor.IMPL.getHintContext(ctx).getInfo();
   46.66 +        TreePath path = APIAccessor.IMPL.getSingleVariable(ctx, forVar);
   46.67 +        Element el = info.getTrees().getElement(path);
   46.68 +
   46.69 +        if (el == null) return null;
   46.70 +
   46.71 +        TreePath source = info.getTrees().getPath(el);
   46.72 +
   46.73 +        if (source == null) return null;
   46.74 +
   46.75 +        return APIAccessor.IMPL.enterAuxiliaryVariable(ctx, source);
   46.76 +    }
   46.77 +}
    47.1 --- a/file/src/org/netbeans/modules/jackpot30/file/DeclarativeHintRegistry.java	Sat Jan 22 21:51:05 2011 +0100
    47.2 +++ b/file/src/org/netbeans/modules/jackpot30/file/DeclarativeHintRegistry.java	Fri Feb 18 20:16:26 2011 +0100
    47.3 @@ -45,6 +45,7 @@
    47.4  import java.util.Collection;
    47.5  import java.util.Collections;
    47.6  import java.util.HashMap;
    47.7 +import java.util.HashSet;
    47.8  import java.util.LinkedHashMap;
    47.9  import java.util.LinkedList;
   47.10  import java.util.List;
   47.11 @@ -70,6 +71,7 @@
   47.12  import org.netbeans.modules.jackpot30.spi.HintContext.MessageKind;
   47.13  import org.netbeans.modules.jackpot30.spi.HintDescription;
   47.14  import org.netbeans.modules.jackpot30.spi.HintDescription.Acceptor;
   47.15 +import org.netbeans.modules.jackpot30.spi.HintDescription.AdditionalQueryConstraints;
   47.16  import org.netbeans.modules.jackpot30.spi.HintDescription.DeclarativeFixDescription;
   47.17  import org.netbeans.modules.jackpot30.spi.HintDescription.PatternDescription;
   47.18  import org.netbeans.modules.jackpot30.spi.HintDescriptionFactory;
   47.19 @@ -256,7 +258,7 @@
   47.20  
   47.21                  Instanceof i = (Instanceof) c;
   47.22  
   47.23 -                constraints.put(i.variable, i.constraint);
   47.24 +                constraints.put(i.variable, i.constraint.trim()); //TODO: may i.constraint contain comments? if so, they need to be removed
   47.25              }
   47.26  
   47.27              String imports = parsed.importsBlock != null ? spec.substring(parsed.importsBlock[0], parsed.importsBlock[1]) : "";
   47.28 @@ -306,6 +308,7 @@
   47.29  //            f = f.setWorker(new DeclarativeHintsWorker(displayName, hint.conditions, imports, fixes, options, primarySuppressWarningsKey));
   47.30              f = f.setWorker(new HintDescription.MarksWorker(filterConditions(hint.conditions), new HintsFixAcceptor(hint.conditions, hint.options), fixes));
   47.31              f = f.setMetadata(currentMeta);
   47.32 +            f = f.setAdditionalConstraints(new AdditionalQueryConstraints(new HashSet<String>(constraints.values())));
   47.33  
   47.34              Collection<HintDescription> hints = result.get(currentMeta);
   47.35  
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/file/src/org/netbeans/modules/jackpot30/file/DeclarativeHintsOptions.java	Fri Feb 18 20:16:26 2011 +0100
    48.3 @@ -0,0 +1,55 @@
    48.4 +/*
    48.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    48.6 + *
    48.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
    48.8 + *
    48.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   48.10 + * Other names may be trademarks of their respective owners.
   48.11 + *
   48.12 + * The contents of this file are subject to the terms of either the GNU
   48.13 + * General Public License Version 2 only ("GPL") or the Common
   48.14 + * Development and Distribution License("CDDL") (collectively, the
   48.15 + * "License"). You may not use this file except in compliance with the
   48.16 + * License. You can obtain a copy of the License at
   48.17 + * http://www.netbeans.org/cddl-gplv2.html
   48.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   48.19 + * specific language governing permissions and limitations under the
   48.20 + * License.  When distributing the software, include this License Header
   48.21 + * Notice in each file and include the License file at
   48.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   48.23 + * particular file as subject to the "Classpath" exception as provided
   48.24 + * by Oracle in the GPL Version 2 section of the License file that
   48.25 + * accompanied this code. If applicable, add the following below the
   48.26 + * License Header, with the fields enclosed by brackets [] replaced by
   48.27 + * your own identifying information:
   48.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   48.29 + *
   48.30 + * If you wish your version of this file to be governed by only the CDDL
   48.31 + * or only the GPL Version 2, indicate your decision by adding
   48.32 + * "[Contributor] elects to include this software in this distribution
   48.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   48.34 + * single choice of license, a recipient has the option to distribute
   48.35 + * your version of this file under either the CDDL, the GPL Version 2 or
   48.36 + * to extend the choice of license to its licensees as provided above.
   48.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   48.38 + * Version 2 license, then the option applies only if the new code is
   48.39 + * made subject to such option by the copyright holder.
   48.40 + *
   48.41 + * Contributor(s):
   48.42 + *
   48.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
   48.44 + */
   48.45 +
   48.46 +package org.netbeans.modules.jackpot30.file;
   48.47 +
   48.48 +/**
   48.49 + *
   48.50 + * @author lahvac
   48.51 + */
   48.52 +public class DeclarativeHintsOptions {
   48.53 +
   48.54 +    public static final String OPTION_ERROR = "error";
   48.55 +    public static final String OPTION_WARNING = "warning";
   48.56 +    public static final String OPTION_REMOVE_FROM_PARENT = "remove-from-parent";
   48.57 +    
   48.58 +}
    49.1 --- a/file/src/org/netbeans/modules/jackpot30/file/DeclarativeHintsWorker.java	Sat Jan 22 21:51:05 2011 +0100
    49.2 +++ b/file/src/org/netbeans/modules/jackpot30/file/DeclarativeHintsWorker.java	Fri Feb 18 20:16:26 2011 +0100
    49.3 @@ -1,7 +1,7 @@
    49.4  /*
    49.5   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    49.6   *
    49.7 - * Copyright 2008-2009 Sun Microsystems, Inc. All rights reserved.
    49.8 + * Copyright 2008-2011 Sun Microsystems, Inc. All rights reserved.
    49.9   *
   49.10   * The contents of this file are subject to the terms of either the GNU
   49.11   * General Public License Version 2 only ("GPL") or the Common
   49.12 @@ -34,18 +34,19 @@
   49.13   *
   49.14   * Contributor(s):
   49.15   *
   49.16 - * Portions Copyrighted 2008-2009 Sun Microsystems, Inc.
   49.17 + * Portions Copyrighted 2008-2011 Sun Microsystems, Inc.
   49.18   */
   49.19  
   49.20  package org.netbeans.modules.jackpot30.file;
   49.21  
   49.22 -import com.sun.source.util.TreePath;
   49.23  import java.util.Collection;
   49.24  import java.util.Collections;
   49.25 +import java.util.EnumSet;
   49.26  import java.util.LinkedList;
   49.27  import java.util.List;
   49.28  import java.util.Map;
   49.29 -import javax.lang.model.type.TypeMirror;
   49.30 +import org.netbeans.api.lexer.TokenHierarchy;
   49.31 +import org.netbeans.api.lexer.TokenSequence;
   49.32  import org.netbeans.modules.jackpot30.file.Condition.Otherwise;
   49.33  import org.netbeans.modules.jackpot30.file.conditionapi.Context;
   49.34  import org.netbeans.modules.jackpot30.spi.HintContext;
   49.35 @@ -121,17 +122,35 @@
   49.36  
   49.37                  reportErrorWarning(ctx, fix.getOptions());
   49.38  
   49.39 -                //XXX: empty/noop fixes should not be realized:
   49.40 -                editorFixes.add(JavaFix.rewriteFix(ctx.getInfo(),
   49.41 -                                                   fix.getDisplayName(),
   49.42 -                                                   ctx.getPath(),
   49.43 -                                                   fix.getPattern(),
   49.44 -                                                   APIAccessor.IMPL.getVariables(context),
   49.45 -                                                   APIAccessor.IMPL.getMultiVariables(context),
   49.46 -                                                   APIAccessor.IMPL.getVariableNames(context),
   49.47 -                                                   ctx.getConstraints(),
   49.48 -                                                   fix.getOptions(),
   49.49 -                                                   imports));
   49.50 +                TokenSequence<DeclarativeHintTokenId> ts = TokenHierarchy.create(fix.getPattern(),
   49.51 +                                                                                 false,
   49.52 +                                                                                 DeclarativeHintTokenId.language(),
   49.53 +                                                                                 EnumSet.of(DeclarativeHintTokenId.BLOCK_COMMENT,
   49.54 +                                                                                            DeclarativeHintTokenId.LINE_COMMENT,
   49.55 +                                                                                            DeclarativeHintTokenId.WHITESPACE),
   49.56 +                                                                                 null).tokenSequence(DeclarativeHintTokenId.language());
   49.57 +
   49.58 +                boolean empty = !ts.moveNext();
   49.59 +
   49.60 +                if (empty) {
   49.61 +                    if (   (   !fix.getOptions().containsKey(DeclarativeHintsOptions.OPTION_ERROR)
   49.62 +                            && !fix.getOptions().containsKey(DeclarativeHintsOptions.OPTION_WARNING))
   49.63 +                        || fix.getOptions().containsKey(DeclarativeHintsOptions.OPTION_REMOVE_FROM_PARENT)) {
   49.64 +                        editorFixes.add(JavaFix.removeFromParent(ctx, ctx.getPath()));
   49.65 +                    }
   49.66 +                    //not realizing empty fixes
   49.67 +                } else {
   49.68 +                    editorFixes.add(JavaFix.rewriteFix(ctx.getInfo(),
   49.69 +                                                       fix.getDisplayName(),
   49.70 +                                                       ctx.getPath(),
   49.71 +                                                       fix.getPattern(),
   49.72 +                                                       APIAccessor.IMPL.getVariables(context),
   49.73 +                                                       APIAccessor.IMPL.getMultiVariables(context),
   49.74 +                                                       APIAccessor.IMPL.getVariableNames(context),
   49.75 +                                                       ctx.getConstraints(),
   49.76 +                                                       fix.getOptions(),
   49.77 +                                                       imports));
   49.78 +                }
   49.79              } finally {
   49.80                  context.leaveScope();
   49.81              }
    50.1 --- a/file/src/org/netbeans/modules/jackpot30/file/conditionapi/Context.java	Sat Jan 22 21:51:05 2011 +0100
    50.2 +++ b/file/src/org/netbeans/modules/jackpot30/file/conditionapi/Context.java	Fri Feb 18 20:16:26 2011 +0100
    50.3 @@ -45,9 +45,7 @@
    50.4  import java.util.Collection;
    50.5  import java.util.Collections;
    50.6  import java.util.EnumSet;
    50.7 -import java.util.HashMap;
    50.8  import java.util.LinkedList;
    50.9 -import java.util.List;
   50.10  import java.util.Map;
   50.11  import java.util.Set;
   50.12  import java.util.concurrent.atomic.AtomicInteger;
   50.13 @@ -138,13 +136,17 @@
   50.14              return null;
   50.15          }
   50.16  
   50.17 +        return enterAuxiliaryVariable(tp.getParentPath());
   50.18 +    }
   50.19 +
   50.20 +    private Variable enterAuxiliaryVariable(TreePath path) {
   50.21          String output = "*" + auxiliaryVariableCounter.getAndIncrement();
   50.22  
   50.23 -        ctx.putVariable(output, tp.getParentPath());
   50.24 +        ctx.putVariable(output, path);
   50.25  
   50.26          return new Variable(output);
   50.27      }
   50.28 -
   50.29 +    
   50.30      public @NonNull Variable variableForName(@NonNull String variableName) {
   50.31          Variable result = new Variable(variableName);
   50.32  
   50.33 @@ -263,5 +265,10 @@
   50.34              return ctx.ctx.getVariableNames();
   50.35          }
   50.36  
   50.37 +        @Override
   50.38 +        public Variable enterAuxiliaryVariable(Context ctx, TreePath source) {
   50.39 +            return ctx.enterAuxiliaryVariable(source);
   50.40 +        }
   50.41 +
   50.42      }
   50.43  }
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/file/test/unit/src/org/netbeans/modules/jackpot30/file/DeclarativeHintRegistryTest.java	Fri Feb 18 20:16:26 2011 +0100
    51.3 @@ -0,0 +1,73 @@
    51.4 +/*
    51.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    51.6 + *
    51.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
    51.8 + *
    51.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   51.10 + * Other names may be trademarks of their respective owners.
   51.11 + *
   51.12 + * The contents of this file are subject to the terms of either the GNU
   51.13 + * General Public License Version 2 only ("GPL") or the Common
   51.14 + * Development and Distribution License("CDDL") (collectively, the
   51.15 + * "License"). You may not use this file except in compliance with the
   51.16 + * License. You can obtain a copy of the License at
   51.17 + * http://www.netbeans.org/cddl-gplv2.html
   51.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   51.19 + * specific language governing permissions and limitations under the
   51.20 + * License.  When distributing the software, include this License Header
   51.21 + * Notice in each file and include the License file at
   51.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   51.23 + * particular file as subject to the "Classpath" exception as provided
   51.24 + * by Oracle in the GPL Version 2 section of the License file that
   51.25 + * accompanied this code. If applicable, add the following below the
   51.26 + * License Header, with the fields enclosed by brackets [] replaced by
   51.27 + * your own identifying information:
   51.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   51.29 + *
   51.30 + * If you wish your version of this file to be governed by only the CDDL
   51.31 + * or only the GPL Version 2, indicate your decision by adding
   51.32 + * "[Contributor] elects to include this software in this distribution
   51.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   51.34 + * single choice of license, a recipient has the option to distribute
   51.35 + * your version of this file under either the CDDL, the GPL Version 2 or
   51.36 + * to extend the choice of license to its licensees as provided above.
   51.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   51.38 + * Version 2 license, then the option applies only if the new code is
   51.39 + * made subject to such option by the copyright holder.
   51.40 + *
   51.41 + * Contributor(s):
   51.42 + *
   51.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
   51.44 + */
   51.45 +
   51.46 +package org.netbeans.modules.jackpot30.file;
   51.47 +
   51.48 +import java.util.Arrays;
   51.49 +import java.util.Collection;
   51.50 +import java.util.HashSet;
   51.51 +import static org.junit.Assert.*;
   51.52 +import org.netbeans.junit.NbTestCase;
   51.53 +import org.netbeans.modules.jackpot30.spi.HintDescription;
   51.54 +
   51.55 +/**
   51.56 + *
   51.57 + * @author lahvac
   51.58 + */
   51.59 +public class DeclarativeHintRegistryTest extends NbTestCase {
   51.60 +
   51.61 +    public DeclarativeHintRegistryTest(String name) {
   51.62 +        super(name);
   51.63 +    }
   51.64 +
   51.65 +    public void testAdditionalConstraints() {
   51.66 +        Collection<Collection<? extends HintDescription>> allHints = DeclarativeHintRegistry.parseHints(null, "$1 :: $1 instanceof java.lang.String ;;").values();
   51.67 +
   51.68 +        assertEquals(1, allHints.size());
   51.69 +        assertEquals(1, allHints.iterator().next().size());
   51.70 +
   51.71 +        HintDescription hd = allHints.iterator().next().iterator().next();
   51.72 +
   51.73 +        assertEquals(new HashSet<String>(Arrays.asList("java.lang.String")), hd.getAdditionalConstraints().requiredErasedTypes);
   51.74 +    }
   51.75 +
   51.76 +}
   51.77 \ No newline at end of file
    52.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2 +++ b/file/test/unit/src/org/netbeans/modules/jackpot30/file/fqn-rewrite-test.hint	Fri Feb 18 20:16:26 2011 +0100
    52.3 @@ -0,0 +1,3 @@
    52.4 +   javax.swing.text.AbstractDocument
    52.5 +=> javax.swing.text.Document
    52.6 +;;
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/file/test/unit/src/org/netbeans/modules/jackpot30/file/fqn-rewrite-test.test	Fri Feb 18 20:16:26 2011 +0100
    53.3 @@ -0,0 +1,19 @@
    53.4 +%%TestCase pos-1
    53.5 +package test;
    53.6 +import javax.swing.text.AbstractDocument;
    53.7 +public class Test {
    53.8 +    private AbstractDocument doc;
    53.9 +}
   53.10 +%%=>
   53.11 +package test;
   53.12 +import javax.swing.text.Document;
   53.13 +public class Test {
   53.14 +    private AbstractDocument doc;
   53.15 +}
   53.16 +%%=>
   53.17 +package test;
   53.18 +import javax.swing.text.AbstractDocument;
   53.19 +import javax.swing.text.Document;
   53.20 +public class Test {
   53.21 +    private Document doc;
   53.22 +}
    54.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.2 +++ b/file/test/unit/src/org/netbeans/modules/jackpot30/file/remove-from-parent.hint	Fri Feb 18 20:16:26 2011 +0100
    54.3 @@ -0,0 +1,9 @@
    54.4 +   int i
    54.5 +=> /*remove-from-parent*/
    54.6 +;;
    54.7 +   float f
    54.8 +=> <!error="err">
    54.9 +;;
   54.10 +   double d
   54.11 +=> <!error="err",remove-from-parent=true>
   54.12 +;;
    55.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.2 +++ b/file/test/unit/src/org/netbeans/modules/jackpot30/file/remove-from-parent.test	Fri Feb 18 20:16:26 2011 +0100
    55.3 @@ -0,0 +1,27 @@
    55.4 +%%TestCase pos-1
    55.5 +package test;
    55.6 +public class Test {
    55.7 +     private void g(int i) {}
    55.8 +}
    55.9 +%%=>
   55.10 +package test;
   55.11 +public class Test {
   55.12 +     private void g() {}
   55.13 +}
   55.14 +%%TestCase pos-2
   55.15 +package test;
   55.16 +public class Test {
   55.17 +     private void g(double d) {}
   55.18 +}
   55.19 +%%=>
   55.20 +package test;
   55.21 +public class Test {
   55.22 +     private void g() {}
   55.23 +}
   55.24 +%%TestCase neg-1
   55.25 +package test;
   55.26 +public class Test {
   55.27 +     private void g(float f) {}
   55.28 +}
   55.29 +%%=>
   55.30 +remove-from-parent:f
    56.1 --- a/hudson/trunk	Sat Jan 22 21:51:05 2011 +0100
    56.2 +++ b/hudson/trunk	Fri Feb 18 20:16:26 2011 +0100
    56.3 @@ -23,7 +23,7 @@
    56.4      unzip -q ../download/*$TRUNK_ID-$1.zip || exit
    56.5  }
    56.6  
    56.7 -for cluster in ide platform java harness nb apisupport; do
    56.8 +for cluster in ide platform java harness nb apisupport extra enterprise; do
    56.9      download_and_unpack_cluster $cluster;
   56.10  done
   56.11  
   56.12 @@ -59,3 +59,4 @@
   56.13  mkdir -p build/server
   56.14  (cp server/do-indexing server/indexer/dist; cd server/indexer/dist/; zip -r ../../../build/server/indexer.zip *)
   56.15  (cd server/web.api/dist/; zip -r ../../../build/server/web.api.zip *)
   56.16 +(cd server/backend; call_ant clean && call_ant build && call_ant test && call_ant build-zip) || exit
    57.1 --- a/kit/nbproject/genfiles.properties	Sat Jan 22 21:51:05 2011 +0100
    57.2 +++ b/kit/nbproject/genfiles.properties	Fri Feb 18 20:16:26 2011 +0100
    57.3 @@ -3,6 +3,6 @@
    57.4  build.xml.stylesheet.CRC32=79c3b980@1.28.0.7
    57.5  # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
    57.6  # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
    57.7 -nbproject/build-impl.xml.data.CRC32=704f6194
    57.8 +nbproject/build-impl.xml.data.CRC32=0e536aba
    57.9  nbproject/build-impl.xml.script.CRC32=c129207c
   57.10  nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.44
    58.1 --- a/libs.jerig/nbproject/genfiles.properties	Sat Jan 22 21:51:05 2011 +0100
    58.2 +++ b/libs.jerig/nbproject/genfiles.properties	Fri Feb 18 20:16:26 2011 +0100
    58.3 @@ -3,6 +3,6 @@
    58.4  build.xml.stylesheet.CRC32=79c3b980@1.29.0.7
    58.5  # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
    58.6  # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
    58.7 -nbproject/build-impl.xml.data.CRC32=82ad5887
    58.8 +nbproject/build-impl.xml.data.CRC32=88a1791a
    58.9  nbproject/build-impl.xml.script.CRC32=0184319b
   58.10 -nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.43
   58.11 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.44
    59.1 --- a/libs.jerig/nbproject/project.xml	Sat Jan 22 21:51:05 2011 +0100
    59.2 +++ b/libs.jerig/nbproject/project.xml	Fri Feb 18 20:16:26 2011 +0100
    59.3 @@ -11,8 +11,8 @@
    59.4                      <build-prerequisite/>
    59.5                      <compile-dependency/>
    59.6                      <run-dependency>
    59.7 -                        <release-version>1</release-version>
    59.8 -                        <specification-version>2.6.0.232</specification-version>
    59.9 +                        <release-version>1-3</release-version>
   59.10 +                        <specification-version>2.13</specification-version>
   59.11                      </run-dependency>
   59.12                  </dependency>
   59.13              </module-dependencies>
    60.1 --- a/nbproject/platform.properties	Sat Jan 22 21:51:05 2011 +0100
    60.2 +++ b/nbproject/platform.properties	Fri Feb 18 20:16:26 2011 +0100
    60.3 @@ -16,6 +16,7 @@
    60.4      ${nbplatform.active.dir}/java:\
    60.5      ${nbplatform.active.dir}/groovy:\
    60.6      ${nbplatform.active.dir}/ruby:\
    60.7 +    ${nbplatform.active.dir}/extra:\
    60.8      ${nbplatform.active.dir}/ide:\
    60.9      borrowedtests/build/cluster
   60.10  nbplatform.active=default
    61.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.2 +++ b/server/backend/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties	Fri Feb 18 20:16:26 2011 +0100
    61.3 @@ -0,0 +1,2 @@
    61.4 +currentVersion=Jackpot 3.0 Backend {0}
    61.5 +LBL_splash_window_title=Starting Jackpot 3.0 Backend
    62.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.2 +++ b/server/backend/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties	Fri Feb 18 20:16:26 2011 +0100
    62.3 @@ -0,0 +1,2 @@
    62.4 +CTL_MainWindow_Title=Jackpot 3.0 Backend {0}
    62.5 +CTL_MainWindow_Title_No_Project=Jackpot 3.0 Backend {0}
    63.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.2 +++ b/server/backend/build.xml	Fri Feb 18 20:16:26 2011 +0100
    63.3 @@ -0,0 +1,8 @@
    63.4 +<?xml version="1.0" encoding="UTF-8"?>
    63.5 +<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
    63.6 +<!-- for some information on what you could do (e.g. targets to override). -->
    63.7 +<!-- If you delete this file and reopen the project it will be recreated. -->
    63.8 +<project name="backend" basedir=".">
    63.9 +    <description>Builds the module suite backend.</description>
   63.10 +    <import file="nbproject/build-impl.xml"/>
   63.11 +</project>
    64.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.2 +++ b/server/backend/impl/build.xml	Fri Feb 18 20:16:26 2011 +0100
    64.3 @@ -0,0 +1,8 @@
    64.4 +<?xml version="1.0" encoding="UTF-8"?>
    64.5 +<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
    64.6 +<!-- for some information on what you could do (e.g. targets to override). -->
    64.7 +<!-- If you delete this file and reopen the project it will be recreated. -->
    64.8 +<project name="org.netbeans.modules.jackpot30.backend.impl" default="netbeans" basedir=".">
    64.9 +    <description>Builds, tests, and runs the project org.netbeans.modules.jackpot30.backend.impl.</description>
   64.10 +    <import file="nbproject/build-impl.xml"/>
   64.11 +</project>
    65.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    65.2 +++ b/server/backend/impl/manifest.mf	Fri Feb 18 20:16:26 2011 +0100
    65.3 @@ -0,0 +1,5 @@
    65.4 +Manifest-Version: 1.0
    65.5 +OpenIDE-Module: org.netbeans.modules.jackpot30.backend.impl
    65.6 +OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/jackpot30/backend/impl/Bundle.properties
    65.7 +OpenIDE-Module-Specification-Version: 1.0
    65.8 +OpenIDE-Module-Layer: org/netbeans/modules/jackpot30/backend/impl/resources/layer.xml
    66.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    66.2 +++ b/server/backend/impl/nbproject/build-impl.xml	Fri Feb 18 20:16:26 2011 +0100
    66.3 @@ -0,0 +1,45 @@
    66.4 +<?xml version="1.0" encoding="UTF-8"?>
    66.5 +<!--
    66.6 +*** GENERATED FROM project.xml - DO NOT EDIT  ***
    66.7 +***         EDIT ../build.xml INSTEAD         ***
    66.8 +-->
    66.9 +<project name="org.netbeans.modules.jackpot30.backend.impl-impl" basedir="..">
   66.10 +    <fail message="Please build using Ant 1.7.1 or higher.">
   66.11 +        <condition>
   66.12 +            <not>
   66.13 +                <antversion atleast="1.7.1"/>
   66.14 +            </not>
   66.15 +        </condition>
   66.16 +    </fail>
   66.17 +    <property file="nbproject/private/suite-private.properties"/>
   66.18 +    <property file="nbproject/suite.properties"/>
   66.19 +    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
   66.20 +    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
   66.21 +    <property file="${suite.dir}/nbproject/platform.properties"/>
   66.22 +    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
   66.23 +        <attribute name="name"/>
   66.24 +        <attribute name="value"/>
   66.25 +        <sequential>
   66.26 +            <property name="@{name}" value="${@{value}}"/>
   66.27 +        </sequential>
   66.28 +    </macrodef>
   66.29 +    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
   66.30 +        <attribute name="property"/>
   66.31 +        <attribute name="value"/>
   66.32 +        <sequential>
   66.33 +            <property name="@{property}" value="@{value}"/>
   66.34 +        </sequential>
   66.35 +    </macrodef>
   66.36 +    <property file="${user.properties.file}"/>
   66.37 +    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
   66.38 +    <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
   66.39 +    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
   66.40 +    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
   66.41 +        <condition>
   66.42 +            <not>
   66.43 +                <contains string="${cluster.path.evaluated}" substring="platform"/>
   66.44 +            </not>
   66.45 +        </condition>
   66.46 +    </fail>
   66.47 +    <import file="${harness.dir}/build.xml"/>
   66.48 +</project>
    67.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    67.2 +++ b/server/backend/impl/nbproject/genfiles.properties	Fri Feb 18 20:16:26 2011 +0100
    67.3 @@ -0,0 +1,8 @@
    67.4 +build.xml.data.CRC32=f3f7e858
    67.5 +build.xml.script.CRC32=c32e03a8
    67.6 +build.xml.stylesheet.CRC32=a56c6a5b@1.44
    67.7 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
    67.8 +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
    67.9 +nbproject/build-impl.xml.data.CRC32=f3f7e858
   67.10 +nbproject/build-impl.xml.script.CRC32=87e6e497
   67.11 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.44
    68.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    68.2 +++ b/server/backend/impl/nbproject/project.properties	Fri Feb 18 20:16:26 2011 +0100
    68.3 @@ -0,0 +1,2 @@
    68.4 +javac.source=1.6
    68.5 +javac.compilerargs=-Xlint -Xlint:-serial
    69.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    69.2 +++ b/server/backend/impl/nbproject/project.xml	Fri Feb 18 20:16:26 2011 +0100
    69.3 @@ -0,0 +1,220 @@
    69.4 +<?xml version="1.0" encoding="UTF-8"?>
    69.5 +<project xmlns="http://www.netbeans.org/ns/project/1">
    69.6 +    <type>org.netbeans.modules.apisupport.project</type>
    69.7 +    <configuration>
    69.8 +        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
    69.9 +            <code-name-base>org.netbeans.modules.jackpot30.backend.impl</code-name-base>
   69.10 +            <suite-component/>
   69.11 +            <module-dependencies>
   69.12 +                <dependency>
   69.13 +                    <code-name-base>org.netbeans.api.java.classpath</code-name-base>
   69.14 +                    <build-prerequisite/>
   69.15 +                    <compile-dependency/>
   69.16 +                    <run-dependency>
   69.17 +                        <release-version>1</release-version>
   69.18 +                        <specification-version>1.27</specification-version>
   69.19 +                    </run-dependency>
   69.20 +                </dependency>
   69.21 +                <dependency>
   69.22 +                    <code-name-base>org.netbeans.api.progress</code-name-base>
   69.23 +                    <build-prerequisite/>
   69.24 +                    <compile-dependency/>
   69.25 +                    <run-dependency>
   69.26 +                        <release-version>1</release-version>
   69.27 +                        <specification-version>1.22</specification-version>
   69.28 +                    </run-dependency>
   69.29 +                </dependency>
   69.30 +                <dependency>
   69.31 +                    <code-name-base>org.netbeans.libs.freemarker</code-name-base>
   69.32 +                    <build-prerequisite/>
   69.33 +                    <compile-dependency/>
   69.34 +                    <run-dependency>
   69.35 +                        <release-version>1</release-version>
   69.36 +                        <implementation-version/>
   69.37 +                    </run-dependency>
   69.38 +                </dependency>
   69.39 +                <dependency>
   69.40 +                    <code-name-base>org.netbeans.libs.javacapi</code-name-base>
   69.41 +                    <build-prerequisite/>
   69.42 +                    <compile-dependency/>
   69.43 +                    <run-dependency>
   69.44 +                        <specification-version>7.2.0.2</specification-version>
   69.45 +                    </run-dependency>
   69.46 +                </dependency>
   69.47 +                <dependency>
   69.48 +                    <code-name-base>org.netbeans.libs.javacimpl</code-name-base>
   69.49 +                    <build-prerequisite/>
   69.50 +                    <compile-dependency/>
   69.51 +                    <run-dependency>
   69.52 +                        <release-version>1</release-version>
   69.53 +                        <implementation-version/>
   69.54 +                    </run-dependency>
   69.55 +                </dependency>
   69.56 +                <dependency>
   69.57 +                    <code-name-base>org.netbeans.libs.lucene</code-name-base>
   69.58 +                    <build-prerequisite/>
   69.59 +                    <compile-dependency/>
   69.60 +                    <run-dependency>
   69.61 +                        <release-version>3</release-version>
   69.62 +                        <specification-version>3.0</specification-version>
   69.63 +                    </run-dependency>
   69.64 +                </dependency>
   69.65 +                <dependency>
   69.66 +                    <code-name-base>org.netbeans.modules.jackpot30.api</code-name-base>
   69.67 +                    <build-prerequisite/>
   69.68 +                    <compile-dependency/>
   69.69 +                    <run-dependency>
   69.70 +                        <implementation-version/>
   69.71 +                    </run-dependency>
   69.72 +                </dependency>
   69.73 +                <dependency>
   69.74 +                    <code-name-base>org.netbeans.modules.java.source</code-name-base>
   69.75 +                    <build-prerequisite/>
   69.76 +                    <compile-dependency/>
   69.77 +                    <run-dependency>
   69.78 +                        <implementation-version/>
   69.79 +                    </run-dependency>
   69.80 +                </dependency>
   69.81 +                <dependency>
   69.82 +                    <code-name-base>org.netbeans.modules.jeriglib</code-name-base>
   69.83 +                    <build-prerequisite/>
   69.84 +                    <compile-dependency/>
   69.85 +                    <run-dependency>
   69.86 +                        <specification-version>1.16</specification-version>
   69.87 +                    </run-dependency>
   69.88 +                </dependency>
   69.89 +                <dependency>
   69.90 +                    <code-name-base>org.netbeans.modules.jumpto</code-name-base>
   69.91 +                    <build-prerequisite/>
   69.92 +                    <compile-dependency/>
   69.93 +                    <run-dependency>
   69.94 +                        <release-version>1</release-version>
   69.95 +                        <implementation-version/>
   69.96 +                    </run-dependency>
   69.97 +                </dependency>
   69.98 +                <dependency>
   69.99 +                    <code-name-base>org.netbeans.modules.project.ant</code-name-base>
  69.100 +                    <build-prerequisite/>
  69.101 +                    <compile-dependency/>
  69.102 +                    <run-dependency>
  69.103 +                        <release-version>1</release-version>
  69.104 +                        <specification-version>1.39</specification-version>
  69.105 +                    </run-dependency>
  69.106 +                </dependency>
  69.107 +                <dependency>
  69.108 +                    <code-name-base>org.netbeans.modules.projectapi</code-name-base>
  69.109 +                    <build-prerequisite/>
  69.110 +                    <compile-dependency/>
  69.111 +                    <run-dependency>
  69.112 +                        <release-version>1</release-version>
  69.113 +                        <specification-version>1.34</specification-version>
  69.114 +                    </run-dependency>
  69.115 +                </dependency>
  69.116 +                <dependency>
  69.117 +                    <code-name-base>org.netbeans.modules.projectuiapi</code-name-base>
  69.118 +                    <build-prerequisite/>
  69.119 +                    <compile-dependency/>
  69.120 +                    <run-dependency>
  69.121 +                        <release-version>1</release-version>
  69.122 +                        <specification-version>1.49.0.8</specification-version>
  69.123 +                    </run-dependency>
  69.124 +                </dependency>
  69.125 +                <dependency>
  69.126 +                    <code-name-base>org.netbeans.modules.sendopts</code-name-base>
  69.127 +                    <build-prerequisite/>
  69.128 +                    <compile-dependency/>
  69.129 +                    <run-dependency>
  69.130 +                        <release-version>2</release-version>
  69.131 +                        <specification-version>2.11</specification-version>
  69.132 +                    </run-dependency>
  69.133 +                </dependency>
  69.134 +                <dependency>
  69.135 +                    <code-name-base>org.netbeans.modules.servletjspapi</code-name-base>
  69.136 +                    <build-prerequisite/>
  69.137 +                    <compile-dependency/>
  69.138 +                    <run-dependency>
  69.139 +                        <release-version>1</release-version>
  69.140 +                        <specification-version>1.10.0.25</specification-version>
  69.141 +                    </run-dependency>
  69.142 +                </dependency>
  69.143 +                <dependency>
  69.144 +                    <code-name-base>org.netbeans.modules.websvc.restlib</code-name-base>
  69.145 +                    <build-prerequisite/>
  69.146 +                    <compile-dependency/>
  69.147 +                    <run-dependency>
  69.148 +                        <release-version>0</release-version>
  69.149 +                        <specification-version>1.9</specification-version>
  69.150 +                    </run-dependency>
  69.151 +                </dependency>
  69.152 +                <dependency>
  69.153 +                    <code-name-base>org.netbeans.spi.editor.hints</code-name-base>
  69.154 +                    <build-prerequisite/>
  69.155 +                    <compile-dependency/>
  69.156 +                    <run-dependency>
  69.157 +                        <release-version>0</release-version>
  69.158 +                        <specification-version>1.16.0.7.6</specification-version>
  69.159 +                    </run-dependency>
  69.160 +                </dependency>
  69.161 +                <dependency>
  69.162 +                    <code-name-base>org.openide.filesystems</code-name-base>
  69.163 +                    <build-prerequisite/>
  69.164 +                    <compile-dependency/>
  69.165 +                    <run-dependency>
  69.166 +                        <specification-version>7.45</specification-version>
  69.167 +                    </run-dependency>
  69.168 +                </dependency>
  69.169 +                <dependency>
  69.170 +                    <code-name-base>org.openide.modules</code-name-base>
  69.171 +                    <build-prerequisite/>
  69.172 +                    <compile-dependency/>
  69.173 +                    <run-dependency>
  69.174 +                        <specification-version>7.21</specification-version>
  69.175 +                    </run-dependency>
  69.176 +                </dependency>
  69.177 +                <dependency>
  69.178 +                    <code-name-base>org.openide.text</code-name-base>
  69.179 +                    <build-prerequisite/>
  69.180 +                    <compile-dependency/>
  69.181 +                    <run-dependency>
  69.182 +                        <specification-version>6.35</specification-version>
  69.183 +                    </run-dependency>
  69.184 +                </dependency>
  69.185 +                <dependency>
  69.186 +                    <code-name-base>org.openide.util</code-name-base>
  69.187 +                    <build-prerequisite/>
  69.188 +                    <compile-dependency/>
  69.189 +                    <run-dependency>
  69.190 +                        <specification-version>8.12</specification-version>
  69.191 +                    </run-dependency>
  69.192 +                </dependency>
  69.193 +                <dependency>
  69.194 +                    <code-name-base>org.openide.util.lookup</code-name-base>
  69.195 +                    <build-prerequisite/>
  69.196 +                    <compile-dependency/>
  69.197 +                    <run-dependency>
  69.198 +                        <specification-version>8.5</specification-version>
  69.199 +                    </run-dependency>
  69.200 +                </dependency>
  69.201 +            </module-dependencies>
  69.202 +            <test-dependencies>
  69.203 +                <test-type>
  69.204 +                    <name>unit</name>
  69.205 +                    <test-dependency>
  69.206 +                        <code-name-base>org.netbeans.libs.junit4</code-name-base>
  69.207 +                        <compile-dependency/>
  69.208 +                    </test-dependency>
  69.209 +                    <test-dependency>
  69.210 +                        <code-name-base>org.netbeans.modules.junitlib</code-name-base>
  69.211 +                        <compile-dependency/>
  69.212 +                    </test-dependency>
  69.213 +                    <test-dependency>
  69.214 +                        <code-name-base>org.netbeans.modules.nbjunit</code-name-base>
  69.215 +                        <recursive/>
  69.216 +                        <compile-dependency/>
  69.217 +                    </test-dependency>
  69.218 +                </test-type>
  69.219 +            </test-dependencies>
  69.220 +            <public-packages/>
  69.221 +        </data>
  69.222 +    </configuration>
  69.223 +</project>
    70.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    70.2 +++ b/server/backend/impl/nbproject/suite.properties	Fri Feb 18 20:16:26 2011 +0100
    70.3 @@ -0,0 +1,1 @@
    70.4 +suite.dir=${basedir}/..
    71.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    71.2 +++ b/server/backend/impl/src/org/netbeans/modules/jackpot30/backend/impl/Bundle.properties	Fri Feb 18 20:16:26 2011 +0100
    71.3 @@ -0,0 +1,1 @@
    71.4 +OpenIDE-Module-Name=Jackpot 3.0 Backend Impl
    72.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    72.2 +++ b/server/backend/impl/src/org/netbeans/modules/jackpot30/backend/impl/CategoryStorage.java	Fri Feb 18 20:16:26 2011 +0100
    72.3 @@ -0,0 +1,126 @@
    72.4 +/*
    72.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    72.6 + *
    72.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
    72.8 + *
    72.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   72.10 + * Other names may be trademarks of their respective owners.
   72.11 + *
   72.12 + * The contents of this file are subject to the terms of either the GNU
   72.13 + * General Public License Version 2 only ("GPL") or the Common
   72.14 + * Development and Distribution License("CDDL") (collectively, the
   72.15 + * "License"). You may not use this file except in compliance with the
   72.16 + * License. You can obtain a copy of the License at
   72.17 + * http://www.netbeans.org/cddl-gplv2.html
   72.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   72.19 + * specific language governing permissions and limitations under the
   72.20 + * License.  When distributing the software, include this License Header
   72.21 + * Notice in each file and include the License file at
   72.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   72.23 + * particular file as subject to the "Classpath" exception as provided
   72.24 + * by Oracle in the GPL Version 2 section of the License file that
   72.25 + * accompanied this code. If applicable, add the following below the
   72.26 + * License Header, with the fields enclosed by brackets [] replaced by
   72.27 + * your own identifying information:
   72.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   72.29 + *
   72.30 + * If you wish your version of this file to be governed by only the CDDL
   72.31 + * or only the GPL Version 2, indicate your decision by adding
   72.32 + * "[Contributor] elects to include this software in this distribution
   72.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   72.34 + * single choice of license, a recipient has the option to distribute
   72.35 + * your version of this file under either the CDDL, the GPL Version 2 or
   72.36 + * to extend the choice of license to its licensees as provided above.
   72.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   72.38 + * Version 2 license, then the option applies only if the new code is
   72.39 + * made subject to such option by the copyright holder.
   72.40 + *
   72.41 + * Contributor(s):
   72.42 + *
   72.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
   72.44 + */
   72.45 +package org.netbeans.modules.jackpot30.backend.impl;
   72.46 +
   72.47 +import java.net.MalformedURLException;
   72.48 +import java.net.URL;
   72.49 +import java.util.HashMap;
   72.50 +import java.util.HashSet;
   72.51 +import java.util.Map;
   72.52 +import java.util.Set;
   72.53 +import java.util.prefs.BackingStoreException;
   72.54 +import java.util.prefs.Preferences;
   72.55 +import org.openide.filesystems.FileObject;
   72.56 +import org.openide.filesystems.FileStateInvalidException;
   72.57 +import org.openide.filesystems.URLMapper;
   72.58 +import org.openide.util.Exceptions;
   72.59 +import org.openide.util.NbPreferences;
   72.60 +
   72.61 +/**
   72.62 + *
   72.63 + * @author lahvac
   72.64 + */
   72.65 +public class CategoryStorage {
   72.66 +
   72.67 +    public static void setCategoryContent(String categoryId, String categoryName, Set<FileObject> content) {
   72.68 +        Preferences categoriesNode = NbPreferences.forModule(CategoryStorage.class).node("categories");
   72.69 +
   72.70 +        categoriesNode.put(categoryId + "_displayName", categoryName);
   72.71 +
   72.72 +        StringBuilder roots = new StringBuilder();
   72.73 +
   72.74 +        for (FileObject f : content) {
   72.75 +            if (roots.length() > 0) {
   72.76 +                roots.append(';');
   72.77 +            }
   72.78 +
   72.79 +            try {
   72.80 +                roots.append(f.getURL().toExternalForm());
   72.81 +            } catch (FileStateInvalidException ex) {
   72.82 +                Exceptions.printStackTrace(ex);
   72.83 +            }
   72.84 +        }
   72.85 +
   72.86 +        categoriesNode.put(categoryId + "_roots", roots.toString());
   72.87 +    }
   72.88 +
   72.89 +    public static Set<FileObject> getCategoryContent(String categoryId) {
   72.90 +        Preferences categoriesNode = NbPreferences.forModule(CategoryStorage.class).node("categories");
   72.91 +        String roots = categoriesNode.get(categoryId + "_roots", "");
   72.92 +        Set<FileObject> result = new HashSet<FileObject>();
   72.93 +
   72.94 +        for (String urlString : roots.split(";")) {
   72.95 +            if (urlString.isEmpty()) continue;
   72.96 +
   72.97 +            try {
   72.98 +                URL url = new URL(urlString);
   72.99 +                FileObject root = URLMapper.findFileObject(url);
  72.100 +
  72.101 +                if (root != null) {
  72.102 +                    result.add(root);
  72.103 +                }
  72.104 +            } catch (MalformedURLException ex) {
  72.105 +                Exceptions.printStackTrace(ex);
  72.106 +            }
  72.107 +        }
  72.108 +
  72.109 +        return result;
  72.110 +    }
  72.111 +
  72.112 +    public static Map<String, String> listCategoriesWithNames() {
  72.113 +        Map<String, String> result = new HashMap<String, String>();
  72.114 +        Preferences categoriesNode = NbPreferences.forModule(CategoryStorage.class).node("categories");
  72.115 +
  72.116 +        try {
  72.117 +            for (String key : categoriesNode.keys()) {
  72.118 +                if (key.endsWith("_displayName")) {
  72.119 +                    String id = key.substring(0, key.length() - "_displayName".length());
  72.120 +                    result.put(id, categoriesNode.get(key, id));
  72.121 +                }
  72.122 +            }
  72.123 +        } catch (BackingStoreException ex) {
  72.124 +            Exceptions.printStackTrace(ex);
  72.125 +        }
  72.126 +
  72.127 +        return result;
  72.128 +    }
  72.129 +}
    73.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    73.2 +++ b/server/backend/impl/src/org/netbeans/modules/jackpot30/backend/impl/MainPage.java	Fri Feb 18 20:16:26 2011 +0100
    73.3 @@ -0,0 +1,59 @@
    73.4 +/*
    73.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    73.6 + *
    73.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
    73.8 + *
    73.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   73.10 + * Other names may be trademarks of their respective owners.
   73.11 + *
   73.12 + * The contents of this file are subject to the terms of either the GNU
   73.13 + * General Public License Version 2 only ("GPL") or the Common
   73.14 + * Development and Distribution License("CDDL") (collectively, the
   73.15 + * "License"). You may not use this file except in compliance with the
   73.16 + * License. You can obtain a copy of the License at
   73.17 + * http://www.netbeans.org/cddl-gplv2.html
   73.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   73.19 + * specific language governing permissions and limitations under the
   73.20 + * License.  When distributing the software, include this License Header
   73.21 + * Notice in each file and include the License file at
   73.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   73.23 + * particular file as subject to the "Classpath" exception as provided
   73.24 + * by Oracle in the GPL Version 2 section of the License file that
   73.25 + * accompanied this code. If applicable, add the following below the
   73.26 + * License Header, with the fields enclosed by brackets [] replaced by
   73.27 + * your own identifying information:
   73.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   73.29 + *
   73.30 + * If you wish your version of this file to be governed by only the CDDL
   73.31 + * or only the GPL Version 2, indicate your decision by adding
   73.32 + * "[Contributor] elects to include this software in this distribution
   73.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   73.34 + * single choice of license, a recipient has the option to distribute
   73.35 + * your version of this file under either the CDDL, the GPL Version 2 or
   73.36 + * to extend the choice of license to its licensees as provided above.
   73.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   73.38 + * Version 2 license, then the option applies only if the new code is
   73.39 + * made subject to such option by the copyright holder.
   73.40 + *
   73.41 + * Contributor(s):
   73.42 + *
   73.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
   73.44 + */
   73.45 +
   73.46 +package org.netbeans.modules.jackpot30.backend.impl;
   73.47 +
   73.48 +import javax.ws.rs.GET;
   73.49 +import javax.ws.rs.Path;
   73.50 +
   73.51 +/**
   73.52 + *
   73.53 + * @author lahvac
   73.54 + */
   73.55 +@Path("/")
   73.56 +public class MainPage {
   73.57 +
   73.58 +    @GET
   73.59 +    public String main() {
   73.60 +        return "<html><body><ul><li><a href='index/ui/search'>Search Pattern</a></li><li><a href='index/ui/apply'>Apply Pattern</a></li></ul></body></html>";
   73.61 +    }
   73.62 +}
    74.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    74.2 +++ b/server/backend/impl/src/org/netbeans/modules/jackpot30/backend/impl/OptionProcessorImpl.java	Fri Feb 18 20:16:26 2011 +0100
    74.3 @@ -0,0 +1,226 @@
    74.4 +/*
    74.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    74.6 + *
    74.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
    74.8 + *
    74.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   74.10 + * Other names may be trademarks of their respective owners.
   74.11 + *
   74.12 + * The contents of this file are subject to the terms of either the GNU
   74.13 + * General Public License Version 2 only ("GPL") or the Common
   74.14 + * Development and Distribution License("CDDL") (collectively, the
   74.15 + * "License"). You may not use this file except in compliance with the
   74.16 + * License. You can obtain a copy of the License at
   74.17 + * http://www.netbeans.org/cddl-gplv2.html
   74.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   74.19 + * specific language governing permissions and limitations under the
   74.20 + * License.  When distributing the software, include this License Header
   74.21 + * Notice in each file and include the License file at
   74.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   74.23 + * particular file as subject to the "Classpath" exception as provided
   74.24 + * by Oracle in the GPL Version 2 section of the License file that
   74.25 + * accompanied this code. If applicable, add the following below the
   74.26 + * License Header, with the fields enclosed by brackets [] replaced by
   74.27 + * your own identifying information:
   74.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   74.29 + *
   74.30 + * If you wish your version of this file to be governed by only the CDDL
   74.31 + * or only the GPL Version 2, indicate your decision by adding
   74.32 + * "[Contributor] elects to include this software in this distribution
   74.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   74.34 + * single choice of license, a recipient has the option to distribute
   74.35 + * your version of this file under either the CDDL, the GPL Version 2 or
   74.36 + * to extend the choice of license to its licensees as provided above.
   74.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   74.38 + * Version 2 license, then the option applies only if the new code is
   74.39 + * made subject to such option by the copyright holder.
   74.40 + *
   74.41 + * Contributor(s):
   74.42 + *
   74.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
   74.44 + */
   74.45 +
   74.46 +package org.netbeans.modules.jackpot30.backend.impl;
   74.47 +
   74.48 +import com.sun.jersey.api.container.httpserver.HttpServerFactory;
   74.49 +import com.sun.jersey.api.core.ClassNamesResourceConfig;
   74.50 +import com.sun.net.httpserver.HttpServer;
   74.51 +import java.io.File;
   74.52 +import java.io.IOException;
   74.53 +import java.util.Arrays;
   74.54 +import java.util.HashSet;
   74.55 +import java.util.Map;
   74.56 +import java.util.Set;
   74.57 +import org.netbeans.api.java.classpath.ClassPath;
   74.58 +import org.netbeans.api.java.classpath.GlobalPathRegistry;
   74.59 +import org.netbeans.api.java.source.SourceUtils;
   74.60 +import org.netbeans.api.project.Project;
   74.61 +import org.netbeans.api.project.ProjectManager;
   74.62 +import org.netbeans.api.project.ProjectUtils;
   74.63 +import org.netbeans.api.project.SourceGroup;
   74.64 +import org.netbeans.api.sendopts.CommandException;
   74.65 +import org.netbeans.modules.jackpot30.backend.impl.api.API;
   74.66 +import org.netbeans.modules.jackpot30.backend.impl.ui.UI;
   74.67 +import org.netbeans.modules.jackpot30.impl.indexing.CustomIndexerImpl;
   74.68 +import org.netbeans.spi.java.classpath.support.ClassPathSupport;
   74.69 +import org.netbeans.spi.project.support.ant.PropertyUtils;
   74.70 +import org.netbeans.spi.sendopts.Env;
   74.71 +import org.netbeans.spi.sendopts.Option;
   74.72 +import org.netbeans.spi.sendopts.OptionProcessor;
   74.73 +import org.openide.LifecycleManager;
   74.74 +import org.openide.filesystems.FileObject;
   74.75 +import org.openide.filesystems.FileUtil;
   74.76 +import org.openide.util.Exceptions;
   74.77 +import org.openide.util.lookup.ServiceProvider;
   74.78 +
   74.79 +/**
   74.80 + *
   74.81 + * @author lahvac
   74.82 + */
   74.83 +@ServiceProvider(service=OptionProcessor.class)
   74.84 +public class OptionProcessorImpl extends OptionProcessor {
   74.85 +
   74.86 +    private final Option SHUTDOWN = Option.withoutArgument(Option.NO_SHORT_NAME, "shutdown");
   74.87 +    private final Option RESTART = Option.withoutArgument(Option.NO_SHORT_NAME, "restart"); //XXX: does not currently work
   74.88 +    private final Option START_SERVER = Option.withoutArgument(Option.NO_SHORT_NAME, "start-server");
   74.89 +    private final Option INDEX = Option.withoutArgument(Option.NO_SHORT_NAME, "index");
   74.90 +    private final Option CATEGORY_ID = Option.requiredArgument(Option.NO_SHORT_NAME, "category-id");
   74.91 +    private final Option CATEGORY_NAME = Option.requiredArgument(Option.NO_SHORT_NAME, "category-name");
   74.92 +    private final Option CATEGORY_PROJECTS = Option.additionalArguments(Option.NO_SHORT_NAME, "category-projects");
   74.93 +    private final Set<Option> OPTIONS = new HashSet<Option>(Arrays.asList(SHUTDOWN, RESTART, START_SERVER, INDEX, CATEGORY_ID, CATEGORY_NAME, CATEGORY_PROJECTS));
   74.94 +    
   74.95 +    @Override
   74.96 +    protected Set<Option> getOptions() {
   74.97 +        return OPTIONS;
   74.98 +    }
   74.99 +
  74.100 +    @Override
  74.101 +    protected void process(Env env, Map<Option, String[]> optionValues) throws CommandException {
  74.102 +        if (optionValues.containsKey(RESTART)) {
  74.103 +            LifecycleManager.getDefault().markForRestart();
  74.104 +        }
  74.105 +
  74.106 +        if (optionValues.containsKey(SHUTDOWN) || optionValues.containsKey(RESTART)) {
  74.107 +            LifecycleManager.getDefault().exit();
  74.108 +        }
  74.109 +
  74.110 +        if (optionValues.containsKey(START_SERVER)) {
  74.111 +            startServer(env);
  74.112 +        }
  74.113 +
  74.114 +        String categoryId = null;
  74.115 +        String categoryName = null;
  74.116 +
  74.117 +        if (optionValues.containsKey(CATEGORY_ID)) {
  74.118 +            categoryId = optionValues.get(CATEGORY_ID)[0];
  74.119 +        }
  74.120 +
  74.121 +        if (optionValues.containsKey(CATEGORY_NAME)) {
  74.122 +            categoryName = optionValues.get(CATEGORY_NAME)[0];
  74.123 +        }
  74.124 +
  74.125 +        if (optionValues.containsKey(CATEGORY_PROJECTS)) {
  74.126 +            if (categoryId == null) {
  74.127 +                env.getErrorStream().println("Error: no category-id specified!");
  74.128 +                return;
  74.129 +            }
  74.130 +
  74.131 +            if (categoryName == null) {
  74.132 +                env.getErrorStream().println("Warning: no category-name specified.");
  74.133 +                return;
  74.134 +            }
  74.135 +
  74.136 +            try {
  74.137 +                CategoryStorage.setCategoryContent(categoryId, categoryName, getRoots(optionValues.get(CATEGORY_PROJECTS), env));
  74.138 +            } catch (InterruptedException ex) {
  74.139 +                throw (CommandException) new CommandException(0).initCause(ex);
  74.140 +            }
  74.141 +        }
  74.142 +
  74.143 +        if (optionValues.containsKey(INDEX)) {
  74.144 +            if (categoryId == null) {
  74.145 +                env.getErrorStream().println("Error: no category-id specified!");
  74.146 +                return;
  74.147 +            }
  74.148 +            
  74.149 +            try {
  74.150 +                indexProjects(CategoryStorage.getCategoryContent(categoryId), env);
  74.151 +            } catch (InterruptedException ex) {
  74.152 +                throw (CommandException) new CommandException(0).initCause(ex);
  74.153 +            }
  74.154 +        }
  74.155 +    }
  74.156 +
  74.157 +    private Set<FileObject> getRoots(String[] projects, Env env) throws IllegalArgumentException, InterruptedException {
  74.158 +        Set<FileObject> sourceRoots = new HashSet<FileObject>(projects.length * 4 / 3 + 1);
  74.159 +
  74.160 +        for (String p : projects) {
  74.161 +            File f = PropertyUtils.resolveFile(env.getCurrentDirectory(), p);
  74.162 +            File normalized = FileUtil.normalizeFile(f);
  74.163 +            FileObject prjFO = FileUtil.toFileObject(normalized);
  74.164 +
  74.165 +            if (prjFO == null) {
  74.166 +                env.getErrorStream().println("Project location cannot be found: " + p);
  74.167 +                continue;
  74.168 +            }
  74.169 +
  74.170 +            if (!prjFO.isFolder()) {
  74.171 +                env.getErrorStream().println("Project specified as: " + p + " does not point to a directory (" + FileUtil.getFileDisplayName(prjFO));
  74.172 +                continue;
  74.173 +            }
  74.174 +
  74.175 +            try {
  74.176 +                Project prj = ProjectManager.getDefault().findProject(prjFO);
  74.177 +
  74.178 +                if (prj == null) {
  74.179 +                    env.getErrorStream().println("Project specified as: " + p + " does not resolve to a project (" + FileUtil.getFileDisplayName(prjFO));
  74.180 +                    continue;
  74.181 +                }
  74.182 +
  74.183 +                SourceGroup[] javaSG = ProjectUtils.getSources(prj).getSourceGroups("java");
  74.184 +
  74.185 +                if (javaSG.length == 0) {
  74.186 +                    env.getErrorStream().println("Project specified as: " + p + " does not define a java source groups (" + FileUtil.getFileDisplayName(prjFO));
  74.187 +                    continue;
  74.188 +                }
  74.189 +
  74.190 +                for (SourceGroup sg : javaSG) {
  74.191 +                    sourceRoots.add(sg.getRootFolder());
  74.192 +                }
  74.193 +            } catch (IOException ex) {
  74.194 +                Exceptions.printStackTrace(ex);
  74.195 +            } catch (IllegalArgumentException ex) {
  74.196 +                Exceptions.printStackTrace(ex);
  74.197 +            }
  74.198 +        }
  74.199 +
  74.200 +        return sourceRoots;
  74.201 +    }
  74.202 +
  74.203 +    private void indexProjects(Set<FileObject> sourceRoots, Env env) throws IllegalArgumentException, InterruptedException {
  74.204 +        if (sourceRoots.isEmpty()) {
  74.205 +            env.getErrorStream().println("Error: There is nothing to index!");
  74.206 +        } else {
  74.207 +            System.setProperty(CustomIndexerImpl.class.getName() + "-attributed", "true");//force partially attributed Jackpot index
  74.208 +            org.netbeans.api.project.ui.OpenProjects.getDefault().getOpenProjects();
  74.209 +            ClassPath source = ClassPathSupport.createClassPath(sourceRoots.toArray(new FileObject[0]));
  74.210 +
  74.211 +            GlobalPathRegistry.getDefault().register(ClassPath.SOURCE, new ClassPath[] {source});
  74.212 +            SourceUtils.waitScanFinished();
  74.213 +            GlobalPathRegistry.getDefault().unregister(ClassPath.SOURCE, new ClassPath[] {source});
  74.214 +        }
  74.215 +    }
  74.216 +
  74.217 +    private void startServer(Env env) {
  74.218 +        try {
  74.219 +            HttpServer server = HttpServerFactory.create("http://localhost:9998/", new ClassNamesResourceConfig(API.class, UI.class, MainPage.class));
  74.220 +
  74.221 +            server.start();
  74.222 +        } catch (IOException ex) {
  74.223 +            Exceptions.printStackTrace(ex);
  74.224 +        } catch (IllegalArgumentException ex) {
  74.225 +            Exceptions.printStackTrace(ex);
  74.226 +        }
  74.227 +    }
  74.228 +
  74.229 +}
    75.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    75.2 +++ b/server/backend/impl/src/org/netbeans/modules/jackpot30/backend/impl/api/API.java	Fri Feb 18 20:16:26 2011 +0100
    75.3 @@ -0,0 +1,528 @@
    75.4 +/*
    75.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    75.6 + *
    75.7 + * Copyright 2009-2010 Sun Microsystems, Inc. All rights reserved.
    75.8 + *
    75.9 + * The contents of this file are subject to the terms of either the GNU
   75.10 + * General Public License Version 2 only ("GPL") or the Common
   75.11 + * Development and Distribution License("CDDL") (collectively, the
   75.12 + * "License"). You may not use this file except in compliance with the
   75.13 + * License. You can obtain a copy of the License at
   75.14 + * http://www.netbeans.org/cddl-gplv2.html
   75.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   75.16 + * specific language governing permissions and limitations under the
   75.17 + * License.  When distributing the software, include this License Header
   75.18 + * Notice in each file and include the License file at
   75.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   75.20 + * particular file as subject to the "Classpath" exception as provided
   75.21 + * by Sun in the GPL Version 2 section of the License file that
   75.22 + * accompanied this code. If applicable, add the following below the
   75.23 + * License Header, with the fields enclosed by brackets [] replaced by
   75.24 + * your own identifying information:
   75.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   75.26 + *
   75.27 + * If you wish your version of this file to be governed by only the CDDL
   75.28 + * or only the GPL Version 2, indicate your decision by adding
   75.29 + * "[Contributor] elects to include this software in this distribution
   75.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   75.31 + * single choice of license, a recipient has the option to distribute
   75.32 + * your version of this file under either the CDDL, the GPL Version 2 or
   75.33 + * to extend the choice of license to its licensees as provided above.
   75.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   75.35 + * Version 2 license, then the option applies only if the new code is
   75.36 + * made subject to such option by the copyright holder.
   75.37 + *
   75.38 + * Contributor(s):
   75.39 + *
   75.40 + * Portions Copyrighted 2009-2010 Sun Microsystems, Inc.
   75.41 + */
   75.42 +
   75.43 +package org.netbeans.modules.jackpot30.backend.impl.api;
   75.44 +
   75.45 +import java.io.File;
   75.46 +import java.io.IOException;
   75.47 +import java.io.OutputStream;
   75.48 +import java.io.OutputStreamWriter;
   75.49 +import java.io.StringWriter;
   75.50 +import java.io.Writer;
   75.51 +import java.lang.reflect.Method;
   75.52 +import java.lang.reflect.Modifier;
   75.53 +import java.net.URL;
   75.54 +import java.util.ArrayList;
   75.55 +import java.util.Arrays;
   75.56 +import java.util.Collection;
   75.57 +import java.util.Collections;
   75.58 +import java.util.EnumSet;
   75.59 +import java.util.HashMap;
   75.60 +import java.util.HashSet;
   75.61 +import java.util.LinkedHashMap;
   75.62 +import java.util.LinkedList;
   75.63 +import java.util.List;
   75.64 +import java.util.Map;
   75.65 +import java.util.Map.Entry;
   75.66 +import java.util.Set;
   75.67 +import java.util.concurrent.atomic.AtomicBoolean;
   75.68 +import java.util.concurrent.atomic.AtomicLong;
   75.69 +import javax.lang.model.element.TypeElement;
   75.70 +import javax.tools.Diagnostic;
   75.71 +import javax.tools.JavaFileObject;
   75.72 +import javax.ws.rs.DefaultValue;
   75.73 +import javax.ws.rs.GET;
   75.74 +import javax.ws.rs.Path;
   75.75 +import javax.ws.rs.Produces;
   75.76 +import javax.ws.rs.QueryParam;
   75.77 +import javax.ws.rs.WebApplicationException;
   75.78 +import javax.ws.rs.core.StreamingOutput;
   75.79 +import org.codeviation.pojson.Pojson;
   75.80 +import org.netbeans.api.java.classpath.ClassPath;
   75.81 +import org.netbeans.api.java.source.ClassIndex.NameKind;
   75.82 +import org.netbeans.api.java.source.ClassIndex.SearchScope;
   75.83 +import org.netbeans.api.java.source.ClasspathInfo;
   75.84 +import org.netbeans.api.java.source.CompilationController;
   75.85 +import org.netbeans.api.java.source.ElementHandle;
   75.86 +import org.netbeans.api.java.source.ModificationResult;
   75.87 +import org.netbeans.modules.jackpot30.backend.impl.CategoryStorage;
   75.88 +import org.netbeans.modules.jackpot30.impl.MessageImpl;
   75.89 +import org.netbeans.modules.jackpot30.impl.batch.BatchSearch;
   75.90 +import org.netbeans.modules.jackpot30.impl.batch.BatchSearch.BatchResult;
   75.91 +import org.netbeans.modules.jackpot30.impl.batch.BatchSearch.Resource;
   75.92 +import org.netbeans.modules.jackpot30.impl.batch.BatchSearch.Scope;
   75.93 +import org.netbeans.modules.jackpot30.impl.batch.BatchUtilities;
   75.94 +import org.netbeans.modules.jackpot30.impl.batch.ProgressHandleWrapper;
   75.95 +import org.netbeans.modules.jackpot30.impl.examples.Example;
   75.96 +import org.netbeans.modules.jackpot30.impl.examples.Example.Option;
   75.97 +import org.netbeans.modules.jackpot30.impl.examples.LoadExamples;
   75.98 +import org.netbeans.modules.jackpot30.impl.indexing.Cache;
   75.99 +import org.netbeans.modules.jackpot30.impl.indexing.FileBasedIndex;
  75.100 +import org.netbeans.modules.jackpot30.impl.indexing.Index;
  75.101 +import org.netbeans.modules.jackpot30.spi.HintDescription;
  75.102 +import org.netbeans.modules.jackpot30.spi.PatternConvertor;
  75.103 +import org.netbeans.modules.java.source.usages.ClassIndexManager;
  75.104 +import org.netbeans.modules.jumpto.type.GoToTypeAction;
  75.105 +import org.netbeans.spi.editor.hints.ErrorDescription;
  75.106 +import org.netbeans.spi.java.classpath.support.ClassPathSupport;
  75.107 +import org.openide.filesystems.FileObject;
  75.108 +import org.openide.filesystems.FileUtil;
  75.109 +import org.openide.util.Exceptions;
  75.110 +
  75.111 +/**
  75.112 + *
  75.113 + * @author lahvac
  75.114 + */
  75.115 +@Path("/index")
  75.116 +public class API {
  75.117 +
  75.118 +    @GET
  75.119 +    @Path("/find")
  75.120 +    @Produces("text/plain")
  75.121 +    //TODO: parameter for "verified"?
  75.122 +    public String find(@QueryParam("path") String segment, @QueryParam("pattern") String pattern, @QueryParam("asynchronous") @DefaultValue(value="false") boolean asynchronous) throws IOException {
  75.123 +        assert !asynchronous;
  75.124 +
  75.125 +        Iterable<? extends HintDescription> hints = PatternConvertor.create(pattern);
  75.126 +        Set<FileObject> srcRoots = CategoryStorage.getCategoryContent(segment);
  75.127 +        final FileObject deepestCommonParent = deepestCommonParent(srcRoots);
  75.128 +        BatchResult batchResult = BatchSearch.findOccurrences(hints, Scope.createGivenSourceRoots(true, srcRoots.toArray(new FileObject[0])));
  75.129 +        final StringBuilder result = new StringBuilder();
  75.130 +
  75.131 +        BatchSearch.getVerifiedSpans(batchResult, new ProgressHandleWrapper(1), new BatchSearch.VerifiedSpansCallBack() {
  75.132 +            @Override public void groupStarted() {}
  75.133 +            @Override public boolean spansVerified(CompilationController wc, Resource r, Collection<? extends ErrorDescription> hints) throws Exception {
  75.134 +                if (!hints.isEmpty()) {
  75.135 +                    result.append(FileUtil.getRelativePath(deepestCommonParent, r.getResolvedFile()));
  75.136 +                    result.append("\n");
  75.137 +                }
  75.138 +                System.err.println("processed file=" + r.getRelativePath());
  75.139 +                return true;
  75.140 +            }
  75.141 +            @Override public void groupFinished() {}
  75.142 +            @Override public void cannotVerifySpan(Resource r) { /*TODO: warn user?*/ }
  75.143 +        }, true, new LinkedList<MessageImpl>()); //TODO: show the messages to the user?
  75.144 +
  75.145 +        return result.toString();
  75.146 +    }
  75.147 +
  75.148 +//    @GET
  75.149 +//    @Path("/findCategorize")
  75.150 +//    @Produces("text/plain")
  75.151 +//    public String findCategorize(@QueryParam("path") final String segment, @QueryParam("pattern") final String pattern, @QueryParam("asynchronous") @DefaultValue(value="false") boolean asynchronous) throws IOException {
  75.152 +//        assert asynchronous;
  75.153 +//
  75.154 +//        long id = this.id.getAndIncrement();
  75.155 +//        final ProgressImpl progress = new ProgressImpl();
  75.156 +//
  75.157 +//        workInProgress.put(id, progress);
  75.158 +//
  75.159 +//        new Thread(new Runnable() {
  75.160 +//            public void run() {
  75.161 +//                try {
  75.162 +//                    File sourceRoot = Cache.sourceRootForKey(segment);
  75.163 +//                    Index idx = FileBasedIndex.get(sourceRoot.toURI().toURL());
  75.164 +//                    new SortedQuery().query(idx, pattern, progress);
  75.165 +//                } catch (IOException ex) {
  75.166 +//                    ex.printStackTrace();
  75.167 +//                    progress.finish();
  75.168 +//                }
  75.169 +//            }
  75.170 +//        }).start();
  75.171 +//
  75.172 +//        return Long.toString(id);
  75.173 +//    }
  75.174 +
  75.175 +    @GET
  75.176 +    @Path("/findSpans")
  75.177 +    @Produces("text/plain")
  75.178 +    public String findSpans(@QueryParam("path") String segment, @QueryParam("relativePath") String relativePath, @QueryParam("pattern") String pattern) throws IOException {
  75.179 +        Iterable<? extends HintDescription> hints = PatternConvertor.create(pattern);
  75.180 +        Set<FileObject> srcRoots = CategoryStorage.getCategoryContent(segment);
  75.181 +        FileObject deepestCommonParent = deepestCommonParent(srcRoots);
  75.182 +        BatchResult batchResult = BatchSearch.findOccurrences(hints, Scope.createGivenSourceRoots(deepestCommonParent.getFileObject(relativePath)));
  75.183 +        final StringBuilder result = new StringBuilder();
  75.184 +
  75.185 +        BatchSearch.getVerifiedSpans(batchResult, new ProgressHandleWrapper(1), new BatchSearch.VerifiedSpansCallBack() {
  75.186 +            @Override public void groupStarted() {}
  75.187 +            @Override public boolean spansVerified(CompilationController wc, Resource r, Collection<? extends ErrorDescription> hints) throws Exception {
  75.188 +                for (ErrorDescription ed : hints) {
  75.189 +                    result.append(ed.getRange().getBegin().getOffset());
  75.190 +                    result.append(":");
  75.191 +                    result.append(ed.getRange().getEnd().getOffset());
  75.192 +                    result.append(":");
  75.193 +                }
  75.194 +                return true;
  75.195 +            }
  75.196 +            @Override public void groupFinished() {}
  75.197 +            @Override public void cannotVerifySpan(Resource r) { /*TODO: warn user?*/ }
  75.198 +        }, true, new LinkedList<MessageImpl>()); //TODO: show the messages to the user?
  75.199 +
  75.200 +        if (result.length() > 0) {
  75.201 +            result.delete(result.length() - 1, result.length());
  75.202 +        }
  75.203 +        return result.toString();
  75.204 +    }
  75.205 +
  75.206 +    @GET
  75.207 +    @Path("/list")
  75.208 +    @Produces("text/plain")
  75.209 +    public String list() throws IOException {
  75.210 +        StringBuilder sb = new StringBuilder();
  75.211 +
  75.212 +        for (Entry<String, String> e : CategoryStorage.listCategoriesWithNames().entrySet()) {
  75.213 +            sb.append(e.getKey());
  75.214 +            sb.append(":");
  75.215 +            sb.append(e.getValue());
  75.216 +            sb.append("\n");
  75.217 +        }
  75.218 +
  75.219 +        return sb.toString();
  75.220 +    }
  75.221 +
  75.222 +    @GET
  75.223 +    @Path("/cat")
  75.224 +    @Produces("text/plain")
  75.225 +    public String cat(@QueryParam("path") String segment, @QueryParam("relative") String relative) throws IOException {
  75.226 +        Set<FileObject> srcRoots = CategoryStorage.getCategoryContent(segment);
  75.227 +        FileObject deepestCommonParent = deepestCommonParent(srcRoots);
  75.228 +        FileObject file = deepestCommonParent.getFileObject(relative);
  75.229 +        ClassPath cp = ClassPathSupport.createClassPath(srcRoots.toArray(new FileObject[0]));
  75.230 +        FileObject root = cp.findOwnerRoot(file);
  75.231 +        String path = cp.getResourceName(file);
  75.232 +        Index index = FileBasedIndex.get(root.getURL());
  75.233 +
  75.234 +        if (index == null) {
  75.235 +            throw new IOException("No index");
  75.236 +        }
  75.237 +
  75.238 +        CharSequence source = index.getSourceCode(path);
  75.239 +
  75.240 +        if (source == null) {
  75.241 +            throw new IOException("Source code not found");
  75.242 +        }
  75.243 +        
  75.244 +        return source.toString().replaceAll("\r\n", "\n");
  75.245 +    }
  75.246 +
  75.247 +    @GET
  75.248 +    @Path("/apply")
  75.249 +    @Produces("text/diff")
  75.250 +    //TODO: parameter for "verified"?
  75.251 +    public StreamingOutput apply(@QueryParam("path") String segment, @QueryParam("pattern") String pattern, @QueryParam("asynchronous") @DefaultValue(value="false") boolean asynchronous) throws IOException {
  75.252 +        assert !asynchronous;
  75.253 +
  75.254 +        Iterable<? extends HintDescription> hints = PatternConvertor.create(pattern);
  75.255 +        Set<FileObject> srcRoots = CategoryStorage.getCategoryContent(segment);
  75.256 +        final FileObject deepestCommonParent = deepestCommonParent(srcRoots);
  75.257 +        BatchResult batchResult = BatchSearch.findOccurrences(hints, Scope.createGivenSourceRoots(srcRoots.toArray(new FileObject[0])));
  75.258 +        final Collection<ModificationResult> modifications = BatchUtilities.applyFixes(batchResult, new ProgressHandleWrapper(1), new AtomicBoolean(), new LinkedList<MessageImpl>());
  75.259 +
  75.260 +        return new StreamingOutput() {
  75.261 +            @Override public void write(OutputStream output) throws IOException, WebApplicationException {
  75.262 +                Writer w = new OutputStreamWriter(output, "UTF-8");
  75.263 +
  75.264 +                try {
  75.265 +                    for (ModificationResult modResult : modifications) {
  75.266 +                        BatchUtilities.exportDiff(modResult, deepestCommonParent, w);
  75.267 +                    }
  75.268 +                } finally {
  75.269 +                    try {
  75.270 +                        w.close();
  75.271 +                    } catch (IOException ex) {
  75.272 +                        Exceptions.printStackTrace(ex);
  75.273 +                    }
  75.274 +                }
  75.275 +            }
  75.276 +        };
  75.277 +    }
  75.278 +
  75.279 +//    @GET
  75.280 +//    @Path("/info")
  75.281 +//    @Produces("text/plain")
  75.282 +//    public String info(@QueryParam("path") String segment) throws IOException {
  75.283 +//        URL sourceRoot = Cache.sourceRootForKey(segment).toURI().toURL();
  75.284 +//        Index index = FileBasedIndex.get(sourceRoot);
  75.285 +//
  75.286 +//        if (index == null) {
  75.287 +//            throw new IOException("No index");
  75.288 +//        }
  75.289 +//
  75.290 +//        return Pojson.save(index.getIndexInfo());
  75.291 +//    }
  75.292 +
  75.293 +    @GET
  75.294 +    @Path("/examples")
  75.295 +    @Produces("text/plain")
  75.296 +    public String examples() throws IOException {
  75.297 +        List<Map<String, String>> examples = new LinkedList<Map<String, String>>();
  75.298 +
  75.299 +        for (Example ex : LoadExamples.loadExamples()) {
  75.300 +            if (ex.getOptions().contains(Option.VERIFY) || ex.getOptions().contains(Option.FIX)) continue;
  75.301 +            Map<String, String> desc = new HashMap<String, String>();
  75.302 +
  75.303 +            desc.put("displayName", ex.getDisplayName());
  75.304 +            desc.put("pattern", ex.getCode());
  75.305 +
  75.306 +            examples.add(desc);
  75.307 +        }
  75.308 +
  75.309 +        return Pojson.save(examples);
  75.310 +    }
  75.311 +
  75.312 +    @GET
  75.313 +    @Path("/errors")
  75.314 +    @Produces("text/plain")
  75.315 +    public String errors(@QueryParam("pattern") String pattern) throws IOException {
  75.316 +        StringBuilder sb = new StringBuilder();
  75.317 +
  75.318 +        for (Diagnostic<? extends JavaFileObject> d : StandaloneFinder.parseAndReportErrors(pattern)) {
  75.319 +            sb.append(d.getMessage(null));
  75.320 +            sb.append("\n");
  75.321 +        }
  75.322 +
  75.323 +        return sb.toString();
  75.324 +    }
  75.325 +
  75.326 +    @GET
  75.327 +    @Path("/findDuplicates")
  75.328 +    @Produces("text/plain")
  75.329 +    public String findDuplicates(@QueryParam("path") String segment, @QueryParam("hashes") String hashes) throws IOException {
  75.330 +        Map<String, Map<String, Collection<? extends String>>> hash2Segment2Contains = new HashMap<String, Map<String, Collection<? extends String>>>();
  75.331 +        Collection<String> segments = new LinkedList<String>();
  75.332 +
  75.333 +        if (segment != null) segments.add(segment);
  75.334 +        else {
  75.335 +            for (String key : Cache.knownSourceRoots()) {
  75.336 +                segments.add(key);
  75.337 +            }
  75.338 +        }
  75.339 +
  75.340 +        Iterable<? extends String> hashesList = Arrays.asList(Pojson.load(String[].class, hashes));
  75.341 +
  75.342 +        for (String key : segments) {
  75.343 +            Map<String, Collection<? extends String>> found = StandaloneFinder.containsHash(Cache.sourceRootForKey(key), hashesList);
  75.344 +
  75.345 +            for (Entry<String, Collection<? extends String>> e : found.entrySet()) {
  75.346 +                Map<String, Collection<? extends String>> perRoot = hash2Segment2Contains.get(e.getKey());
  75.347 +
  75.348 +                if (perRoot == null) {
  75.349 +                    hash2Segment2Contains.put(e.getKey(), perRoot = new HashMap<String, Collection<? extends String>>());
  75.350 +                }
  75.351 +
  75.352 +                perRoot.put(key, e.getValue());
  75.353 +            }
  75.354 +        }
  75.355 +
  75.356 +        return Pojson.save(hash2Segment2Contains);
  75.357 +    }
  75.358 +
  75.359 +    @GET
  75.360 +    @Path("/checkProgress")
  75.361 +    @Produces("text/plain")
  75.362 +    public String checkProgress(@QueryParam("id") long id) throws IOException {
  75.363 +        ProgressImpl progress = workInProgress.get(id);
  75.364 +        Map<String, Object> result;
  75.365 +
  75.366 +        if (progress == null) {
  75.367 +            result = new HashMap<String, Object>();
  75.368 +            result.put("total", 0);
  75.369 +            result.put("workDone", 0);
  75.370 +            result.put("finished", true);
  75.371 +            result.put("result", Collections.<String>emptyList());
  75.372 +        } else {
  75.373 +            result = progress.progressPacket();
  75.374 +        }
  75.375 +
  75.376 +        if (result.get("finished") == Boolean.TRUE) {
  75.377 +            workInProgress.remove(id);
  75.378 +        }
  75.379 +
  75.380 +        return Pojson.save(result);
  75.381 +    }
  75.382 +
  75.383 +    @GET
  75.384 +    @Path("/cancelProgress")
  75.385 +    @Produces("text/plain")
  75.386 +    public String cancelProgress(@QueryParam("id") long id) throws IOException {
  75.387 +        ProgressImpl progress = workInProgress.get(id);
  75.388 +
  75.389 +        if (progress != null) {
  75.390 +            progress.cancel.set(true);
  75.391 +        }
  75.392 +
  75.393 +        return "done";
  75.394 +    }
  75.395 +
  75.396 +    @GET
  75.397 +    @Path("/capabilities")
  75.398 +    @Produces("text/plain")
  75.399 +    public String capabilities() throws IOException {
  75.400 +        Map<String, Object> result = new HashMap<String, Object>();
  75.401 +        List<String> methods = new ArrayList<String>(API.class.getDeclaredMethods().length);
  75.402 +
  75.403 +        for (Method m : API.class.getDeclaredMethods()) {
  75.404 +            if (m.isAnnotationPresent(GET.class) && (m.getModifiers() & Modifier.PUBLIC) != 0) {
  75.405 +                methods.add(m.getName());
  75.406 +            }
  75.407 +        }
  75.408 +
  75.409 +        result.put("methods", methods);
  75.410 +        result.put("attributed", true);
  75.411 +
  75.412 +        return Pojson.save(result);
  75.413 +    }
  75.414 +
  75.415 +    @GET
  75.416 +    @Path("/findType")
  75.417 +    @Produces("text/plain")
  75.418 +    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 {
  75.419 +        assert !asynchronous;
  75.420 +
  75.421 +        //copied (and converted to NameKind) from jumpto's GoToTypeAction:
  75.422 +        boolean exact = prefix.endsWith(" "); // NOI18N
  75.423 +
  75.424 +        prefix = prefix.trim();
  75.425 +
  75.426 +        if ( prefix.length() == 0) {
  75.427 +            return "";
  75.428 +        }
  75.429 +
  75.430 +        NameKind nameKind;
  75.431 +        int wildcard = GoToTypeAction.containsWildCard(prefix);
  75.432 +
  75.433 +        if (exact) {
  75.434 +            //nameKind = panel.isCaseSensitive() ? SearchType.EXACT_NAME : SearchType.CASE_INSENSITIVE_EXACT_NAME;
  75.435 +            nameKind = NameKind.SIMPLE_NAME;
  75.436 +        }
  75.437 +        else if ((GoToTypeAction.isAllUpper(prefix) && prefix.length() > 1) || GoToTypeAction.isCamelCase(prefix)) {
  75.438 +            nameKind = NameKind.CAMEL_CASE;
  75.439 +        }
  75.440 +        else if (wildcard != -1) {
  75.441 +            nameKind = casesensitive ? NameKind.REGEXP : NameKind.CASE_INSENSITIVE_REGEXP;
  75.442 +        }
  75.443 +        else {
  75.444 +            nameKind = casesensitive ? NameKind.PREFIX : NameKind.CASE_INSENSITIVE_PREFIX;
  75.445 +        }
  75.446 +
  75.447 +        Map<String, List<String>> result = new LinkedHashMap<String, List<String>>();
  75.448 +        Set<FileObject> srcRoots = CategoryStorage.getCategoryContent(segment);
  75.449 +        FileObject deepestCommonParent = deepestCommonParent(srcRoots);
  75.450 +
  75.451 +        for (FileObject srcRoot : srcRoots) {
  75.452 +            String rootId = FileUtil.getRelativePath(deepestCommonParent, srcRoot);
  75.453 +            List<String> currentResult = new ArrayList<String>();
  75.454 +
  75.455 +            result.put(rootId, currentResult);
  75.456 +
  75.457 +            ClassIndexManager.getDefault().createUsagesQuery(srcRoot.getURL(), true);
  75.458 +            ClasspathInfo cpInfo = ClasspathInfo.create(ClassPath.EMPTY, ClassPath.EMPTY, ClassPathSupport.createClassPath(srcRoot));
  75.459 +            Set<ElementHandle<TypeElement>> names = new HashSet<ElementHandle<TypeElement>>(cpInfo.getClassIndex().getDeclaredTypes(prefix, nameKind, EnumSet.of(SearchScope.SOURCE)));
  75.460 +
  75.461 +            if (nameKind == NameKind.CAMEL_CASE) {
  75.462 +                names.addAll(cpInfo.getClassIndex().getDeclaredTypes(prefix, NameKind.CASE_INSENSITIVE_PREFIX, EnumSet.of(SearchScope.SOURCE)));
  75.463 +            }
  75.464 +
  75.465 +            for (ElementHandle<TypeElement> d : names) {
  75.466 +                currentResult.add(d.getBinaryName());
  75.467 +            }
  75.468 +        }
  75.469 +
  75.470 +        return Pojson.save(result);
  75.471 +    }
  75.472 +
  75.473 +    //XXX: not really correct, a base directory(-ies?) should be set in the category!
  75.474 +    private static FileObject deepestCommonParent(Set<FileObject> roots) {
  75.475 +        FileObject result = null;
  75.476 +
  75.477 +        for (FileObject r : roots) {
  75.478 +            if (result == null) {
  75.479 +                result = r;
  75.480 +            } else {
  75.481 +                while (!FileUtil.isParentOf(result, r)) {
  75.482 +                    result = result.getParent();
  75.483 +                }
  75.484 +            }
  75.485 +        }
  75.486 +
  75.487 +        return result;
  75.488 +    }
  75.489 +
  75.490 +    private final static AtomicLong id = new AtomicLong();
  75.491 +    private final static Map<Long, ProgressImpl> workInProgress = new HashMap<Long, ProgressImpl>();//XXX: should be cleared eventually even if not read
  75.492 +
  75.493 +    private static final class ProgressImpl implements Progress {
  75.494 +        private int total = -1;
  75.495 +        private int workDone = 0;
  75.496 +        private boolean finished;
  75.497 +        private final List<String> result = new ArrayList<String>();
  75.498 +        private final AtomicBoolean cancel = new AtomicBoolean();
  75.499 +        public synchronized void setTotalWork(int total) {
  75.500 +            this.total = total;
  75.501 +        }
  75.502 +        public synchronized void progress(int totalDone) {
  75.503 +            workDone = totalDone;
  75.504 +        }
  75.505 +        public synchronized void updateProgress(int updateDone) {
  75.506 +            workDone += updateDone;
  75.507 +        }
  75.508 +        public synchronized void addResultPart(String part) {
  75.509 +            result.add(part);
  75.510 +        }
  75.511 +        public synchronized void finish() {
  75.512 +            finished = true;
  75.513 +        }
  75.514 +        public synchronized boolean isCancelled() {
  75.515 +            return cancel.get();
  75.516 +        }
  75.517 +        synchronized Map<String, Object> progressPacket() {
  75.518 +            Map<String, Object> result = new HashMap<String, Object>();
  75.519 +
  75.520 +            result.put("total", total);
  75.521 +            result.put("workDone", workDone);
  75.522 +            result.put("finished", finished);
  75.523 +            result.put("result", new ArrayList<String>(this.result));
  75.524 +
  75.525 +            this.result.clear();
  75.526 +
  75.527 +            return result;
  75.528 +        }
  75.529 +    }
  75.530 +
  75.531 +}
    76.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    76.2 +++ b/server/backend/impl/src/org/netbeans/modules/jackpot30/backend/impl/api/Progress.java	Fri Feb 18 20:16:26 2011 +0100
    76.3 @@ -0,0 +1,60 @@
    76.4 +/*
    76.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    76.6 + *
    76.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
    76.8 + *
    76.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   76.10 + * Other names may be trademarks of their respective owners.
   76.11 + *
   76.12 + * The contents of this file are subject to the terms of either the GNU
   76.13 + * General Public License Version 2 only ("GPL") or the Common
   76.14 + * Development and Distribution License("CDDL") (collectively, the
   76.15 + * "License"). You may not use this file except in compliance with the
   76.16 + * License. You can obtain a copy of the License at
   76.17 + * http://www.netbeans.org/cddl-gplv2.html
   76.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   76.19 + * specific language governing permissions and limitations under the
   76.20 + * License.  When distributing the software, include this License Header
   76.21 + * Notice in each file and include the License file at
   76.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   76.23 + * particular file as subject to the "Classpath" exception as provided
   76.24 + * by Oracle in the GPL Version 2 section of the License file that
   76.25 + * accompanied this code. If applicable, add the following below the
   76.26 + * License Header, with the fields enclosed by brackets [] replaced by
   76.27 + * your own identifying information:
   76.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   76.29 + *
   76.30 + * If you wish your version of this file to be governed by only the CDDL
   76.31 + * or only the GPL Version 2, indicate your decision by adding
   76.32 + * "[Contributor] elects to include this software in this distribution
   76.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   76.34 + * single choice of license, a recipient has the option to distribute
   76.35 + * your version of this file under either the CDDL, the GPL Version 2 or
   76.36 + * to extend the choice of license to its licensees as provided above.
   76.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   76.38 + * Version 2 license, then the option applies only if the new code is
   76.39 + * made subject to such option by the copyright holder.
   76.40 + *
   76.41 + * Contributor(s):
   76.42 + *
   76.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
   76.44 + */
   76.45 +
   76.46 +package org.netbeans.modules.jackpot30.backend.impl.api;
   76.47 +
   76.48 +/**
   76.49 + *
   76.50 + * @author lahvac
   76.51 + */
   76.52 +public interface Progress {
   76.53 +
   76.54 +    public void setTotalWork(int total);
   76.55 +    public void progress(int totalDone);
   76.56 +    public void updateProgress(int updateDone);
   76.57 +    public void addResultPart(String part);
   76.58 +    public void finish();
   76.59 +    
   76.60 +    public boolean isCancelled();
   76.61 +
   76.62 +
   76.63 +}
    77.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    77.2 +++ b/server/backend/impl/src/org/netbeans/modules/jackpot30/backend/impl/api/StandaloneFinder.java	Fri Feb 18 20:16:26 2011 +0100
    77.3 @@ -0,0 +1,201 @@
    77.4 +/*
    77.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    77.6 + *
    77.7 + * Copyright 2009-2010 Sun Microsystems, Inc. All rights reserved.
    77.8 + *
    77.9 + * The contents of this file are subject to the terms of either the GNU
   77.10 + * General Public License Version 2 only ("GPL") or the Common
   77.11 + * Development and Distribution License("CDDL") (collectively, the
   77.12 + * "License"). You may not use this file except in compliance with the
   77.13 + * License. You can obtain a copy of the License at
   77.14 + * http://www.netbeans.org/cddl-gplv2.html
   77.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   77.16 + * specific language governing permissions and limitations under the
   77.17 + * License.  When distributing the software, include this License Header
   77.18 + * Notice in each file and include the License file at
   77.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   77.20 + * particular file as subject to the "Classpath" exception as provided
   77.21 + * by Sun in the GPL Version 2 section of the License file that
   77.22 + * accompanied this code. If applicable, add the following below the
   77.23 + * License Header, with the fields enclosed by brackets [] replaced by
   77.24 + * your own identifying information:
   77.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   77.26 + *
   77.27 + * If you wish your version of this file to be governed by only the CDDL
   77.28 + * or only the GPL Version 2, indicate your decision by adding
   77.29 + * "[Contributor] elects to include this software in this distribution
   77.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   77.31 + * single choice of license, a recipient has the option to distribute
   77.32 + * your version of this file under either the CDDL, the GPL Version 2 or
   77.33 + * to extend the choice of license to its licensees as provided above.
   77.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   77.35 + * Version 2 license, then the option applies only if the new code is
   77.36 + * made subject to such option by the copyright holder.
   77.37 + *
   77.38 + * Contributor(s):
   77.39 + *
   77.40 + * Portions Copyrighted 2009-2010 Sun Microsystems, Inc.
   77.41 + */
   77.42 +
   77.43 +package org.netbeans.modules.jackpot30.backend.impl.api;
   77.44 +
   77.45 +import com.sun.source.tree.CompilationUnitTree;
   77.46 +import com.sun.source.tree.Tree;
   77.47 +import com.sun.source.util.TreePath;
   77.48 +import com.sun.source.util.Trees;
   77.49 +import com.sun.tools.javac.api.JavacTaskImpl;
   77.50 +import java.io.File;
   77.51 +import java.io.IOException;
   77.52 +import java.net.URI;
   77.53 +import java.util.Arrays;
   77.54 +import java.util.BitSet;
   77.55 +import java.util.Collection;
   77.56 +import java.util.Collections;
   77.57 +import java.util.HashMap;
   77.58 +import java.util.LinkedList;
   77.59 +import java.util.Map;
   77.60 +import javax.tools.Diagnostic;
   77.61 +import javax.tools.JavaCompiler;
   77.62 +import javax.tools.JavaFileObject;
   77.63 +import javax.tools.SimpleJavaFileObject;
   77.64 +import javax.tools.ToolProvider;
   77.65 +import org.apache.lucene.document.Document;
   77.66 +import org.apache.lucene.index.IndexReader;
   77.67 +import org.apache.lucene.index.Term;
   77.68 +import org.apache.lucene.search.Collector;
   77.69 +import org.apache.lucene.search.IndexSearcher;
   77.70 +import org.apache.lucene.search.Query;
   77.71 +import org.apache.lucene.search.Searcher;
   77.72 +import org.apache.lucene.search.TermQuery;
   77.73 +import org.apache.lucene.store.FSDirectory;
   77.74 +import org.netbeans.modules.jackpot30.impl.Utilities;
   77.75 +import org.netbeans.modules.jackpot30.impl.duplicates.indexing.DuplicatesIndex;
   77.76 +import org.netbeans.modules.jackpot30.impl.indexing.AbstractLuceneIndex.BitSetCollector;
   77.77 +import org.netbeans.modules.jackpot30.impl.indexing.Cache;
   77.78 +import org.netbeans.modules.jackpot30.impl.indexing.FileBasedIndex;
   77.79 +import org.netbeans.modules.jackpot30.impl.pm.BulkSearch;
   77.80 +import org.netbeans.modules.jackpot30.impl.pm.BulkSearch.BulkPattern;
   77.81 +import org.netbeans.modules.jackpot30.spi.HintDescription;
   77.82 +import org.netbeans.modules.jackpot30.spi.HintDescription.AdditionalQueryConstraints;
   77.83 +import org.netbeans.modules.jackpot30.spi.PatternConvertor;
   77.84 +
   77.85 +/**
   77.86 + *
   77.87 + * @author lahvac
   77.88 + */
   77.89 +public class StandaloneFinder {
   77.90 +
   77.91 +    public static Collection<? extends String> findCandidates(File sourceRoot, String pattern) throws IOException {
   77.92 +        BulkPattern bulkPattern = preparePattern(pattern, null);
   77.93 +        
   77.94 +        return FileBasedIndex.get(sourceRoot.toURI().toURL()).findCandidates(bulkPattern);
   77.95 +    }
   77.96 +
   77.97 +    public static int[] findCandidateOccurrenceSpans(File sourceRoot, String relativePath, String pattern) throws IOException {
   77.98 +        BulkPattern bulkPattern = preparePattern(pattern, null);
   77.99 +        CharSequence source = FileBasedIndex.get(sourceRoot.toURI().toURL()).getSourceCode(relativePath).toString().replaceAll("\r\n", "\n");
  77.100 +        JavacTaskImpl jti = prepareJavacTaskImpl();
  77.101 +        CompilationUnitTree cut = jti.parse(new JFOImpl(source)).iterator().next();
  77.102 +        Collection<TreePath> paths = new LinkedList<TreePath>();
  77.103 +        
  77.104 +        for (Collection<TreePath> c : BulkSearch.getDefault().match(null, new TreePath(cut), bulkPattern).values()) {
  77.105 +            paths.addAll(c);
  77.106 +        }
  77.107 +
  77.108 +        Trees t = Trees.instance(jti);
  77.109 +        int[] result = new int[2 * paths.size()];
  77.110 +        int i = 0;
  77.111 +
  77.112 +        for (TreePath tp : paths) {
  77.113 +            result[i++] = (int) t.getSourcePositions().getStartPosition(cut, tp.getLeaf());
  77.114 +            result[i++] = (int) t.getSourcePositions().getEndPosition(cut, tp.getLeaf());
  77.115 +        }
  77.116 +
  77.117 +        return result;
  77.118 +    }
  77.119 +
  77.120 +    public static Collection<Diagnostic<? extends JavaFileObject>> parseAndReportErrors(String pattern) {
  77.121 +        Collection<Diagnostic<? extends JavaFileObject>> errors = new LinkedList<Diagnostic<? extends JavaFileObject>>();
  77.122 +
  77.123 +        preparePattern(pattern, errors);
  77.124 +
  77.125 +        return errors;
  77.126 +    }
  77.127 +
  77.128 +    public static Map<String, Collection<? extends String>> containsHash(File sourceRoot, Iterable<? extends String> hashes) throws IOException {
  77.129 +        File cacheRoot = Cache.findCache(DuplicatesIndex.NAME, DuplicatesIndex.VERSION).findCacheRoot(sourceRoot.toURI().toURL());
  77.130 +        File dir = new File(cacheRoot, "fulltext");
  77.131 +
  77.132 +        if (dir.listFiles() != null && dir.listFiles().length > 0) {
  77.133 +            IndexReader reader = IndexReader.open(FSDirectory.open(dir), true);
  77.134 +            Map<String, Collection<? extends String>> result = new HashMap<String, Collection<? extends String>>();
  77.135 +
  77.136 +            for (String hash : hashes) {
  77.137 +                Collection<String> found = new LinkedList<String>();
  77.138 +                Query query = new TermQuery(new Term("generalized", hash));
  77.139 +                Searcher s = new IndexSearcher(reader);
  77.140 +                BitSet matchingDocuments = new BitSet(reader.maxDoc());
  77.141 +                Collector c = new BitSetCollector(matchingDocuments);
  77.142 +
  77.143 +                s.search(query, c);
  77.144 +
  77.145 +                for (int docNum = matchingDocuments.nextSetBit(0); docNum >= 0; docNum = matchingDocuments.nextSetBit(docNum + 1)) {
  77.146 +                    final Document doc = reader.document(docNum);
  77.147 +
  77.148 +                    found.add(doc.getField("path").stringValue());
  77.149 +                }
  77.150 +
  77.151 +                result.put(hash, found);
  77.152 +            }
  77.153 +            
  77.154 +            return result;
  77.155 +        }
  77.156 +
  77.157 +        return Collections.emptyMap();
  77.158 +    }
  77.159 +    
  77.160 +    private static BulkPattern preparePattern(String pattern, Collection<Diagnostic<? extends JavaFileObject>> errors) {
  77.161 +        return preparePattern(PatternConvertor.create(pattern), errors);
  77.162 +    }
  77.163 +
  77.164 +    //XXX: copied from BatchSearch, may be possible to merge once CompilationInfo is accessible in server mode
  77.165 +    private static BulkPattern preparePattern(final Iterable<? extends HintDescription> patterns, Collection<Diagnostic<? extends JavaFileObject>> errors) {
  77.166 +        JavacTaskImpl javac = prepareJavacTaskImpl();
  77.167 +        Collection<String> code = new LinkedList<String>();
  77.168 +        Collection<Tree> trees = new LinkedList<Tree>();
  77.169 +        Collection<AdditionalQueryConstraints> additionalConstraints = new LinkedList<AdditionalQueryConstraints>();
  77.170 +
  77.171 +        for (HintDescription pattern : patterns) {
  77.172 +            String textPattern = pattern.getTriggerPattern().getPattern();
  77.173 +
  77.174 +            code.add(textPattern);
  77.175 +            trees.add(Utilities.parseAndAttribute(javac, textPattern, errors));
  77.176 +            additionalConstraints.add(pattern.getAdditionalConstraints());
  77.177 +        }
  77.178 +
  77.179 +        return BulkSearch.getDefault().create(code, trees, additionalConstraints);
  77.180 +    }
  77.181 +
  77.182 +    private static JavacTaskImpl prepareJavacTaskImpl() {
  77.183 +        final String bootPath = System.getProperty("sun.boot.class.path"); //NOI18N
  77.184 +        final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
  77.185 +
  77.186 +        assert tool != null;
  77.187 +
  77.188 +        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, Arrays.asList("-bootclasspath",  bootPath, "-Xjcov"), null, Collections.<JavaFileObject>emptyList());
  77.189 +        
  77.190 +        return ct;
  77.191 +    }
  77.192 +
  77.193 +    private static final class JFOImpl extends SimpleJavaFileObject {
  77.194 +        private final CharSequence code;
  77.195 +        public JFOImpl(CharSequence code) {
  77.196 +            super(URI.create(""), Kind.SOURCE);
  77.197 +            this.code = code;
  77.198 +        }
  77.199 +        @Override
  77.200 +        public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  77.201 +            return code;
  77.202 +        }
  77.203 +    }
  77.204 +}
    78.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    78.2 +++ b/server/backend/impl/src/org/netbeans/modules/jackpot30/backend/impl/resources/layer.xml	Fri Feb 18 20:16:26 2011 +0100
    78.3 @@ -0,0 +1,14 @@
    78.4 +<?xml version="1.0" encoding="UTF-8"?>
    78.5 +<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
    78.6 +<filesystem>
    78.7 +    <folder name="public_html">
    78.8 +        <folder name="index">
    78.9 +            <folder name="find">
   78.10 +                <attr name="net.sf.dvbcentral.http.spi.UnknownPageRequest" methodvalue="org.netbeans.modules.jackpot30.backend.impl.api.API.createFindPageRequest" />
   78.11 +            </folder>
   78.12 +            <folder name="list">
   78.13 +                <attr name="net.sf.dvbcentral.http.spi.UnknownPageRequest" methodvalue="org.netbeans.modules.jackpot30.backend.impl.api.API.createListPageRequest" />
   78.14 +            </folder>
   78.15 +        </folder>
   78.16 +    </folder>
   78.17 +</filesystem>
    79.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    79.2 +++ b/server/backend/impl/src/org/netbeans/modules/jackpot30/backend/impl/ui/UI.java	Fri Feb 18 20:16:26 2011 +0100
    79.3 @@ -0,0 +1,423 @@
    79.4 +/*
    79.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    79.6 + *
    79.7 + * Copyright 2009-2010 Sun Microsystems, Inc. All rights reserved.
    79.8 + *
    79.9 + * The contents of this file are subject to the terms of either the GNU
   79.10 + * General Public License Version 2 only ("GPL") or the Common
   79.11 + * Development and Distribution License("CDDL") (collectively, the
   79.12 + * "License"). You may not use this file except in compliance with the
   79.13 + * License. You can obtain a copy of the License at
   79.14 + * http://www.netbeans.org/cddl-gplv2.html
   79.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   79.16 + * specific language governing permissions and limitations under the
   79.17 + * License.  When distributing the software, include this License Header
   79.18 + * Notice in each file and include the License file at
   79.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
   79.20 + * particular file as subject to the "Classpath" exception as provided
   79.21 + * by Sun in the GPL Version 2 section of the License file that
   79.22 + * accompanied this code. If applicable, add the following below the
   79.23 + * License Header, with the fields enclosed by brackets [] replaced by
   79.24 + * your own identifying information:
   79.25 + * "Portions Copyrighted [year] [name of copyright owner]"
   79.26 + *
   79.27 + * If you wish your version of this file to be governed by only the CDDL
   79.28 + * or only the GPL Version 2, indicate your decision by adding
   79.29 + * "[Contributor] elects to include this software in this distribution
   79.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   79.31 + * single choice of license, a recipient has the option to distribute
   79.32 + * your version of this file under either the CDDL, the GPL Version 2 or
   79.33 + * to extend the choice of license to its licensees as provided above.
   79.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   79.35 + * Version 2 license, then the option applies only if the new code is
   79.36 + * made subject to such option by the copyright holder.
   79.37 + *
   79.38 + * Contributor(s):
   79.39 + *
   79.40 + * Portions Copyrighted 2009-2010 Sun Microsystems, Inc.
   79.41 + */
   79.42 +
   79.43 +package org.netbeans.modules.jackpot30.backend.impl.ui;
   79.44 +
   79.45 +import java.util.Comparator;
   79.46 +import javax.ws.rs.core.Response;
   79.47 +import java.util.LinkedHashMap;
   79.48 +import java.util.Map.Entry;
   79.49 +import freemarker.cache.TemplateLoader;
   79.50 +import freemarker.template.Configuration;
   79.51 +import freemarker.template.Template;
   79.52 +import freemarker.template.TemplateException;
   79.53 +import java.io.IOException;
   79.54 +import java.io.InputStream;
   79.55 +import java.io.InputStreamReader;
   79.56 +import java.io.Reader;
   79.57 +import java.io.StringWriter;
   79.58 +import java.net.URI;
   79.59 +import java.net.URISyntaxException;
   79.60 +import java.util.ArrayList;
   79.61 +import java.util.Collections;
   79.62 +import java.util.HashMap;
   79.63 +import java.util.LinkedList;
   79.64 +import java.util.List;
   79.65 +import java.util.Map;
   79.66 +import javax.ws.rs.DefaultValue;
   79.67 +import javax.ws.rs.GET;
   79.68 +import javax.ws.rs.Path;
   79.69 +import javax.ws.rs.Produces;
   79.70 +import javax.ws.rs.QueryParam;
   79.71 +import org.codeviation.pojson.Pojson;
   79.72 +import org.netbeans.modules.jackpot30.impl.WebUtilities;
   79.73 +import static org.netbeans.modules.jackpot30.impl.WebUtilities.escapeForQuery;
   79.74 +
   79.75 +/**
   79.76 + *
   79.77 + * @author lahvac
   79.78 + */
   79.79 +@Path("/index/ui")
   79.80 +public class UI {
   79.81 +
   79.82 +    @GET
   79.83 +    @Path("/search")
   79.84 +    @Produces("text/html")
   79.85 +    public String search(@QueryParam("path") String path, @QueryParam("pattern") String pattern) throws URISyntaxException, IOException, TemplateException {
   79.86 +        Map<String, Object> configurationData = new HashMap<String, Object>();
   79.87 +
   79.88 +        configurationData.put("paths", list());
   79.89 +        configurationData.put("selectedPath", path);
   79.90 +        configurationData.put("pattern", pattern);
   79.91 +        configurationData.put("patternEscaped", escapeForQuery(pattern));
   79.92 +        configurationData.put("examples", loadExamples());
   79.93 +
   79.94 +        if (pattern != null && path != null) {
   79.95 +            URI u = new URI("http://localhost:9998/index/find?path=" + escapeForQuery(path) + "&pattern=" + escapeForQuery(pattern));
   79.96 +            List<Map<String, Object>> results = new LinkedList<Map<String, Object>>();
   79.97 +            long queryTime = System.currentTimeMillis();
   79.98 +            List<String> candidates = new ArrayList<String>(WebUtilities.requestStringArrayResponse(u));
   79.99 +
  79.100 +            queryTime = System.currentTimeMillis() - queryTime;
  79.101 +
  79.102 +            Collections.sort(candidates);
  79.103 +
  79.104 +            for (String c : candidates) {
  79.105 +                Map<String, Object> found = new HashMap<String, Object>(3);
  79.106 +
  79.107 +                found.put("relativePath", c);
  79.108 +
  79.109 +                results.add(found);
  79.110 +            }
  79.111 +
  79.112 +            configurationData.put("results", results);
  79.113 +
  79.114 +            Map<String, Object> statistics = new HashMap<String, Object>();
  79.115 +
  79.116 +            statistics.put("files", candidates.size());
  79.117 +            statistics.put("queryTime", queryTime);
  79.118 +
  79.119 +            configurationData.put("statistics", statistics);
  79.120 +        }
  79.121 +
  79.122 +        return processTemplate("ui-search.html", configurationData);
  79.123 +    }
  79.124 +
  79.125 +//    @GET
  79.126 +//    @Path("/searchCategorized")
  79.127 +//    @Produces("text/html")
  79.128 +//    public String searchCategorized(@QueryParam("path") String path, @QueryParam("pattern") String pattern) throws URISyntaxException, IOException, TemplateException {
  79.129 +//        Map<String, Object> configurationData = new HashMap<String, Object>();
  79.130 +//
  79.131 +//        configurationData.put("paths", list());
  79.132 +//        configurationData.put("selectedPath", path);
  79.133 +//        configurationData.put("pattern", pattern);
  79.134 +//        configurationData.put("patternEscaped", escapeForQuery(pattern));
  79.135 +//        configurationData.put("examples", loadExamples());
  79.136 +//
  79.137 +//        if (pattern != null && path != null) {
  79.138 +//            Result queryResult = new DoQuery().doQuery(path, pattern, new Cancel() {
  79.139 +//                                                           public boolean isCancelled() {
  79.140 +//                                                               return false;
  79.141 +//                                                           }
  79.142 +//                                                       });
  79.143 +//
  79.144 +//            configurationData.put("result", queryResult.result);
  79.145 +//        }
  79.146 +//
  79.147 +//        return processTemplate("ui-search-categorized.html", configurationData);
  79.148 +//    }
  79.149 +
  79.150 +    @GET
  79.151 +    @Path("/show")
  79.152 +    @Produces("text/html")
  79.153 +    public String show(@QueryParam("path") String path, @QueryParam("relative") String relativePath, @QueryParam("pattern") String pattern) throws URISyntaxException, IOException, TemplateException {
  79.154 +        Map<String, Object> configurationData = new HashMap<String, Object>();
  79.155 +        List<Map<String, String>> occurrences = new LinkedList<Map<String, String>>();
  79.156 +
  79.157 +        configurationData.put("occurrences", occurrences);
  79.158 +
  79.159 +        URI codeURL = new URI("http://localhost:9998/index/cat?path=" + escapeForQuery(path) + "&relative=" + escapeForQuery(relativePath));
  79.160 +        String code = WebUtilities.requestStringResponse(codeURL);
  79.161 +
  79.162 +        if (pattern != null) {
  79.163 +            URI spansURL = new URI("http://localhost:9998/index/findSpans?path=" + escapeForQuery(path) + "&relativePath=" + escapeForQuery(relativePath) + "&pattern=" + escapeForQuery(pattern));
  79.164 +            int currentCodePos = 0;
  79.165 +            for (int[] span : parseSpans(WebUtilities.requestStringResponse(spansURL))) { //XXX: sorted!
  79.166 +                Map<String, String> occ = new HashMap<String, String>();
  79.167 +                occ.put("prefix", WebUtilities.escapeForHTMLElement(code.substring(currentCodePos, span[0])));
  79.168 +                occ.put("occurrence", WebUtilities.escapeForHTMLElement(code.substring(span[0], span[1])));
  79.169 +                occurrences.add(occ);
  79.170 +                currentCodePos = span[1];
  79.171 +            }
  79.172 +
  79.173 +            configurationData.put("suffix", WebUtilities.escapeForHTMLElement(code.substring(currentCodePos, code.length())));
  79.174 +        } else {
  79.175 +            configurationData.put("suffix", WebUtilities.escapeForHTMLElement(code));
  79.176 +        }
  79.177 +
  79.178 +        return processTemplate("ui-cat.html", configurationData);
  79.179 +    }
  79.180 +    
  79.181 +    @GET
  79.182 +    @Path("/snippet")
  79.183 +    @Produces("text/html")
  79.184 +    public String snippet(@QueryParam("path") String path, @QueryParam("relative") String relativePath, @QueryParam("pattern") String pattern) throws URISyntaxException, IOException, TemplateException {
  79.185 +        List<Map<String, String>> snippets = new LinkedList<Map<String, String>>();
  79.186 +
  79.187 +        URI codeURL = new URI("http://localhost:9998/index/cat?path=" + escapeForQuery(path) + "&relative=" + escapeForQuery(relativePath));
  79.188 +        String code = WebUtilities.requestStringResponse(codeURL);
  79.189 +        URI spansURL = new URI("http://localhost:9998/index/findSpans?path=" + escapeForQuery(path) + "&relativePath=" + escapeForQuery(relativePath) + "&pattern=" + escapeForQuery(pattern));
  79.190 +
  79.191 +        for (int[] span : parseSpans(WebUtilities.requestStringResponse(spansURL))) {
  79.192 +            snippets.add(prepareSnippet(code, span));
  79.193 +        }
  79.194 +
  79.195 +        return processTemplate("ui-snippet.html", Collections.<String, Object>singletonMap("snippets", snippets));
  79.196 +    }
  79.197 +
  79.198 +    @GET
  79.199 +    @Path("/apply")
  79.200 +    @Produces("text/html")
  79.201 +    public Response apply(@QueryParam("path") String path, @QueryParam("pattern") String pattern, @QueryParam("preview") @DefaultValue("") String preview, @QueryParam("download") @DefaultValue("") String download) throws URISyntaxException, IOException, TemplateException {
  79.202 +        if (!download.isEmpty()) {
  79.203 +            if (pattern != null && path != null) {
  79.204 +                URI u = new URI("http://localhost:9998/index/apply?path=" + escapeForQuery(path) + "&pattern=" + escapeForQuery(pattern));
  79.205 +
  79.206 +                return Response.temporaryRedirect(u).header("meta", "Content-Disposition: download; filename=\"patch.diff\"").build();
  79.207 +            }
  79.208 +        }
  79.209 +
  79.210 +        Map<String, Object> configurationData = new HashMap<String, Object>();
  79.211 +
  79.212 +        configurationData.put("paths", list());
  79.213 +        configurationData.put("selectedPath", path);
  79.214 +        configurationData.put("pattern", pattern);
  79.215 +        configurationData.put("patternEscaped", escapeForQuery(pattern));
  79.216 +        configurationData.put("examples", loadExamples());
  79.217 +
  79.218 +        if (pattern != null && path != null) {
  79.219 +            URI u = new URI("http://localhost:9998/index/apply?path=" + escapeForQuery(path) + "&pattern=" + escapeForQuery(pattern));
  79.220 +            long queryTime = System.currentTimeMillis();
  79.221 +            String diff = WebUtilities.requestStringResponse(u);
  79.222 +
  79.223 +            queryTime = System.currentTimeMillis() - queryTime;
  79.224 +
  79.225 +            configurationData.put("diff", diff);
  79.226 +
  79.227 +            StringBuilder sb = new StringBuilder();
  79.228 +
  79.229 +            for (String l : diff.split("\n")) {
  79.230 +                sb.append("<span");
  79.231 +
  79.232 +                for (Entry<String, String> e : prefix2SpanName.entrySet()) {
  79.233 +                    if (l.startsWith(e.getKey())) {
  79.234 +                        sb.append(" class='" + e.getValue() + "'");
  79.235 +                        break;
  79.236 +                    }
  79.237 +                }
  79.238 +
  79.239 +                sb.append(">");
  79.240 +                sb.append(l);
  79.241 +                sb.append("</span>\n");
  79.242 +            }
  79.243 +
  79.244 +            configurationData.put("result", sb.toString());
  79.245 +        }
  79.246 +
  79.247 +        return Response.ok(processTemplate("ui-apply.html", configurationData), "text/html").build();
  79.248 +    }
  79.249 +
  79.250 +    @GET
  79.251 +    @Path("/searchType")
  79.252 +    @Produces("text/html")
  79.253 +    public String searchType(@QueryParam("path") String path, @QueryParam("prefix") String prefix) throws URISyntaxException, IOException, TemplateException {
  79.254 +        Map<String, Object> configurationData = new HashMap<String, Object>();
  79.255 +
  79.256 +        configurationData.put("paths", list());
  79.257 +        configurationData.put("selectedPath", path);
  79.258 +        configurationData.put("prefix", prefix);
  79.259 +
  79.260 +        if (prefix != null && path != null) {
  79.261 +            URI u = new URI("http://localhost:9998/index/findType?path=" + escapeForQuery(path) + "&prefix=" + escapeForQuery(prefix));
  79.262 +            long queryTime = System.currentTimeMillis();
  79.263 +            @SuppressWarnings("unchecked") //XXX: should not trust something got from the network!
  79.264 +            Map<String, List<String>> types = Pojson.load(LinkedHashMap.class, u);
  79.265 +            List<Map<String, Object>> results = new LinkedList<Map<String, Object>>();
  79.266 +
  79.267 +            queryTime = System.currentTimeMillis() - queryTime;
  79.268 +
  79.269 +            for (Entry<String, List<String>> e : types.entrySet()) {
  79.270 +                for (String fqn : e.getValue()) {
  79.271 +                    Map<String, Object> found = new HashMap<String, Object>(3);
  79.272 +
  79.273 +                    found.put("fqn", fqn);
  79.274 +
  79.275 +                    if (fqn.contains("$")) {
  79.276 +                        fqn = fqn.substring(0, fqn.indexOf("$"));
  79.277 +                    }
  79.278 +
  79.279 +                    found.put("relativePath", e.getKey() + "/" + fqn.replace('.', '/') + ".java");
  79.280 +
  79.281 +                    results.add(found);
  79.282 +                }
  79.283 +            }
  79.284 +
  79.285 +            Collections.sort(results, new Comparator<Map<String, Object>>() {
  79.286 +                @Override public int compare(Map<String, Object> o1, Map<String, Object> o2) {
  79.287 +                    return ((String) o1.get("fqn")).compareTo((String) o2.get("fqn"));
  79.288 +                }
  79.289 +            });
  79.290 +            
  79.291 +            configurationData.put("results", results);
  79.292 +
  79.293 +            Map<String, Object> statistics = new HashMap<String, Object>();
  79.294 +
  79.295 +            statistics.put("queryTime", queryTime);
  79.296 +
  79.297 +            configurationData.put("statistics", statistics);
  79.298 +        }
  79.299 +
  79.300 +        return processTemplate("ui-findType.html", configurationData);
  79.301 +    }
  79.302 +
  79.303 +    private static final Map<String, String> prefix2SpanName = new LinkedHashMap<String, String>();
  79.304 +
  79.305 +    static {
  79.306 +        prefix2SpanName.put("-", "diff-removed");
  79.307 +        prefix2SpanName.put("+", "diff-added");
  79.308 +        prefix2SpanName.put("@@", "diff-hunk");
  79.309 +        prefix2SpanName.put("Index:", "diff-index");
  79.310 +    }
  79.311 +
  79.312 +    private static List<Map<String, String>> list() throws URISyntaxException {
  79.313 +        List<Map<String, String>> result = new LinkedList<Map<String, String>>();
  79.314 +
  79.315 +        for (String enc : WebUtilities.requestStringArrayResponse(new URI("http://localhost:9998/index/list"))) {
  79.316 +            Map<String, String> rootDesc = new HashMap<String, String>();
  79.317 +            String[] col = enc.split(":", 2);
  79.318 +
  79.319 +            rootDesc.put("segment", col[0]);
  79.320 +            rootDesc.put("displayName", col[1]);
  79.321 +            result.add(rootDesc);
  79.322 +        }
  79.323 +
  79.324 +        return result;
  79.325 +    }
  79.326 +    
  79.327 +    private static Iterable<int[]> parseSpans(String from) {
  79.328 +        if (from.isEmpty()) {
  79.329 +            return Collections.emptyList();
  79.330 +        }
  79.331 +        String[] split = from.split(":");
  79.332 +        List<int[]> result = new LinkedList<int[]>();
  79.333 +
  79.334 +        for (int i = 0; i < split.length; i += 2) {
  79.335 +            result.add(new int[] {
  79.336 +                Integer.parseInt(split[i + 0].trim()),
  79.337 +                Integer.parseInt(split[i + 1].trim())
  79.338 +            });
  79.339 +        }
  79.340 +
  79.341 +        return result;
  79.342 +    }
  79.343 +
  79.344 +    private static final int DESIRED_CONTEXT = 2;
  79.345 +
  79.346 +    private static Map<String, String> prepareSnippet(String code, int[] span) {
  79.347 +        int grandStart = span[0];
  79.348 +        int firstLineStart = grandStart = lineStart(code, grandStart);
  79.349 +
  79.350 +        while (grandStart > 0 && contextLength(code.substring(grandStart, firstLineStart)) < DESIRED_CONTEXT)
  79.351 +            grandStart = lineStart(code, grandStart - 1);
  79.352 +
  79.353 +        int grandEnd = span[1];
  79.354 +        int firstLineEnd = grandEnd = lineEnd(code, grandEnd);
  79.355 +        
  79.356 +        while (grandEnd < code.length() - 1 && contextLength(code.substring(firstLineEnd, grandEnd)) < DESIRED_CONTEXT)
  79.357 +            grandEnd = lineEnd(code, grandEnd + 1);
  79.358 +
  79.359 +        Map<String, String> result = new HashMap<String, String>();
  79.360 +        
  79.361 +        result.put("prefix", WebUtilities.escapeForHTMLElement(code.substring(grandStart, span[0])));
  79.362 +        result.put("occurrence", WebUtilities.escapeForHTMLElement(code.substring(span[0], span[1])));
  79.363 +        result.put("suffix", WebUtilities.escapeForHTMLElement(code.substring(span[1], grandEnd)));
  79.364 +
  79.365 +        return result;
  79.366 +    }
  79.367 +
  79.368 +    private static int lineStart(String code, int o) {
  79.369 +        while (o > 0 && code.charAt(o) != '\n') {
  79.370 +            o--;
  79.371 +        }
  79.372 +
  79.373 +        return o;
  79.374 +    }
  79.375 +
  79.376 +    private static int lineEnd(String code, int o) {
  79.377 +        while (o < code.length() - 1 && code.charAt(o) != '\n') {
  79.378 +            o++;
  79.379 +        }
  79.380 +
  79.381 +        return o;
  79.382 +    }
  79.383 +
  79.384 +    private static int contextLength(String in) {
  79.385 +        return in.replaceAll("\n[ \t]*\n", "\n").trim().split("\n").length;
  79.386 +    }
  79.387 +
  79.388 +    @SuppressWarnings("unchecked")
  79.389 +    private List<Map<String, String>> loadExamples() throws IOException, URISyntaxException {
  79.390 +        return Pojson.load(LinkedList.class, new URI("http://localhost:9998/index/examples"));
  79.391 +    }
  79.392 +
  79.393 +    private static String processTemplate(String template, Map<String, Object> configurationData) throws TemplateException, IOException {
  79.394 +        Configuration conf = new Configuration();
  79.395 +
  79.396 +        conf.setTemplateLoader(new TemplateLoaderImpl());
  79.397 +
  79.398 +        Template templ = conf.getTemplate(template);
  79.399 +        StringWriter out = new StringWriter();
  79.400 +
  79.401 +        templ.process(configurationData, out);
  79.402 +
  79.403 +        return out.toString();
  79.404 +    }
  79.405 +
  79.406 +    private static final class TemplateLoaderImpl implements TemplateLoader {
  79.407 +
  79.408 +        public Object findTemplateSource(String name) throws IOException {
  79.409 +            return TemplateLoaderImpl.class.getResourceAsStream(name);
  79.410 +        }
  79.411 +
  79.412 +        public long getLastModified(Object templateSource) {
  79.413 +            return 0L;
  79.414 +        }
  79.415 +
  79.416 +        public Reader getReader(Object templateSource, String encoding) throws IOException {
  79.417 +            InputStream in = (InputStream) templateSource;
  79.418 +
  79.419 +            return new InputStreamReader(in);
  79.420 +        }
  79.421 +
  79.422 +        public void closeTemplateSource(Object templateSource) throws IOException {
  79.423 +        }
  79.424 +    }
  79.425 +
  79.426 +}
    80.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    80.2 +++ b/server/backend/impl/src/org/netbeans/modules/jackpot30/backend/impl/ui/ui-apply.html	Fri Feb 18 20:16:26 2011 +0100
    80.3 @@ -0,0 +1,68 @@
    80.4 +<html>
    80.5 +<head>
    80.6 +    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
    80.7 +<#if results??>
    80.8 +    <script type="text/javascript">
    80.9 +        $(document).ready(function() {
   80.10 +            $('#list').find('dd').hide().end().find('dt').click(function() {
   80.11 +                current_dd=$(this).next();
   80.12 +                //XXX: will do the AJAX call for both show and hide!
   80.13 +                $.get("snippet?path=${selectedPath}&relative=" + current_dd.attr("id") + "&pattern=${patternEscaped}",function(data) {
   80.14 +                    current_dd.html(data).slideToggle();
   80.15 +                })
   80.16 +            });
   80.17 +        });
   80.18 +    </script>
   80.19 +</#if>
   80.20 +    <style type="text/css">
   80.21 +        .occurrence {background: #DDDD00;}
   80.22 +        .diff-removed {color: #FF0000;}
   80.23 +        .diff-added {color: #00FF00;}
   80.24 +        .diff-index {color: #0000FF;}
   80.25 +        .diff-hunk {color: #FF00FF;}
   80.26 +    </style>
   80.27 +</head>
   80.28 +<body>
   80.29 +<form method="get">
   80.30 +
   80.31 +<label for="path">Project:</label>
   80.32 +<select size="1" name="path">");
   80.33 +    <#list paths as path>
   80.34 +        <option <#if selectedPath?? && path.segment == selectedPath>selected</#if> value="${path.segment}">
   80.35 +            ${path.displayName}
   80.36 +        </option>
   80.37 +    </#list>
   80.38 +</select>
   80.39 +<br>
   80.40 +<label for="pattern">Pattern:</label><br>
   80.41 +<textarea rows="10" cols="40" name="pattern">
   80.42 +<#if pattern??>
   80.43 +${pattern}
   80.44 +</#if>
   80.45 +</textarea><br>
   80.46 +<input type="submit" name="preview" value="Show diff preview"/><input type="submit" name="download" value="Download diff"/>
   80.47 +</form>
   80.48 +
   80.49 +<div class="examples">
   80.50 +<#if examples??>
   80.51 +    Examples:
   80.52 +    <dl id="examples-list">
   80.53 +        <#list examples as example>
   80.54 +            <dt>${example.displayName}</dt>
   80.55 +            <dd><pre>${example.pattern}</pre>
   80.56 +            </dd>
   80.57 +        </#list>
   80.58 +    </dl>
   80.59 +</#if>
   80.60 +</div>
   80.61 +
   80.62 +<#if result??>
   80.63 +    Diff for rule: ${pattern}
   80.64 +<pre>${result}</pre>
   80.65 +</#if>
   80.66 +
   80.67 +<#if statistics??>
   80.68 +     Query time: ${statistics.queryTime}ms, matching files: ${statistics.files}.
   80.69 +</#if>
   80.70 +</body>
   80.71 +</html>
    81.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    81.2 +++ b/server/backend/impl/src/org/netbeans/modules/jackpot30/backend/impl/ui/ui-cat.html	Fri Feb 18 20:16:26 2011 +0100
    81.3 @@ -0,0 +1,10 @@
    81.4 +<html>
    81.5 +<head>
    81.6 +    <style type="text/css">
    81.7 +        .occurrence {BACKGROUND: #DDDD00;}
    81.8 +    </style>
    81.9 +</head>
   81.10 +<body>
   81.11 +<pre><#list occurrences as occurrence>${occurrence.prefix}<span class="occurrence">${occurrence.occurrence}</span></#list>${suffix}</pre>
   81.12 +</body>
   81.13 +</html>
    82.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    82.2 +++ b/server/backend/impl/src/org/netbeans/modules/jackpot30/backend/impl/ui/ui-findType.html	Fri Feb 18 20:16:26 2011 +0100
    82.3 @@ -0,0 +1,28 @@
    82.4 +<html>
    82.5 +<head>
    82.6 +    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
    82.7 +</head>
    82.8 +<body>
    82.9 +<form method="get">
   82.10 +<label for="path">Project:</label>
   82.11 +<select size="1" name="path">");
   82.12 +    <#list paths as path>
   82.13 +        <option <#if selectedPath?? && path.segment == selectedPath>selected</#if> value="${path.segment}">
   82.14 +            ${path.displayName}
   82.15 +        </option>
   82.16 +    </#list>
   82.17 +</select>
   82.18 +<br>
   82.19 +<label for="prefix">Type Name:</label><input type="text" name="prefix"<#if prefix??>value="${prefix}"</#if>/><br>
   82.20 +<input type="submit" name="Find Candidates"/>
   82.21 +</form>
   82.22 +
   82.23 +<#if results??>
   82.24 +    Found types:<br>
   82.25 +    <#list results as result>
   82.26 +        <a href="/index/ui/show?path=${selectedPath}&relative=${result.relativePath}">${result.fqn}</a><br>
   82.27 +    </#list>
   82.28 +</#if>
   82.29 +
   82.30 +</body>
   82.31 +</html>
    83.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    83.2 +++ b/server/backend/impl/src/org/netbeans/modules/jackpot30/backend/impl/ui/ui-search.html	Fri Feb 18 20:16:26 2011 +0100
    83.3 @@ -0,0 +1,70 @@
    83.4 +<html>
    83.5 +<head>
    83.6 +    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
    83.7 +<#if results??>
    83.8 +    <script type="text/javascript">
    83.9 +        $(document).ready(function() {
   83.10 +            $('#list').find('dd').hide().end().find('dt').click(function() {
   83.11 +                current_dd=$(this).next();
   83.12 +                //XXX: will do the AJAX call for both show and hide!
   83.13 +                $.get("snippet?path=${selectedPath}&relative=" + current_dd.attr("id") + "&pattern=${patternEscaped}",function(data) {
   83.14 +                    current_dd.html(data).slideToggle();
   83.15 +                })
   83.16 +            });
   83.17 +        });
   83.18 +    </script>
   83.19 +</#if>
   83.20 +    <style type="text/css">
   83.21 +        .occurrence {BACKGROUND: #DDDD00;}
   83.22 +    </style>
   83.23 +</head>
   83.24 +<body>
   83.25 +<form method="get">
   83.26 +
   83.27 +<label for="path">Project:</label>
   83.28 +<select size="1" name="path">");
   83.29 +    <#list paths as path>
   83.30 +        <option <#if selectedPath?? && path.segment == selectedPath>selected</#if> value="${path.segment}">
   83.31 +            ${path.displayName}
   83.32 +        </option>
   83.33 +    </#list>
   83.34 +</select>
   83.35 +<br>
   83.36 +<label for="pattern">Pattern:</label><br>
   83.37 +<textarea rows="10" cols="40" name="pattern">
   83.38 +<#if pattern??>
   83.39 +${pattern}
   83.40 +</#if>
   83.41 +</textarea><br>
   83.42 +<input type="submit" name="Find Candidates"/>
   83.43 +</form>
   83.44 +
   83.45 +<div class="examples">
   83.46 +<#if examples??>
   83.47 +    Examples:
   83.48 +    <dl id="examples-list">
   83.49 +        <#list examples as example>
   83.50 +            <dt>${example.displayName}</dt>
   83.51 +            <dd><pre>${example.pattern}</pre>
   83.52 +            </dd>
   83.53 +        </#list>
   83.54 +    </dl>
   83.55 +</#if>
   83.56 +</div>
   83.57 +
   83.58 +<#if results??>
   83.59 +    Found candidates for pattern: ${pattern}
   83.60 +    <dl id="list">
   83.61 +        <#list results as result>
   83.62 +            <dt>${result.relativePath}<a href="/index/ui/show?path=${selectedPath}&relative=${result.relativePath}&pattern=${patternEscaped}">show</a></dt>
   83.63 +            <dd id="${result.relativePath}">
   83.64 +            </dd>
   83.65 +        </#list>
   83.66 +    </dl>
   83.67 +</#if>
   83.68 +
   83.69 +<#if statistics??>
   83.70 +     Query time: ${statistics.queryTime}ms, matching files: ${statistics.files}.
   83.71 +</#if>
   83.72 +</body>
   83.73 +</html>
    84.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    84.2 +++ b/server/backend/impl/src/org/netbeans/modules/jackpot30/backend/impl/ui/ui-snippet.html	Fri Feb 18 20:16:26 2011 +0100
    84.3 @@ -0,0 +1,7 @@
    84.4 +<#if snippets??>
    84.5 +    <#list snippets as snippet>
    84.6 +        <pre>${snippet.prefix}<span class="occurrence">${snippet.occurrence}</span>${snippet.suffix}</pre><br>
    84.7 +    </#list>
    84.8 +<#else>
    84.9 +    No occurrences.
   84.10 +</#if>
    85.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    85.2 +++ b/server/backend/nbproject/build-impl.xml	Fri Feb 18 20:16:26 2011 +0100
    85.3 @@ -0,0 +1,49 @@
    85.4 +<?xml version="1.0" encoding="UTF-8"?>
    85.5 +<!--
    85.6 +*** GENERATED FROM project.xml - DO NOT EDIT  ***
    85.7 +***         EDIT ../build.xml INSTEAD         ***
    85.8 +-->
    85.9 +<project name="backend-impl" basedir=".." xmlns:sproject="http://www.netbeans.org/ns/nb-module-suite-project/1">
   85.10 +    <fail message="Please build using Ant 1.7.1 or higher.">
   85.11 +        <condition>
   85.12 +            <not>
   85.13 +                <antversion atleast="1.7.1"/>
   85.14 +            </not>
   85.15 +        </condition>
   85.16 +    </fail>
   85.17 +    <property file="nbproject/private/platform-private.properties"/>
   85.18 +    <property file="nbproject/platform.properties"/>
   85.19 +    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-suite-project/1">
   85.20 +        <attribute name="name"/>
   85.21 +        <attribute name="value"/>
   85.22 +        <sequential>
   85.23 +            <property name="@{name}" value="${@{value}}"/>
   85.24 +        </sequential>
   85.25 +    </macrodef>
   85.26 +    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-suite-project/1">
   85.27 +        <attribute name="property"/>
   85.28 +        <attribute name="value"/>
   85.29 +        <sequential>
   85.30 +            <property name="@{property}" value="@{value}"/>
   85.31 +        </sequential>
   85.32 +    </macrodef>
   85.33 +    <property file="${user.properties.file}"/>
   85.34 +    <sproject:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir"/>
   85.35 +    <sproject:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir"/>
   85.36 +    <sproject:evalprops property="cluster.path.evaluated" value="${cluster.path}"/>
   85.37 +    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
   85.38 +        <condition>
   85.39 +            <not>
   85.40 +                <contains string="${cluster.path.evaluated}" substring="platform"/>
   85.41 +            </not>
   85.42 +        </condition>
   85.43 +    </fail>
   85.44 +    <fail message="Cannot find NetBeans build harness. ${line.separator}Check that nbplatform.${nbplatform.active}.netbeans.dest.dir and nbplatform.${nbplatform.active}.harness.dir are defined. ${line.separator}On a developer machine these are normally defined in ${user.properties.file}=${netbeans.user}/build.properties ${line.separator}but for automated builds you should pass these properties to Ant explicitly.">
   85.45 +        <condition>
   85.46 +            <not>
   85.47 +                <available type="dir" file="${harness.dir}"/>
   85.48 +            </not>
   85.49 +        </condition>
   85.50 +    </fail>
   85.51 +    <import file="${harness.dir}/suite.xml"/>
   85.52 +</project>
    86.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    86.2 +++ b/server/backend/nbproject/genfiles.properties	Fri Feb 18 20:16:26 2011 +0100
    86.3 @@ -0,0 +1,8 @@
    86.4 +build.xml.data.CRC32=2aaf9598
    86.5 +build.xml.script.CRC32=616acaee
    86.6 +build.xml.stylesheet.CRC32=eaf9f76a@1.44
    86.7 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
    86.8 +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
    86.9 +nbproject/build-impl.xml.data.CRC32=2aaf9598
   86.10 +nbproject/build-impl.xml.script.CRC32=e8ecb000
   86.11 +nbproject/build-impl.xml.stylesheet.CRC32=183e6ef3@1.44
    87.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    87.2 +++ b/server/backend/nbproject/platform.properties	Fri Feb 18 20:16:26 2011 +0100
    87.3 @@ -0,0 +1,12 @@
    87.4 +cluster.path=\
    87.5 +    ${nbplatform.active.dir}/apisupport:\
    87.6 +    ${nbplatform.active.dir}/enterprise:\
    87.7 +    ${nbplatform.active.dir}/harness:\
    87.8 +    ${nbplatform.active.dir}/ide:\
    87.9 +    ${nbplatform.active.dir}/java:\
   87.10 +    ${nbplatform.active.dir}/platform:\
   87.11 +    ${nbplatform.active.dir}/profiler:\
   87.12 +    ${nbplatform.active.dir}/websvccommon:\
   87.13 +    ../../build/cluster
   87.14 +disabled.modules=
   87.15 +nbplatform.active=default
    88.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    88.2 +++ b/server/backend/nbproject/project.properties	Fri Feb 18 20:16:26 2011 +0100
    88.3 @@ -0,0 +1,9 @@
    88.4 +app.name=backend
    88.5 +app.title=Jackpot 3.0 Backend
    88.6 +branding.token=${app.name}
    88.7 +modules=\
    88.8 +    ${project.org.netbeans.modules.jackpot30.backend.impl}
    88.9 +project.org.netbeans.modules.jackpot30.backend.impl=impl
   88.10 +#should used -nogui, but many parts (i.e. projects) use invokeWhenUIReady which is not invoked currently when -nogui is used:
   88.11 +run.args=--nosplash --start-server -J-Xdebug -J-Xrunjdwp:transport=dt_socket,suspend=n,server=y,address=8889
   88.12 +project.license=cddl-netbeans-sun
    89.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    89.2 +++ b/server/backend/nbproject/project.xml	Fri Feb 18 20:16:26 2011 +0100
    89.3 @@ -0,0 +1,9 @@
    89.4 +<?xml version="1.0" encoding="UTF-8"?>
    89.5 +<project xmlns="http://www.netbeans.org/ns/project/1">
    89.6 +    <type>org.netbeans.modules.apisupport.project.suite</type>
    89.7 +    <configuration>
    89.8 +        <data xmlns="http://www.netbeans.org/ns/nb-module-suite-project/1">
    89.9 +            <name>backend</name>
   89.10 +        </data>
   89.11 +    </configuration>
   89.12 +</project>
    90.1 --- a/server/download.xml	Sat Jan 22 21:51:05 2011 +0100
    90.2 +++ b/server/download.xml	Fri Feb 18 20:16:26 2011 +0100
    90.3 @@ -31,9 +31,9 @@
    90.4          <download url="http://repo2.maven.org/maven2/asm/asm-all/3.1/asm-all-3.1.jar" target="jersey-1.1/asm-all-3.1.jar"/>
    90.5          <download url="http://repo2.maven.org/maven2/asm/asm-all/3.1/asm-all-3.1-sources.jar" target="jersey-1.1/asm-all-3.1-sources.jar"/>
    90.6  
    90.7 -        <download url="http://repo1.maven.org/maven2/org/apache/lucene/lucene-core/2.9.3/lucene-core-2.9.3.jar" target="lucene-2.9.3/lucene-core-2.9.3.jar" />
    90.8 -        <download url="http://repo1.maven.org/maven2/org/apache/lucene/lucene-core/2.9.3/lucene-core-2.9.3-javadoc.jar" target="lucene-2.9.3/lucene-core-2.9.3-javadoc.jar" />
    90.9 -        <download url="http://repo1.maven.org/maven2/org/apache/lucene/lucene-core/2.9.3/lucene-core-2.9.3-sources.jar" target="lucene-2.9.3/lucene-core-2.9.3-sources.jar" />
   90.10 +        <download url="http://repo1.maven.org/maven2/org/apache/lucene/lucene-core/3.0.3/lucene-core-3.0.3.jar" target="lucene-3.0.3/lucene-core-3.0.3.jar" />
   90.11 +        <download url="http://repo1.maven.org/maven2/org/apache/lucene/lucene-core/3.0.3/lucene-core-3.0.3-javadoc.jar" target="lucene-3.0.3/lucene-core-3.0.3-javadoc.jar" />
   90.12 +        <download url="http://repo1.maven.org/maven2/org/apache/lucene/lucene-core/3.0.3/lucene-core-3.0.3-sources.jar" target="lucene-3.0.3/lucene-core-3.0.3-sources.jar" />
   90.13  
   90.14          <download url="http://repo1.maven.org/maven2/junit/junit/4.5/junit-4.5.jar" target="junit_4/junit-4.5.jar" />
   90.15          <download url="http://switch.dl.sourceforge.net/project/junit/junit/4.5/junit4.5.zip" target="junit_4/junit-4.5-api.zip" />
    91.1 --- a/server/hudson/src/main/java/org/netbeans/modules/jackpot30/hudson/Cache.java	Sat Jan 22 21:51:05 2011 +0100
    91.2 +++ b/server/hudson/src/main/java/org/netbeans/modules/jackpot30/hudson/Cache.java	Fri Feb 18 20:16:26 2011 +0100
    91.3 @@ -67,20 +67,22 @@
    91.4      private static File standaloneCacheRoot;
    91.5      private static Map<String, Cache> name2Cache = new HashMap<String, Cache>();
    91.6  
    91.7 -    public static Cache findCache(String indexName) {
    91.8 +    public static Cache findCache(String indexName, int version) {
    91.9          Cache cache = name2Cache.get(indexName);
   91.10  
   91.11          if (cache == null) {
   91.12 -            name2Cache.put(indexName, cache = new Cache(indexName));
   91.13 +            name2Cache.put(indexName, cache = new Cache(indexName, version));
   91.14          }
   91.15  
   91.16          return cache;
   91.17      }
   91.18  
   91.19      private final String name;
   91.20 +    private final int version;
   91.21  
   91.22 -    private Cache(String name) {
   91.23 +    private Cache(String name, int version) {
   91.24          this.name = name;
   91.25 +        this.version = version;
   91.26      }
   91.27      
   91.28      public File findCacheRoot(URL sourceRoot) throws IOException {
   91.29 @@ -90,7 +92,7 @@
   91.30              Logger.getLogger(Cache.class.getName()).log(Level.SEVERE, null, ex);
   91.31          }
   91.32          if (standaloneCacheRoot != null) {
   91.33 -            return getDataFolder(sourceRoot, name);
   91.34 +            return getDataFolder(sourceRoot, name, version);
   91.35          } else {
   91.36              throw new IllegalStateException();
   91.37          }
   91.38 @@ -179,7 +181,7 @@
   91.39          }
   91.40      }
   91.41  
   91.42 -    private static synchronized File getDataFolder (final URL root, String name) throws IOException {
   91.43 +    private static synchronized File getDataFolder (final URL root, String name, int version) throws IOException {
   91.44          loadSegments ();
   91.45          final String rootName = root.toExternalForm();
   91.46          String slice = invertedSegments.get (rootName);
   91.47 @@ -193,7 +195,7 @@
   91.48              storeSegments ();
   91.49          }
   91.50          final File folder = standaloneCacheRoot;
   91.51 -        return new File(new File(folder, slice), name);
   91.52 +        return new File(new File(new File(folder, slice), name), Integer.toString(version));
   91.53      }
   91.54  
   91.55      private static synchronized File getCacheFolder () {
    92.1 --- a/server/hudson/src/main/java/org/netbeans/modules/jackpot30/hudson/ClearIndexProperty.java	Sat Jan 22 21:51:05 2011 +0100
    92.2 +++ b/server/hudson/src/main/java/org/netbeans/modules/jackpot30/hudson/ClearIndexProperty.java	Fri Feb 18 20:16:26 2011 +0100
    92.3 @@ -89,7 +89,7 @@
    92.4          public void doDynamic(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, InterruptedException {
    92.5              String jobName = job.getName();
    92.6              Project<?, ?> prj = Hudson.getInstance().getItemByFullName(jobName, Project.class);
    92.7 -            File cacheRoot = Cache.findCache("clear-workspace").findCacheRoot(prj.getSomeWorkspace().toURI().toURL()).getParentFile();
    92.8 +            File cacheRoot = Cache.findCache("clear-workspace", 0).findCacheRoot(prj.getSomeWorkspace().toURI().toURL()).getParentFile().getParentFile();
    92.9  
   92.10              deleteRecursivelly(cacheRoot);
   92.11              
    93.1 --- a/server/hudson/src/main/java/org/netbeans/modules/jackpot30/hudson/IndexingBuilder.java	Sat Jan 22 21:51:05 2011 +0100
    93.2 +++ b/server/hudson/src/main/java/org/netbeans/modules/jackpot30/hudson/IndexingBuilder.java	Fri Feb 18 20:16:26 2011 +0100
    93.3 @@ -142,7 +142,7 @@
    93.4              success &= indexer.index(new IndexingContext(getDescriptor().getCacheDir(), build, launcher, listener, addedFiles, removedFiles));
    93.5          }
    93.6          //XXX:
    93.7 -        File info = new File(Cache.findCache("jackpot30").findCacheRoot(build.getWorkspace().toURI().toURL()), "info");
    93.8 +        File info = new File(Cache.findCache("jackpot30", 1002).findCacheRoot(build.getWorkspace().toURI().toURL()), "info");
    93.9          String jsonContent = readFully(info);
   93.10          JSONObject json = JSONObject.fromObject(jsonContent);
   93.11  
    94.1 --- a/server/indexer/src/org/netbeans/modules/jackpot30/server/indexer/StandaloneFinder.java	Sat Jan 22 21:51:05 2011 +0100
    94.2 +++ b/server/indexer/src/org/netbeans/modules/jackpot30/server/indexer/StandaloneFinder.java	Fri Feb 18 20:16:26 2011 +0100
    94.3 @@ -93,7 +93,7 @@
    94.4  
    94.5      public static int[] findCandidateOccurrenceSpans(File sourceRoot, String relativePath, String pattern) throws IOException {
    94.6          BulkPattern bulkPattern = preparePattern(pattern, null);
    94.7 -        CharSequence source = FileBasedIndex.get(sourceRoot.toURI().toURL()).getSourceCode(relativePath);
    94.8 +        CharSequence source = FileBasedIndex.get(sourceRoot.toURI().toURL()).getSourceCode(relativePath).toString().replaceAll("\r\n", "\n");
    94.9          JavacTaskImpl jti = prepareJavacTaskImpl();
   94.10          CompilationUnitTree cut = jti.parse(new JFOImpl(source)).iterator().next();
   94.11          Collection<TreePath> paths = new LinkedList<TreePath>();
    95.1 --- a/server/lib/nblibraries.properties	Sat Jan 22 21:51:05 2011 +0100
    95.2 +++ b/server/lib/nblibraries.properties	Fri Feb 18 20:16:26 2011 +0100
    95.3 @@ -30,16 +30,16 @@
    95.4      ${base}/jersey-1.1/asm-all-3.1-sources.jar:\
    95.5      ${base}/jersey-1.1/jsr311-api-1.0-sources.jar
    95.6  libs.lucene.classpath=\
    95.7 -    ${base}/lucene-2.9.3/lucene-core-2.9.3.jar
    95.8 +    ${base}/lucene-3.0.3/lucene-core-3.0.3.jar
    95.9  libs.jersey.javadoc=\
   95.10      ${base}/jersey-1.1/jersey-client-1.0.1-javadoc.jar!//:\
   95.11      ${base}/jersey-1.1/jersey-core-1.0.1-javadoc.jar!//:\
   95.12      ${base}/jersey-1.1/jersey-server-1.0.1-javadoc.jar!//:\
   95.13      ${base}/jersey-1.1/jsr311-api-1.0-javadoc.jar!//
   95.14  libs.lucene.javadoc=\
   95.15 -    ${base}/lucene-2.9.3/lucene-core-2.9.3-javadoc.jar!//
   95.16 +    ${base}/lucene-3.0.3/lucene-core-3.0.3-javadoc.jar!//
   95.17  libs.lucene.src=\
   95.18 -    ${base}/lucene-2.9.3/lucene-core-2.9.3-sources.jar
   95.19 +    ${base}/lucene-3.0.3/lucene-core-3.0.3-sources.jar
   95.20  libs.javac.classpath=\
   95.21      ${base}/javac/javac-api-nb-7.0-b07.jar:\
   95.22      ${base}/javac/javac-impl-nb-7.0-b07.jar
    96.1 --- a/server/web.api/nbproject/project.properties	Sat Jan 22 21:51:05 2011 +0100
    96.2 +++ b/server/web.api/nbproject/project.properties	Fri Feb 18 20:16:26 2011 +0100
    96.3 @@ -26,6 +26,7 @@
    96.4  endorsed.classpath=
    96.5  excludes=
    96.6  file.reference.org-netbeans-modules-java-source.jar=../lib/org-netbeans-modules-java-source.jar
    96.7 +file.reference.org-netbeans-spi-editor-hints.jar=../lib/org-netbeans-spi-editor-hints.jar
    96.8  file.reference.org-openide-filesystems.jar=../lib/org-openide-filesystems.jar
    96.9  file.reference.org-openide-util-lookup.jar=../lib/org-openide-util-lookup.jar
   96.10  file.reference.org-openide-util.jar=../lib/org-openide-util.jar
   96.11 @@ -49,7 +50,8 @@
   96.12      ${file.reference.org-openide-filesystems.jar}:\
   96.13      ${libs.freemarker.classpath}:\
   96.14      ${file.reference.org-openide-util.jar}:\
   96.15 -    ${file.reference.org-openide-util-lookup.jar}
   96.16 +    ${file.reference.org-openide-util-lookup.jar}:\
   96.17 +    ${file.reference.org-netbeans-spi-editor-hints.jar}
   96.18  # Space-separated list of extra javac options
   96.19  javac.compilerargs=
   96.20  javac.deprecation=false
    97.1 --- a/server/web.api/src/org/netbeans/modules/jackpot30/server/webapi/API.java	Sat Jan 22 21:51:05 2011 +0100
    97.2 +++ b/server/web.api/src/org/netbeans/modules/jackpot30/server/webapi/API.java	Fri Feb 18 20:16:26 2011 +0100
    97.3 @@ -148,7 +148,7 @@
    97.4              throw new IOException("Source code not found");
    97.5          }
    97.6          
    97.7 -        return source.toString();
    97.8 +        return source.toString().replaceAll("\r\n", "\n");
    97.9      }
   97.10  
   97.11      @GET
    98.1 --- a/server/web.api/src/org/netbeans/modules/jackpot30/server/webapi/UI.java	Sat Jan 22 21:51:05 2011 +0100
    98.2 +++ b/server/web.api/src/org/netbeans/modules/jackpot30/server/webapi/UI.java	Fri Feb 18 20:16:26 2011 +0100
    98.3 @@ -135,9 +135,9 @@
    98.4          for (int[] span : parseSpans(WebUtilities.requestStringResponse(spansURL))) { //XXX: sorted!
    98.5              Map<String, String> occ = new HashMap<String, String>();
    98.6              occ.put("prefix", WebUtilities.escapeForHTMLElement(code.substring(currentCodePos, span[0])));
    98.7 -            occ.put("occurrence", WebUtilities.escapeForHTMLElement(code.substring(span[0], span[1] + 1)));
    98.8 +            occ.put("occurrence", WebUtilities.escapeForHTMLElement(code.substring(span[0], span[1])));
    98.9              occurrences.add(occ);
   98.10 -            currentCodePos = span[1] + 1;
   98.11 +            currentCodePos = span[1];
   98.12          }
   98.13  
   98.14          configurationData.put("suffix", WebUtilities.escapeForHTMLElement(code.substring(currentCodePos, code.length())));
   98.15 @@ -212,8 +212,8 @@
   98.16          Map<String, String> result = new HashMap<String, String>();
   98.17          
   98.18          result.put("prefix", WebUtilities.escapeForHTMLElement(code.substring(grandStart, span[0])));
   98.19 -        result.put("occurrence", WebUtilities.escapeForHTMLElement(code.substring(span[0], span[1] + 1)));
   98.20 -        result.put("suffix", WebUtilities.escapeForHTMLElement(code.substring(span[1] + 1, grandEnd)));
   98.21 +        result.put("occurrence", WebUtilities.escapeForHTMLElement(code.substring(span[0], span[1])));
   98.22 +        result.put("suffix", WebUtilities.escapeForHTMLElement(code.substring(span[1], grandEnd)));
   98.23  
   98.24          return result;
   98.25      }