Allow to search for usages on remote side using an attributed remote index.
authorJan Lahoda <jlahoda@netbeans.org>
Sat, 05 Mar 2011 23:03:17 +0100
changeset 552e0855a9f6040
parent 551 4e37e4d972ba
child 556 e588b90864a6
Allow to search for usages on remote side using an attributed remote index.
api/nbproject/genfiles.properties
api/nbproject/project.xml
api/src/org/netbeans/modules/jackpot30/impl/WebUtilities.java
api/src/org/netbeans/modules/jackpot30/impl/batch/BatchSearch.java
api/src/org/netbeans/modules/jackpot30/impl/indexing/RemoteIndex.java
api/src/org/netbeans/modules/jackpot30/impl/indexing/options/Bundle.properties
api/src/org/netbeans/modules/jackpot30/impl/indexing/options/CustomizeRemoteIndex.form
api/src/org/netbeans/modules/jackpot30/impl/indexing/options/CustomizeRemoteIndex.java
api/src/org/netbeans/modules/jackpot30/impl/indexing/options/IndexOptionsPanelController.java
api/src/org/netbeans/modules/jackpot30/impl/indexing/options/IndexPanel.form
api/src/org/netbeans/modules/jackpot30/impl/indexing/options/IndexPanel.java
api/src/org/netbeans/modules/jackpot30/impl/refactoring/AbstractApplyHintsRefactoringPlugin.java
api/src/org/netbeans/modules/jackpot30/impl/refactoring/FindDuplicatesRefactoringPlugin.java
api/src/org/netbeans/modules/jackpot30/impl/refactoring/RefactoringPluginFactoryImpl.java
api/src/org/netbeans/modules/jackpot30/impl/refactoring/Utilities.java
api/src/org/netbeans/modules/jackpot30/impl/refactoring/findusages/GlobalFindUsagesAction.java
api/src/org/netbeans/modules/jackpot30/impl/refactoring/findusages/GlobalFindUsagesRefactoring.java
api/src/org/netbeans/modules/jackpot30/impl/refactoring/findusages/GlobalFindUsagesRefactoringPlugin.java
api/src/org/netbeans/modules/jackpot30/impl/refactoring/findusages/GlobalFindUsagesRefactoringUI.java
api/src/org/netbeans/modules/jackpot30/impl/refactoring/findusages/PatternGenerator.java
api/src/org/netbeans/modules/jackpot30/spi/HintDescription.java
api/src/org/netbeans/modules/jackpot30/spi/HintDescriptionFactory.java
api/test/unit/src/org/netbeans/modules/jackpot30/impl/batch/BatchSearchTest.java
api/test/unit/src/org/netbeans/modules/jackpot30/impl/indexing/IndexTest.java
api/test/unit/src/org/netbeans/modules/jackpot30/impl/refactoring/findusages/PatternGeneratorTest.java
file/src/org/netbeans/modules/jackpot30/file/DeclarativeHintRegistry.java
file/src/org/netbeans/modules/jackpot30/file/DeclarativeHintsParser.java
server/backend/impl/src/org/netbeans/modules/jackpot30/backend/impl/api/API.java
     1.1 --- a/api/nbproject/genfiles.properties	Fri Feb 25 19:39:47 2011 +0100
     1.2 +++ b/api/nbproject/genfiles.properties	Sat Mar 05 23:03:17 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=a7e51eed
     1.8 +nbproject/build-impl.xml.data.CRC32=9dd73a80
     1.9  nbproject/build-impl.xml.script.CRC32=c4574e66
    1.10 -nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.44
    1.11 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.45
     2.1 --- a/api/nbproject/project.xml	Fri Feb 25 19:39:47 2011 +0100
     2.2 +++ b/api/nbproject/project.xml	Sat Mar 05 23:03:17 2011 +0100
     2.3 @@ -78,6 +78,15 @@
     2.4                      </run-dependency>
     2.5                  </dependency>
     2.6                  <dependency>
     2.7 +                    <code-name-base>org.netbeans.modules.editor</code-name-base>
     2.8 +                    <build-prerequisite/>
     2.9 +                    <compile-dependency/>
    2.10 +                    <run-dependency>
    2.11 +                        <release-version>3</release-version>
    2.12 +                        <specification-version>1.56.0.5.13.6</specification-version>
    2.13 +                    </run-dependency>
    2.14 +                </dependency>
    2.15 +                <dependency>
    2.16                      <code-name-base>org.netbeans.modules.editor.lib</code-name-base>
    2.17                      <build-prerequisite/>
    2.18                      <compile-dependency/>
    2.19 @@ -174,6 +183,15 @@
    2.20                      </run-dependency>
    2.21                  </dependency>
    2.22                  <dependency>
    2.23 +                    <code-name-base>org.netbeans.modules.options.api</code-name-base>
    2.24 +                    <build-prerequisite/>
    2.25 +                    <compile-dependency/>
    2.26 +                    <run-dependency>
    2.27 +                        <release-version>1</release-version>
    2.28 +                        <specification-version>1.20</specification-version>
    2.29 +                    </run-dependency>
    2.30 +                </dependency>
    2.31 +                <dependency>
    2.32                      <code-name-base>org.netbeans.modules.parsing.api</code-name-base>
    2.33                      <build-prerequisite/>
    2.34                      <compile-dependency/>
     3.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/WebUtilities.java	Fri Feb 25 19:39:47 2011 +0100
     3.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/WebUtilities.java	Sat Mar 05 23:03:17 2011 +0100
     3.3 @@ -52,6 +52,7 @@
     3.4  import java.util.List;
     3.5  import java.util.regex.Matcher;
     3.6  import java.util.regex.Pattern;
     3.7 +import org.netbeans.api.annotations.common.CheckForNull;
     3.8  
     3.9  /**
    3.10   *
    3.11 @@ -61,7 +62,7 @@
    3.12      private WebUtilities() {
    3.13      }
    3.14  
    3.15 -    public static String requestStringResponse (URI uri) {
    3.16 +    public static @CheckForNull String requestStringResponse (URI uri) {
    3.17          final StringBuffer sb = new StringBuffer ();
    3.18          final URL url;
    3.19          try {
    3.20 @@ -85,6 +86,7 @@
    3.21              }
    3.22          } catch (IOException e) {
    3.23              e.printStackTrace ();  // TODO
    3.24 +            return null;
    3.25          }
    3.26          return sb.toString ();
    3.27      }
     4.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/batch/BatchSearch.java	Fri Feb 25 19:39:47 2011 +0100
     4.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/batch/BatchSearch.java	Sat Mar 05 23:03:17 2011 +0100
     4.3 @@ -39,6 +39,8 @@
     4.4  
     4.5  package org.netbeans.modules.jackpot30.impl.batch;
     4.6  
     4.7 +import org.netbeans.spi.editor.hints.Severity;
     4.8 +import java.util.Iterator;
     4.9  import com.sun.source.tree.Tree;
    4.10  import com.sun.source.tree.Tree.Kind;
    4.11  import com.sun.source.util.TreePath;
    4.12 @@ -56,6 +58,8 @@
    4.13  import java.io.OutputStreamWriter;
    4.14  import java.io.Writer;
    4.15  import java.lang.reflect.Field;
    4.16 +import java.net.URI;
    4.17 +import java.net.URISyntaxException;
    4.18  import java.net.URL;
    4.19  import java.nio.ByteBuffer;
    4.20  import java.util.ArrayList;
    4.21 @@ -72,6 +76,7 @@
    4.22  import java.util.Set;
    4.23  import java.util.concurrent.atomic.AtomicBoolean;
    4.24  import java.util.concurrent.atomic.AtomicInteger;
    4.25 +import java.util.concurrent.atomic.AtomicReference;
    4.26  import java.util.logging.Level;
    4.27  import java.util.logging.Logger;
    4.28  import org.codeviation.pojson.Pojson;
    4.29 @@ -91,10 +96,12 @@
    4.30  import org.netbeans.modules.jackpot30.impl.MessageImpl;
    4.31  import org.netbeans.modules.jackpot30.impl.RulesManager;
    4.32  import org.netbeans.modules.jackpot30.impl.Utilities;
    4.33 +import org.netbeans.modules.jackpot30.impl.WebUtilities;
    4.34  import org.netbeans.modules.jackpot30.impl.hints.HintsInvoker;
    4.35  import org.netbeans.modules.jackpot30.impl.indexing.CustomIndexerImpl;
    4.36  import org.netbeans.modules.jackpot30.impl.indexing.FileBasedIndex;
    4.37  import org.netbeans.modules.jackpot30.impl.indexing.Index;
    4.38 +import org.netbeans.modules.jackpot30.impl.indexing.RemoteIndex;
    4.39  import org.netbeans.modules.jackpot30.impl.pm.BulkSearch;
    4.40  import org.netbeans.modules.jackpot30.impl.pm.BulkSearch.BulkPattern;
    4.41  import org.netbeans.modules.jackpot30.impl.pm.CopyFinder;
    4.42 @@ -104,11 +111,13 @@
    4.43  import org.netbeans.modules.jackpot30.spi.HintDescription.PatternDescription;
    4.44  import org.netbeans.modules.java.source.JavaSourceAccessor;
    4.45  import org.netbeans.spi.editor.hints.ErrorDescription;
    4.46 +import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
    4.47  import org.openide.filesystems.FileObject;
    4.48  import org.openide.filesystems.FileStateInvalidException;
    4.49  import org.openide.filesystems.FileUtil;
    4.50  import org.openide.filesystems.URLMapper;
    4.51  import org.openide.util.Exceptions;
    4.52 +import static org.netbeans.modules.jackpot30.impl.WebUtilities.escapeForQuery;
    4.53  
    4.54  /**
    4.55   *
    4.56 @@ -122,7 +131,7 @@
    4.57          return findOccurrences(patterns, scope, new ProgressHandleWrapper(null));
    4.58      }
    4.59  
    4.60 -    public static BatchResult findOccurrences(Iterable<? extends HintDescription> patterns, final Scope scope, final ProgressHandleWrapper progress) {
    4.61 +    public static BatchResult findOccurrences(final Iterable<? extends HintDescription> patterns, final Scope scope, final ProgressHandleWrapper progress) {
    4.62          for (HintDescription pattern : patterns) {
    4.63              if (pattern.getTriggerKind() != null || pattern.getTriggerPattern() == null) {
    4.64                  throw new UnsupportedOperationException();
    4.65 @@ -131,11 +140,11 @@
    4.66  
    4.67          MapIndices knownSourceRootsMapper = new MapIndices() {
    4.68              private Set<FileObject> KNOWN_SOURCE_ROOTS = new HashSet<FileObject>(GlobalPathRegistry.getDefault().getSourceRoots());
    4.69 -            public Index findIndex(FileObject root, ProgressHandleWrapper progress) {
    4.70 +            public IndexEnquirer findIndex(FileObject root, ProgressHandleWrapper progress) {
    4.71                  progress.startNextPart(1);
    4.72                  if (KNOWN_SOURCE_ROOTS.contains(root) || scope.forceIndicesUpToDate) {
    4.73                      try {
    4.74 -                        return FileBasedIndex.get(root.getURL());
    4.75 +                        return new SimpleIndexIndexEnquirer(root, FileBasedIndex.get(root.getURL()));
    4.76                      } catch (IOException ex) {
    4.77                          //TODO: would log+return null be more appropriate?
    4.78                          throw new IllegalStateException(ex);
    4.79 @@ -176,16 +185,16 @@
    4.80                  if (scope.indexURL != null) {
    4.81                      if (scope.subIndex == null) {
    4.82                          mapper = new MapIndices() {
    4.83 -                            public Index findIndex(FileObject root, ProgressHandleWrapper progress) {
    4.84 -                                return createOrUpdateIndex(root, new File(scope.indexURL), scope.update, progress);
    4.85 +                            public IndexEnquirer findIndex(FileObject root, ProgressHandleWrapper progress) {
    4.86 +                                return new SimpleIndexIndexEnquirer(root, createOrUpdateIndex(root, new File(scope.indexURL), scope.update, progress));
    4.87                              }
    4.88                          };
    4.89                      } else {
    4.90                          mapper = new MapIndices() {
    4.91 -                            public Index findIndex(FileObject root, ProgressHandleWrapper progress) {
    4.92 +                            public IndexEnquirer findIndex(FileObject root, ProgressHandleWrapper progress) {
    4.93                                  progress.startNextPart(1);
    4.94                                  try {
    4.95 -                                    return Index.createWithRemoteIndex(root.getURL(), scope.indexURL, scope.subIndex);
    4.96 +                                    return new SimpleIndexIndexEnquirer(root, Index.createWithRemoteIndex(root.getURL(), scope.indexURL, scope.subIndex));
    4.97                                  } catch (FileStateInvalidException ex) {
    4.98                                      Exceptions.printStackTrace(ex);
    4.99                                      return null;
   4.100 @@ -198,6 +207,23 @@
   4.101                  }
   4.102  
   4.103                  return findOccurrencesLocal(patterns, mapper, todo, progress);
   4.104 +            case ALL_REMOTE:
   4.105 +                todo = new HashSet<FileObject>();
   4.106 +
   4.107 +                for (RemoteIndex remoteIndex : RemoteIndex.loadIndices()) {
   4.108 +                    todo.add(FileUtil.toFileObject(FileUtil.normalizeFile(new File(remoteIndex.folder))));
   4.109 +                }
   4.110 +
   4.111 +                return findOccurrencesLocal(patterns, new MapIndices() {
   4.112 +                    public IndexEnquirer findIndex(FileObject root, ProgressHandleWrapper progress) {
   4.113 +                        for (RemoteIndex remoteIndex : RemoteIndex.loadIndices()) {
   4.114 +                            if (FileUtil.toFileObject(FileUtil.normalizeFile(new File(remoteIndex.folder))) == root) {
   4.115 +                                return enquirerForRemoteIndex(root, remoteIndex, patterns);
   4.116 +                            }
   4.117 +                        }
   4.118 +                        throw new IllegalStateException();
   4.119 +                    }
   4.120 +                }, todo, progress);
   4.121              default:
   4.122                  throw new UnsupportedOperationException(scope.scopeType.name());
   4.123          }
   4.124 @@ -219,86 +245,37 @@
   4.125          return result[0];
   4.126      }
   4.127      
   4.128 -    private static BatchResult findOccurrencesLocalImpl(CompilationInfo info, final Iterable<? extends HintDescription> patterns, MapIndices indexMapper, Collection<? extends FileObject> todo, ProgressHandleWrapper progress) {
   4.129 -        final BulkPattern bulkPattern = preparePattern(patterns, info);
   4.130 -        final Map<Container, Collection<Resource>> result = new HashMap<Container, Collection<Resource>>();
   4.131 +    private static BatchResult findOccurrencesLocalImpl(final CompilationInfo info, final Iterable<? extends HintDescription> patterns, MapIndices indexMapper, Collection<? extends FileObject> todo, ProgressHandleWrapper progress) {
   4.132 +        final DelayedBulkPattern bulkPattern = new DelayedBulkPattern() {
   4.133 +            private final AtomicReference<BulkPattern> pattern = new AtomicReference<BulkPattern>();
   4.134 +            public BulkPattern get() {
   4.135 +                if (pattern.get() == null) {
   4.136 +                    pattern.set(preparePattern(patterns, info));
   4.137 +                }
   4.138 +
   4.139 +                return pattern.get();
   4.140 +            }
   4.141 +        };
   4.142 +        final Map<IndexEnquirer, Collection<? extends Resource>> result = new HashMap<IndexEnquirer, Collection<? extends Resource>>();
   4.143          final Collection<MessageImpl> problems = new LinkedList<MessageImpl>();
   4.144          ProgressHandleWrapper innerForAll = progress.startNextPartWithEmbedding(ProgressHandleWrapper.prepareParts(2 * todo.size()));
   4.145          
   4.146          for (final FileObject src : todo) {
   4.147              LOG.log(Level.FINE, "Processing: {0}", FileUtil.getFileDisplayName(src));
   4.148              
   4.149 -            try {
   4.150 -                Index i = indexMapper.findIndex(src, innerForAll);
   4.151 +            IndexEnquirer indexEnquirer = indexMapper.findIndex(src, innerForAll);
   4.152  
   4.153 -                if (i != null) {
   4.154 -                    innerForAll.startNextPart(1);
   4.155 -                    
   4.156 -                    Container id = new LocalContainer(src);
   4.157 -
   4.158 -                    for (String candidate : i.findCandidates(bulkPattern)) {
   4.159 -                        Collection<Resource> resources = result.get(id);
   4.160 -
   4.161 -                        if (resources == null) {
   4.162 -                            result.put(id, resources = new LinkedList<Resource>());
   4.163 -                        }
   4.164 -
   4.165 -                        resources.add(new Resource(id, candidate, patterns, bulkPattern));
   4.166 -                    }
   4.167 -                } else {
   4.168 -                    Collection<FileObject> files = new LinkedList<FileObject>();
   4.169 -                    final Container id = new LocalContainer(src);
   4.170 -
   4.171 -                    final ProgressHandleWrapper innerProgress = innerForAll.startNextPartWithEmbedding(30, 70);
   4.172 -                    
   4.173 -                    recursive(src, src, files, innerProgress, 0, null, null);
   4.174 -
   4.175 -                    LOG.log(Level.FINE, "files: {0}", files);
   4.176 -
   4.177 -                    innerProgress.startNextPart(files.size());
   4.178 -
   4.179 -                    if (!files.isEmpty()) {
   4.180 -                        long start = System.currentTimeMillis();
   4.181 -
   4.182 -                        JavaSource.create(Utilities.createUniversalCPInfo(), files).runUserActionTask(new Task<CompilationController>() {
   4.183 -                            public void run(CompilationController cc) throws Exception {
   4.184 -                                if (cc.toPhase(Phase.PARSED).compareTo(Phase.PARSED) <0) {
   4.185 -                                    return ;
   4.186 -                                }
   4.187 -
   4.188 -                                try {
   4.189 -                                    boolean matches = BulkSearch.getDefault().matches(cc, new TreePath(cc.getCompilationUnit()), bulkPattern);
   4.190 -
   4.191 -                                    if (matches) {
   4.192 -                                        Collection<Resource> resources = result.get(id);
   4.193 -
   4.194 -                                        if (resources == null) {
   4.195 -                                            result.put(id, resources = new LinkedList<Resource>());
   4.196 -                                        }
   4.197 -
   4.198 -                                        resources.add(new Resource(id, FileUtil.getRelativePath(src, cc.getFileObject()), patterns, bulkPattern));
   4.199 -                                    }
   4.200 -                                } catch (ThreadDeath td) {
   4.201 -                                    throw td;
   4.202 -                                } catch (Throwable t) {
   4.203 -                                    LOG.log(Level.INFO, "Exception while performing batch search in " + FileUtil.getFileDisplayName(cc.getFileObject()), t);
   4.204 -                                    problems.add(new MessageImpl(MessageKind.WARNING, "An exception occurred while testing file: " + FileUtil.getFileDisplayName(cc.getFileObject()) + " (" + t.getLocalizedMessage() + ")."));
   4.205 -                                }
   4.206 -
   4.207 -                                innerProgress.tick();
   4.208 -                            }
   4.209 -                        }, true);
   4.210 -
   4.211 -                        long end = System.currentTimeMillis();
   4.212 -
   4.213 -                        LOG.log(Level.FINE, "took: {0}, per file: {1}", new Object[]{end - start, (end - start) / files.size()});
   4.214 -                    }
   4.215 -                }
   4.216 -            } catch (IOException ex) {
   4.217 -                Exceptions.printStackTrace(ex);
   4.218 +            if (indexEnquirer == null) {
   4.219 +                indexEnquirer = new FileSystemBasedIndexEnquirer(src);
   4.220              }
   4.221  
   4.222 -            progress.tick();
   4.223 +            Collection<? extends Resource> occurrences = indexEnquirer.findResources(patterns, innerForAll, bulkPattern, problems);
   4.224 +
   4.225 +            if (!occurrences.isEmpty()) {
   4.226 +                result.put(indexEnquirer, occurrences);
   4.227 +            }
   4.228 +
   4.229 +            innerForAll.tick();
   4.230          }
   4.231  
   4.232          return new BatchResult(result, problems);
   4.233 @@ -422,7 +399,7 @@
   4.234  
   4.235          return index;
   4.236      }
   4.237 -    
   4.238 +
   4.239      public static void getVerifiedSpans(BatchResult candidates, @NonNull ProgressHandleWrapper progress, final VerifiedSpansCallBack callback, final Collection<? super MessageImpl> problems) {
   4.240          getVerifiedSpans(candidates, progress, callback, false, problems);
   4.241      }
   4.242 @@ -431,20 +408,20 @@
   4.243          int[] parts = new int[candidates.projectId2Resources.size()];
   4.244          int   index = 0;
   4.245  
   4.246 -        for (Entry<? extends Container, ? extends Collection<? extends Resource>> e : candidates.projectId2Resources.entrySet()) {
   4.247 +        for (Entry<? extends IndexEnquirer, ? extends Collection<? extends Resource>> e : candidates.projectId2Resources.entrySet()) {
   4.248              parts[index++] = e.getValue().size();
   4.249          }
   4.250  
   4.251          ProgressHandleWrapper inner = progress.startNextPartWithEmbedding(parts);
   4.252  
   4.253 -        for (Collection<? extends Resource> it :candidates.projectId2Resources.values()) {
   4.254 -            inner.startNextPart(it.size());
   4.255 +        for (Entry<? extends IndexEnquirer, ? extends Collection<? extends Resource>> e : candidates.projectId2Resources.entrySet()) {
   4.256 +            inner.startNextPart(e.getValue().size());
   4.257  
   4.258 -            getVerifiedSpans(it, inner, callback, doNotRegisterClassPath, problems);
   4.259 +            e.getKey().validateResource(e.getValue(), progress, callback, problems);
   4.260          }
   4.261      }
   4.262  
   4.263 -    private static void getVerifiedSpans(Collection<? extends Resource> resources, @NonNull final ProgressHandleWrapper progress, final VerifiedSpansCallBack callback, boolean doNotRegisterClassPath, final Collection<? super MessageImpl> problems) {
   4.264 +    private static void getLocalVerifiedSpans(Collection<? extends Resource> resources, @NonNull final ProgressHandleWrapper progress, final VerifiedSpansCallBack callback, boolean doNotRegisterClassPath, final Collection<? super MessageImpl> problems) {
   4.265          Collection<FileObject> files = new LinkedList<FileObject>();
   4.266          final Map<FileObject, Resource> file2Resource = new HashMap<FileObject, Resource>();
   4.267  
   4.268 @@ -557,6 +534,57 @@
   4.269          }
   4.270      }
   4.271  
   4.272 +    private static boolean isAttributedIndexWithSpans(RemoteIndex remoteIndex) {
   4.273 +        try {
   4.274 +            URI capabilitiesURI = new URI(remoteIndex.remote.toExternalForm() + "/capabilities");
   4.275 +            String capabilitiesString = WebUtilities.requestStringResponse(capabilitiesURI);
   4.276 +
   4.277 +            if (capabilitiesURI == null) return false;
   4.278 +
   4.279 +            @SuppressWarnings("unchecked")
   4.280 +            Map<String, Object> capabilities = Pojson.load(HashMap.class, capabilitiesString);
   4.281 +
   4.282 +            return capabilities.get("attributed") == Boolean.TRUE; //TODO: should also check "methods contains findWithSpans"
   4.283 +        } catch (URISyntaxException ex) {
   4.284 +            LOG.log(Level.FINE, null, ex);
   4.285 +            return false;
   4.286 +        }
   4.287 +    }
   4.288 +
   4.289 +    private static IndexEnquirer enquirerForRemoteIndex(FileObject src, RemoteIndex remoteIndex, Iterable<? extends HintDescription> hints) {
   4.290 +        boolean fullySupported = isAttributedIndexWithSpans(remoteIndex);
   4.291 +        StringBuilder textualRepresentation = new StringBuilder();
   4.292 +
   4.293 +        for (HintDescription hd : hints) {
   4.294 +            if (hd.getTriggerPattern().getImports().iterator().hasNext()) {
   4.295 +                fullySupported = false;
   4.296 +            }
   4.297 +
   4.298 +            if (!fullySupported) break;
   4.299 +
   4.300 +            String hintText = hd.getHintText();
   4.301 +
   4.302 +            if (hintText != null) {
   4.303 +                textualRepresentation.append(hintText);
   4.304 +            } else {
   4.305 +                textualRepresentation.append(defaultHintText(hd));
   4.306 +                fullySupported = false;
   4.307 +            }
   4.308 +
   4.309 +            textualRepresentation.append("\n");
   4.310 +        }
   4.311 +
   4.312 +        if (fullySupported) {
   4.313 +            return new RemoteFullyAttributedIndexEnquirer(src, remoteIndex, textualRepresentation.toString());
   4.314 +        } else {
   4.315 +            try {
   4.316 +                return new SimpleIndexIndexEnquirer(src, Index.createWithRemoteIndex(src.getURL(), remoteIndex.remote.toExternalForm(), remoteIndex.remoteSegment));
   4.317 +            } catch (FileStateInvalidException ex) {
   4.318 +                throw new IllegalStateException(ex);
   4.319 +            }
   4.320 +        }
   4.321 +    }
   4.322 +
   4.323      public interface VerifiedSpansCallBack {
   4.324          public void groupStarted();
   4.325          public boolean spansVerified(CompilationController wc, Resource r, Collection<? extends ErrorDescription> hints) throws Exception;
   4.326 @@ -572,12 +600,13 @@
   4.327          public  final boolean update; //public only for AddScopePanel
   4.328          private final Collection<? extends FileObject> sourceRoots;
   4.329          private final boolean forceIndicesUpToDate;
   4.330 +        private final boolean allRemote;
   4.331  
   4.332          private Scope() {
   4.333 -            this(null, null, null, null, true, null, false);
   4.334 +            this(null, null, null, null, true, null, false, false);
   4.335          }
   4.336  
   4.337 -        private Scope(ScopeType scopeType, String folder, String indexURL, String subIndex, boolean update, Collection<? extends FileObject> sourceRoots, boolean forceIndicesUpToDate) {
   4.338 +        private Scope(ScopeType scopeType, String folder, String indexURL, String subIndex, boolean update, Collection<? extends FileObject> sourceRoots, boolean forceIndicesUpToDate, boolean allRemote) {
   4.339              this.scopeType = scopeType;
   4.340              this.folder = folder;
   4.341              this.indexURL = indexURL;
   4.342 @@ -585,6 +614,7 @@
   4.343              this.update = update;
   4.344              this.sourceRoots = sourceRoots;
   4.345              this.forceIndicesUpToDate = forceIndicesUpToDate;
   4.346 +            this.allRemote = allRemote;
   4.347          }
   4.348  
   4.349          public String serialize() {
   4.350 @@ -601,23 +631,23 @@
   4.351          }
   4.352  
   4.353          public static Scope createAllOpenedProjectsScope() {
   4.354 -            return new Scope(ScopeType.ALL_OPENED_PROJECTS, null, null, null, false, null, false);
   4.355 +            return new Scope(ScopeType.ALL_OPENED_PROJECTS, null, null, null, false, null, false, false);
   4.356          }
   4.357  
   4.358          public static Scope createAllDependentOpenedSourceRoots(FileObject from) {
   4.359 -            return new Scope(ScopeType.ALL_DEPENDENT_OPENED_SOURCE_ROOTS, null, null, null, false, Collections.singletonList(from), false);
   4.360 +            return new Scope(ScopeType.ALL_DEPENDENT_OPENED_SOURCE_ROOTS, null, null, null, false, Collections.singletonList(from), false, false);
   4.361          }
   4.362  
   4.363          public static Scope createGivenFolderNoIndex(String folder) {
   4.364 -            return new Scope(ScopeType.GIVEN_FOLDER, folder, null, null, false, null, false);
   4.365 +            return new Scope(ScopeType.GIVEN_FOLDER, folder, null, null, false, null, false, false);
   4.366          }
   4.367  
   4.368          public static Scope createGivenFolderLocalIndex(String folder, File indexFolder, boolean update) {
   4.369 -            return new Scope(ScopeType.GIVEN_FOLDER, folder, indexFolder.getAbsolutePath(), null, update, null, false);
   4.370 +            return new Scope(ScopeType.GIVEN_FOLDER, folder, indexFolder.getAbsolutePath(), null, update, null, false, false);
   4.371          }
   4.372  
   4.373          public static Scope createGivenFolderRemoteIndex(String folder, String urlIndex, String subIndex) {
   4.374 -            return new Scope(ScopeType.GIVEN_FOLDER, folder, urlIndex, subIndex, false, null, false);
   4.375 +            return new Scope(ScopeType.GIVEN_FOLDER, folder, urlIndex, subIndex, false, null, false, false);
   4.376          }
   4.377  
   4.378          public static Scope createGivenSourceRoots(FileObject... sourceRoots) {
   4.379 @@ -625,7 +655,11 @@
   4.380          }
   4.381  
   4.382          public static Scope createGivenSourceRoots(boolean forceIndicesUpToDate, FileObject... sourceRoots) {
   4.383 -            return new Scope(ScopeType.GIVEN_SOURCE_ROOTS, null, null, null, false, Arrays.asList(sourceRoots), forceIndicesUpToDate);
   4.384 +            return new Scope(ScopeType.GIVEN_SOURCE_ROOTS, null, null, null, false, Arrays.asList(sourceRoots), forceIndicesUpToDate, false);
   4.385 +        }
   4.386 +
   4.387 +        public static Scope createAllRemote() {
   4.388 +            return new Scope(ScopeType.ALL_REMOTE, null, null, null, false, null, false, true);
   4.389          }
   4.390  
   4.391          public String getDisplayName() {
   4.392 @@ -641,85 +675,48 @@
   4.393          ALL_OPENED_PROJECTS,
   4.394          ALL_DEPENDENT_OPENED_SOURCE_ROOTS,
   4.395          GIVEN_SOURCE_ROOTS,
   4.396 -        GIVEN_FOLDER;
   4.397 +        GIVEN_FOLDER,
   4.398 +        ALL_REMOTE;
   4.399      }
   4.400  
   4.401      public static final class BatchResult {
   4.402          
   4.403 -        public final Map<? extends Container, ? extends Collection<? extends Resource>> projectId2Resources;
   4.404 +        private final Map<? extends IndexEnquirer, ? extends Collection<? extends Resource>> projectId2Resources;
   4.405          public final Collection<? extends MessageImpl> problems;
   4.406          
   4.407 -        public BatchResult(Map<? extends Container, ? extends Collection<? extends Resource>> projectId2Resources, Collection<? extends MessageImpl> problems) {
   4.408 +        public BatchResult(Map<? extends IndexEnquirer, ? extends Collection<? extends Resource>> projectId2Resources, Collection<? extends MessageImpl> problems) {
   4.409              this.projectId2Resources = projectId2Resources;
   4.410              this.problems = problems;
   4.411          }
   4.412  
   4.413 -    }
   4.414 -
   4.415 -    public static abstract class Container {
   4.416 -        Container() {}
   4.417 -
   4.418 -        public abstract boolean isLocal();
   4.419 -               abstract CharSequence getSourceCode(String relativePath);
   4.420 -               abstract FileObject resolve(String relativePath);
   4.421 -               abstract String toDebugString() throws Exception;
   4.422 -    }
   4.423 -
   4.424 -    public static final class LocalContainer extends Container {
   4.425 -
   4.426 -        private final FileObject localFO;
   4.427 -        
   4.428 -        LocalContainer(@NonNull FileObject localFO) {
   4.429 -            this.localFO = localFO;
   4.430 -        }
   4.431 -        
   4.432 -        @Override
   4.433 -        public boolean isLocal() {
   4.434 -            return true;
   4.435 +        public Collection<? extends Collection<? extends Resource>> getResources() {
   4.436 +            return projectId2Resources.values();
   4.437          }
   4.438  
   4.439 -        @Override
   4.440 -        CharSequence getSourceCode(String relativePath) {
   4.441 -            try {
   4.442 -                FileObject file = localFO.getFileObject(relativePath);
   4.443 -                ByteBuffer bb = ByteBuffer.wrap(file.asBytes());
   4.444 +        public Map<FileObject, Collection<? extends Resource>> getResourcesWithRoots() {
   4.445 +            Map<FileObject, Collection<? extends Resource>> result = new HashMap<FileObject, Collection<? extends Resource>>();
   4.446  
   4.447 -                return FileEncodingQuery.getEncoding(file).decode(bb);
   4.448 -            } catch (IOException ex) {
   4.449 -                Exceptions.printStackTrace(ex);
   4.450 -                return null;
   4.451 +            for (Entry<? extends IndexEnquirer, ? extends Collection<? extends Resource>> e : projectId2Resources.entrySet()) {
   4.452 +                result.put(e.getKey().src, e.getValue());
   4.453              }
   4.454 +
   4.455 +            return result;
   4.456          }
   4.457 -
   4.458 -        @Override
   4.459 -        FileObject resolve(String relativePath) {
   4.460 -            return localFO.getFileObject(relativePath);
   4.461 -        }
   4.462 -
   4.463 -        @Override
   4.464 -        String toDebugString() throws FileStateInvalidException {
   4.465 -            return localFO.getURL().toExternalForm();
   4.466 -        }
   4.467 -
   4.468      }
   4.469  
   4.470      public static final class Resource {
   4.471 -        private final Container container;
   4.472 +        private final IndexEnquirer indexEnquirer;
   4.473          private final String relativePath;
   4.474          final Iterable<? extends HintDescription> hints;
   4.475          private final BulkPattern pattern;
   4.476  
   4.477 -        public Resource(Container container, String relativePath, Iterable<? extends HintDescription> hints, BulkPattern pattern) {
   4.478 -            this.container = container;
   4.479 +        public Resource(IndexEnquirer indexEnquirer, String relativePath, Iterable<? extends HintDescription> hints, BulkPattern pattern) {
   4.480 +            this.indexEnquirer = indexEnquirer;
   4.481              this.relativePath = relativePath;
   4.482              this.hints = hints;
   4.483              this.pattern = pattern;
   4.484          }
   4.485  
   4.486 -        public Container getContainer() {
   4.487 -            return container;
   4.488 -        }
   4.489 -
   4.490          public String getRelativePath() {
   4.491              return relativePath;
   4.492          }
   4.493 @@ -803,7 +800,7 @@
   4.494          }
   4.495          
   4.496          public FileObject getResolvedFile() {
   4.497 -            return container.resolve(relativePath);
   4.498 +            return indexEnquirer.src.getFileObject(relativePath);
   4.499          }
   4.500  
   4.501          public String getDisplayName() {
   4.502 @@ -817,12 +814,231 @@
   4.503          }
   4.504          
   4.505          public CharSequence getSourceCode() {
   4.506 -            return container.getSourceCode(relativePath);
   4.507 +            try {
   4.508 +                FileObject file = getResolvedFile();
   4.509 +                ByteBuffer bb = ByteBuffer.wrap(file.asBytes());
   4.510 +
   4.511 +                return FileEncodingQuery.getEncoding(file).decode(bb);
   4.512 +            } catch (IOException ex) {
   4.513 +                Exceptions.printStackTrace(ex);
   4.514 +                return null;
   4.515 +            }
   4.516 +        }
   4.517 +
   4.518 +        public FileObject getRoot() {
   4.519 +            return indexEnquirer.src;
   4.520          }
   4.521      }
   4.522  
   4.523      private static interface MapIndices {
   4.524 -        public Index findIndex(FileObject root, ProgressHandleWrapper progress);
   4.525 +        public IndexEnquirer findIndex(FileObject root, ProgressHandleWrapper progress);
   4.526      }
   4.527  
   4.528 +    private static interface DelayedBulkPattern {
   4.529 +        public BulkPattern get();
   4.530 +    }
   4.531 +
   4.532 +    private static abstract class IndexEnquirer {
   4.533 +        final FileObject src;
   4.534 +        public IndexEnquirer(FileObject src) {
   4.535 +            this.src = src;
   4.536 +        }
   4.537 +        public abstract Collection<? extends Resource> findResources(Iterable<? extends HintDescription> hints, ProgressHandleWrapper progress, DelayedBulkPattern bulkPattern, Collection<? super MessageImpl> problems);
   4.538 +        public abstract void validateResource(Collection<? extends Resource> resources, ProgressHandleWrapper progress, VerifiedSpansCallBack callback, Collection<? super MessageImpl> problems);
   4.539 +//        public int[] getEstimatedSpan(Resource r);
   4.540 +    }
   4.541 +
   4.542 +    private static abstract class LocalIndexEnquirer extends IndexEnquirer {
   4.543 +        public LocalIndexEnquirer(FileObject src) {
   4.544 +            super(src);
   4.545 +        }
   4.546 +        public void validateResource(Collection<? extends Resource> resources, ProgressHandleWrapper progress, VerifiedSpansCallBack callback, Collection<? super MessageImpl> problems) {
   4.547 +            getLocalVerifiedSpans(resources, progress, callback, false/*XXX*/, problems);
   4.548 +        }
   4.549 +    }
   4.550 +
   4.551 +    private static final class FileSystemBasedIndexEnquirer extends LocalIndexEnquirer {
   4.552 +        public FileSystemBasedIndexEnquirer(FileObject src) {
   4.553 +            super(src);
   4.554 +        }
   4.555 +        public Collection<? extends Resource> findResources(final Iterable<? extends HintDescription> hints, ProgressHandleWrapper progress, final DelayedBulkPattern bulkPattern, final Collection<? super MessageImpl> problems) {
   4.556 +            Collection<FileObject> files = new LinkedList<FileObject>();
   4.557 +
   4.558 +            final ProgressHandleWrapper innerProgress = progress.startNextPartWithEmbedding(30, 70);
   4.559 +
   4.560 +            recursive(src, src, files, innerProgress, 0, null, null);
   4.561 +
   4.562 +            LOG.log(Level.FINE, "files: {0}", files);
   4.563 +
   4.564 +            innerProgress.startNextPart(files.size());
   4.565 +
   4.566 +            final Collection<Resource> result = new ArrayList<Resource>();
   4.567 +
   4.568 +            if (!files.isEmpty()) {
   4.569 +                try {
   4.570 +                    long start = System.currentTimeMillis();
   4.571 +
   4.572 +                    JavaSource.create(Utilities.createUniversalCPInfo(), files).runUserActionTask(new Task<CompilationController>() {
   4.573 +                        public void run(CompilationController cc) throws Exception {
   4.574 +                            if (cc.toPhase(Phase.PARSED).compareTo(Phase.PARSED) <0) {
   4.575 +                                return ;
   4.576 +                            }
   4.577 +
   4.578 +                            try {
   4.579 +                                boolean matches = BulkSearch.getDefault().matches(cc, new TreePath(cc.getCompilationUnit()), bulkPattern.get());
   4.580 +
   4.581 +                                if (matches) {
   4.582 +                                    result.add(new Resource(FileSystemBasedIndexEnquirer.this, FileUtil.getRelativePath(src, cc.getFileObject()), hints, bulkPattern.get()));
   4.583 +                                }
   4.584 +                            } catch (ThreadDeath td) {
   4.585 +                                throw td;
   4.586 +                            } catch (Throwable t) {
   4.587 +                                LOG.log(Level.INFO, "Exception while performing batch search in " + FileUtil.getFileDisplayName(cc.getFileObject()), t);
   4.588 +                                problems.add(new MessageImpl(MessageKind.WARNING, "An exception occurred while testing file: " + FileUtil.getFileDisplayName(cc.getFileObject()) + " (" + t.getLocalizedMessage() + ")."));
   4.589 +                            }
   4.590 +
   4.591 +                            innerProgress.tick();
   4.592 +                        }
   4.593 +                    }, true);
   4.594 +
   4.595 +                    long end = System.currentTimeMillis();
   4.596 +
   4.597 +                    LOG.log(Level.FINE, "took: {0}, per file: {1}", new Object[]{end - start, (end - start) / files.size()});
   4.598 +                } catch (IOException ex) {
   4.599 +                    Exceptions.printStackTrace(ex);
   4.600 +                }
   4.601 +            }
   4.602 +
   4.603 +            return result;
   4.604 +        }
   4.605 +
   4.606 +    }
   4.607 +
   4.608 +    private static final class SimpleIndexIndexEnquirer extends LocalIndexEnquirer {
   4.609 +        private final Index idx;
   4.610 +        public SimpleIndexIndexEnquirer(FileObject src, Index idx) {
   4.611 +            super(src);
   4.612 +            this.idx = idx;
   4.613 +        }
   4.614 +        public Collection<? extends Resource> findResources(final Iterable<? extends HintDescription> hints, ProgressHandleWrapper progress, final DelayedBulkPattern bulkPattern, final Collection<? super MessageImpl> problems) {
   4.615 +            final Collection<Resource> result = new ArrayList<Resource>();
   4.616 +
   4.617 +            progress.startNextPart(1);
   4.618 +
   4.619 +            try {
   4.620 +                for (String candidate : idx.findCandidates(bulkPattern.get())) {
   4.621 +                    result.add(new Resource(this, candidate, hints, bulkPattern.get()));
   4.622 +                }
   4.623 +            } catch (IOException ex) {
   4.624 +                Exceptions.printStackTrace(ex);
   4.625 +            }
   4.626 +
   4.627 +            return result;
   4.628 +        }
   4.629 +
   4.630 +    }
   4.631 +
   4.632 +    private static final class RemoteFullyAttributedIndexEnquirer extends IndexEnquirer {
   4.633 +        private final RemoteIndex remoteIndex;
   4.634 +        private final String textualHintRepresentation;
   4.635 +        public RemoteFullyAttributedIndexEnquirer(FileObject src, RemoteIndex remoteIndex, String textualHintRepresentation) {
   4.636 +            super(src);
   4.637 +            assert isAttributedIndexWithSpans(remoteIndex);
   4.638 +            this.remoteIndex = remoteIndex;
   4.639 +            this.textualHintRepresentation = textualHintRepresentation;
   4.640 +        }
   4.641 +        public Collection<? extends Resource> findResources(final Iterable<? extends HintDescription> hints, ProgressHandleWrapper progress, final DelayedBulkPattern bulkPattern, final Collection<? super MessageImpl> problems) {
   4.642 +            final Collection<Resource> result = new ArrayList<Resource>();
   4.643 +
   4.644 +            progress.startNextPart(1);
   4.645 +
   4.646 +            try {
   4.647 +                URI u = new URI(remoteIndex.remote.toExternalForm() + "/find?path=" + escapeForQuery(remoteIndex.remoteSegment) + "&pattern=" + escapeForQuery(textualHintRepresentation));
   4.648 +
   4.649 +                for (String occurrence : new ArrayList<String>(WebUtilities.requestStringArrayResponse(u))) {
   4.650 +                    result.add(new Resource(this, occurrence, hints, bulkPattern.get()));
   4.651 +                }
   4.652 +
   4.653 +            } catch (URISyntaxException ex) {
   4.654 +                Exceptions.printStackTrace(ex);
   4.655 +            }
   4.656 +
   4.657 +            return result;
   4.658 +        }
   4.659 +
   4.660 +        @Override
   4.661 +        public void validateResource(Collection<? extends Resource> resources, ProgressHandleWrapper progress, VerifiedSpansCallBack callback, Collection<? super MessageImpl> problems) {
   4.662 +            for (Resource r : resources) {
   4.663 +                try {
   4.664 +                    URI spanURI = new URI(remoteIndex.remote.toExternalForm() + "/findSpans?path=" + escapeForQuery(remoteIndex.remoteSegment) + "&relativePath=" + escapeForQuery(r.relativePath) + "&pattern=" + escapeForQuery(textualHintRepresentation));
   4.665 +                    FileObject fo = r.getResolvedFile();
   4.666 +
   4.667 +                    if (fo == null) {
   4.668 +                        callback.cannotVerifySpan(r);
   4.669 +                    } else {
   4.670 +                        List<ErrorDescription> result = new ArrayList<ErrorDescription>();
   4.671 +
   4.672 +                        for (int[] span : parseSpans(WebUtilities.requestStringResponse(spanURI))) {
   4.673 +                            result.add(ErrorDescriptionFactory.createErrorDescription(Severity.WARNING, "Occurrence", fo, span[0], span[1]));
   4.674 +                        }
   4.675 +
   4.676 +                        callback.spansVerified(null, r, result);
   4.677 +                    }
   4.678 +                } catch (Exception ex) {
   4.679 +                    Exceptions.printStackTrace(ex);
   4.680 +                }
   4.681 +            }
   4.682 +        }
   4.683 +
   4.684 +    }
   4.685 +
   4.686 +    private static Iterable<int[]> parseSpans(String from) {
   4.687 +        if (from.isEmpty()) {
   4.688 +            return Collections.emptyList();
   4.689 +        }
   4.690 +        String[] split = from.split(":");
   4.691 +        List<int[]> result = new LinkedList<int[]>();
   4.692 +
   4.693 +        for (int i = 0; i < split.length; i += 2) {
   4.694 +            result.add(new int[] {
   4.695 +                Integer.parseInt(split[i + 0].trim()),
   4.696 +                Integer.parseInt(split[i + 1].trim())
   4.697 +            });
   4.698 +        }
   4.699 +
   4.700 +        return result;
   4.701 +    }
   4.702 +
   4.703 +    private static String defaultHintText(HintDescription hd) {
   4.704 +        StringBuilder result = new StringBuilder();
   4.705 +
   4.706 +        PatternDescription pd = hd.getTriggerPattern();
   4.707 +
   4.708 +        if (pd == null) return null;
   4.709 +
   4.710 +        if (pd.getImports().iterator().hasNext()) {
   4.711 +            //cannot currently handle patterns with imports:
   4.712 +            return null;
   4.713 +        }
   4.714 +
   4.715 +        result.append(pd.getPattern());
   4.716 +
   4.717 +        if (!pd.getConstraints().isEmpty()) {
   4.718 +            result.append(" :: ");
   4.719 +
   4.720 +            for (Iterator<Entry<String, String>> it = pd.getConstraints().entrySet().iterator(); it.hasNext(); ) {
   4.721 +                Entry<String, String> e = it.next();
   4.722 +
   4.723 +                result.append(e.getKey()).append(" instanceof ").append(e.getValue());
   4.724 +
   4.725 +                if (it.hasNext()) {
   4.726 +                    result.append(" && ");
   4.727 +                }
   4.728 +            }
   4.729 +        }
   4.730 +
   4.731 +        result.append(";;\n");
   4.732 +
   4.733 +        return result.toString();
   4.734 +    }
   4.735  }
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/indexing/RemoteIndex.java	Sat Mar 05 23:03:17 2011 +0100
     5.3 @@ -0,0 +1,123 @@
     5.4 +/*
     5.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     5.6 + *
     5.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
     5.8 + *
     5.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    5.10 + * Other names may be trademarks of their respective owners.
    5.11 + *
    5.12 + * The contents of this file are subject to the terms of either the GNU
    5.13 + * General Public License Version 2 only ("GPL") or the Common
    5.14 + * Development and Distribution License("CDDL") (collectively, the
    5.15 + * "License"). You may not use this file except in compliance with the
    5.16 + * License. You can obtain a copy of the License at
    5.17 + * http://www.netbeans.org/cddl-gplv2.html
    5.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    5.19 + * specific language governing permissions and limitations under the
    5.20 + * License.  When distributing the software, include this License Header
    5.21 + * Notice in each file and include the License file at
    5.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    5.23 + * particular file as subject to the "Classpath" exception as provided
    5.24 + * by Oracle in the GPL Version 2 section of the License file that
    5.25 + * accompanied this code. If applicable, add the following below the
    5.26 + * License Header, with the fields enclosed by brackets [] replaced by
    5.27 + * your own identifying information:
    5.28 + * "Portions Copyrighted [year] [name of copyright owner]"
    5.29 + *
    5.30 + * If you wish your version of this file to be governed by only the CDDL
    5.31 + * or only the GPL Version 2, indicate your decision by adding
    5.32 + * "[Contributor] elects to include this software in this distribution
    5.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    5.34 + * single choice of license, a recipient has the option to distribute
    5.35 + * your version of this file under either the CDDL, the GPL Version 2 or
    5.36 + * to extend the choice of license to its licensees as provided above.
    5.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    5.38 + * Version 2 license, then the option applies only if the new code is
    5.39 + * made subject to such option by the copyright holder.
    5.40 + *
    5.41 + * Contributor(s):
    5.42 + *
    5.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
    5.44 + */
    5.45 +
    5.46 +package org.netbeans.modules.jackpot30.impl.indexing;
    5.47 +
    5.48 +import java.net.URL;
    5.49 +import java.util.LinkedList;
    5.50 +import java.util.List;
    5.51 +import java.util.prefs.BackingStoreException;
    5.52 +import java.util.prefs.Preferences;
    5.53 +import org.codeviation.pojson.Pojson;
    5.54 +import org.netbeans.modules.jackpot30.impl.refactoring.ScopesPanel;
    5.55 +import org.openide.util.Exceptions;
    5.56 +import org.openide.util.NbPreferences;
    5.57 +
    5.58 +/**
    5.59 + *
    5.60 + * @author lahvac
    5.61 + */
    5.62 +public class RemoteIndex {
    5.63 +
    5.64 +    public final String folder;
    5.65 +    public final URL    remote;
    5.66 +    public final String remoteSegment;
    5.67 +
    5.68 +    public static RemoteIndex create(String folder, URL remote, String remoteSegment) {
    5.69 +        return new RemoteIndex(folder, remote, remoteSegment);
    5.70 +    }
    5.71 +
    5.72 +    private RemoteIndex() {//used by Pojson
    5.73 +        this.folder = null;
    5.74 +        this.remote = null;
    5.75 +        this.remoteSegment = null;
    5.76 +    }
    5.77 +
    5.78 +    private RemoteIndex(String folder, URL remote, String remoteSegment) {
    5.79 +        this.folder = folder;
    5.80 +        this.remote = remote;
    5.81 +        this.remoteSegment = remoteSegment;
    5.82 +    }
    5.83 +
    5.84 +    private static final String KEY_REMOTE_INDICES = RemoteIndex.class.getSimpleName();
    5.85 +
    5.86 +    public static Iterable<? extends RemoteIndex> loadIndices() {
    5.87 +        List<RemoteIndex> result = new LinkedList<RemoteIndex>();
    5.88 +        Preferences prefs = NbPreferences.forModule(RemoteIndex.class).node(KEY_REMOTE_INDICES);
    5.89 +
    5.90 +        if (prefs != null) {
    5.91 +            try {
    5.92 +                for (String key : prefs.keys()) {
    5.93 +                    if (key.startsWith("index")) {
    5.94 +                        result.add(Pojson.load(RemoteIndex.class, prefs.get(key, null)));
    5.95 +                    }
    5.96 +                }
    5.97 +            } catch (BackingStoreException ex) {
    5.98 +                Exceptions.printStackTrace(ex);
    5.99 +            }
   5.100 +        }
   5.101 +
   5.102 +        return result;
   5.103 +    }
   5.104 +    
   5.105 +    public static void saveIndices(Iterable<? extends RemoteIndex> indices) {
   5.106 +        Preferences prefs = NbPreferences.forModule(RemoteIndex.class).node(KEY_REMOTE_INDICES);
   5.107 +
   5.108 +        try {
   5.109 +            prefs.clear();
   5.110 +        } catch (BackingStoreException ex) {
   5.111 +            Exceptions.printStackTrace(ex);
   5.112 +        }
   5.113 +
   5.114 +        int i = 0;
   5.115 +
   5.116 +        for (RemoteIndex idx : indices) {
   5.117 +            prefs.put("index" + i++, Pojson.save(idx));
   5.118 +        }
   5.119 +        
   5.120 +        try {
   5.121 +            prefs.flush();
   5.122 +        } catch (BackingStoreException ex) {
   5.123 +            Exceptions.printStackTrace(ex);
   5.124 +        }
   5.125 +    }
   5.126 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/indexing/options/Bundle.properties	Sat Mar 05 23:03:17 2011 +0100
     6.3 @@ -0,0 +1,11 @@
     6.4 +AdvancedOption_DisplayName_Index=Jackpot 3.0 Indices
     6.5 +AdvancedOption_Keywords_Index=index indices jackpot
     6.6 +CustomizeRemoteIndex.indexURLLabel.text=Index URL:
     6.7 +CustomizeRemoteIndex.indexURL.text=
     6.8 +CustomizeRemoteIndex.jLabel1.text=Subindex:
     6.9 +CustomizeRemoteIndex.folderLabel.text=&Folder:
    6.10 +CustomizeRemoteIndex.folderChooser.text=Browse
    6.11 +CustomizeRemoteIndex.folder.text=
    6.12 +IndexPanel.addButton.text=Add Mapping
    6.13 +IndexPanel.removeButton.text=Remove Mapping
    6.14 +IndexPanel.editButton.text=Edit Mapping
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/indexing/options/CustomizeRemoteIndex.form	Sat Mar 05 23:03:17 2011 +0100
     7.3 @@ -0,0 +1,178 @@
     7.4 +<?xml version="1.1" encoding="UTF-8" ?>
     7.5 +
     7.6 +<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
     7.7 +  <NonVisualComponents>
     7.8 +    <Component class="javax.swing.ButtonGroup" name="buttonGroup1">
     7.9 +    </Component>
    7.10 +  </NonVisualComponents>
    7.11 +  <Properties>
    7.12 +    <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
    7.13 +      <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
    7.14 +        <EmptyBorder bottom="12" left="12" right="12" top="12"/>
    7.15 +      </Border>
    7.16 +    </Property>
    7.17 +  </Properties>
    7.18 +  <AuxValues>
    7.19 +    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
    7.20 +    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
    7.21 +    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
    7.22 +    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
    7.23 +    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
    7.24 +    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
    7.25 +    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
    7.26 +    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
    7.27 +    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
    7.28 +    <AuxValue 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,53,0,0,2,-37"/>
    7.29 +  </AuxValues>
    7.30 +
    7.31 +  <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
    7.32 +  <SubComponents>
    7.33 +    <Container class="javax.swing.JPanel" name="folderPanel">
    7.34 +      <Constraints>
    7.35 +        <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
    7.36 +          <GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="17" weightX="1.0" weightY="0.0"/>
    7.37 +        </Constraint>
    7.38 +      </Constraints>
    7.39 +
    7.40 +      <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
    7.41 +      <SubComponents>
    7.42 +        <Component class="javax.swing.JLabel" name="folderLabel">
    7.43 +          <Properties>
    7.44 +            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
    7.45 +              <ResourceString bundle="org/netbeans/modules/jackpot30/impl/indexing/options/Bundle.properties" key="CustomizeRemoteIndex.folderLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
    7.46 +            </Property>
    7.47 +          </Properties>
    7.48 +          <Constraints>
    7.49 +            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
    7.50 +              <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="6" anchor="17" weightX="0.0" weightY="0.0"/>
    7.51 +            </Constraint>
    7.52 +          </Constraints>
    7.53 +        </Component>
    7.54 +        <Component class="javax.swing.JButton" name="folderChooser">
    7.55 +          <Properties>
    7.56 +            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
    7.57 +              <ResourceString bundle="org/netbeans/modules/jackpot30/impl/indexing/options/Bundle.properties" key="CustomizeRemoteIndex.folderChooser.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
    7.58 +            </Property>
    7.59 +          </Properties>
    7.60 +          <Events>
    7.61 +            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="folderChooserActionPerformed"/>
    7.62 +          </Events>
    7.63 +          <Constraints>
    7.64 +            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
    7.65 +              <GridBagConstraints gridX="2" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
    7.66 +            </Constraint>
    7.67 +          </Constraints>
    7.68 +        </Component>
    7.69 +        <Component class="javax.swing.JTextField" name="folder">
    7.70 +          <Properties>
    7.71 +            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
    7.72 +              <ResourceString bundle="org/netbeans/modules/jackpot30/impl/indexing/options/Bundle.properties" key="CustomizeRemoteIndex.folder.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
    7.73 +            </Property>
    7.74 +          </Properties>
    7.75 +          <Constraints>
    7.76 +            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
    7.77 +              <GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="0.0"/>
    7.78 +            </Constraint>
    7.79 +          </Constraints>
    7.80 +        </Component>
    7.81 +      </SubComponents>
    7.82 +    </Container>
    7.83 +    <Component class="javax.swing.JTextArea" name="indexInfo">
    7.84 +      <Properties>
    7.85 +        <Property name="columns" type="int" value="20"/>
    7.86 +        <Property name="editable" type="boolean" value="false"/>
    7.87 +        <Property name="rows" type="int" value="5"/>
    7.88 +        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
    7.89 +          <Border info="null"/>
    7.90 +        </Property>
    7.91 +      </Properties>
    7.92 +      <Constraints>
    7.93 +        <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
    7.94 +          <GridBagConstraints gridX="0" gridY="2" 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"/>
    7.95 +        </Constraint>
    7.96 +      </Constraints>
    7.97 +    </Component>
    7.98 +    <Container class="javax.swing.JPanel" name="remoteIndexPanel">
    7.99 +      <Constraints>
   7.100 +        <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
   7.101 +          <GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="0.0"/>
   7.102 +        </Constraint>
   7.103 +      </Constraints>
   7.104 +
   7.105 +      <Layout>
   7.106 +        <DimensionLayout dim="0">
   7.107 +          <Group type="103" groupAlignment="0" attributes="0">
   7.108 +              <Group type="102" alignment="0" attributes="0">
   7.109 +                  <EmptySpace max="-2" attributes="0"/>
   7.110 +                  <Group type="103" groupAlignment="0" attributes="0">
   7.111 +                      <Group type="102" alignment="0" attributes="0">
   7.112 +                          <EmptySpace min="12" pref="12" max="12" attributes="0"/>
   7.113 +                          <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
   7.114 +                          <EmptySpace max="-2" attributes="0"/>
   7.115 +                          <Component id="subIndex" pref="589" max="32767" attributes="0"/>
   7.116 +                      </Group>
   7.117 +                      <Group type="102" alignment="0" attributes="0">
   7.118 +                          <Component id="indexURLLabel" min="-2" max="-2" attributes="0"/>
   7.119 +                          <EmptySpace max="-2" attributes="0"/>
   7.120 +                          <Component id="indexURL" min="-2" max="-2" attributes="0"/>
   7.121 +                      </Group>
   7.122 +                  </Group>
   7.123 +                  <EmptySpace max="-2" attributes="0"/>
   7.124 +              </Group>
   7.125 +          </Group>
   7.126 +        </DimensionLayout>
   7.127 +        <DimensionLayout dim="1">
   7.128 +          <Group type="103" groupAlignment="0" attributes="0">
   7.129 +              <Group type="102" alignment="0" attributes="0">
   7.130 +                  <EmptySpace max="-2" attributes="0"/>
   7.131 +                  <Group type="103" groupAlignment="3" attributes="0">
   7.132 +                      <Component id="indexURLLabel" alignment="3" min="-2" max="-2" attributes="0"/>
   7.133 +                      <Component id="indexURL" alignment="3" min="-2" max="-2" attributes="0"/>
   7.134 +                  </Group>
   7.135 +                  <EmptySpace type="unrelated" max="-2" attributes="0"/>
   7.136 +                  <Group type="103" groupAlignment="3" attributes="0">
   7.137 +                      <Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
   7.138 +                      <Component id="subIndex" alignment="3" min="-2" max="-2" attributes="0"/>
   7.139 +                  </Group>
   7.140 +                  <EmptySpace max="32767" attributes="0"/>
   7.141 +              </Group>
   7.142 +          </Group>
   7.143 +        </DimensionLayout>
   7.144 +      </Layout>
   7.145 +      <SubComponents>
   7.146 +        <Component class="javax.swing.JTextField" name="indexURL">
   7.147 +          <Properties>
   7.148 +            <Property name="columns" type="int" value="40"/>
   7.149 +            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   7.150 +              <ResourceString bundle="org/netbeans/modules/jackpot30/impl/indexing/options/Bundle.properties" key="CustomizeRemoteIndex.indexURL.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   7.151 +            </Property>
   7.152 +          </Properties>
   7.153 +        </Component>
   7.154 +        <Component class="javax.swing.JLabel" name="indexURLLabel">
   7.155 +          <Properties>
   7.156 +            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   7.157 +              <ResourceString bundle="org/netbeans/modules/jackpot30/impl/indexing/options/Bundle.properties" key="CustomizeRemoteIndex.indexURLLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   7.158 +            </Property>
   7.159 +          </Properties>
   7.160 +        </Component>
   7.161 +        <Component class="javax.swing.JComboBox" name="subIndex">
   7.162 +          <Properties>
   7.163 +            <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
   7.164 +              <StringArray count="0"/>
   7.165 +            </Property>
   7.166 +          </Properties>
   7.167 +          <Events>
   7.168 +            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="subIndexActionPerformed"/>
   7.169 +          </Events>
   7.170 +        </Component>
   7.171 +        <Component class="javax.swing.JLabel" name="jLabel1">
   7.172 +          <Properties>
   7.173 +            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   7.174 +              <ResourceString bundle="org/netbeans/modules/jackpot30/impl/indexing/options/Bundle.properties" key="CustomizeRemoteIndex.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   7.175 +            </Property>
   7.176 +          </Properties>
   7.177 +        </Component>
   7.178 +      </SubComponents>
   7.179 +    </Container>
   7.180 +  </SubComponents>
   7.181 +</Form>
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/indexing/options/CustomizeRemoteIndex.java	Sat Mar 05 23:03:17 2011 +0100
     8.3 @@ -0,0 +1,479 @@
     8.4 +/*
     8.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     8.6 + *
     8.7 + * Copyright 2010-2011 Sun Microsystems, Inc. All rights reserved.
     8.8 + *
     8.9 + * The contents of this file are subject to the terms of either the GNU
    8.10 + * General Public License Version 2 only ("GPL") or the Common
    8.11 + * Development and Distribution License("CDDL") (collectively, the
    8.12 + * "License"). You may not use this file except in compliance with the
    8.13 + * License. You can obtain a copy of the License at
    8.14 + * http://www.netbeans.org/cddl-gplv2.html
    8.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    8.16 + * specific language governing permissions and limitations under the
    8.17 + * License.  When distributing the software, include this License Header
    8.18 + * Notice in each file and include the License file at
    8.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
    8.20 + * particular file as subject to the "Classpath" exception as provided
    8.21 + * by Sun in the GPL Version 2 section of the License file that
    8.22 + * accompanied this code. If applicable, add the following below the
    8.23 + * License Header, with the fields enclosed by brackets [] replaced by
    8.24 + * your own identifying information:
    8.25 + * "Portions Copyrighted [year] [name of copyright owner]"
    8.26 + *
    8.27 + * If you wish your version of this file to be governed by only the CDDL
    8.28 + * or only the GPL Version 2, indicate your decision by adding
    8.29 + * "[Contributor] elects to include this software in this distribution
    8.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    8.31 + * single choice of license, a recipient has the option to distribute
    8.32 + * your version of this file under either the CDDL, the GPL Version 2 or
    8.33 + * to extend the choice of license to its licensees as provided above.
    8.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    8.35 + * Version 2 license, then the option applies only if the new code is
    8.36 + * made subject to such option by the copyright holder.
    8.37 + *
    8.38 + * Contributor(s):
    8.39 + *
    8.40 + * Portions Copyrighted 2010-2011 Sun Microsystems, Inc.
    8.41 + */
    8.42 +package org.netbeans.modules.jackpot30.impl.indexing.options;
    8.43 +
    8.44 +import java.awt.Component;
    8.45 +import java.io.File;
    8.46 +import java.net.MalformedURLException;
    8.47 +import java.net.URISyntaxException;
    8.48 +import java.net.URL;
    8.49 +import java.text.DateFormat;
    8.50 +import java.util.Collection;
    8.51 +import java.util.Date;
    8.52 +import java.util.HashMap;
    8.53 +import java.util.Map;
    8.54 +import java.util.concurrent.atomic.AtomicBoolean;
    8.55 +import java.util.concurrent.atomic.AtomicReference;
    8.56 +import java.util.logging.Level;
    8.57 +import java.util.logging.Logger;
    8.58 +import javax.swing.DefaultComboBoxModel;
    8.59 +import javax.swing.DefaultListCellRenderer;
    8.60 +import javax.swing.JButton;
    8.61 +import javax.swing.JFileChooser;
    8.62 +import javax.swing.JList;
    8.63 +import javax.swing.JTextField;
    8.64 +import javax.swing.SwingUtilities;
    8.65 +import javax.swing.UIManager;
    8.66 +import javax.swing.event.DocumentEvent;
    8.67 +import javax.swing.event.DocumentListener;
    8.68 +import org.codeviation.pojson.Pojson;
    8.69 +import org.netbeans.modules.jackpot30.impl.WebUtilities;
    8.70 +import org.netbeans.modules.jackpot30.impl.indexing.IndexInfo;
    8.71 +import org.netbeans.modules.jackpot30.impl.indexing.RemoteIndex;
    8.72 +import org.openide.NotificationLineSupport;
    8.73 +import org.openide.util.RequestProcessor;
    8.74 +
    8.75 +/**
    8.76 + *
    8.77 + * @author lahvac
    8.78 + */
    8.79 +public class CustomizeRemoteIndex extends javax.swing.JPanel {
    8.80 +
    8.81 +    private final JButton okButton;
    8.82 +
    8.83 +    public CustomizeRemoteIndex(JButton okButton) {
    8.84 +        this.okButton = okButton;
    8.85 +        initComponents();
    8.86 +        DocumentListener updateErrorsListener = new DocumentListener() {
    8.87 +            public void insertUpdate(DocumentEvent e) {
    8.88 +                updateErrors();
    8.89 +            }
    8.90 +            public void removeUpdate(DocumentEvent e) {
    8.91 +                updateErrors();
    8.92 +            }
    8.93 +            public void changedUpdate(DocumentEvent e) {}
    8.94 +        };
    8.95 +        folder.getDocument().addDocumentListener(updateErrorsListener);
    8.96 +        indexURL.getDocument().addDocumentListener(new DocumentListener() {
    8.97 +            public void insertUpdate(DocumentEvent e) {
    8.98 +                indexURLUpdated();
    8.99 +            }
   8.100 +            public void removeUpdate(DocumentEvent e) {
   8.101 +                indexURLUpdated();
   8.102 +            }
   8.103 +            public void changedUpdate(DocumentEvent e) {
   8.104 +            }
   8.105 +        });
   8.106 +        indexInfo.setFont(UIManager.getFont("Label.font"));
   8.107 +        indexInfo.setBackground(UIManager.getColor("Label.background"));
   8.108 +        indexInfo.setDisabledTextColor(UIManager.getColor("Label.foreground"));
   8.109 +    }
   8.110 +
   8.111 +    /** This method is called from within the constructor to
   8.112 +     * initialize the form.
   8.113 +     * WARNING: Do NOT modify this code. The content of this method is
   8.114 +     * always regenerated by the Form Editor.
   8.115 +     */
   8.116 +    @SuppressWarnings("unchecked")
   8.117 +    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
   8.118 +    private void initComponents() {
   8.119 +        java.awt.GridBagConstraints gridBagConstraints;
   8.120 +
   8.121 +        buttonGroup1 = new javax.swing.ButtonGroup();
   8.122 +        folderPanel = new javax.swing.JPanel();
   8.123 +        folderLabel = new javax.swing.JLabel();
   8.124 +        folderChooser = new javax.swing.JButton();
   8.125 +        folder = new javax.swing.JTextField();
   8.126 +        indexInfo = new javax.swing.JTextArea();
   8.127 +        remoteIndexPanel = new javax.swing.JPanel();
   8.128 +        indexURL = new javax.swing.JTextField();
   8.129 +        indexURLLabel = new javax.swing.JLabel();
   8.130 +        subIndex = new javax.swing.JComboBox();
   8.131 +        jLabel1 = new javax.swing.JLabel();
   8.132 +
   8.133 +        setBorder(javax.swing.BorderFactory.createEmptyBorder(12, 12, 12, 12));
   8.134 +        setLayout(new java.awt.GridBagLayout());
   8.135 +
   8.136 +        folderPanel.setLayout(new java.awt.GridBagLayout());
   8.137 +
   8.138 +        org.openide.awt.Mnemonics.setLocalizedText(folderLabel, org.openide.util.NbBundle.getMessage(CustomizeRemoteIndex.class, "CustomizeRemoteIndex.folderLabel.text")); // NOI18N
   8.139 +        gridBagConstraints = new java.awt.GridBagConstraints();
   8.140 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
   8.141 +        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 6);
   8.142 +        folderPanel.add(folderLabel, gridBagConstraints);
   8.143 +
   8.144 +        org.openide.awt.Mnemonics.setLocalizedText(folderChooser, org.openide.util.NbBundle.getMessage(CustomizeRemoteIndex.class, "CustomizeRemoteIndex.folderChooser.text")); // NOI18N
   8.145 +        folderChooser.addActionListener(new java.awt.event.ActionListener() {
   8.146 +            public void actionPerformed(java.awt.event.ActionEvent evt) {
   8.147 +                folderChooserActionPerformed(evt);
   8.148 +            }
   8.149 +        });
   8.150 +        gridBagConstraints = new java.awt.GridBagConstraints();
   8.151 +        gridBagConstraints.gridx = 2;
   8.152 +        gridBagConstraints.gridy = 0;
   8.153 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
   8.154 +        gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 0);
   8.155 +        folderPanel.add(folderChooser, gridBagConstraints);
   8.156 +
   8.157 +        folder.setText(org.openide.util.NbBundle.getMessage(CustomizeRemoteIndex.class, "CustomizeRemoteIndex.folder.text")); // NOI18N
   8.158 +        gridBagConstraints = new java.awt.GridBagConstraints();
   8.159 +        gridBagConstraints.gridx = 1;
   8.160 +        gridBagConstraints.gridy = 0;
   8.161 +        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
   8.162 +        gridBagConstraints.weightx = 1.0;
   8.163 +        folderPanel.add(folder, gridBagConstraints);
   8.164 +
   8.165 +        gridBagConstraints = new java.awt.GridBagConstraints();
   8.166 +        gridBagConstraints.gridx = 0;
   8.167 +        gridBagConstraints.gridy = 0;
   8.168 +        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
   8.169 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
   8.170 +        gridBagConstraints.weightx = 1.0;
   8.171 +        add(folderPanel, gridBagConstraints);
   8.172 +
   8.173 +        indexInfo.setColumns(20);
   8.174 +        indexInfo.setEditable(false);
   8.175 +        indexInfo.setRows(5);
   8.176 +        indexInfo.setBorder(null);
   8.177 +        gridBagConstraints = new java.awt.GridBagConstraints();
   8.178 +        gridBagConstraints.gridx = 0;
   8.179 +        gridBagConstraints.gridy = 2;
   8.180 +        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
   8.181 +        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
   8.182 +        gridBagConstraints.weightx = 1.0;
   8.183 +        gridBagConstraints.weighty = 1.0;
   8.184 +        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
   8.185 +        add(indexInfo, gridBagConstraints);
   8.186 +
   8.187 +        indexURL.setColumns(40);
   8.188 +        indexURL.setText(org.openide.util.NbBundle.getMessage(CustomizeRemoteIndex.class, "CustomizeRemoteIndex.indexURL.text")); // NOI18N
   8.189 +
   8.190 +        org.openide.awt.Mnemonics.setLocalizedText(indexURLLabel, org.openide.util.NbBundle.getMessage(CustomizeRemoteIndex.class, "CustomizeRemoteIndex.indexURLLabel.text")); // NOI18N
   8.191 +
   8.192 +        subIndex.addActionListener(new java.awt.event.ActionListener() {
   8.193 +            public void actionPerformed(java.awt.event.ActionEvent evt) {
   8.194 +                subIndexActionPerformed(evt);
   8.195 +            }
   8.196 +        });
   8.197 +
   8.198 +        org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(CustomizeRemoteIndex.class, "CustomizeRemoteIndex.jLabel1.text")); // NOI18N
   8.199 +
   8.200 +        javax.swing.GroupLayout remoteIndexPanelLayout = new javax.swing.GroupLayout(remoteIndexPanel);
   8.201 +        remoteIndexPanel.setLayout(remoteIndexPanelLayout);
   8.202 +        remoteIndexPanelLayout.setHorizontalGroup(
   8.203 +            remoteIndexPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
   8.204 +            .addGroup(remoteIndexPanelLayout.createSequentialGroup()
   8.205 +                .addContainerGap()
   8.206 +                .addGroup(remoteIndexPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
   8.207 +                    .addGroup(remoteIndexPanelLayout.createSequentialGroup()
   8.208 +                        .addGap(12, 12, 12)
   8.209 +                        .addComponent(jLabel1)
   8.210 +                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
   8.211 +                        .addComponent(subIndex, 0, 589, Short.MAX_VALUE))
   8.212 +                    .addGroup(remoteIndexPanelLayout.createSequentialGroup()
   8.213 +                        .addComponent(indexURLLabel)
   8.214 +                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
   8.215 +                        .addComponent(indexURL, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
   8.216 +                .addContainerGap())
   8.217 +        );
   8.218 +        remoteIndexPanelLayout.setVerticalGroup(
   8.219 +            remoteIndexPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
   8.220 +            .addGroup(remoteIndexPanelLayout.createSequentialGroup()
   8.221 +                .addContainerGap()
   8.222 +                .addGroup(remoteIndexPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
   8.223 +                    .addComponent(indexURLLabel)
   8.224 +                    .addComponent(indexURL, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
   8.225 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
   8.226 +                .addGroup(remoteIndexPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
   8.227 +                    .addComponent(jLabel1)
   8.228 +                    .addComponent(subIndex, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
   8.229 +                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
   8.230 +        );
   8.231 +
   8.232 +        gridBagConstraints = new java.awt.GridBagConstraints();
   8.233 +        gridBagConstraints.gridx = 0;
   8.234 +        gridBagConstraints.gridy = 1;
   8.235 +        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
   8.236 +        gridBagConstraints.weightx = 1.0;
   8.237 +        add(remoteIndexPanel, gridBagConstraints);
   8.238 +    }// </editor-fold>//GEN-END:initComponents
   8.239 +
   8.240 +    private void folderChooserActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_folderChooserActionPerformed
   8.241 +        showFileChooser(folder);
   8.242 +}//GEN-LAST:event_folderChooserActionPerformed
   8.243 +
   8.244 +    private void subIndexActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_subIndexActionPerformed
   8.245 +        subindexSelectionUpdated();
   8.246 +    }//GEN-LAST:event_subIndexActionPerformed
   8.247 +
   8.248 +    // Variables declaration - do not modify//GEN-BEGIN:variables
   8.249 +    private javax.swing.ButtonGroup buttonGroup1;
   8.250 +    private javax.swing.JTextField folder;
   8.251 +    private javax.swing.JButton folderChooser;
   8.252 +    private javax.swing.JLabel folderLabel;
   8.253 +    private javax.swing.JPanel folderPanel;
   8.254 +    private javax.swing.JTextArea indexInfo;
   8.255 +    private javax.swing.JTextField indexURL;
   8.256 +    private javax.swing.JLabel indexURLLabel;
   8.257 +    private javax.swing.JLabel jLabel1;
   8.258 +    private javax.swing.JPanel remoteIndexPanel;
   8.259 +    private javax.swing.JComboBox subIndex;
   8.260 +    // End of variables declaration//GEN-END:variables
   8.261 +
   8.262 +    private void showFileChooser(JTextField folder) {
   8.263 +        JFileChooser c = new JFileChooser();
   8.264 +
   8.265 +        c.setSelectedFile(new File(folder.getText()));
   8.266 +        c.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
   8.267 +        c.setMultiSelectionEnabled(false);
   8.268 +        c.setApproveButtonText("Select");
   8.269 +
   8.270 +        if (c.showDialog(this, null) == JFileChooser.APPROVE_OPTION) {
   8.271 +            folder.setText(c.getSelectedFile().getAbsolutePath());
   8.272 +        }
   8.273 +    }
   8.274 +
   8.275 +    public void setIndex(RemoteIndex index) {
   8.276 +        folder.setText(index.folder);
   8.277 +        indexURL.setText(index.remote.toExternalForm());
   8.278 +        subIndex.setSelectedItem(index.remoteSegment);
   8.279 +    }
   8.280 +
   8.281 +    public RemoteIndex getIndex() {
   8.282 +        try {
   8.283 +            return RemoteIndex.create(folder.getText(), new URL(indexURL.getText()), (String) subIndex.getSelectedItem());
   8.284 +        } catch (MalformedURLException ex) {
   8.285 +            throw new IllegalStateException(ex);
   8.286 +        }
   8.287 +    }
   8.288 +
   8.289 +    private NotificationLineSupport notificationSupport;
   8.290 +
   8.291 +    public void setNotificationSupport(NotificationLineSupport notificationSupport) {
   8.292 +        this.notificationSupport = notificationSupport;
   8.293 +    }
   8.294 +
   8.295 +    private void updateErrors() {
   8.296 +        notificationSupport.clearMessages();
   8.297 +        
   8.298 +        File folderFile = new File(folder.getText());
   8.299 +
   8.300 +        if (!folderFile.exists()) {
   8.301 +            notificationSupport.setErrorMessage("Specified directory does not exist.");
   8.302 +            okButton.setEnabled(false);
   8.303 +            return;
   8.304 +        }
   8.305 +
   8.306 +        if (!folderFile.isDirectory()) {
   8.307 +            notificationSupport.setErrorMessage("Specified directory is not directory.");
   8.308 +            okButton.setEnabled(false);
   8.309 +            return ;
   8.310 +        }
   8.311 +
   8.312 +        if (checkingIndexURL.get()) {
   8.313 +            notificationSupport.setInformationMessage("Checking index URL");
   8.314 +            okButton.setEnabled(false);
   8.315 +            return;
   8.316 +        }
   8.317 +
   8.318 +        String urlError = checkingIndexURLError.get();
   8.319 +
   8.320 +        if (urlError != null) {
   8.321 +            notificationSupport.setErrorMessage(urlError);
   8.322 +            okButton.setEnabled(false);
   8.323 +            return;
   8.324 +        }
   8.325 +        
   8.326 +        okButton.setEnabled(true);
   8.327 +    }
   8.328 +
   8.329 +    private final AtomicBoolean checkingIndexURL = new AtomicBoolean();
   8.330 +    private final AtomicReference<String> checkingIndexURLContentCopy = new AtomicReference<String>();
   8.331 +    private final AtomicReference<String> checkingIndexURLError = new AtomicReference<String>();
   8.332 +
   8.333 +    private void indexURLUpdated() {
   8.334 +        checkingIndexURLContentCopy.set(indexURL.getText());
   8.335 +        urlCheckerTask.cancel();
   8.336 +        urlCheckerTask.schedule(50);
   8.337 +    }
   8.338 +
   8.339 +    private static final RequestProcessor WORKER = new RequestProcessor(CustomizeRemoteIndex.class.getName(), 1, false, false);
   8.340 +    private final RequestProcessor.Task urlCheckerTask = WORKER.create(new Runnable() {
   8.341 +
   8.342 +        public void run() {
   8.343 +            checkingIndexURL.set(true);
   8.344 +            checkingIndexURLError.set(null);
   8.345 +
   8.346 +            SwingUtilities.invokeLater(new Runnable() {
   8.347 +                public void run() {
   8.348 +                    updateErrors();
   8.349 +                }
   8.350 +            });
   8.351 +
   8.352 +            String urlText = checkingIndexURLContentCopy.get();
   8.353 +            Collection<? extends String> subindices = null;
   8.354 +
   8.355 +            try {
   8.356 +                URL url = new URL(urlText);
   8.357 +
   8.358 +                if (!url.getPath().endsWith("/"))
   8.359 +                    url = new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getPath() + "/" + (url.getQuery() != null ? "?" + url.getQuery() : ""));
   8.360 +                
   8.361 +                subindices = WebUtilities.requestStringArrayResponse(url.toURI().resolve("list"));
   8.362 +
   8.363 +                if (subindices.isEmpty()) {
   8.364 +                   checkingIndexURLError.set("Not an index.");
   8.365 +                }
   8.366 +            } catch (URISyntaxException ex) {
   8.367 +                checkingIndexURLError.set(ex.getLocalizedMessage());
   8.368 +            } catch (MalformedURLException ex) {
   8.369 +                checkingIndexURLError.set(ex.getLocalizedMessage());
   8.370 +            }
   8.371 +            
   8.372 +            checkingIndexURL.set(false);
   8.373 +
   8.374 +            final Collection<? extends String> subindicesFinal = subindices;
   8.375 +
   8.376 +            SwingUtilities.invokeLater(new Runnable() {
   8.377 +                public void run() {
   8.378 +                    updateErrors();
   8.379 +
   8.380 +                    if (subindicesFinal == null) return;
   8.381 +
   8.382 +                    DefaultComboBoxModel model = (DefaultComboBoxModel) subIndex.getModel();
   8.383 +                    String selected = (String) model.getSelectedItem();
   8.384 +
   8.385 +                    model.removeAllElements();
   8.386 +
   8.387 +                    boolean containsSelection = false;
   8.388 +                    Map<String, String> displayNames = new HashMap<String, String>();
   8.389 +
   8.390 +                    for (String subindex : subindicesFinal) {
   8.391 +                        String[] subindexSplit = subindex.split(":", 2);
   8.392 +                        if (subindexSplit[0].equals(selected)) containsSelection = true;
   8.393 +                        model.addElement(subindexSplit[0]);
   8.394 +                        displayNames.put(subindexSplit[0], subindexSplit[1]);
   8.395 +                    }
   8.396 +
   8.397 +                    if (containsSelection) {
   8.398 +                        model.setSelectedItem(selected);
   8.399 +                    }
   8.400 +
   8.401 +                    subindexSelectionUpdated();
   8.402 +                    subIndex.setRenderer(new RendererImpl(displayNames));
   8.403 +                }
   8.404 +            });
   8.405 +        }
   8.406 +    });
   8.407 +
   8.408 +    private final AtomicReference<String> indexInfoURLContentCopy = new AtomicReference<String>();
   8.409 +    private final AtomicReference<String> indexInfoSubIndexCopy = new AtomicReference<String>();
   8.410 +    private void subindexSelectionUpdated() {
   8.411 +        indexInfoURLContentCopy.set(indexURL.getText());
   8.412 +        indexInfoSubIndexCopy.set((String) subIndex.getSelectedItem());
   8.413 +        indexInfoTask.cancel();
   8.414 +        indexInfoTask.schedule(50);
   8.415 +    }
   8.416 +
   8.417 +    private final RequestProcessor.Task indexInfoTask = WORKER.create(new Runnable() {
   8.418 +
   8.419 +        public void run() {
   8.420 +            String urlText = indexInfoURLContentCopy.get();
   8.421 +            String subIndex = indexInfoSubIndexCopy.get();
   8.422 +            IndexInfo info = null;
   8.423 +
   8.424 +            try {
   8.425 +                URL url = new URL(urlText);
   8.426 +
   8.427 +                if (!url.getPath().endsWith("/"))
   8.428 +                    url = new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getPath() + "/" + (url.getQuery() != null ? "?" + url.getQuery() : ""));
   8.429 +
   8.430 +                String indexInfoText = WebUtilities.requestStringResponse(url.toURI().resolve("info?path=" + WebUtilities.escapeForQuery(subIndex)));
   8.431 +                info = IndexInfo.empty();
   8.432 +
   8.433 +                Pojson.update(info, indexInfoText);
   8.434 +            } catch (URISyntaxException ex) {
   8.435 +                Logger.getLogger(CustomizeRemoteIndex.class.getName()).log(Level.FINE, null, ex);
   8.436 +            } catch (MalformedURLException ex) {
   8.437 +                Logger.getLogger(CustomizeRemoteIndex.class.getName()).log(Level.FINE, null, ex);
   8.438 +            }
   8.439 +
   8.440 +            final IndexInfo infoFinal = info;
   8.441 +
   8.442 +            SwingUtilities.invokeLater(new Runnable() {
   8.443 +                public void run() {
   8.444 +                    if (infoFinal != null) {
   8.445 +                        indexInfo.setText(toDisplayText(infoFinal));
   8.446 +                    } else {
   8.447 +                        indexInfo.setText("");
   8.448 +                    }
   8.449 +                }
   8.450 +            });
   8.451 +        }
   8.452 +    });
   8.453 +
   8.454 +    private static String toDisplayText(IndexInfo info) {
   8.455 +        StringBuilder sb = new StringBuilder();
   8.456 +
   8.457 +        if (info.sourceLocation != null) {
   8.458 +            sb.append("Source Location: ").append(info.sourceLocation).append("\n");
   8.459 +        }
   8.460 +        if (info.lastUpdate >= 0) {
   8.461 +            sb.append("Last Update:\t").append(DateFormat.getDateTimeInstance().format(new Date(info.lastUpdate))).append("\n");
   8.462 +        }
   8.463 +        if (info.totalFiles >= 0) {
   8.464 +            sb.append("Indexed Files:\t").append(info.totalFiles).append("\n");
   8.465 +        }
   8.466 +
   8.467 +        return sb.toString();
   8.468 +    }
   8.469 +
   8.470 +    private static final class RendererImpl extends DefaultListCellRenderer {
   8.471 +        private final Map<String, String> displayNames;
   8.472 +        public RendererImpl(Map<String, String> displayNames) {
   8.473 +            this.displayNames = displayNames;
   8.474 +        }
   8.475 +
   8.476 +        @Override
   8.477 +        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
   8.478 +            return super.getListCellRendererComponent(list, displayNames.get(value), index, isSelected, cellHasFocus);
   8.479 +        }
   8.480 +
   8.481 +    }
   8.482 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/indexing/options/IndexOptionsPanelController.java	Sat Mar 05 23:03:17 2011 +0100
     9.3 @@ -0,0 +1,113 @@
     9.4 +/*
     9.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     9.6 + *
     9.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
     9.8 + *
     9.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    9.10 + * Other names may be trademarks of their respective owners.
    9.11 + *
    9.12 + * The contents of this file are subject to the terms of either the GNU
    9.13 + * General Public License Version 2 only ("GPL") or the Common
    9.14 + * Development and Distribution License("CDDL") (collectively, the
    9.15 + * "License"). You may not use this file except in compliance with the
    9.16 + * License. You can obtain a copy of the License at
    9.17 + * http://www.netbeans.org/cddl-gplv2.html
    9.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    9.19 + * specific language governing permissions and limitations under the
    9.20 + * License.  When distributing the software, include this License Header
    9.21 + * Notice in each file and include the License file at
    9.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    9.23 + * particular file as subject to the "Classpath" exception as provided
    9.24 + * by Oracle in the GPL Version 2 section of the License file that
    9.25 + * accompanied this code. If applicable, add the following below the
    9.26 + * License Header, with the fields enclosed by brackets [] replaced by
    9.27 + * your own identifying information:
    9.28 + * "Portions Copyrighted [year] [name of copyright owner]"
    9.29 + *
    9.30 + * If you wish your version of this file to be governed by only the CDDL
    9.31 + * or only the GPL Version 2, indicate your decision by adding
    9.32 + * "[Contributor] elects to include this software in this distribution
    9.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    9.34 + * single choice of license, a recipient has the option to distribute
    9.35 + * your version of this file under either the CDDL, the GPL Version 2 or
    9.36 + * to extend the choice of license to its licensees as provided above.
    9.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    9.38 + * Version 2 license, then the option applies only if the new code is
    9.39 + * made subject to such option by the copyright holder.
    9.40 + *
    9.41 + * Contributor(s):
    9.42 + *
    9.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
    9.44 + */
    9.45 +package org.netbeans.modules.jackpot30.impl.indexing.options;
    9.46 +
    9.47 +import java.beans.PropertyChangeListener;
    9.48 +import java.beans.PropertyChangeSupport;
    9.49 +import javax.swing.JComponent;
    9.50 +import org.netbeans.spi.options.OptionsPanelController;
    9.51 +import org.openide.util.HelpCtx;
    9.52 +import org.openide.util.Lookup;
    9.53 +
    9.54 +@OptionsPanelController.SubRegistration(location = "Editor",
    9.55 +displayName = "#AdvancedOption_DisplayName_Index",
    9.56 +keywords = "#AdvancedOption_Keywords_Index",
    9.57 +keywordsCategory = "Editor/Index")
    9.58 +public final class IndexOptionsPanelController extends OptionsPanelController {
    9.59 +
    9.60 +    private IndexPanel panel;
    9.61 +    private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
    9.62 +    private boolean changed;
    9.63 +
    9.64 +    public void update() {
    9.65 +        getPanel().load();
    9.66 +        changed = false;
    9.67 +    }
    9.68 +
    9.69 +    public void applyChanges() {
    9.70 +        getPanel().store();
    9.71 +        changed = false;
    9.72 +    }
    9.73 +
    9.74 +    public void cancel() {
    9.75 +        // need not do anything special, if no changes have been persisted yet
    9.76 +    }
    9.77 +
    9.78 +    public boolean isValid() {
    9.79 +        return getPanel().valid();
    9.80 +    }
    9.81 +
    9.82 +    public boolean isChanged() {
    9.83 +        return changed;
    9.84 +    }
    9.85 +
    9.86 +    public HelpCtx getHelpCtx() {
    9.87 +        return null; // new HelpCtx("...ID") if you have a help set
    9.88 +    }
    9.89 +
    9.90 +    public JComponent getComponent(Lookup masterLookup) {
    9.91 +        return getPanel();
    9.92 +    }
    9.93 +
    9.94 +    public void addPropertyChangeListener(PropertyChangeListener l) {
    9.95 +        pcs.addPropertyChangeListener(l);
    9.96 +    }
    9.97 +
    9.98 +    public void removePropertyChangeListener(PropertyChangeListener l) {
    9.99 +        pcs.removePropertyChangeListener(l);
   9.100 +    }
   9.101 +
   9.102 +    private IndexPanel getPanel() {
   9.103 +        if (panel == null) {
   9.104 +            panel = new IndexPanel(this);
   9.105 +        }
   9.106 +        return panel;
   9.107 +    }
   9.108 +
   9.109 +    void changed() {
   9.110 +        if (!changed) {
   9.111 +            changed = true;
   9.112 +            pcs.firePropertyChange(OptionsPanelController.PROP_CHANGED, false, true);
   9.113 +        }
   9.114 +        pcs.firePropertyChange(OptionsPanelController.PROP_VALID, null, null);
   9.115 +    }
   9.116 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/indexing/options/IndexPanel.form	Sat Mar 05 23:03:17 2011 +0100
    10.3 @@ -0,0 +1,106 @@
    10.4 +<?xml version="1.1" encoding="UTF-8" ?>
    10.5 +
    10.6 +<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
    10.7 +  <AuxValues>
    10.8 +    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
    10.9 +    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
   10.10 +    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
   10.11 +    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
   10.12 +    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
   10.13 +    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
   10.14 +    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
   10.15 +    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
   10.16 +    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
   10.17 +  </AuxValues>
   10.18 +
   10.19 +  <Layout>
   10.20 +    <DimensionLayout dim="0">
   10.21 +      <Group type="103" groupAlignment="0" attributes="0">
   10.22 +          <Group type="102" alignment="1" attributes="0">
   10.23 +              <EmptySpace max="-2" attributes="0"/>
   10.24 +              <Component id="jScrollPane1" pref="281" max="32767" attributes="0"/>
   10.25 +              <EmptySpace max="-2" attributes="0"/>
   10.26 +              <Group type="103" groupAlignment="1" attributes="0">
   10.27 +                  <Component id="removeButton" alignment="1" pref="154" max="32767" attributes="1"/>
   10.28 +                  <Component id="addButton" alignment="1" pref="154" max="32767" attributes="1"/>
   10.29 +                  <Component id="editButton" alignment="1" pref="154" max="32767" attributes="0"/>
   10.30 +              </Group>
   10.31 +              <EmptySpace max="-2" attributes="0"/>
   10.32 +          </Group>
   10.33 +      </Group>
   10.34 +    </DimensionLayout>
   10.35 +    <DimensionLayout dim="1">
   10.36 +      <Group type="103" groupAlignment="0" attributes="0">
   10.37 +          <Group type="102" alignment="0" attributes="0">
   10.38 +              <EmptySpace max="-2" attributes="0"/>
   10.39 +              <Group type="103" groupAlignment="0" attributes="0">
   10.40 +                  <Component id="jScrollPane1" alignment="0" pref="306" max="32767" attributes="0"/>
   10.41 +                  <Group type="102" alignment="0" attributes="0">
   10.42 +                      <Component id="addButton" min="-2" max="-2" attributes="0"/>
   10.43 +                      <EmptySpace max="-2" attributes="0"/>
   10.44 +                      <Component id="editButton" min="-2" max="-2" attributes="0"/>
   10.45 +                      <EmptySpace max="-2" attributes="0"/>
   10.46 +                      <Component id="removeButton" min="-2" max="-2" attributes="0"/>
   10.47 +                  </Group>
   10.48 +              </Group>
   10.49 +              <EmptySpace max="-2" attributes="0"/>
   10.50 +          </Group>
   10.51 +      </Group>
   10.52 +    </DimensionLayout>
   10.53 +  </Layout>
   10.54 +  <SubComponents>
   10.55 +    <Container class="javax.swing.JScrollPane" name="jScrollPane1">
   10.56 +      <AuxValues>
   10.57 +        <AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
   10.58 +        <AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
   10.59 +        <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
   10.60 +      </AuxValues>
   10.61 +
   10.62 +      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
   10.63 +      <SubComponents>
   10.64 +        <Component class="javax.swing.JTable" name="indices">
   10.65 +          <Properties>
   10.66 +            <Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
   10.67 +              <Table columnCount="4" rowCount="4">
   10.68 +                <Column editable="true" title="Title 1" type="java.lang.Object"/>
   10.69 +                <Column editable="true" title="Title 2" type="java.lang.Object"/>
   10.70 +                <Column editable="true" title="Title 3" type="java.lang.Object"/>
   10.71 +                <Column editable="true" title="Title 4" type="java.lang.Object"/>
   10.72 +              </Table>
   10.73 +            </Property>
   10.74 +          </Properties>
   10.75 +        </Component>
   10.76 +      </SubComponents>
   10.77 +    </Container>
   10.78 +    <Component class="javax.swing.JButton" name="addButton">
   10.79 +      <Properties>
   10.80 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   10.81 +          <ResourceString bundle="org/netbeans/modules/jackpot30/impl/indexing/options/Bundle.properties" key="IndexPanel.addButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   10.82 +        </Property>
   10.83 +      </Properties>
   10.84 +      <Events>
   10.85 +        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="addButtonActionPerformed"/>
   10.86 +      </Events>
   10.87 +    </Component>
   10.88 +    <Component class="javax.swing.JButton" name="removeButton">
   10.89 +      <Properties>
   10.90 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
   10.91 +          <ResourceString bundle="org/netbeans/modules/jackpot30/impl/indexing/options/Bundle.properties" key="IndexPanel.removeButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
   10.92 +        </Property>
   10.93 +      </Properties>
   10.94 +      <Events>
   10.95 +        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="removeButtonActionPerformed"/>
   10.96 +      </Events>
   10.97 +    </Component>
   10.98 +    <Component class="javax.swing.JButton" name="editButton">
   10.99 +      <Properties>
  10.100 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
  10.101 +          <ResourceString bundle="org/netbeans/modules/jackpot30/impl/indexing/options/Bundle.properties" key="IndexPanel.editButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
  10.102 +        </Property>
  10.103 +      </Properties>
  10.104 +      <Events>
  10.105 +        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="editButtonActionPerformed"/>
  10.106 +      </Events>
  10.107 +    </Component>
  10.108 +  </SubComponents>
  10.109 +</Form>
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/indexing/options/IndexPanel.java	Sat Mar 05 23:03:17 2011 +0100
    11.3 @@ -0,0 +1,265 @@
    11.4 +/*
    11.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    11.6 + *
    11.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
    11.8 + *
    11.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   11.10 + * Other names may be trademarks of their respective owners.
   11.11 + *
   11.12 + * The contents of this file are subject to the terms of either the GNU
   11.13 + * General Public License Version 2 only ("GPL") or the Common
   11.14 + * Development and Distribution License("CDDL") (collectively, the
   11.15 + * "License"). You may not use this file except in compliance with the
   11.16 + * License. You can obtain a copy of the License at
   11.17 + * http://www.netbeans.org/cddl-gplv2.html
   11.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   11.19 + * specific language governing permissions and limitations under the
   11.20 + * License.  When distributing the software, include this License Header
   11.21 + * Notice in each file and include the License file at
   11.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   11.23 + * particular file as subject to the "Classpath" exception as provided
   11.24 + * by Oracle in the GPL Version 2 section of the License file that
   11.25 + * accompanied this code. If applicable, add the following below the
   11.26 + * License Header, with the fields enclosed by brackets [] replaced by
   11.27 + * your own identifying information:
   11.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   11.29 + *
   11.30 + * If you wish your version of this file to be governed by only the CDDL
   11.31 + * or only the GPL Version 2, indicate your decision by adding
   11.32 + * "[Contributor] elects to include this software in this distribution
   11.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   11.34 + * single choice of license, a recipient has the option to distribute
   11.35 + * your version of this file under either the CDDL, the GPL Version 2 or
   11.36 + * to extend the choice of license to its licensees as provided above.
   11.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   11.38 + * Version 2 license, then the option applies only if the new code is
   11.39 + * made subject to such option by the copyright holder.
   11.40 + *
   11.41 + * Contributor(s):
   11.42 + *
   11.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
   11.44 + */
   11.45 +package org.netbeans.modules.jackpot30.impl.indexing.options;
   11.46 +
   11.47 +import java.util.ArrayList;
   11.48 +import java.util.List;
   11.49 +import javax.swing.JButton;
   11.50 +import javax.swing.event.ListSelectionEvent;
   11.51 +import javax.swing.event.ListSelectionListener;
   11.52 +import javax.swing.table.AbstractTableModel;
   11.53 +import org.netbeans.modules.jackpot30.impl.indexing.RemoteIndex;
   11.54 +import org.openide.DialogDescriptor;
   11.55 +import org.openide.DialogDisplayer;
   11.56 +
   11.57 +final class IndexPanel extends javax.swing.JPanel {
   11.58 +
   11.59 +    private final IndexOptionsPanelController controller;
   11.60 +
   11.61 +    IndexPanel(IndexOptionsPanelController controller) {
   11.62 +        this.controller = controller;
   11.63 +        initComponents();
   11.64 +        indices.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
   11.65 +            public void valueChanged(ListSelectionEvent e) {
   11.66 +                enableDisable();
   11.67 +            }
   11.68 +        });
   11.69 +        enableDisable();
   11.70 +    }
   11.71 +
   11.72 +    /** This method is called from within the constructor to
   11.73 +     * initialize the form.
   11.74 +     * WARNING: Do NOT modify this code. The content of this method is
   11.75 +     * always regenerated by the Form Editor.
   11.76 +     */
   11.77 +    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
   11.78 +    private void initComponents() {
   11.79 +
   11.80 +        javax.swing.JScrollPane jScrollPane1 = new javax.swing.JScrollPane();
   11.81 +        indices = new javax.swing.JTable();
   11.82 +        addButton = new javax.swing.JButton();
   11.83 +        removeButton = new javax.swing.JButton();
   11.84 +        editButton = new javax.swing.JButton();
   11.85 +
   11.86 +        indices.setModel(new javax.swing.table.DefaultTableModel(
   11.87 +            new Object [][] {
   11.88 +                {null, null, null, null},
   11.89 +                {null, null, null, null},
   11.90 +                {null, null, null, null},
   11.91 +                {null, null, null, null}
   11.92 +            },
   11.93 +            new String [] {
   11.94 +                "Title 1", "Title 2", "Title 3", "Title 4"
   11.95 +            }
   11.96 +        ));
   11.97 +        jScrollPane1.setViewportView(indices);
   11.98 +
   11.99 +        org.openide.awt.Mnemonics.setLocalizedText(addButton, org.openide.util.NbBundle.getMessage(IndexPanel.class, "IndexPanel.addButton.text")); // NOI18N
  11.100 +        addButton.addActionListener(new java.awt.event.ActionListener() {
  11.101 +            public void actionPerformed(java.awt.event.ActionEvent evt) {
  11.102 +                addButtonActionPerformed(evt);
  11.103 +            }
  11.104 +        });
  11.105 +
  11.106 +        org.openide.awt.Mnemonics.setLocalizedText(removeButton, org.openide.util.NbBundle.getMessage(IndexPanel.class, "IndexPanel.removeButton.text")); // NOI18N
  11.107 +        removeButton.addActionListener(new java.awt.event.ActionListener() {
  11.108 +            public void actionPerformed(java.awt.event.ActionEvent evt) {
  11.109 +                removeButtonActionPerformed(evt);
  11.110 +            }
  11.111 +        });
  11.112 +
  11.113 +        org.openide.awt.Mnemonics.setLocalizedText(editButton, org.openide.util.NbBundle.getMessage(IndexPanel.class, "IndexPanel.editButton.text")); // NOI18N
  11.114 +        editButton.addActionListener(new java.awt.event.ActionListener() {
  11.115 +            public void actionPerformed(java.awt.event.ActionEvent evt) {
  11.116 +                editButtonActionPerformed(evt);
  11.117 +            }
  11.118 +        });
  11.119 +
  11.120 +        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
  11.121 +        this.setLayout(layout);
  11.122 +        layout.setHorizontalGroup(
  11.123 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  11.124 +            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
  11.125 +                .addContainerGap()
  11.126 +                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 281, Short.MAX_VALUE)
  11.127 +                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  11.128 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
  11.129 +                    .addComponent(removeButton, javax.swing.GroupLayout.DEFAULT_SIZE, 154, Short.MAX_VALUE)
  11.130 +                    .addComponent(addButton, javax.swing.GroupLayout.DEFAULT_SIZE, 154, Short.MAX_VALUE)
  11.131 +                    .addComponent(editButton, javax.swing.GroupLayout.DEFAULT_SIZE, 154, Short.MAX_VALUE))
  11.132 +                .addContainerGap())
  11.133 +        );
  11.134 +        layout.setVerticalGroup(
  11.135 +            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  11.136 +            .addGroup(layout.createSequentialGroup()
  11.137 +                .addContainerGap()
  11.138 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
  11.139 +                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 306, Short.MAX_VALUE)
  11.140 +                    .addGroup(layout.createSequentialGroup()
  11.141 +                        .addComponent(addButton)
  11.142 +                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  11.143 +                        .addComponent(editButton)
  11.144 +                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
  11.145 +                        .addComponent(removeButton)))
  11.146 +                .addContainerGap())
  11.147 +        );
  11.148 +    }// </editor-fold>//GEN-END:initComponents
  11.149 +
  11.150 +    private void addButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addButtonActionPerformed
  11.151 +        addEditIndex(false);
  11.152 +    }//GEN-LAST:event_addButtonActionPerformed
  11.153 +
  11.154 +    private void editButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editButtonActionPerformed
  11.155 +        addEditIndex(true);
  11.156 +    }//GEN-LAST:event_editButtonActionPerformed
  11.157 +
  11.158 +    private void removeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeButtonActionPerformed
  11.159 +        TableModelImpl model = (TableModelImpl) indices.getModel();
  11.160 +
  11.161 +        model.indices.remove(indices.getSelectedRow());
  11.162 +        model.fireTableDataChanged();
  11.163 +    }//GEN-LAST:event_removeButtonActionPerformed
  11.164 +
  11.165 +    private void addEditIndex(boolean edit) {
  11.166 +        JButton okButton = new JButton("OK");
  11.167 +        CustomizeRemoteIndex panel = new CustomizeRemoteIndex(okButton);
  11.168 +        DialogDescriptor dd = new DialogDescriptor(panel, edit ? "Edit Index" : "Add Index", true, new Object[] {okButton, DialogDescriptor.CANCEL_OPTION}, okButton, DialogDescriptor.DEFAULT_ALIGN, null, null);
  11.169 +
  11.170 +        dd.setClosingOptions(null);
  11.171 +        panel.setNotificationSupport(dd.createNotificationLineSupport());
  11.172 +
  11.173 +        TableModelImpl model = (TableModelImpl) indices.getModel();
  11.174 +
  11.175 +        if (edit) {
  11.176 +            panel.setIndex(model.indices.get(indices.getSelectedRow()));
  11.177 +        }
  11.178 +
  11.179 +        if (DialogDisplayer.getDefault().notify(dd) == okButton) {
  11.180 +            RemoteIndex remoteIndex = panel.getIndex();
  11.181 +
  11.182 +            if (edit) {
  11.183 +                int index = model.indices.indexOf(indices.getSelectedRow());
  11.184 +
  11.185 +                model.indices.remove(index);
  11.186 +                model.indices.add(index, remoteIndex);
  11.187 +            } else {
  11.188 +                model.indices.add(remoteIndex);
  11.189 +            }
  11.190 +
  11.191 +            model.fireTableDataChanged();
  11.192 +        }
  11.193 +    }
  11.194 +
  11.195 +    private void enableDisable() {
  11.196 +        if (indices.getSelectedRow() != (-1)) {
  11.197 +            editButton.setEnabled(true);
  11.198 +            removeButton.setEnabled(true);
  11.199 +        } else {
  11.200 +            editButton.setEnabled(false);
  11.201 +            removeButton.setEnabled(false);
  11.202 +        }
  11.203 +    }
  11.204 +
  11.205 +    void load() {
  11.206 +        TableModelImpl model = new TableModelImpl();
  11.207 +
  11.208 +        for (RemoteIndex idx : RemoteIndex.loadIndices()) {
  11.209 +            model.indices.add(idx);
  11.210 +        }
  11.211 +
  11.212 +        indices.setModel(model);
  11.213 +    }
  11.214 +
  11.215 +    void store() {
  11.216 +        TableModelImpl model = (TableModelImpl) indices.getModel();
  11.217 +        
  11.218 +        RemoteIndex.saveIndices(model.indices);
  11.219 +    }
  11.220 +
  11.221 +    boolean valid() {
  11.222 +        // TODO check whether form is consistent and complete
  11.223 +        return true;
  11.224 +    }
  11.225 +    // Variables declaration - do not modify//GEN-BEGIN:variables
  11.226 +    private javax.swing.JButton addButton;
  11.227 +    private javax.swing.JButton editButton;
  11.228 +    private javax.swing.JTable indices;
  11.229 +    private javax.swing.JButton removeButton;
  11.230 +    // End of variables declaration//GEN-END:variables
  11.231 +
  11.232 +    private static final class TableModelImpl extends AbstractTableModel {
  11.233 +
  11.234 +        private final List<RemoteIndex> indices = new ArrayList<RemoteIndex>();
  11.235 +
  11.236 +        public int getRowCount() {
  11.237 +            return indices.size();
  11.238 +        }
  11.239 +
  11.240 +        public int getColumnCount() {
  11.241 +            return 3;
  11.242 +        }
  11.243 +
  11.244 +        public String getColumnName(int columnIndex) {
  11.245 +            switch (columnIndex) {
  11.246 +                case 0: return "Local folder";
  11.247 +                case 1: return "Remote URL";
  11.248 +                case 2: return "Remote project";
  11.249 +                default: throw new IllegalStateException();
  11.250 +            }
  11.251 +        }
  11.252 +
  11.253 +        public Class<?> getColumnClass(int columnIndex) {
  11.254 +            return String.class;
  11.255 +        }
  11.256 +
  11.257 +        public Object getValueAt(int rowIndex, int columnIndex) {
  11.258 +            RemoteIndex idx = indices.get(rowIndex);
  11.259 +
  11.260 +            switch (columnIndex) {
  11.261 +                case 0: return idx.folder;
  11.262 +                case 1: return idx.remote.toExternalForm();
  11.263 +                case 2: return idx.remoteSegment;
  11.264 +                default: throw new IllegalStateException();
  11.265 +            }
  11.266 +        }
  11.267 +    }
  11.268 +}
    12.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/refactoring/AbstractApplyHintsRefactoringPlugin.java	Fri Feb 25 19:39:47 2011 +0100
    12.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/refactoring/AbstractApplyHintsRefactoringPlugin.java	Sat Mar 05 23:03:17 2011 +0100
    12.3 @@ -44,12 +44,15 @@
    12.4  
    12.5  import java.util.Collection;
    12.6  import java.util.LinkedList;
    12.7 +import java.util.List;
    12.8  import java.util.concurrent.atomic.AtomicBoolean;
    12.9 +import org.netbeans.api.java.source.CompilationController;
   12.10  import org.netbeans.api.java.source.ModificationResult;
   12.11  import org.netbeans.api.java.source.ModificationResult.Difference;
   12.12  import org.netbeans.modules.jackpot30.impl.MessageImpl;
   12.13  import org.netbeans.modules.jackpot30.impl.batch.BatchSearch;
   12.14  import org.netbeans.modules.jackpot30.impl.batch.BatchSearch.BatchResult;
   12.15 +import org.netbeans.modules.jackpot30.impl.batch.BatchSearch.Resource;
   12.16  import org.netbeans.modules.jackpot30.impl.batch.BatchSearch.Scope;
   12.17  import org.netbeans.modules.jackpot30.impl.batch.BatchUtilities;
   12.18  import org.netbeans.modules.jackpot30.impl.batch.ProgressHandleWrapper;
   12.19 @@ -62,7 +65,9 @@
   12.20  import org.netbeans.modules.refactoring.spi.ProgressProviderAdapter;
   12.21  import org.netbeans.modules.refactoring.spi.RefactoringElementsBag;
   12.22  import org.netbeans.modules.refactoring.spi.RefactoringPlugin;
   12.23 +import org.netbeans.spi.editor.hints.ErrorDescription;
   12.24  import org.openide.filesystems.FileObject;
   12.25 +import org.openide.text.PositionBounds;
   12.26  
   12.27  /**
   12.28   *
   12.29 @@ -116,6 +121,51 @@
   12.30          return problems;
   12.31      }
   12.32  
   12.33 +    protected final void prepareElements(BatchResult candidates, ProgressHandleWrapper w, final RefactoringElementsBag refactoringElements, final boolean verify, List<MessageImpl> problems) {
   12.34 +        if (verify) {
   12.35 +            BatchSearch.getVerifiedSpans(candidates, w, new BatchSearch.VerifiedSpansCallBack() {
   12.36 +                public void groupStarted() {}
   12.37 +                public boolean spansVerified(CompilationController wc, Resource r, Collection<? extends ErrorDescription> hints) throws Exception {
   12.38 +                    List<PositionBounds> spans = new LinkedList<PositionBounds>();
   12.39 +
   12.40 +                    for (ErrorDescription ed : hints) {
   12.41 +                        spans.add(ed.getRange());
   12.42 +                    }
   12.43 +
   12.44 +                    refactoringElements.addAll(refactoring, Utilities.createRefactoringElementImplementation(r.getResolvedFile(), spans, verify));
   12.45 +
   12.46 +                    return true;
   12.47 +                }
   12.48 +                public void groupFinished() {}
   12.49 +                public void cannotVerifySpan(Resource r) {
   12.50 +                    refactoringElements.addAll(refactoring, Utilities.createRefactoringElementImplementation(r.getResolvedFile(), prepareSpansFor(r), verify));
   12.51 +                }
   12.52 +            }, problems);
   12.53 +        } else {
   12.54 +            int[] parts = new int[candidates.getResources().size()];
   12.55 +            int   index = 0;
   12.56 +
   12.57 +            for (Collection<? extends Resource> resources : candidates.getResources()) {
   12.58 +                parts[index++] = resources.size();
   12.59 +            }
   12.60 +
   12.61 +            ProgressHandleWrapper inner = w.startNextPartWithEmbedding(parts);
   12.62 +
   12.63 +            for (Collection<? extends Resource> it :candidates.getResources()) {
   12.64 +                inner.startNextPart(it.size());
   12.65 +
   12.66 +                for (Resource r : it) {
   12.67 +                    refactoringElements.addAll(refactoring, Utilities.createRefactoringElementImplementation(r.getResolvedFile(), prepareSpansFor(r), verify));
   12.68 +                    inner.tick();
   12.69 +                }
   12.70 +            }
   12.71 +        }
   12.72 +    }
   12.73 +
   12.74 +    private static List<PositionBounds> prepareSpansFor(Resource r) {
   12.75 +        return Utilities.prepareSpansFor(r.getResolvedFile(), r.getCandidateSpans());
   12.76 +    }
   12.77 +
   12.78      public void start(int totalWork) {
   12.79          fireProgressListenerStart(-1, totalWork);
   12.80          lastWorkDone = 0;
    13.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/refactoring/FindDuplicatesRefactoringPlugin.java	Fri Feb 25 19:39:47 2011 +0100
    13.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/refactoring/FindDuplicatesRefactoringPlugin.java	Sat Mar 05 23:03:17 2011 +0100
    13.3 @@ -39,40 +39,16 @@
    13.4  
    13.5  package org.netbeans.modules.jackpot30.impl.refactoring;
    13.6  
    13.7 -import java.io.CharConversionException;
    13.8 -import java.io.IOException;
    13.9 -import java.util.ArrayList;
   13.10  import java.util.Collection;
   13.11  import java.util.LinkedList;
   13.12  import java.util.List;
   13.13 -import java.util.Map.Entry;
   13.14 -import javax.swing.text.Position.Bias;
   13.15 -import org.netbeans.api.java.source.CompilationController;
   13.16  import org.netbeans.modules.jackpot30.impl.MessageImpl;
   13.17  import org.netbeans.modules.jackpot30.impl.batch.BatchSearch;
   13.18  import org.netbeans.modules.jackpot30.impl.batch.BatchSearch.BatchResult;
   13.19 -import org.netbeans.modules.jackpot30.impl.batch.BatchSearch.Container;
   13.20 -import org.netbeans.modules.jackpot30.impl.batch.BatchSearch.Resource;
   13.21  import org.netbeans.modules.jackpot30.impl.batch.ProgressHandleWrapper;
   13.22  import org.netbeans.modules.jackpot30.spi.HintContext.MessageKind;
   13.23  import org.netbeans.modules.refactoring.api.Problem;
   13.24 -import org.netbeans.modules.refactoring.spi.RefactoringElementImplementation;
   13.25  import org.netbeans.modules.refactoring.spi.RefactoringElementsBag;
   13.26 -import org.netbeans.modules.refactoring.spi.SimpleRefactoringElementImplementation;
   13.27 -import org.netbeans.spi.editor.hints.ErrorDescription;
   13.28 -import org.openide.cookies.EditorCookie;
   13.29 -import org.openide.cookies.LineCookie;
   13.30 -import org.openide.filesystems.FileObject;
   13.31 -import org.openide.loaders.DataObject;
   13.32 -import org.openide.loaders.DataObjectNotFoundException;
   13.33 -import org.openide.text.CloneableEditorSupport;
   13.34 -import org.openide.text.Line;
   13.35 -import org.openide.text.PositionBounds;
   13.36 -import org.openide.text.PositionRef;
   13.37 -import org.openide.util.Exceptions;
   13.38 -import org.openide.util.Lookup;
   13.39 -import org.openide.util.lookup.Lookups;
   13.40 -import org.openide.xml.XMLUtil;
   13.41  
   13.42  public class FindDuplicatesRefactoringPlugin extends AbstractApplyHintsRefactoringPlugin {
   13.43  
   13.44 @@ -117,167 +93,15 @@
   13.45          BatchResult candidates = BatchSearch.findOccurrences(refactoring.getPattern(), refactoring.getScope(), w);
   13.46          List<MessageImpl> problems = new LinkedList<MessageImpl>(candidates.problems);
   13.47  
   13.48 -        final boolean verify = refactoring.isVerify();
   13.49 -
   13.50 -        if (verify) {
   13.51 -            BatchSearch.getVerifiedSpans(candidates, w, new BatchSearch.VerifiedSpansCallBack() {
   13.52 -                public void groupStarted() {}
   13.53 -                public boolean spansVerified(CompilationController wc, Resource r, Collection<? extends ErrorDescription> hints) throws Exception {
   13.54 -                    List<PositionBounds> spans = new LinkedList<PositionBounds>();
   13.55 -
   13.56 -                    for (ErrorDescription ed : hints) {
   13.57 -                        spans.add(ed.getRange());
   13.58 -                    }
   13.59 -
   13.60 -                    refactoringElements.addAll(refactoring, createRefactoringElementImplementation(r.getResolvedFile(), spans, verify));
   13.61 -
   13.62 -                    return true;
   13.63 -                }
   13.64 -                public void groupFinished() {}
   13.65 -                public void cannotVerifySpan(Resource r) {
   13.66 -                    refactoringElements.addAll(refactoring, createRefactoringElementImplementation(r.getResolvedFile(), prepareSpansFor(r), verify));
   13.67 -                }
   13.68 -            }, problems);
   13.69 -        } else {
   13.70 -            int[] parts = new int[candidates.projectId2Resources.size()];
   13.71 -            int   index = 0;
   13.72 -
   13.73 -            for (Entry<? extends Container, ? extends Collection<? extends Resource>> e : candidates.projectId2Resources.entrySet()) {
   13.74 -                parts[index++] = e.getValue().size();
   13.75 -            }
   13.76 -
   13.77 -            ProgressHandleWrapper inner = w.startNextPartWithEmbedding(parts);
   13.78 -
   13.79 -            for (Collection<? extends Resource> it :candidates.projectId2Resources.values()) {
   13.80 -                inner.startNextPart(it.size());
   13.81 -
   13.82 -                for (Resource r : it) {
   13.83 -                    refactoringElements.addAll(refactoring, createRefactoringElementImplementation(r.getResolvedFile(), prepareSpansFor(r), verify));
   13.84 -                    inner.tick();
   13.85 -                }
   13.86 -            }
   13.87 -        }
   13.88 +        prepareElements(candidates, w, refactoringElements, refactoring.isVerify(), problems);
   13.89  
   13.90          w.finish();
   13.91  
   13.92          return problems;
   13.93       }
   13.94  
   13.95 -    private static List<PositionBounds> prepareSpansFor(Resource r) {
   13.96 -        List<PositionBounds> spans = new ArrayList<PositionBounds>();
   13.97 -
   13.98 -        try {
   13.99 -            FileObject file = r.getResolvedFile();
  13.100 -            DataObject d = DataObject.find(file);
  13.101 -            EditorCookie ec = d.getLookup().lookup(EditorCookie.class);
  13.102 -            CloneableEditorSupport ces = (CloneableEditorSupport) ec;
  13.103 -
  13.104 -            spans = new LinkedList<PositionBounds>();
  13.105 -
  13.106 -            for (int[] span : r.getCandidateSpans()) {
  13.107 -                PositionRef start = ces.createPositionRef(span[0], Bias.Forward);
  13.108 -                PositionRef end = ces.createPositionRef(span[1], Bias.Forward);
  13.109 -
  13.110 -                spans.add(new PositionBounds(start, end));
  13.111 -            }
  13.112 -        } catch (DataObjectNotFoundException ex) {
  13.113 -            Exceptions.printStackTrace(ex);
  13.114 -        }
  13.115 -
  13.116 -        return spans;
  13.117 -    }
  13.118 -
  13.119 -    private static Collection<RefactoringElementImplementation> createRefactoringElementImplementation(FileObject file, List<PositionBounds> spans, boolean verified) {
  13.120 -        List<RefactoringElementImplementation> result = new LinkedList<RefactoringElementImplementation>();
  13.121 -
  13.122 -        try {
  13.123 -            DataObject d = DataObject.find(file);
  13.124 -            LineCookie lc = d.getLookup().lookup(LineCookie.class);
  13.125 -
  13.126 -            for (PositionBounds bound : spans) {
  13.127 -                PositionRef start = bound.getBegin();
  13.128 -                PositionRef end = bound.getEnd();
  13.129 -                Line l = lc.getLineSet().getCurrent(start.getLine());
  13.130 -                String lineText = l.getText();
  13.131 -
  13.132 -                int boldStart = start.getColumn();
  13.133 -                int boldEnd   = end.getLine() == start.getLine() ? end.getColumn() : lineText.length();
  13.134 -
  13.135 -                StringBuilder displayName = new StringBuilder();
  13.136 -
  13.137 -                if (!verified) {
  13.138 -                    displayName.append("(not verified) ");
  13.139 -                }
  13.140 -
  13.141 -                displayName.append(escapedSubstring(lineText, 0, boldStart).replaceAll("^[ ]*", ""));
  13.142 -                displayName.append("<b>");
  13.143 -                displayName.append(escapedSubstring(lineText, boldStart, boldEnd));
  13.144 -                displayName.append("</b>");
  13.145 -                displayName.append(escapedSubstring(lineText, boldEnd, lineText.length()));
  13.146 -
  13.147 -                result.add(new RefactoringElementImpl(file, bound, displayName.toString()));
  13.148 -            }
  13.149 -        } catch (IOException ex) {
  13.150 -            Exceptions.printStackTrace(ex);
  13.151 -        }
  13.152 -
  13.153 -        return result;
  13.154 -    }
  13.155 -
  13.156      private Collection<MessageImpl> performApplyPattern(RefactoringElementsBag refactoringElements) {
  13.157          return performApplyPattern(refactoring.getPattern(), refactoring.getScope(), refactoringElements);
  13.158      }
  13.159  
  13.160 -    private static String escapedSubstring(String str, int start, int end) {
  13.161 -        String substring = str.substring(start, end);
  13.162 -        
  13.163 -        try {
  13.164 -            return XMLUtil.toElementContent(substring);
  13.165 -        } catch (CharConversionException ex) {
  13.166 -            Exceptions.printStackTrace(ex);
  13.167 -            return substring;
  13.168 -        }
  13.169 -    }
  13.170 -
  13.171 -    private static final class RefactoringElementImpl extends SimpleRefactoringElementImplementation {
  13.172 -
  13.173 -        private final FileObject file;
  13.174 -        private final PositionBounds span;
  13.175 -        private final String displayName;
  13.176 -
  13.177 -        private final Lookup lookup;
  13.178 -        
  13.179 -        public RefactoringElementImpl(FileObject file, PositionBounds span, String displayName) {
  13.180 -            this.file = file;
  13.181 -            this.span = span;
  13.182 -            this.lookup = Lookups.fixed(file);
  13.183 -            this.displayName = displayName;
  13.184 -        }
  13.185 -
  13.186 -        public String getText() {
  13.187 -            return getDisplayText();
  13.188 -        }
  13.189 -
  13.190 -        public String getDisplayText() {
  13.191 -            return displayName;
  13.192 -        }
  13.193 -
  13.194 -        public void performChange() {
  13.195 -            throw new IllegalStateException();
  13.196 -        }
  13.197 -
  13.198 -        public Lookup getLookup() {
  13.199 -            return lookup;
  13.200 -        }
  13.201 -
  13.202 -        public FileObject getParentFile() {
  13.203 -            return file;
  13.204 -        }
  13.205 -
  13.206 -        public PositionBounds getPosition() {
  13.207 -            return span;
  13.208 -        }
  13.209 -        
  13.210 -    }
  13.211 -    
  13.212  }
  13.213 \ No newline at end of file
    14.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/refactoring/RefactoringPluginFactoryImpl.java	Fri Feb 25 19:39:47 2011 +0100
    14.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/refactoring/RefactoringPluginFactoryImpl.java	Sat Mar 05 23:03:17 2011 +0100
    14.3 @@ -39,6 +39,8 @@
    14.4  
    14.5  package org.netbeans.modules.jackpot30.impl.refactoring;
    14.6  
    14.7 +import org.netbeans.modules.jackpot30.impl.refactoring.findusages.GlobalFindUsagesRefactoring;
    14.8 +import org.netbeans.modules.jackpot30.impl.refactoring.findusages.GlobalFindUsagesRefactoringPlugin;
    14.9  import org.netbeans.modules.jackpot30.impl.refactoring.upgrade.UpgradeRefactoring;
   14.10  import org.netbeans.modules.jackpot30.impl.refactoring.upgrade.UpgradeRefactoringPlugin;
   14.11  import org.netbeans.modules.refactoring.api.AbstractRefactoring;
   14.12 @@ -54,6 +56,8 @@
   14.13              return new FindDuplicatesRefactoringPlugin((FindDuplicatesRefactoring) refactoring);
   14.14          } else if (refactoring instanceof UpgradeRefactoring) {
   14.15              return new UpgradeRefactoringPlugin((UpgradeRefactoring) refactoring);
   14.16 +        } else if (refactoring instanceof GlobalFindUsagesRefactoring) {
   14.17 +            return new GlobalFindUsagesRefactoringPlugin((GlobalFindUsagesRefactoring) refactoring);
   14.18          }
   14.19  
   14.20          return null;
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/refactoring/Utilities.java	Sat Mar 05 23:03:17 2011 +0100
    15.3 @@ -0,0 +1,185 @@
    15.4 +/*
    15.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    15.6 + *
    15.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
    15.8 + *
    15.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   15.10 + * Other names may be trademarks of their respective owners.
   15.11 + *
   15.12 + * The contents of this file are subject to the terms of either the GNU
   15.13 + * General Public License Version 2 only ("GPL") or the Common
   15.14 + * Development and Distribution License("CDDL") (collectively, the
   15.15 + * "License"). You may not use this file except in compliance with the
   15.16 + * License. You can obtain a copy of the License at
   15.17 + * http://www.netbeans.org/cddl-gplv2.html
   15.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   15.19 + * specific language governing permissions and limitations under the
   15.20 + * License.  When distributing the software, include this License Header
   15.21 + * Notice in each file and include the License file at
   15.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   15.23 + * particular file as subject to the "Classpath" exception as provided
   15.24 + * by Oracle in the GPL Version 2 section of the License file that
   15.25 + * accompanied this code. If applicable, add the following below the
   15.26 + * License Header, with the fields enclosed by brackets [] replaced by
   15.27 + * your own identifying information:
   15.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   15.29 + *
   15.30 + * If you wish your version of this file to be governed by only the CDDL
   15.31 + * or only the GPL Version 2, indicate your decision by adding
   15.32 + * "[Contributor] elects to include this software in this distribution
   15.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   15.34 + * single choice of license, a recipient has the option to distribute
   15.35 + * your version of this file under either the CDDL, the GPL Version 2 or
   15.36 + * to extend the choice of license to its licensees as provided above.
   15.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   15.38 + * Version 2 license, then the option applies only if the new code is
   15.39 + * made subject to such option by the copyright holder.
   15.40 + *
   15.41 + * Contributor(s):
   15.42 + *
   15.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
   15.44 + */
   15.45 +
   15.46 +package org.netbeans.modules.jackpot30.impl.refactoring;
   15.47 +
   15.48 +import java.io.CharConversionException;
   15.49 +import java.io.IOException;
   15.50 +import java.util.ArrayList;
   15.51 +import java.util.Collection;
   15.52 +import java.util.LinkedList;
   15.53 +import java.util.List;
   15.54 +import javax.swing.text.Position.Bias;
   15.55 +import org.netbeans.modules.refactoring.spi.RefactoringElementImplementation;
   15.56 +import org.netbeans.modules.refactoring.spi.SimpleRefactoringElementImplementation;
   15.57 +import org.openide.cookies.EditorCookie;
   15.58 +import org.openide.cookies.LineCookie;
   15.59 +import org.openide.filesystems.FileObject;
   15.60 +import org.openide.loaders.DataObject;
   15.61 +import org.openide.loaders.DataObjectNotFoundException;
   15.62 +import org.openide.text.CloneableEditorSupport;
   15.63 +import org.openide.text.Line;
   15.64 +import org.openide.text.PositionBounds;
   15.65 +import org.openide.text.PositionRef;
   15.66 +import org.openide.util.Exceptions;
   15.67 +import org.openide.util.Lookup;
   15.68 +import org.openide.util.lookup.Lookups;
   15.69 +import org.openide.xml.XMLUtil;
   15.70 +
   15.71 +/**
   15.72 + *
   15.73 + * @author lahvac
   15.74 + */
   15.75 +public class Utilities {
   15.76 +    public static List<PositionBounds> prepareSpansFor(FileObject file, Iterable<? extends int[]> spans) {
   15.77 +        List<PositionBounds> result = new ArrayList<PositionBounds>();
   15.78 +
   15.79 +        try {
   15.80 +            DataObject d = DataObject.find(file);
   15.81 +            EditorCookie ec = d.getLookup().lookup(EditorCookie.class);
   15.82 +            CloneableEditorSupport ces = (CloneableEditorSupport) ec;
   15.83 +
   15.84 +            result = new LinkedList<PositionBounds>();
   15.85 +
   15.86 +            for (int[] span : spans) {
   15.87 +                PositionRef start = ces.createPositionRef(span[0], Bias.Forward);
   15.88 +                PositionRef end = ces.createPositionRef(span[1], Bias.Forward);
   15.89 +
   15.90 +                result.add(new PositionBounds(start, end));
   15.91 +            }
   15.92 +        } catch (DataObjectNotFoundException ex) {
   15.93 +            Exceptions.printStackTrace(ex);
   15.94 +        }
   15.95 +
   15.96 +        return result;
   15.97 +    }
   15.98 +
   15.99 +    public static Collection<RefactoringElementImplementation> createRefactoringElementImplementation(FileObject file, List<PositionBounds> spans, boolean verified) {
  15.100 +        List<RefactoringElementImplementation> result = new LinkedList<RefactoringElementImplementation>();
  15.101 +
  15.102 +        try {
  15.103 +            DataObject d = DataObject.find(file);
  15.104 +            LineCookie lc = d.getLookup().lookup(LineCookie.class);
  15.105 +
  15.106 +            for (PositionBounds bound : spans) {
  15.107 +                PositionRef start = bound.getBegin();
  15.108 +                PositionRef end = bound.getEnd();
  15.109 +                Line l = lc.getLineSet().getCurrent(start.getLine());
  15.110 +                String lineText = l.getText();
  15.111 +
  15.112 +                int boldStart = start.getColumn();
  15.113 +                int boldEnd   = end.getLine() == start.getLine() ? end.getColumn() : lineText.length();
  15.114 +
  15.115 +                StringBuilder displayName = new StringBuilder();
  15.116 +
  15.117 +                if (!verified) {
  15.118 +                    displayName.append("(not verified) ");
  15.119 +                }
  15.120 +
  15.121 +                displayName.append(escapedSubstring(lineText, 0, boldStart).replaceAll("^[ ]*", ""));
  15.122 +                displayName.append("<b>");
  15.123 +                displayName.append(escapedSubstring(lineText, boldStart, boldEnd));
  15.124 +                displayName.append("</b>");
  15.125 +                displayName.append(escapedSubstring(lineText, boldEnd, lineText.length()));
  15.126 +
  15.127 +                result.add(new RefactoringElementImpl(file, bound, displayName.toString()));
  15.128 +            }
  15.129 +        } catch (IOException ex) {
  15.130 +            Exceptions.printStackTrace(ex);
  15.131 +        }
  15.132 +
  15.133 +        return result;
  15.134 +    }
  15.135 +
  15.136 +    private static String escapedSubstring(String str, int start, int end) {
  15.137 +        String substring = str.substring(start, end);
  15.138 +
  15.139 +        try {
  15.140 +            return XMLUtil.toElementContent(substring);
  15.141 +        } catch (CharConversionException ex) {
  15.142 +            Exceptions.printStackTrace(ex);
  15.143 +            return substring;
  15.144 +        }
  15.145 +    }
  15.146 +
  15.147 +    private static final class RefactoringElementImpl extends SimpleRefactoringElementImplementation {
  15.148 +
  15.149 +        private final FileObject file;
  15.150 +        private final PositionBounds span;
  15.151 +        private final String displayName;
  15.152 +
  15.153 +        private final Lookup lookup;
  15.154 +
  15.155 +        public RefactoringElementImpl(FileObject file, PositionBounds span, String displayName) {
  15.156 +            this.file = file;
  15.157 +            this.span = span;
  15.158 +            this.lookup = Lookups.fixed(file);
  15.159 +            this.displayName = displayName;
  15.160 +        }
  15.161 +
  15.162 +        public String getText() {
  15.163 +            return getDisplayText();
  15.164 +        }
  15.165 +
  15.166 +        public String getDisplayText() {
  15.167 +            return displayName;
  15.168 +        }
  15.169 +
  15.170 +        public void performChange() {
  15.171 +            throw new IllegalStateException();
  15.172 +        }
  15.173 +
  15.174 +        public Lookup getLookup() {
  15.175 +            return lookup;
  15.176 +        }
  15.177 +
  15.178 +        public FileObject getParentFile() {
  15.179 +            return file;
  15.180 +        }
  15.181 +
  15.182 +        public PositionBounds getPosition() {
  15.183 +            return span;
  15.184 +        }
  15.185 +
  15.186 +    }
  15.187 +
  15.188 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/refactoring/findusages/GlobalFindUsagesAction.java	Sat Mar 05 23:03:17 2011 +0100
    16.3 @@ -0,0 +1,107 @@
    16.4 +/*
    16.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    16.6 + *
    16.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
    16.8 + *
    16.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   16.10 + * Other names may be trademarks of their respective owners.
   16.11 + *
   16.12 + * The contents of this file are subject to the terms of either the GNU
   16.13 + * General Public License Version 2 only ("GPL") or the Common
   16.14 + * Development and Distribution License("CDDL") (collectively, the
   16.15 + * "License"). You may not use this file except in compliance with the
   16.16 + * License. You can obtain a copy of the License at
   16.17 + * http://www.netbeans.org/cddl-gplv2.html
   16.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   16.19 + * specific language governing permissions and limitations under the
   16.20 + * License.  When distributing the software, include this License Header
   16.21 + * Notice in each file and include the License file at
   16.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   16.23 + * particular file as subject to the "Classpath" exception as provided
   16.24 + * by Oracle in the GPL Version 2 section of the License file that
   16.25 + * accompanied this code. If applicable, add the following below the
   16.26 + * License Header, with the fields enclosed by brackets [] replaced by
   16.27 + * your own identifying information:
   16.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   16.29 + *
   16.30 + * If you wish your version of this file to be governed by only the CDDL
   16.31 + * or only the GPL Version 2, indicate your decision by adding
   16.32 + * "[Contributor] elects to include this software in this distribution
   16.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   16.34 + * single choice of license, a recipient has the option to distribute
   16.35 + * your version of this file under either the CDDL, the GPL Version 2 or
   16.36 + * to extend the choice of license to its licensees as provided above.
   16.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   16.38 + * Version 2 license, then the option applies only if the new code is
   16.39 + * made subject to such option by the copyright holder.
   16.40 + *
   16.41 + * Contributor(s):
   16.42 + *
   16.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
   16.44 + */
   16.45 +package org.netbeans.modules.jackpot30.impl.refactoring.findusages;
   16.46 +
   16.47 +import com.sun.source.util.TreePath;
   16.48 +import java.awt.event.ActionEvent;
   16.49 +import java.awt.event.ActionListener;
   16.50 +import java.io.IOException;
   16.51 +import javax.lang.model.element.Element;
   16.52 +import javax.lang.model.element.ElementKind;
   16.53 +import javax.swing.text.JTextComponent;
   16.54 +import org.netbeans.api.editor.EditorRegistry;
   16.55 +import org.netbeans.api.java.source.CompilationController;
   16.56 +import org.netbeans.api.java.source.JavaSource;
   16.57 +import org.netbeans.api.java.source.Task;
   16.58 +import org.netbeans.modules.editor.NbEditorUtilities;
   16.59 +import org.netbeans.modules.refactoring.spi.ui.UI;
   16.60 +import org.openide.awt.ActionRegistration;
   16.61 +import org.openide.awt.ActionReference;
   16.62 +import org.openide.awt.ActionReferences;
   16.63 +import org.openide.awt.ActionID;
   16.64 +import org.openide.filesystems.FileObject;
   16.65 +import org.openide.util.Exceptions;
   16.66 +import org.openide.util.NbBundle.Messages;
   16.67 +
   16.68 +@ActionID(category = "Refactoring",
   16.69 +id = "org.netbeans.modules.jackpot30.impl.refactoring.findusages.GlobalFindUsagesAction")
   16.70 +@ActionRegistration(displayName = "#CTL_GlobalFindUsagesAction")
   16.71 +@ActionReferences({
   16.72 +    @ActionReference(path = "Menu/Edit", position = 2225)
   16.73 +})
   16.74 +@Messages("CTL_GlobalFindUsagesAction=Global Find Usages")
   16.75 +public final class GlobalFindUsagesAction implements ActionListener {
   16.76 +
   16.77 +    public void actionPerformed(ActionEvent e) {
   16.78 +        JTextComponent focusedComponent = EditorRegistry.lastFocusedComponent();
   16.79 +
   16.80 +        if (focusedComponent == null) {
   16.81 +            return;
   16.82 +        }
   16.83 +
   16.84 +        final int pos = focusedComponent.getCaretPosition();
   16.85 +        JavaSource js = JavaSource.forDocument(focusedComponent.getDocument());
   16.86 +
   16.87 +        if (js == null) {
   16.88 +            return ;
   16.89 +        }
   16.90 +
   16.91 +        final String[] script = new String[1];
   16.92 +        
   16.93 +        try {
   16.94 +            js.runUserActionTask(new Task<CompilationController>() {
   16.95 +                public void run(CompilationController parameter) throws Exception {
   16.96 +                    TreePath sel = parameter.getTreeUtilities().pathFor(pos);
   16.97 +                    Element el = parameter.getTrees().getElement(sel);
   16.98 +
   16.99 +                    if (el != null && el.getKind() == ElementKind.METHOD) {
  16.100 +                        script[0] = PatternGenerator.generateFindUsagesScript(parameter, el);
  16.101 +                    }
  16.102 +                }
  16.103 +            }, true);
  16.104 +        } catch (IOException ex) {
  16.105 +            Exceptions.printStackTrace(ex);
  16.106 +        }
  16.107 +
  16.108 +        UI.openRefactoringUI(new GlobalFindUsagesRefactoringUI(new GlobalFindUsagesRefactoring(script[0])));
  16.109 +    }
  16.110 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/refactoring/findusages/GlobalFindUsagesRefactoring.java	Sat Mar 05 23:03:17 2011 +0100
    17.3 @@ -0,0 +1,61 @@
    17.4 +/*
    17.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    17.6 + *
    17.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
    17.8 + *
    17.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   17.10 + * Other names may be trademarks of their respective owners.
   17.11 + *
   17.12 + * The contents of this file are subject to the terms of either the GNU
   17.13 + * General Public License Version 2 only ("GPL") or the Common
   17.14 + * Development and Distribution License("CDDL") (collectively, the
   17.15 + * "License"). You may not use this file except in compliance with the
   17.16 + * License. You can obtain a copy of the License at
   17.17 + * http://www.netbeans.org/cddl-gplv2.html
   17.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   17.19 + * specific language governing permissions and limitations under the
   17.20 + * License.  When distributing the software, include this License Header
   17.21 + * Notice in each file and include the License file at
   17.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   17.23 + * particular file as subject to the "Classpath" exception as provided
   17.24 + * by Oracle in the GPL Version 2 section of the License file that
   17.25 + * accompanied this code. If applicable, add the following below the
   17.26 + * License Header, with the fields enclosed by brackets [] replaced by
   17.27 + * your own identifying information:
   17.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   17.29 + *
   17.30 + * If you wish your version of this file to be governed by only the CDDL
   17.31 + * or only the GPL Version 2, indicate your decision by adding
   17.32 + * "[Contributor] elects to include this software in this distribution
   17.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   17.34 + * single choice of license, a recipient has the option to distribute
   17.35 + * your version of this file under either the CDDL, the GPL Version 2 or
   17.36 + * to extend the choice of license to its licensees as provided above.
   17.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   17.38 + * Version 2 license, then the option applies only if the new code is
   17.39 + * made subject to such option by the copyright holder.
   17.40 + *
   17.41 + * Contributor(s):
   17.42 + *
   17.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
   17.44 + */
   17.45 +
   17.46 +package org.netbeans.modules.jackpot30.impl.refactoring.findusages;
   17.47 +
   17.48 +import org.netbeans.modules.refactoring.api.AbstractRefactoring;
   17.49 +import org.openide.util.lookup.Lookups;
   17.50 +
   17.51 +/**
   17.52 + *
   17.53 + * @author lahvac
   17.54 + */
   17.55 +public class GlobalFindUsagesRefactoring extends AbstractRefactoring {
   17.56 +
   17.57 +    public final String script;
   17.58 +
   17.59 +    public GlobalFindUsagesRefactoring(String script) {
   17.60 +        super(Lookups.singleton(script));
   17.61 +        this.script = script;
   17.62 +    }
   17.63 +
   17.64 +}
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/refactoring/findusages/GlobalFindUsagesRefactoringPlugin.java	Sat Mar 05 23:03:17 2011 +0100
    18.3 @@ -0,0 +1,105 @@
    18.4 +/*
    18.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    18.6 + *
    18.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
    18.8 + *
    18.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   18.10 + * Other names may be trademarks of their respective owners.
   18.11 + *
   18.12 + * The contents of this file are subject to the terms of either the GNU
   18.13 + * General Public License Version 2 only ("GPL") or the Common
   18.14 + * Development and Distribution License("CDDL") (collectively, the
   18.15 + * "License"). You may not use this file except in compliance with the
   18.16 + * License. You can obtain a copy of the License at
   18.17 + * http://www.netbeans.org/cddl-gplv2.html
   18.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   18.19 + * specific language governing permissions and limitations under the
   18.20 + * License.  When distributing the software, include this License Header
   18.21 + * Notice in each file and include the License file at
   18.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   18.23 + * particular file as subject to the "Classpath" exception as provided
   18.24 + * by Oracle in the GPL Version 2 section of the License file that
   18.25 + * accompanied this code. If applicable, add the following below the
   18.26 + * License Header, with the fields enclosed by brackets [] replaced by
   18.27 + * your own identifying information:
   18.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   18.29 + *
   18.30 + * If you wish your version of this file to be governed by only the CDDL
   18.31 + * or only the GPL Version 2, indicate your decision by adding
   18.32 + * "[Contributor] elects to include this software in this distribution
   18.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   18.34 + * single choice of license, a recipient has the option to distribute
   18.35 + * your version of this file under either the CDDL, the GPL Version 2 or
   18.36 + * to extend the choice of license to its licensees as provided above.
   18.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   18.38 + * Version 2 license, then the option applies only if the new code is
   18.39 + * made subject to such option by the copyright holder.
   18.40 + *
   18.41 + * Contributor(s):
   18.42 + *
   18.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
   18.44 + */
   18.45 +
   18.46 +package org.netbeans.modules.jackpot30.impl.refactoring.findusages;
   18.47 +
   18.48 +import java.util.Collection;
   18.49 +import java.util.LinkedList;
   18.50 +import java.util.List;
   18.51 +import org.netbeans.modules.jackpot30.impl.MessageImpl;
   18.52 +import org.netbeans.modules.jackpot30.impl.batch.BatchSearch;
   18.53 +import org.netbeans.modules.jackpot30.impl.batch.BatchSearch.BatchResult;
   18.54 +import org.netbeans.modules.jackpot30.impl.batch.BatchSearch.Scope;
   18.55 +import org.netbeans.modules.jackpot30.impl.batch.ProgressHandleWrapper;
   18.56 +import org.netbeans.modules.jackpot30.impl.refactoring.AbstractApplyHintsRefactoringPlugin;
   18.57 +import org.netbeans.modules.jackpot30.spi.HintDescription;
   18.58 +import org.netbeans.modules.jackpot30.spi.PatternConvertor;
   18.59 +import org.netbeans.modules.refactoring.api.Problem;
   18.60 +import org.netbeans.modules.refactoring.spi.RefactoringElementsBag;
   18.61 +
   18.62 +/**
   18.63 + *
   18.64 + * @author lahvac
   18.65 + */
   18.66 +public class GlobalFindUsagesRefactoringPlugin extends AbstractApplyHintsRefactoringPlugin {
   18.67 +
   18.68 +    private final GlobalFindUsagesRefactoring refactoring;
   18.69 +
   18.70 +    public GlobalFindUsagesRefactoringPlugin(GlobalFindUsagesRefactoring refactoring) {
   18.71 +        super(refactoring);
   18.72 +        this.refactoring = refactoring;
   18.73 +    }
   18.74 +
   18.75 +    public Problem preCheck() {
   18.76 +        return null;
   18.77 +    }
   18.78 +
   18.79 +    public Problem checkParameters() {
   18.80 +        return null;
   18.81 +    }
   18.82 +
   18.83 +    public Problem fastCheckParameters() {
   18.84 +        return null;
   18.85 +    }
   18.86 +
   18.87 +     public Problem prepare(RefactoringElementsBag refactoringElements) {
   18.88 +        cancel.set(false);
   18.89 +
   18.90 +        Collection<MessageImpl> problems = performSearchForPattern(refactoringElements);
   18.91 +
   18.92 +        return messagesToProblem(problems);
   18.93 +    }
   18.94 +
   18.95 +    private List<MessageImpl> performSearchForPattern(final RefactoringElementsBag refactoringElements) {
   18.96 +        ProgressHandleWrapper w = new ProgressHandleWrapper(this, 50, 50);
   18.97 +        Iterable<? extends HintDescription> hints = PatternConvertor.create(refactoring.script);
   18.98 +        BatchResult candidates = BatchSearch.findOccurrences(hints, Scope.createAllRemote(), w);
   18.99 +        List<MessageImpl> problems = new LinkedList<MessageImpl>(candidates.problems);
  18.100 +
  18.101 +        prepareElements(candidates, w, refactoringElements, true, problems);
  18.102 +
  18.103 +        w.finish();
  18.104 +
  18.105 +        return problems;
  18.106 +     }
  18.107 +    
  18.108 +}
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/refactoring/findusages/GlobalFindUsagesRefactoringUI.java	Sat Mar 05 23:03:17 2011 +0100
    19.3 @@ -0,0 +1,108 @@
    19.4 +/*
    19.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    19.6 + *
    19.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
    19.8 + *
    19.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   19.10 + * Other names may be trademarks of their respective owners.
   19.11 + *
   19.12 + * The contents of this file are subject to the terms of either the GNU
   19.13 + * General Public License Version 2 only ("GPL") or the Common
   19.14 + * Development and Distribution License("CDDL") (collectively, the
   19.15 + * "License"). You may not use this file except in compliance with the
   19.16 + * License. You can obtain a copy of the License at
   19.17 + * http://www.netbeans.org/cddl-gplv2.html
   19.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   19.19 + * specific language governing permissions and limitations under the
   19.20 + * License.  When distributing the software, include this License Header
   19.21 + * Notice in each file and include the License file at
   19.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   19.23 + * particular file as subject to the "Classpath" exception as provided
   19.24 + * by Oracle in the GPL Version 2 section of the License file that
   19.25 + * accompanied this code. If applicable, add the following below the
   19.26 + * License Header, with the fields enclosed by brackets [] replaced by
   19.27 + * your own identifying information:
   19.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   19.29 + *
   19.30 + * If you wish your version of this file to be governed by only the CDDL
   19.31 + * or only the GPL Version 2, indicate your decision by adding
   19.32 + * "[Contributor] elects to include this software in this distribution
   19.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   19.34 + * single choice of license, a recipient has the option to distribute
   19.35 + * your version of this file under either the CDDL, the GPL Version 2 or
   19.36 + * to extend the choice of license to its licensees as provided above.
   19.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   19.38 + * Version 2 license, then the option applies only if the new code is
   19.39 + * made subject to such option by the copyright holder.
   19.40 + *
   19.41 + * Contributor(s):
   19.42 + *
   19.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
   19.44 + */
   19.45 +
   19.46 +package org.netbeans.modules.jackpot30.impl.refactoring.findusages;
   19.47 +
   19.48 +import java.awt.Component;
   19.49 +import javax.swing.JPanel;
   19.50 +import javax.swing.event.ChangeListener;
   19.51 +import org.netbeans.modules.refactoring.api.AbstractRefactoring;
   19.52 +import org.netbeans.modules.refactoring.api.Problem;
   19.53 +import org.netbeans.modules.refactoring.spi.ui.CustomRefactoringPanel;
   19.54 +import org.netbeans.modules.refactoring.spi.ui.RefactoringUI;
   19.55 +import org.openide.util.HelpCtx;
   19.56 +
   19.57 +/**
   19.58 + *
   19.59 + * @author lahvac
   19.60 + */
   19.61 +public class GlobalFindUsagesRefactoringUI implements RefactoringUI {
   19.62 +
   19.63 +    private final GlobalFindUsagesRefactoring globalFindUsagesRefactoring;
   19.64 +
   19.65 +    GlobalFindUsagesRefactoringUI(GlobalFindUsagesRefactoring globalFindUsagesRefactoring) {
   19.66 +        this.globalFindUsagesRefactoring = globalFindUsagesRefactoring;
   19.67 +    }
   19.68 +
   19.69 +    public String getName() {
   19.70 +        return "Global Find Usages";
   19.71 +    }
   19.72 +
   19.73 +    public String getDescription() {
   19.74 +        return "Global Find Usages";
   19.75 +    }
   19.76 +
   19.77 +    public boolean isQuery() {
   19.78 +        return true;
   19.79 +    }
   19.80 +
   19.81 +    public CustomRefactoringPanel getPanel(ChangeListener parent) {
   19.82 +        return new CustomRefactoringPanel() {
   19.83 +            public void initialize() {
   19.84 +            }
   19.85 +            public Component getComponent() {
   19.86 +                return new JPanel();
   19.87 +            }
   19.88 +        };
   19.89 +    }
   19.90 +
   19.91 +    public Problem setParameters() {
   19.92 +        return null;
   19.93 +    }
   19.94 +
   19.95 +    public Problem checkParameters() {
   19.96 +        return null;
   19.97 +    }
   19.98 +
   19.99 +    public boolean hasParameters() {
  19.100 +        return false;
  19.101 +    }
  19.102 +
  19.103 +    public AbstractRefactoring getRefactoring() {
  19.104 +        return globalFindUsagesRefactoring;
  19.105 +    }
  19.106 +
  19.107 +    public HelpCtx getHelpCtx() {
  19.108 +        return null;
  19.109 +    }
  19.110 +
  19.111 +}
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/refactoring/findusages/PatternGenerator.java	Sat Mar 05 23:03:17 2011 +0100
    20.3 @@ -0,0 +1,144 @@
    20.4 +/*
    20.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    20.6 + *
    20.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
    20.8 + *
    20.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   20.10 + * Other names may be trademarks of their respective owners.
   20.11 + *
   20.12 + * The contents of this file are subject to the terms of either the GNU
   20.13 + * General Public License Version 2 only ("GPL") or the Common
   20.14 + * Development and Distribution License("CDDL") (collectively, the
   20.15 + * "License"). You may not use this file except in compliance with the
   20.16 + * License. You can obtain a copy of the License at
   20.17 + * http://www.netbeans.org/cddl-gplv2.html
   20.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   20.19 + * specific language governing permissions and limitations under the
   20.20 + * License.  When distributing the software, include this License Header
   20.21 + * Notice in each file and include the License file at
   20.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   20.23 + * particular file as subject to the "Classpath" exception as provided
   20.24 + * by Oracle in the GPL Version 2 section of the License file that
   20.25 + * accompanied this code. If applicable, add the following below the
   20.26 + * License Header, with the fields enclosed by brackets [] replaced by
   20.27 + * your own identifying information:
   20.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   20.29 + *
   20.30 + * If you wish your version of this file to be governed by only the CDDL
   20.31 + * or only the GPL Version 2, indicate your decision by adding
   20.32 + * "[Contributor] elects to include this software in this distribution
   20.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   20.34 + * single choice of license, a recipient has the option to distribute
   20.35 + * your version of this file under either the CDDL, the GPL Version 2 or
   20.36 + * to extend the choice of license to its licensees as provided above.
   20.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   20.38 + * Version 2 license, then the option applies only if the new code is
   20.39 + * made subject to such option by the copyright holder.
   20.40 + *
   20.41 + * Contributor(s):
   20.42 + *
   20.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
   20.44 + */
   20.45 +
   20.46 +package org.netbeans.modules.jackpot30.impl.refactoring.findusages;
   20.47 +
   20.48 +import javax.lang.model.element.Element;
   20.49 +import javax.lang.model.element.ExecutableElement;
   20.50 +import javax.lang.model.element.Modifier;
   20.51 +import javax.lang.model.element.TypeElement;
   20.52 +import javax.lang.model.element.VariableElement;
   20.53 +import org.netbeans.api.java.source.CompilationInfo;
   20.54 +
   20.55 +/**
   20.56 + *
   20.57 + * @author lahvac
   20.58 + */
   20.59 +public class PatternGenerator {
   20.60 +
   20.61 +    public static String generateFindUsagesScript(CompilationInfo info, Element usagesOf) {
   20.62 +        switch (usagesOf.getKind()) {
   20.63 +            case METHOD: return generateMethodFindUsagesScript(info, (ExecutableElement) usagesOf);
   20.64 +            case ENUM_CONSTANT:
   20.65 +            case FIELD: return generateFieldFindUsagesScript(info, (VariableElement) usagesOf);
   20.66 +            case ANNOTATION_TYPE:
   20.67 +            case CLASS:
   20.68 +            case ENUM:
   20.69 +            case INTERFACE: return generateClassFindUsagesScript(info, (TypeElement) usagesOf);
   20.70 +            default: throw new IllegalStateException();
   20.71 +        }
   20.72 +    }
   20.73 +
   20.74 +    private static String generateMethodFindUsagesScript(CompilationInfo info, ExecutableElement usagesOf) {
   20.75 +        StringBuilder script = new StringBuilder();
   20.76 +        StringBuilder parameters = new StringBuilder();
   20.77 +        StringBuilder constraints = new StringBuilder();
   20.78 +        String enclosingType = info.getTypes().erasure(usagesOf.getEnclosingElement().asType()).toString();
   20.79 +        int count = 1;
   20.80 +
   20.81 +        if (usagesOf.getModifiers().contains(Modifier.STATIC)) {
   20.82 +            script.append(enclosingType);
   20.83 +        } else {
   20.84 +            script.append("$this");
   20.85 +            constraints.append("$this instanceof ").append(enclosingType);
   20.86 +        }
   20.87 +
   20.88 +        script.append(".").append(usagesOf.getSimpleName()).append("(");
   20.89 +
   20.90 +        for (VariableElement p : usagesOf.getParameters()) {
   20.91 +            if (count > 1) {
   20.92 +                parameters.append(", ");
   20.93 +            }
   20.94 +
   20.95 +            if (constraints.length() > 0) {
   20.96 +                constraints.append(" && ");
   20.97 +            }
   20.98 +            parameters.append("$").append(count);
   20.99 +            constraints.append("$").append(count).append(" instanceof ").append(info.getTypes().erasure(p.asType()));
  20.100 +            count++;
  20.101 +        }
  20.102 +
  20.103 +        script.append(parameters).append(")");
  20.104 +
  20.105 +        if (constraints.length() > 0) {
  20.106 +            script.append(" :: ").append(constraints);
  20.107 +        }
  20.108 +
  20.109 +        script.append(";;");
  20.110 +
  20.111 +        return script.toString();
  20.112 +    }
  20.113 +
  20.114 +    private static String generateFieldFindUsagesScript(CompilationInfo info, VariableElement usagesOf) {
  20.115 +        StringBuilder script = new StringBuilder();
  20.116 +        StringBuilder constraints = new StringBuilder();
  20.117 +        String enclosingType = info.getTypes().erasure(usagesOf.getEnclosingElement().asType()).toString();
  20.118 +        int count = 1;
  20.119 +
  20.120 +        if (usagesOf.getModifiers().contains(Modifier.STATIC)) {
  20.121 +            script.append(enclosingType);
  20.122 +        } else {
  20.123 +            script.append("$this");
  20.124 +            constraints.append("$this instanceof ").append(enclosingType);
  20.125 +        }
  20.126 +
  20.127 +        script.append(".").append(usagesOf.getSimpleName());
  20.128 +
  20.129 +        if (constraints.length() > 0) {
  20.130 +            script.append(" :: ").append(constraints);
  20.131 +        }
  20.132 +
  20.133 +        script.append(";;");
  20.134 +
  20.135 +        return script.toString();
  20.136 +    }
  20.137 +
  20.138 +    private static String generateClassFindUsagesScript(CompilationInfo info, TypeElement usagesOf) {
  20.139 +        StringBuilder script = new StringBuilder();
  20.140 +
  20.141 +        script.append(usagesOf.getQualifiedName());
  20.142 +        script.append(";;");
  20.143 +
  20.144 +        return script.toString();
  20.145 +    }
  20.146 +
  20.147 +}
    21.1 --- a/api/src/org/netbeans/modules/jackpot30/spi/HintDescription.java	Fri Feb 25 19:39:47 2011 +0100
    21.2 +++ b/api/src/org/netbeans/modules/jackpot30/spi/HintDescription.java	Sat Mar 05 23:03:17 2011 +0100
    21.3 @@ -46,6 +46,7 @@
    21.4  import java.util.HashSet;
    21.5  import java.util.Map;
    21.6  import java.util.Set;
    21.7 +import org.netbeans.api.annotations.common.CheckForNull;
    21.8  import org.netbeans.spi.editor.hints.ErrorDescription;
    21.9  import org.openide.util.Parameters;
   21.10  
   21.11 @@ -60,13 +61,15 @@
   21.12      private final PatternDescription triggerPattern;
   21.13      private final Worker worker;
   21.14      private final AdditionalQueryConstraints additionalConstraints;
   21.15 +    private final String hintText;
   21.16  
   21.17 -    private HintDescription(HintMetadata metadata, Kind triggerKind, PatternDescription triggerPattern, Worker worker, AdditionalQueryConstraints additionalConstraints) {
   21.18 +    private HintDescription(HintMetadata metadata, Kind triggerKind, PatternDescription triggerPattern, Worker worker, AdditionalQueryConstraints additionalConstraints, String hintText) {
   21.19          this.metadata = metadata;
   21.20          this.triggerKind = triggerKind;
   21.21          this.triggerPattern = triggerPattern;
   21.22          this.worker = worker;
   21.23          this.additionalConstraints = additionalConstraints;
   21.24 +        this.hintText = hintText;
   21.25      }
   21.26  
   21.27      //XXX: should not be public
   21.28 @@ -96,12 +99,17 @@
   21.29          return additionalConstraints;
   21.30      }
   21.31  
   21.32 -    static HintDescription create(HintMetadata metadata, PatternDescription triggerPattern, Worker worker, AdditionalQueryConstraints additionalConstraints) {
   21.33 -        return new HintDescription(metadata, null, triggerPattern, worker, additionalConstraints);
   21.34 +    //XXX: should not be accessible to public
   21.35 +    public @CheckForNull String getHintText() {
   21.36 +        return hintText;
   21.37      }
   21.38  
   21.39 -    static HintDescription create(HintMetadata metadata, Kind triggerKind, Worker worker, AdditionalQueryConstraints additionalConstraints) {
   21.40 -        return new HintDescription(metadata, triggerKind, null, worker, additionalConstraints);
   21.41 +    static HintDescription create(HintMetadata metadata, PatternDescription triggerPattern, Worker worker, AdditionalQueryConstraints additionalConstraints, String hintText) {
   21.42 +        return new HintDescription(metadata, null, triggerPattern, worker, additionalConstraints, hintText);
   21.43 +    }
   21.44 +
   21.45 +    static HintDescription create(HintMetadata metadata, Kind triggerKind, Worker worker, AdditionalQueryConstraints additionalConstraints, String hintText) {
   21.46 +        return new HintDescription(metadata, triggerKind, null, worker, additionalConstraints, hintText);
   21.47      }
   21.48  
   21.49      @Override
    22.1 --- a/api/src/org/netbeans/modules/jackpot30/spi/HintDescriptionFactory.java	Fri Feb 25 19:39:47 2011 +0100
    22.2 +++ b/api/src/org/netbeans/modules/jackpot30/spi/HintDescriptionFactory.java	Sat Mar 05 23:03:17 2011 +0100
    22.3 @@ -41,8 +41,7 @@
    22.4  
    22.5  import com.sun.source.tree.Tree.Kind;
    22.6  import java.util.Collections;
    22.7 -import java.util.LinkedList;
    22.8 -import java.util.List;
    22.9 +import org.netbeans.api.annotations.common.NonNull;
   22.10  import org.netbeans.modules.jackpot30.spi.HintDescription.AdditionalQueryConstraints;
   22.11  import org.netbeans.modules.jackpot30.spi.HintDescription.PatternDescription;
   22.12  import org.netbeans.modules.jackpot30.spi.HintDescription.Worker;
   22.13 @@ -59,6 +58,7 @@
   22.14      private       PatternDescription triggerPattern;
   22.15      private       Worker worker;
   22.16      private       AdditionalQueryConstraints additionalConstraints;
   22.17 +    private       String hintText;
   22.18      private       boolean finished;
   22.19  
   22.20      private HintDescriptionFactory() {
   22.21 @@ -101,6 +101,11 @@
   22.22          return this;
   22.23      }
   22.24  
   22.25 +    public HintDescriptionFactory setHintText(@NonNull String hintText) {
   22.26 +        this.hintText = hintText;
   22.27 +        return this;
   22.28 +    }
   22.29 +
   22.30      public HintDescription produce() {
   22.31          if (metadata == null) {
   22.32              metadata = new HintMetadata("no-id", "", "", "", true, HintMetadata.Kind.HINT_NON_GUI, HintSeverity.WARNING, null, Collections.<String>emptyList());
   22.33 @@ -109,9 +114,9 @@
   22.34              this.additionalConstraints = AdditionalQueryConstraints.empty();
   22.35          }
   22.36          if (this.triggerKind == null) {
   22.37 -            return HintDescription.create(metadata, triggerPattern, worker, additionalConstraints);
   22.38 +            return HintDescription.create(metadata, triggerPattern, worker, additionalConstraints, hintText);
   22.39          } else {
   22.40 -            return HintDescription.create(metadata, triggerKind, worker, additionalConstraints);
   22.41 +            return HintDescription.create(metadata, triggerKind, worker, additionalConstraints, hintText);
   22.42          }
   22.43      }
   22.44      
    23.1 --- a/api/test/unit/src/org/netbeans/modules/jackpot30/impl/batch/BatchSearchTest.java	Fri Feb 25 19:39:47 2011 +0100
    23.2 +++ b/api/test/unit/src/org/netbeans/modules/jackpot30/impl/batch/BatchSearchTest.java	Sat Mar 05 23:03:17 2011 +0100
    23.3 @@ -74,10 +74,10 @@
    23.4  import org.netbeans.junit.NbTestSuite;
    23.5  import org.netbeans.modules.jackpot30.impl.MessageImpl;
    23.6  import org.netbeans.modules.jackpot30.impl.batch.BatchSearch.BatchResult;
    23.7 -import org.netbeans.modules.jackpot30.impl.batch.BatchSearch.Container;
    23.8  import org.netbeans.modules.jackpot30.impl.batch.BatchSearch.Resource;
    23.9  import org.netbeans.modules.jackpot30.impl.batch.BatchSearch.Scope;
   23.10  import org.netbeans.modules.jackpot30.impl.indexing.IndexingTestUtils.File;
   23.11 +import org.netbeans.modules.jackpot30.impl.indexing.RemoteIndex;
   23.12  import org.netbeans.modules.jackpot30.spi.HintDescription;
   23.13  import org.netbeans.modules.jackpot30.spi.PatternConvertor;
   23.14  import org.netbeans.modules.parsing.impl.indexing.CacheFolder;
   23.15 @@ -139,14 +139,14 @@
   23.16          BatchResult result = BatchSearch.findOccurrences(hints, Scope.createAllOpenedProjectsScope());
   23.17          Map<String, Iterable<String>> output = new HashMap<String, Iterable<String>>();
   23.18  
   23.19 -        for (Entry<? extends Container, ? extends Iterable<? extends Resource>> e : result.projectId2Resources.entrySet()) {
   23.20 +        for (Entry<FileObject, Collection<? extends Resource>> e : result.getResourcesWithRoots().entrySet()) {
   23.21              Collection<String> resourcesRepr = new LinkedList<String>();
   23.22  
   23.23              for (Resource r : e.getValue()) {
   23.24                  resourcesRepr.add(r.getRelativePath());
   23.25              }
   23.26  
   23.27 -            output.put(e.getKey().toDebugString(), resourcesRepr);
   23.28 +            output.put(e.getKey().getURL().toExternalForm(), resourcesRepr);
   23.29          }
   23.30  
   23.31          Map<String, Iterable<String>> golden = new HashMap<String, Iterable<String>>();
   23.32 @@ -172,8 +172,8 @@
   23.33          Iterable<? extends HintDescription> hints = PatternConvertor.create("$0.getFileObject($1)");
   23.34          BatchResult result = BatchSearch.findOccurrences(hints, Scope.createAllOpenedProjectsScope());
   23.35  
   23.36 -        assertEquals(1, result.projectId2Resources.size());
   23.37 -        Iterator<? extends Resource> resources = result.projectId2Resources.values().iterator().next().iterator();
   23.38 +        assertEquals(1, result.getResources().size());
   23.39 +        Iterator<? extends Resource> resources = result.getResources().iterator().next().iterator();
   23.40          Resource r = resources.next();
   23.41  
   23.42          assertFalse(resources.hasNext());
   23.43 @@ -200,14 +200,14 @@
   23.44          BatchResult result = BatchSearch.findOccurrences(hints, Scope.createGivenSourceRoots(src1, src3, empty));
   23.45          Map<String, Iterable<String>> output = new HashMap<String, Iterable<String>>();
   23.46  
   23.47 -        for (Entry<? extends Container, ? extends Iterable<? extends Resource>> e : result.projectId2Resources.entrySet()) {
   23.48 +        for (Entry<FileObject, Collection<? extends Resource>> e : result.getResourcesWithRoots().entrySet()) {
   23.49              Collection<String> resourcesRepr = new LinkedList<String>();
   23.50  
   23.51              for (Resource r : e.getValue()) {
   23.52                  resourcesRepr.add(r.getRelativePath());
   23.53              }
   23.54  
   23.55 -            output.put(e.getKey().toDebugString(), resourcesRepr);
   23.56 +            output.put(e.getKey().getURL().toExternalForm(), resourcesRepr);
   23.57          }
   23.58  
   23.59          Map<String, Iterable<String>> golden = new HashMap<String, Iterable<String>>();
   23.60 @@ -244,14 +244,14 @@
   23.61          BatchResult result = BatchSearch.findOccurrences(hints, Scope.createGivenSourceRoots(data));
   23.62          Map<String, Iterable<String>> output = new HashMap<String, Iterable<String>>();
   23.63  
   23.64 -        for (Entry<? extends Container, ? extends Iterable<? extends Resource>> e : result.projectId2Resources.entrySet()) {
   23.65 +        for (Entry<FileObject, Collection<? extends Resource>> e : result.getResourcesWithRoots().entrySet()) {
   23.66              Collection<String> resourcesRepr = new HashSet<String>();
   23.67  
   23.68              for (Resource r : e.getValue()) {
   23.69                  resourcesRepr.add(r.getRelativePath());
   23.70              }
   23.71  
   23.72 -            output.put(e.getKey().toDebugString(), resourcesRepr);
   23.73 +            output.put(e.getKey().getURL().toExternalForm(), resourcesRepr);
   23.74          }
   23.75  
   23.76          Map<String, Iterable<String>> golden = new HashMap<String, Iterable<String>>();
   23.77 @@ -370,6 +370,41 @@
   23.78          assertEquals(golden, output);
   23.79      }
   23.80  
   23.81 +    public void testBatchSearchRemoteAttributedIndex() throws Exception {
   23.82 +        FileObject data = FileUtil.createFolder(workdir, "data");
   23.83 +        Iterable<? extends HintDescription> hints = PatternConvertor.create("$1.isDirectory() :: $1 instanceof java.io.File;;");
   23.84 +        Map<String, Iterable<String>> golden = new HashMap<String, Iterable<String>>();
   23.85 +
   23.86 +        golden.put(data.getURL().toExternalForm(), new HashSet<String>(Arrays.asList("test/Test1.java", "test/Test2.java")));
   23.87 +
   23.88 +        content.clear();
   23.89 +        content.put(new URL("test://test/index/capabilities"), "{ \"methods\": [ \"find\", \"findWithSpans\", \"findSpans\" ], \"attributed\": true }");
   23.90 +        content.put(new URL("test://test/index/find?path=foo&pattern=$1.isDirectory()%20::%20$1%20instanceof%20java.io.File;;%0A"), "test/Test1.java\ntest/Test2.java");
   23.91 +        RemoteIndex.saveIndices(Arrays.asList(RemoteIndex.create(FileUtil.toFile(data).getAbsolutePath(), new URL("test://test/index"), "foo")));
   23.92 +        BatchResult result = BatchSearch.findOccurrences(hints, Scope.createAllRemote());
   23.93 +        Map<String, Iterable<String>> output = toDebugOutput(result);
   23.94 +
   23.95 +        assertEquals(golden, output);
   23.96 +
   23.97 +        //verify that the spans are from the remote side:
   23.98 +        content.put(new URL("test://test/index/findSpans?path=foo&relativePath=test/Test1.java&pattern=$1.isDirectory()%20::%20$1%20instanceof%20java.io.File;;%0A"), "2:5");
   23.99 +        content.put(new URL("test://test/index/findSpans?path=foo&relativePath=test/Test2.java&pattern=$1.isDirectory()%20::%20$1%20instanceof%20java.io.File;;%0A"), "1:3:5:7");
  23.100 +        
  23.101 +        writeFiles(data,
  23.102 +                   new File("test/Test1.java", "0123456789"),
  23.103 +                   new File("test/Test2.java", "0123456789"));
  23.104 +
  23.105 +        Map<String, Map<String, Iterable<String>>> verifiedOutput = verifiedSpans(result, false);
  23.106 +        Map<String, Map<String, Iterable<String>>> verifiedGolden = new HashMap<String, Map<String, Iterable<String>>>();
  23.107 +
  23.108 +        verifiedGolden.put(data.getURL().toExternalForm(), new HashMap<String, Iterable<String>>(){{
  23.109 +            put("test/Test1.java", Arrays.asList("0:2-0:5:warning:Occurrence"));
  23.110 +            put("test/Test2.java", Arrays.asList("0:1-0:3:warning:Occurrence", "0:5-0:7:warning:Occurrence"));
  23.111 +        }});
  23.112 +
  23.113 +        assertEquals(verifiedGolden, verifiedOutput);
  23.114 +    }
  23.115 +
  23.116      public void testEfficientIndexQuery() throws Exception {
  23.117          String orig = System.getProperty(CustomIndexerImpl.class.getName() + "-attributed", "false");
  23.118  
  23.119 @@ -496,14 +531,14 @@
  23.120      private Map<String, Iterable<String>> toDebugOutput(BatchResult result) throws Exception {
  23.121          Map<String, Iterable<String>> output = new HashMap<String, Iterable<String>>();
  23.122  
  23.123 -        for (Entry<? extends Container, ? extends Iterable<? extends Resource>> e : result.projectId2Resources.entrySet()) {
  23.124 +        for (Entry<FileObject, Collection<? extends Resource>> e : result.getResourcesWithRoots().entrySet()) {
  23.125              Collection<String> resourcesRepr = new HashSet<String>();
  23.126  
  23.127              for (Resource r : e.getValue()) {
  23.128                  resourcesRepr.add(r.getRelativePath());
  23.129              }
  23.130  
  23.131 -            output.put(e.getKey().toDebugString(), resourcesRepr);
  23.132 +            output.put(e.getKey().getURL().toExternalForm(), resourcesRepr);
  23.133          }
  23.134  
  23.135          return output;
  23.136 @@ -515,10 +550,10 @@
  23.137          BatchSearch.getVerifiedSpans(candidates, new ProgressHandleWrapper(1), new BatchSearch.VerifiedSpansCallBack() {
  23.138              public void groupStarted() {}
  23.139              public boolean spansVerified(CompilationController wc, Resource r, Collection<? extends ErrorDescription> hints) throws Exception {
  23.140 -                Map<String, Iterable<String>> files = result.get(r.getContainer().toDebugString());
  23.141 +                Map<String, Iterable<String>> files = result.get(r.getRoot().getURL().toExternalForm());
  23.142  
  23.143                  if (files == null) {
  23.144 -                    result.put(r.getContainer().toDebugString(), files = new HashMap<String, Iterable<String>>());
  23.145 +                    result.put(r.getRoot().getURL().toExternalForm(), files = new HashMap<String, Iterable<String>>());
  23.146                  }
  23.147  
  23.148                  Collection<String> currentHints = new LinkedList<String>();
    24.1 --- a/api/test/unit/src/org/netbeans/modules/jackpot30/impl/indexing/IndexTest.java	Fri Feb 25 19:39:47 2011 +0100
    24.2 +++ b/api/test/unit/src/org/netbeans/modules/jackpot30/impl/indexing/IndexTest.java	Sat Mar 05 23:03:17 2011 +0100
    24.3 @@ -178,6 +178,15 @@
    24.4          verifyIndexWithFrequencies(patterns, golden);
    24.5      }
    24.6  
    24.7 +    public void testInnerClass() throws Exception {
    24.8 +        Index index = FileBasedIndex.get(src.getURL());
    24.9 +        indexFiles(src.getURL().toURI(),
   24.10 +                   index,
   24.11 +                   new File("test/Test1.java", "package test; public class Test1 { private static final class O implements Iterable<String> { private String next; private String computeNext() { return null; } public String hasNext() { next = computeNext(); return next != null; } } }", true));
   24.12 +
   24.13 +        verifyIndex("$this.computeNext()", new AdditionalQueryConstraints(Collections.singleton("test.Test1.O")), "test/Test1.java");
   24.14 +    }
   24.15 +
   24.16      private void verifyIndex(final String[] patterns, String... containedIn) throws Exception {
   24.17          ClassPath EMPTY = ClassPathSupport.createClassPath(new FileObject[0]);
   24.18          ClasspathInfo cpInfo = ClasspathInfo.create(ClassPathSupport.createClassPath(SourceUtilsTestUtil.getBootClassPath().toArray(new URL[0])),
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/api/test/unit/src/org/netbeans/modules/jackpot30/impl/refactoring/findusages/PatternGeneratorTest.java	Sat Mar 05 23:03:17 2011 +0100
    25.3 @@ -0,0 +1,143 @@
    25.4 +/*
    25.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    25.6 + *
    25.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
    25.8 + *
    25.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   25.10 + * Other names may be trademarks of their respective owners.
   25.11 + *
   25.12 + * The contents of this file are subject to the terms of either the GNU
   25.13 + * General Public License Version 2 only ("GPL") or the Common
   25.14 + * Development and Distribution License("CDDL") (collectively, the
   25.15 + * "License"). You may not use this file except in compliance with the
   25.16 + * License. You can obtain a copy of the License at
   25.17 + * http://www.netbeans.org/cddl-gplv2.html
   25.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   25.19 + * specific language governing permissions and limitations under the
   25.20 + * License.  When distributing the software, include this License Header
   25.21 + * Notice in each file and include the License file at
   25.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   25.23 + * particular file as subject to the "Classpath" exception as provided
   25.24 + * by Oracle in the GPL Version 2 section of the License file that
   25.25 + * accompanied this code. If applicable, add the following below the
   25.26 + * License Header, with the fields enclosed by brackets [] replaced by
   25.27 + * your own identifying information:
   25.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   25.29 + *
   25.30 + * If you wish your version of this file to be governed by only the CDDL
   25.31 + * or only the GPL Version 2, indicate your decision by adding
   25.32 + * "[Contributor] elects to include this software in this distribution
   25.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   25.34 + * single choice of license, a recipient has the option to distribute
   25.35 + * your version of this file under either the CDDL, the GPL Version 2 or
   25.36 + * to extend the choice of license to its licensees as provided above.
   25.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   25.38 + * Version 2 license, then the option applies only if the new code is
   25.39 + * made subject to such option by the copyright holder.
   25.40 + *
   25.41 + * Contributor(s):
   25.42 + *
   25.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
   25.44 + */
   25.45 +
   25.46 +package org.netbeans.modules.jackpot30.impl.refactoring.findusages;
   25.47 +
   25.48 +import com.sun.source.tree.Tree.Kind;
   25.49 +import com.sun.source.util.TreePath;
   25.50 +import java.util.HashMap;
   25.51 +import java.util.List;
   25.52 +import java.util.Map;
   25.53 +import java.util.concurrent.atomic.AtomicBoolean;
   25.54 +import org.netbeans.api.java.source.CompilationInfo;
   25.55 +import org.netbeans.modules.jackpot30.impl.RulesManager;
   25.56 +import org.netbeans.modules.jackpot30.impl.hints.HintsInvoker;
   25.57 +import org.netbeans.modules.jackpot30.spi.HintDescription;
   25.58 +import org.netbeans.modules.jackpot30.spi.HintDescription.PatternDescription;
   25.59 +import org.netbeans.modules.jackpot30.spi.PatternConvertor;
   25.60 +import org.netbeans.modules.java.hints.infrastructure.TreeRuleTestBase;
   25.61 +import org.netbeans.spi.editor.hints.ErrorDescription;
   25.62 +
   25.63 +/**
   25.64 + *
   25.65 + * @author lahvac
   25.66 + */
   25.67 +public class PatternGeneratorTest extends TreeRuleTestBase {
   25.68 +
   25.69 +    public PatternGeneratorTest(String name) {
   25.70 +        super(name);
   25.71 +    }
   25.72 +
   25.73 +    public void testStaticMethod() throws Exception {
   25.74 +        performTest("package test;\n" +
   25.75 +                    "public class Test {\n" +
   25.76 +                    "    public static void te|st(int i, String s) {\n" +
   25.77 +                    "        test(i, s);\n" +
   25.78 +                    "    }\n" +
   25.79 +                    "}\n",
   25.80 +                    "3:8-3:12:verifier:TODO: No display name");
   25.81 +    }
   25.82 +
   25.83 +    public void testInstanceMethod() throws Exception {
   25.84 +        performTest("package test;\n" +
   25.85 +                    "public class Test {\n" +
   25.86 +                    "    public void te|st(int i, String s) {\n" +
   25.87 +                    "        new Test().test(i, s);\n" +
   25.88 +                    "        test(i, s);\n" +
   25.89 +                    "    }\n" +
   25.90 +                    "}\n",
   25.91 +                    "3:19-3:23:verifier:TODO: No display name",
   25.92 +                    "4:8-4:12:verifier:TODO: No display name");
   25.93 +    }
   25.94 +
   25.95 +    public void testStaticField() throws Exception {
   25.96 +        performTest("package test;\n" +
   25.97 +                    "public class Test {\n" +
   25.98 +                    "    public static int I|I = 0;" +
   25.99 +                    "    public int test() {\n" +
  25.100 +                    "        return II;\n" +
  25.101 +                    "    }\n" +
  25.102 +                    "}\n",
  25.103 +                    "3:15-3:17:verifier:TODO: No display name");
  25.104 +    }
  25.105 +
  25.106 +    public void testInstanceField() throws Exception {
  25.107 +        performTest("package test;\n" +
  25.108 +                    "public class Test {\n" +
  25.109 +                    "    public int I|I = 0;" +
  25.110 +                    "    public int test() {\n" +
  25.111 +                    "        if (true) return II; else return new Test().II;\n" +
  25.112 +                    "    }\n" +
  25.113 +                    "}\n",
  25.114 +                    "3:25-3:27:verifier:TODO: No display name",
  25.115 +                    "3:52-3:54:verifier:TODO: No display name");
  25.116 +    }
  25.117 +
  25.118 +    private void performTest(String code, String... golden) throws Exception {
  25.119 +        performAnalysisTest("test/Test.java",
  25.120 +                            code,
  25.121 +                            golden);
  25.122 +    }
  25.123 +
  25.124 +    @Override
  25.125 +    protected List<ErrorDescription> computeErrors(CompilationInfo info, TreePath path) {
  25.126 +        String script = PatternGenerator.generateFindUsagesScript(info, info.getTrees().getElement(path));
  25.127 +        Map<Kind, List<HintDescription>> kind2Hints = new HashMap<Kind, List<HintDescription>>();
  25.128 +        Map<PatternDescription, List<HintDescription>> pattern2Hint = new HashMap<PatternDescription, List<HintDescription>>();
  25.129 +        RulesManager.sortOut(PatternConvertor.create(script), kind2Hints, pattern2Hint);
  25.130 +
  25.131 +        return new HintsInvoker(info, new AtomicBoolean()).computeHints(info, kind2Hints, pattern2Hint);
  25.132 +    }
  25.133 +
  25.134 +    @Override
  25.135 +    public void testIssue105979() throws Exception {}
  25.136 +
  25.137 +    @Override
  25.138 +    public void testIssue108246() throws Exception {}
  25.139 +
  25.140 +    @Override
  25.141 +    public void testIssue113933() throws Exception {}
  25.142 +
  25.143 +    @Override
  25.144 +    public void testNoHintsForSimpleInitialize() throws Exception {}
  25.145 +
  25.146 +}
    26.1 --- a/file/src/org/netbeans/modules/jackpot30/file/DeclarativeHintRegistry.java	Fri Feb 25 19:39:47 2011 +0100
    26.2 +++ b/file/src/org/netbeans/modules/jackpot30/file/DeclarativeHintRegistry.java	Sat Mar 05 23:03:17 2011 +0100
    26.3 @@ -258,8 +258,9 @@
    26.4              }
    26.5  
    26.6              String imports = parsed.importsBlock != null ? spec.substring(parsed.importsBlock[0], parsed.importsBlock[1]) : "";
    26.7 +            String[] importsArray = parsed.importsBlock != null ? new String[] {spec.substring(parsed.importsBlock[0], parsed.importsBlock[1])} : new String[0];
    26.8  
    26.9 -            f = f.setTriggerPattern(PatternDescription.create(spec.substring(hint.textStart, hint.textEnd), constraints, imports));
   26.10 +            f = f.setTriggerPattern(PatternDescription.create(spec.substring(hint.textStart, hint.textEnd), constraints, importsArray));
   26.11  
   26.12              List<DeclarativeFix> fixes = new LinkedList<DeclarativeFix>();
   26.13  
   26.14 @@ -301,6 +302,7 @@
   26.15              f = f.setWorker(new DeclarativeHintsWorker(displayName, hint.conditions, imports, fixes, options, primarySuppressWarningsKey));
   26.16              f = f.setMetadata(currentMeta);
   26.17              f = f.setAdditionalConstraints(new AdditionalQueryConstraints(new HashSet<String>(constraints.values())));
   26.18 +            f = f.setHintText(spec.substring(hint.textStart, hint.hintEnd));
   26.19  
   26.20              Collection<HintDescription> hints = result.get(currentMeta);
   26.21  
    27.1 --- a/file/src/org/netbeans/modules/jackpot30/file/DeclarativeHintsParser.java	Fri Feb 25 19:39:47 2011 +0100
    27.2 +++ b/file/src/org/netbeans/modules/jackpot30/file/DeclarativeHintsParser.java	Sat Mar 05 23:03:17 2011 +0100
    27.3 @@ -254,7 +254,7 @@
    27.4              targets.add(new FixTextDescription(fixDisplayName, span, fixConditions, fixConditionSpans, fixOptions));
    27.5          }
    27.6  
    27.7 -        hints.add(new HintTextDescription(displayName, patternStart, patternEnd, conditions, conditionsSpans, targets, ruleOptions));
    27.8 +        hints.add(new HintTextDescription(displayName, patternStart, patternEnd, input.offset() + input.token().length(), conditions, conditionsSpans, targets, ruleOptions));
    27.9      }
   27.10      
   27.11      private void parseConditions(List<Condition> conditions, List<int[]> spans) {
   27.12 @@ -492,15 +492,17 @@
   27.13          public final String displayName;
   27.14          public final int textStart;
   27.15          public final int textEnd;
   27.16 +        public final int hintEnd;
   27.17          public final List<Condition> conditions;
   27.18          public final List<int[]> conditionSpans;
   27.19          public final List<FixTextDescription> fixes;
   27.20          public final Map<String, String> options;
   27.21  
   27.22 -        public HintTextDescription(String displayName, int textStart, int textEnd, List<Condition> conditions, List<int[]> conditionSpans, List<FixTextDescription> fixes, Map<String, String> options) {
   27.23 +        public HintTextDescription(String displayName, int textStart, int textEnd, int hintEnd, List<Condition> conditions, List<int[]> conditionSpans, List<FixTextDescription> fixes, Map<String, String> options) {
   27.24              this.displayName = displayName;
   27.25              this.textStart = textStart;
   27.26              this.textEnd = textEnd;
   27.27 +            this.hintEnd = hintEnd;
   27.28              this.conditions = conditions;
   27.29              this.conditionSpans = conditionSpans;
   27.30              this.fixes = fixes;
    28.1 --- a/server/backend/impl/src/org/netbeans/modules/jackpot30/backend/impl/api/API.java	Fri Feb 25 19:39:47 2011 +0100
    28.2 +++ b/server/backend/impl/src/org/netbeans/modules/jackpot30/backend/impl/api/API.java	Sat Mar 05 23:03:17 2011 +0100
    28.3 @@ -132,7 +132,6 @@
    28.4                      result.append(FileUtil.getRelativePath(deepestCommonParent, r.getResolvedFile()));
    28.5                      result.append("\n");
    28.6                  }
    28.7 -                System.err.println("processed file=" + r.getRelativePath());
    28.8                  return true;
    28.9              }
   28.10              @Override public void groupFinished() {}
   28.11 @@ -142,6 +141,44 @@
   28.12          return result.toString();
   28.13      }
   28.14  
   28.15 +    @GET
   28.16 +    @Path("/findWithSpans")
   28.17 +    @Produces("text/plain")
   28.18 +    //TODO: parameter for "verified"?
   28.19 +    public String findWithSpans(@QueryParam("path") String segment, @QueryParam("pattern") String pattern, @QueryParam("asynchronous") @DefaultValue(value="false") boolean asynchronous) throws IOException {
   28.20 +        assert !asynchronous;
   28.21 +
   28.22 +        Iterable<? extends HintDescription> hints = PatternConvertor.create(pattern);
   28.23 +        Set<FileObject> srcRoots = CategoryStorage.getCategoryContent(segment);
   28.24 +        final FileObject deepestCommonParent = deepestCommonParent(srcRoots);
   28.25 +        BatchResult batchResult = BatchSearch.findOccurrences(hints, Scope.createGivenSourceRoots(true, srcRoots.toArray(new FileObject[0])));
   28.26 +        final Map<String, int[][]> result = new HashMap<String, int[][]>();
   28.27 +
   28.28 +        BatchSearch.getVerifiedSpans(batchResult, new ProgressHandleWrapper(1), new BatchSearch.VerifiedSpansCallBack() {
   28.29 +            @Override public void groupStarted() {}
   28.30 +            @Override public boolean spansVerified(CompilationController wc, Resource r, Collection<? extends ErrorDescription> hints) throws Exception {
   28.31 +                if (!hints.isEmpty()) {
   28.32 +                    int[][] spans = new int[hints.size()][];
   28.33 +                    int i = 0;
   28.34 +
   28.35 +                    for (ErrorDescription ed : hints) {
   28.36 +                        spans[i++] = new int[] {
   28.37 +                            ed.getRange().getBegin().getOffset(),
   28.38 +                            ed.getRange().getEnd().getOffset()
   28.39 +                        };
   28.40 +                    }
   28.41 +
   28.42 +                    result.put(FileUtil.getRelativePath(deepestCommonParent, r.getResolvedFile()), spans);
   28.43 +                }
   28.44 +                return true;
   28.45 +            }
   28.46 +            @Override public void groupFinished() {}
   28.47 +            @Override public void cannotVerifySpan(Resource r) { /*TODO: warn user?*/ }
   28.48 +        }, true, new LinkedList<MessageImpl>()); //TODO: show the messages to the user?
   28.49 +
   28.50 +        return Pojson.save(result);
   28.51 +    }
   28.52 +
   28.53  //    @GET
   28.54  //    @Path("/findCategorize")
   28.55  //    @Produces("text/plain")