Indexing in the standalone compiler+associated changes in hudson plugin
authorJan Lahoda <jlahoda@netbeans.org>
Sun, 16 Jan 2011 19:22:56 +0100
changeset 5197c187dccaf45
parent 518 b5c29f249d1f
child 520 cb67f7df8dd1
Indexing in the standalone compiler+associated changes in hudson plugin
api/src/org/netbeans/modules/jackpot30/impl/indexing/Cache.java
cmdline/compiler/antsrc/org/netbeans/modules/jackpot30/compiler/ant/JackpotCompiler.java
cmdline/compiler/build.xml
cmdline/compiler/src/org/netbeans/modules/jackpot30/compiler/IndexingAnnotationProcessor.java
cmdline/compiler/test/unit/src/org/netbeans/modules/jackpot30/compiler/CreateStandaloneCompilerJar.java
cmdline/compiler/test/unit/src/org/netbeans/modules/jackpot30/compiler/CreateStandaloneCompilerJarTest.java
cmdline/compiler/test/unit/src/org/netbeans/modules/jackpot30/compiler/HintsAnnotationProcessingTest.java
cmdline/compiler/test/unit/src/org/netbeans/modules/jackpot30/compiler/HintsAnnotationProcessingTestBase.java
cmdline/compiler/test/unit/src/org/netbeans/modules/jackpot30/compiler/IndexingAnnotationProcessorTest.java
cmdline/lib/test/unit/src/org/netbeans/modules/jackpot30/cmdline/lib/CreateStandaloneJar.java
cmdline/lib/test/unit/src/org/netbeans/modules/jackpot30/cmdline/lib/CreateStandaloneLibJar.java
cmdline/tool/test/unit/src/org/netbeans/modules/jackpot30/cmdline/CreateTool.java
server/hudson/src/main/java/org/netbeans/modules/jackpot30/hudson/BuildWrapperImpl.java
server/hudson/src/main/resources/org/netbeans/modules/jackpot30/hudson/BuildWrapperImpl/config.jelly
     1.1 --- a/api/src/org/netbeans/modules/jackpot30/impl/indexing/Cache.java	Sun Jan 16 19:22:56 2011 +0100
     1.2 +++ b/api/src/org/netbeans/modules/jackpot30/impl/indexing/Cache.java	Sun Jan 16 19:22:56 2011 +0100
     1.3 @@ -94,7 +94,7 @@
     1.4              Logger.getLogger(Cache.class.getName()).log(Level.SEVERE, null, ex);
     1.5          }
     1.6          if (standaloneCacheRoot != null) {
     1.7 -            return getDataFolder(sourceRoot, name);
     1.8 +            return getDataFolder(sourceRoot, name, version);
     1.9          } else {
    1.10              return findCacheRootNB(sourceRoot, version);
    1.11          }
    1.12 @@ -109,6 +109,10 @@
    1.13  
    1.14      public static void setStandaloneCacheRoot(File standaloneCacheRoot) {
    1.15          Cache.standaloneCacheRoot = standaloneCacheRoot;
    1.16 +        segments = null;
    1.17 +        lastSegmentsTimeStamp = -1;
    1.18 +        invertedSegments = null;
    1.19 +        index = 0;
    1.20      }
    1.21  
    1.22  
    1.23 @@ -128,6 +132,9 @@
    1.24          if (lastSegmentsTimeStamp != segmentsFile.lastModified()) {
    1.25              lastSegmentsTimeStamp = segmentsFile.lastModified();
    1.26              segments = null;
    1.27 +            lastSegmentsTimeStamp = -1;
    1.28 +            invertedSegments = null;
    1.29 +            index = 0;
    1.30          }
    1.31  
    1.32          if (segments == null) {
    1.33 @@ -190,7 +197,7 @@
    1.34          }
    1.35      }
    1.36  
    1.37 -    private static synchronized File getDataFolder (final URL root, String name) throws IOException {
    1.38 +    private static synchronized File getDataFolder (final URL root, String name, int version) throws IOException {
    1.39          loadSegments ();
    1.40          final String rootName = root.toExternalForm();
    1.41          String slice = invertedSegments.get (rootName);
    1.42 @@ -204,12 +211,7 @@
    1.43              storeSegments ();
    1.44          }
    1.45          final File folder = standaloneCacheRoot;
    1.46 -        return new File(new File(folder, slice), name);
    1.47 +        return new File(new File(new File(folder, slice), name), Integer.toString(version));
    1.48      }
    1.49  
    1.50 -    private static synchronized File getCacheFolder () {
    1.51 -        return standaloneCacheRoot;
    1.52 -    }
    1.53 -
    1.54 -
    1.55  }
     2.1 --- a/cmdline/compiler/antsrc/org/netbeans/modules/jackpot30/compiler/ant/JackpotCompiler.java	Sun Jan 16 19:22:56 2011 +0100
     2.2 +++ b/cmdline/compiler/antsrc/org/netbeans/modules/jackpot30/compiler/ant/JackpotCompiler.java	Sun Jan 16 19:22:56 2011 +0100
     2.3 @@ -43,13 +43,17 @@
     2.4  import java.net.URL;
     2.5  import java.util.Arrays;
     2.6  import java.util.HashSet;
     2.7 +import java.util.LinkedList;
     2.8 +import java.util.List;
     2.9  import java.util.Set;
    2.10  import org.apache.tools.ant.BuildException;
    2.11 +import org.apache.tools.ant.Project;
    2.12  import org.apache.tools.ant.taskdefs.Javac;
    2.13  import org.apache.tools.ant.taskdefs.compilers.JavacExternal;
    2.14  import org.apache.tools.ant.types.Commandline;
    2.15  import org.apache.tools.ant.types.Commandline.Argument;
    2.16  import org.netbeans.modules.jackpot30.compiler.HintsAnnotationProcessing;
    2.17 +import org.netbeans.modules.jackpot30.compiler.IndexingAnnotationProcessor;
    2.18  import org.openide.util.Exceptions;
    2.19  
    2.20  /**
    2.21 @@ -85,10 +89,13 @@
    2.22          URL jackpotCompiler = HintsAnnotationProcessing.class.getProtectionDomain().getCodeSource().getLocation();
    2.23          String jackpotCompilerPath = jackpotCompiler.getPath();
    2.24          Argument arg = cmd.createArgument(true);
    2.25 -
    2.26 +        List<String> options = new LinkedList<String>();
    2.27          StringBuilder enabledHintsProp = new StringBuilder();
    2.28  
    2.29 -        for (String prop : HintsAnnotationProcessing.OPTIONS) {
    2.30 +        options.addAll(HintsAnnotationProcessing.OPTIONS);
    2.31 +        options.addAll(IndexingAnnotationProcessor.OPTIONS);
    2.32 +
    2.33 +        for (String prop : options) {
    2.34              String val = getProject().getProperty(prop);
    2.35  
    2.36              if (val != null) {
     3.1 --- a/cmdline/compiler/build.xml	Sun Jan 16 19:22:56 2011 +0100
     3.2 +++ b/cmdline/compiler/build.xml	Sun Jan 16 19:22:56 2011 +0100
     3.3 @@ -21,9 +21,9 @@
     3.4          <copy todir="build/antclasses">
     3.5              <fileset dir="antsrc" excludes="${jar-excludes}"/>
     3.6          </copy>
     3.7 -        <property name="ant.library.dir" value="${cluster}/antextra" />
     3.8 -        <mkdir dir="${ant.library.dir}"/>
     3.9 -        <jar jarfile="${ant.library.dir}/${code.name.base.dashes}.jar" compress="false">
    3.10 +        <property name="ant.library.target.dir" value="${cluster}/antextra" />
    3.11 +        <mkdir dir="${ant.library.target.dir}"/>
    3.12 +        <jar jarfile="${ant.library.target.dir}/${code.name.base.dashes}.jar" compress="false">
    3.13              <fileset dir="build/antclasses"/>
    3.14          </jar>
    3.15      </target>
    3.16 @@ -36,7 +36,7 @@
    3.17  
    3.18      <target name="create-standalone-compiler" depends="init,ant">
    3.19          <mkdir dir="${build.classes.dir}/../jackpotc" />
    3.20 -        <copy file="${ant.library.dir}/${code.name.base.dashes}.jar" tofile="${build.classes.dir}/../jackpotc/ant-jackpotc.jar"/>
    3.21 +        <copy file="${ant.library.target.dir}/${code.name.base.dashes}.jar" tofile="${build.classes.dir}/../jackpotc/ant-jackpotc.jar"/>
    3.22          <copy todir="${build.classes.dir}/../jackpotc">
    3.23              <fileset dir="scripts"/>
    3.24          </copy>
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/cmdline/compiler/src/org/netbeans/modules/jackpot30/compiler/IndexingAnnotationProcessor.java	Sun Jan 16 19:22:56 2011 +0100
     4.3 @@ -0,0 +1,205 @@
     4.4 +/*
     4.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     4.6 + *
     4.7 + * Copyright 2009-2011 Sun Microsystems, Inc. All rights reserved.
     4.8 + *
     4.9 + * The contents of this file are subject to the terms of either the GNU
    4.10 + * General Public License Version 2 only ("GPL") or the Common
    4.11 + * Development and Distribution License("CDDL") (collectively, the
    4.12 + * "License"). You may not use this file except in compliance with the
    4.13 + * License. You can obtain a copy of the License at
    4.14 + * http://www.netbeans.org/cddl-gplv2.html
    4.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    4.16 + * specific language governing permissions and limitations under the
    4.17 + * License.  When distributing the software, include this License Header
    4.18 + * Notice in each file and include the License file at
    4.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
    4.20 + * particular file as subject to the "Classpath" exception as provided
    4.21 + * by Sun in the GPL Version 2 section of the License file that
    4.22 + * accompanied this code. If applicable, add the following below the
    4.23 + * License Header, with the fields enclosed by brackets [] replaced by
    4.24 + * your own identifying information:
    4.25 + * "Portions Copyrighted [year] [name of copyright owner]"
    4.26 + *
    4.27 + * If you wish your version of this file to be governed by only the CDDL
    4.28 + * or only the GPL Version 2, indicate your decision by adding
    4.29 + * "[Contributor] elects to include this software in this distribution
    4.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    4.31 + * single choice of license, a recipient has the option to distribute
    4.32 + * your version of this file under either the CDDL, the GPL Version 2 or
    4.33 + * to extend the choice of license to its licensees as provided above.
    4.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    4.35 + * Version 2 license, then the option applies only if the new code is
    4.36 + * made subject to such option by the copyright holder.
    4.37 + *
    4.38 + * Contributor(s):
    4.39 + *
    4.40 + * Portions Copyrighted 2009 Sun Microsystems, Inc.
    4.41 + */
    4.42 +package org.netbeans.modules.jackpot30.compiler;
    4.43 +
    4.44 +import com.sun.source.tree.MemberSelectTree;
    4.45 +import com.sun.source.tree.Tree;
    4.46 +import com.sun.source.tree.Tree.Kind;
    4.47 +import java.io.File;
    4.48 +import java.io.IOException;
    4.49 +import java.net.URL;
    4.50 +import java.util.Arrays;
    4.51 +import java.util.Collections;
    4.52 +import java.util.HashMap;
    4.53 +import java.util.HashSet;
    4.54 +import java.util.Map;
    4.55 +import java.util.Set;
    4.56 +import javax.annotation.processing.ProcessingEnvironment;
    4.57 +import javax.tools.Diagnostic;
    4.58 +import org.netbeans.api.annotations.common.NonNull;
    4.59 +import org.netbeans.api.annotations.common.NullAllowed;
    4.60 +import org.netbeans.api.java.source.ClasspathInfo.PathKind;
    4.61 +import org.netbeans.api.java.source.CompilationInfo;
    4.62 +import org.netbeans.api.java.source.CompilationInfoHack;
    4.63 +import org.netbeans.modules.jackpot30.impl.duplicates.indexing.DuplicatesIndex;
    4.64 +import org.netbeans.modules.jackpot30.impl.indexing.FileBasedIndex;
    4.65 +import org.netbeans.modules.jackpot30.impl.indexing.Index.AttributionWrapper;
    4.66 +import org.netbeans.modules.jackpot30.impl.indexing.Index.IndexWriter;
    4.67 +import org.netbeans.modules.parsing.impl.indexing.CacheFolder;
    4.68 +import org.openide.filesystems.FileObject;
    4.69 +import org.openide.filesystems.FileUtil;
    4.70 +import org.openide.util.Exceptions;
    4.71 +import org.openide.util.lookup.ServiceProvider;
    4.72 +
    4.73 +/**
    4.74 + *
    4.75 + * @author lahvac
    4.76 + */
    4.77 +@ServiceProvider(service=AbstractHintsAnnotationProcessing.class)
    4.78 +public class IndexingAnnotationProcessor extends AbstractHintsAnnotationProcessing {
    4.79 +
    4.80 +    static final String CACHE_ROOT = "jackpot30_cache_root";
    4.81 +    static final String SOURCE_ROOT = "jackpot30_root";
    4.82 +    static final String INDEXED_FILES = "jackpot30_indexed_files";
    4.83 +
    4.84 +    public static final Set<String> OPTIONS = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
    4.85 +            CACHE_ROOT,
    4.86 +            SOURCE_ROOT,
    4.87 +            INDEXED_FILES
    4.88 +    )));
    4.89 +
    4.90 +    private boolean enabled;
    4.91 +    private Map<FileObject, Writers> writers;
    4.92 +
    4.93 +    @Override
    4.94 +    protected boolean initialize(ProcessingEnvironment processingEnv) {
    4.95 +        String cacheRoot = processingEnv.getOptions().get(CACHE_ROOT);
    4.96 +
    4.97 +        if (cacheRoot == null) return false;
    4.98 +
    4.99 +        enabled = true;
   4.100 +
   4.101 +        File cache = new File(cacheRoot);
   4.102 +        cache.mkdirs();
   4.103 +
   4.104 +        cache = FileUtil.normalizeFile(cache);
   4.105 +        FileUtil.refreshFor(cache.getParentFile());
   4.106 +        CacheFolder.setCacheFolder(FileUtil.toFileObject(cache));
   4.107 +
   4.108 +        writers = new HashMap<FileObject, Writers>();
   4.109 +
   4.110 +        return true;
   4.111 +    }
   4.112 +
   4.113 +    @Override
   4.114 +    protected void doProcess(CompilationInfoHack info, ProcessingEnvironment processingEnv, Reporter reporter) {
   4.115 +        try {
   4.116 +            if (!enabled) return;
   4.117 +
   4.118 +            FileObject root;
   4.119 +
   4.120 +            if (processingEnv.getOptions().containsKey(SOURCE_ROOT)) {
   4.121 +                File rootFile = new File(processingEnv.getOptions().get(SOURCE_ROOT));
   4.122 +
   4.123 +                root = FileUtil.toFileObject(FileUtil.normalizeFile(rootFile));
   4.124 +
   4.125 +                if (root == null) {
   4.126 +                    processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Specified root (" + rootFile.getAbsolutePath() + ") does not exist");
   4.127 +                    return;
   4.128 +                }
   4.129 +            } else {
   4.130 +                root = info.getClasspathInfo().getClassPath(PathKind.SOURCE).findOwnerRoot(info.getFileObject());
   4.131 +                
   4.132 +                if (root == null) {
   4.133 +                    //try to find the source path from the package clause:
   4.134 +                    root = info.getFileObject().getParent();
   4.135 +
   4.136 +                    if (info.getCompilationUnit().getPackageName() != null) {
   4.137 +                        Tree t = info.getCompilationUnit().getPackageName();
   4.138 +
   4.139 +                        while (t.getKind() == Kind.MEMBER_SELECT) {
   4.140 +                            root = root.getParent();
   4.141 +                            t = ((MemberSelectTree) t).getExpression();
   4.142 +                        }
   4.143 +
   4.144 +                        root = root.getParent();
   4.145 +                    }
   4.146 +                }
   4.147 +            }
   4.148 +
   4.149 +            Writers w = writers.get(root);
   4.150 +
   4.151 +            if (w == null) {
   4.152 +                writers.put(root, w = new Writers(root.getURL()));
   4.153 +            }
   4.154 +
   4.155 +            w.record(info);
   4.156 +        } catch (IOException ex) {
   4.157 +            Exceptions.printStackTrace(ex);
   4.158 +        }
   4.159 +    }
   4.160 +
   4.161 +    @Override
   4.162 +    protected void finish() {
   4.163 +        if (!enabled) return;
   4.164 +
   4.165 +        for (Writers w : writers.values()) {
   4.166 +            try {
   4.167 +                w.close();
   4.168 +            } catch (IOException ex) {
   4.169 +                Exceptions.printStackTrace(ex);
   4.170 +            }
   4.171 +        }
   4.172 +
   4.173 +        writers = null;
   4.174 +    }
   4.175 +
   4.176 +    @Override
   4.177 +    public Set<String> getSupportedOptions() {
   4.178 +        return OPTIONS;
   4.179 +    }
   4.180 +
   4.181 +    static final class Writers {
   4.182 +        private final @NonNull IndexWriter w;
   4.183 +        private final @NullAllowed DuplicatesIndex.IndexWriter dw;
   4.184 +
   4.185 +        public Writers(URL src) throws IOException {
   4.186 +            w = FileBasedIndex.get(src).openForWriting();
   4.187 +            //duplicates index does not currently work:
   4.188 +//            dw = DuplicatesIndex.get(src).openForWriting();
   4.189 +            dw = null;
   4.190 +        }
   4.191 +
   4.192 +        public void record(CompilationInfo info) throws IOException {
   4.193 +            w.record(info.getFileObject().getURL(), info.getCompilationUnit(), new AttributionWrapper(info));
   4.194 +
   4.195 +            if (dw != null) {
   4.196 +                dw.record(info, info.getFileObject().getURL(), info.getCompilationUnit());
   4.197 +            }
   4.198 +        }
   4.199 +
   4.200 +        public void close() throws IOException {
   4.201 +            w.close();
   4.202 +
   4.203 +            if (dw != null) {
   4.204 +                dw.close();
   4.205 +            }
   4.206 +        }
   4.207 +    }
   4.208 +}
     5.1 --- a/cmdline/compiler/test/unit/src/org/netbeans/modules/jackpot30/compiler/CreateStandaloneCompilerJar.java	Sun Jan 16 19:22:56 2011 +0100
     5.2 +++ b/cmdline/compiler/test/unit/src/org/netbeans/modules/jackpot30/compiler/CreateStandaloneCompilerJar.java	Sun Jan 16 19:22:56 2011 +0100
     5.3 @@ -54,7 +54,7 @@
     5.4  
     5.5      @Override
     5.6      protected Info computeInfo() {
     5.7 -        return new Info().addAdditionalRoots(UtilitiesSPIImpl.class.getName(), "com.sun.tools.javac.Main", HintsAnnotationProcessing.class.getName(), HintsAnnotationProcessingImpl.class.getName())
     5.8 +        return new Info().addAdditionalRoots(UtilitiesSPIImpl.class.getName(), "com.sun.tools.javac.Main", HintsAnnotationProcessing.class.getName(), HintsAnnotationProcessingImpl.class.getName(), IndexingAnnotationProcessor.class.getName())
     5.9                           .addMetaInfRegistrations(new MetaInfRegistration(Utilities.SPI.class, UtilitiesSPIImpl.class))
    5.10                           .addMetaInfRegistrations(new MetaInfRegistration(Processor.class, HintsAnnotationProcessingImpl.class))
    5.11                           .addMetaInfRegistrationToCopy(AbstractHintsAnnotationProcessing.class.getName());
     6.1 --- a/cmdline/compiler/test/unit/src/org/netbeans/modules/jackpot30/compiler/CreateStandaloneCompilerJarTest.java	Sun Jan 16 19:22:56 2011 +0100
     6.2 +++ b/cmdline/compiler/test/unit/src/org/netbeans/modules/jackpot30/compiler/CreateStandaloneCompilerJarTest.java	Sun Jan 16 19:22:56 2011 +0100
     6.3 @@ -40,86 +40,29 @@
     6.4  package org.netbeans.modules.jackpot30.compiler;
     6.5  
     6.6  import java.io.File;
     6.7 -import java.io.IOException;
     6.8 -import java.io.InputStream;
     6.9 -import java.io.OutputStream;
    6.10 -import java.util.Arrays;
    6.11 -import java.util.LinkedList;
    6.12 -import java.util.List;
    6.13  import junit.extensions.TestSetup;
    6.14  import junit.framework.Test;
    6.15 +import org.netbeans.junit.NbTestCase;
    6.16  import org.netbeans.junit.NbTestSuite;
    6.17 -import org.openide.filesystems.FileUtil;
    6.18 -import org.openide.util.Exceptions;
    6.19  
    6.20  /**
    6.21   *
    6.22   * @author lahvac
    6.23   */
    6.24 -public class CreateStandaloneCompilerJarTest extends HintsAnnotationProcessingTest {
    6.25 +public class CreateStandaloneCompilerJarTest extends NbTestCase {
    6.26  
    6.27      public CreateStandaloneCompilerJarTest(String name) {
    6.28          super(name);
    6.29      }
    6.30  
    6.31 -    private static File compiler;
    6.32 -
    6.33 -    @Override
    6.34 -    protected void reallyRunCompiler(File workingDir, String... params) throws IOException, Exception {
    6.35 -        assertNotNull(compiler);
    6.36 -        List<String> ll = new LinkedList<String>();
    6.37 -        ll.add("java");
    6.38 -        ll.add("-Xbootclasspath/p:" + compiler.getAbsolutePath());
    6.39 -        ll.add("com.sun.tools.javac.Main");
    6.40 -        ll.addAll(Arrays.asList(params));
    6.41 -        try {
    6.42 -            Process p = Runtime.getRuntime().exec(ll.toArray(new String[0]), null, workingDir);
    6.43 -
    6.44 -            new CopyStream(p.getInputStream(), System.out).start();
    6.45 -            new CopyStream(p.getErrorStream(), System.err).start();
    6.46 -
    6.47 -            assertEquals(0, p.waitFor());
    6.48 -        } catch (Throwable t) {
    6.49 -            throw new IOException(t);
    6.50 -        }
    6.51 -    }
    6.52 -
    6.53 -    @Override
    6.54 -    public void testCodeAPI() throws Exception {
    6.55 -    }
    6.56 -
    6.57 -    private static final class CopyStream extends Thread {
    6.58 -        private final InputStream ins;
    6.59 -        private final OutputStream out;
    6.60 -
    6.61 -        public CopyStream(InputStream ins, OutputStream out) {
    6.62 -            this.ins = ins;
    6.63 -            this.out = out;
    6.64 -        }
    6.65 -
    6.66 -        @Override
    6.67 -        public void run() {
    6.68 -            try {
    6.69 -                FileUtil.copy(ins, out);
    6.70 -            } catch (IOException ex) {
    6.71 -                Exceptions.printStackTrace(ex);
    6.72 -            } finally {
    6.73 -                try {
    6.74 -                    ins.close();
    6.75 -                } catch (IOException ex) {
    6.76 -                    Exceptions.printStackTrace(ex);
    6.77 -                }
    6.78 -            }
    6.79 -        }
    6.80 -
    6.81 -    }
    6.82 -
    6.83      public static Test suite() {
    6.84          NbTestSuite suite = new NbTestSuite();
    6.85          
    6.86 -        suite.addTestSuite(CreateStandaloneCompilerJarTest.class);
    6.87 +        suite.addTestSuite(HintsAnnotationProcessingTest.class);
    6.88 +        suite.addTestSuite(IndexingAnnotationProcessorTest.class);
    6.89  
    6.90          return new TestSetup(suite) {
    6.91 +            private File compiler;
    6.92              private File hintsList;
    6.93              protected void setUp() throws Exception {
    6.94                  compiler = File.createTempFile("jackpotc", ".jar");
    6.95 @@ -128,6 +71,7 @@
    6.96  //                if (!compiler.canRead()) {
    6.97                      new CreateStandaloneCompilerJar("").createCompiler(compiler, hintsList);
    6.98  //                }
    6.99 +                System.setProperty("test.javacJar", compiler.getAbsolutePath());
   6.100              }
   6.101              protected void tearDown() {
   6.102                  compiler.delete();
     7.1 --- a/cmdline/compiler/test/unit/src/org/netbeans/modules/jackpot30/compiler/HintsAnnotationProcessingTest.java	Sun Jan 16 19:22:56 2011 +0100
     7.2 +++ b/cmdline/compiler/test/unit/src/org/netbeans/modules/jackpot30/compiler/HintsAnnotationProcessingTest.java	Sun Jan 16 19:22:56 2011 +0100
     7.3 @@ -38,21 +38,9 @@
     7.4   */
     7.5  package org.netbeans.modules.jackpot30.compiler;
     7.6  
     7.7 -import com.sun.tools.javac.Main;
     7.8  import java.io.File;
     7.9 -import java.io.FileInputStream;
    7.10 -import java.io.FileOutputStream;
    7.11 -import java.io.IOException;
    7.12 -import java.io.InputStreamReader;
    7.13 -import java.io.OutputStreamWriter;
    7.14 -import java.io.Reader;
    7.15 -import java.io.Writer;
    7.16 -import java.util.Arrays;
    7.17  import java.util.Collections;
    7.18 -import java.util.LinkedList;
    7.19 -import java.util.List;
    7.20  import javax.lang.model.type.TypeMirror;
    7.21 -import org.netbeans.junit.NbTestCase;
    7.22  import org.netbeans.modules.java.hints.jackpot.code.spi.Hint;
    7.23  import org.netbeans.modules.java.hints.jackpot.code.spi.TriggerCompileTime;
    7.24  import org.netbeans.modules.java.hints.jackpot.code.spi.TriggerPattern;
    7.25 @@ -65,7 +53,7 @@
    7.26   *
    7.27   * @author lahvac
    7.28   */
    7.29 -public class HintsAnnotationProcessingTest extends NbTestCase {
    7.30 +public class HintsAnnotationProcessingTest extends HintsAnnotationProcessingTestBase {
    7.31  
    7.32      public HintsAnnotationProcessingTest(String name) {
    7.33          super(name);
    7.34 @@ -250,93 +238,15 @@
    7.35      }
    7.36  
    7.37      private void doRunCompiler(String goldenDiff, String... fileContentAndExtraOptions) throws Exception {
    7.38 -        List<String> fileAndContent = new LinkedList<String>();
    7.39 -        List<String> extraOptions = new LinkedList<String>();
    7.40 -        List<String> fileContentAndExtraOptionsList = Arrays.asList(fileContentAndExtraOptions);
    7.41 -        int nullPos = fileContentAndExtraOptionsList.indexOf(null);
    7.42 +        runCompiler(fileContentAndExtraOptions);
    7.43  
    7.44 -        if (nullPos == (-1)) {
    7.45 -            fileAndContent = fileContentAndExtraOptionsList;
    7.46 -            extraOptions = Collections.emptyList();
    7.47 -        } else {
    7.48 -            fileAndContent = fileContentAndExtraOptionsList.subList(0, nullPos);
    7.49 -            extraOptions = fileContentAndExtraOptionsList.subList(nullPos + 1, fileContentAndExtraOptionsList.size());
    7.50 -        }
    7.51 -
    7.52 -        assertTrue(fileAndContent.size() % 2 == 0);
    7.53 -
    7.54 -        clearWorkDir();
    7.55 -
    7.56 -        for (int cntr = 0; cntr < fileAndContent.size(); cntr += 2) {
    7.57 -            createAndFill(fileAndContent.get(cntr), fileAndContent.get(cntr + 1));
    7.58 -        }
    7.59 -
    7.60 -        File wd = getWorkDir();
    7.61 -        File source = new File(wd, "src/test/Test.java");
    7.62 -
    7.63 -        File sourceOutput = new File(wd, "src-out");
    7.64 -
    7.65 -        sourceOutput.mkdirs();
    7.66 -
    7.67 -        List<String> options = new LinkedList<String>();
    7.68 -        
    7.69 -        options.add(source.getAbsolutePath());
    7.70 -        options.add("-sourcepath");
    7.71 -        options.add(source.getParentFile().getParentFile().getAbsolutePath());
    7.72 -        options.add("-s");
    7.73 -        options.add(sourceOutput.getAbsolutePath());
    7.74 -        options.add("-source");
    7.75 -        options.add("1.5");
    7.76 -        options.add("-Xjcov");
    7.77 -        options.addAll(extraOptions);
    7.78 -
    7.79 -        reallyRunCompiler(wd, options.toArray(new String[0]));
    7.80 -        
    7.81          File diff = new File(sourceOutput, "META-INF/upgrade/upgrade.diff");
    7.82          String diffText = readFully(diff);
    7.83  
    7.84 -        goldenDiff = goldenDiff != null ? goldenDiff.replace("{0}", wd.getAbsolutePath()) : null;
    7.85 +        goldenDiff = goldenDiff != null ? goldenDiff.replace("{0}", workDir.getAbsolutePath()) : null;
    7.86          assertEquals(goldenDiff, diffText);
    7.87      }
    7.88  
    7.89 -    protected void reallyRunCompiler(File workDir, String... params) throws Exception {
    7.90 -        String oldUserDir = System.getProperty("user.dir");
    7.91 -
    7.92 -        System.setProperty("user.dir", workDir.getAbsolutePath());
    7.93 -        
    7.94 -        try {
    7.95 -            assertEquals(0, Main.compile(params));
    7.96 -        } finally {
    7.97 -            System.setProperty("user.dir", oldUserDir);
    7.98 -        }
    7.99 -    }
   7.100 -
   7.101 -    private void createAndFill(String path, String content) throws IOException {
   7.102 -        File wd = getWorkDir();
   7.103 -        File source = new File(wd, path);
   7.104 -
   7.105 -        source.getParentFile().mkdirs();
   7.106 -        
   7.107 -        Writer out = new OutputStreamWriter(new FileOutputStream(source));
   7.108 -
   7.109 -        out.write(content);
   7.110 -
   7.111 -        out.close();
   7.112 -    }
   7.113 -
   7.114 -    private String readFully(File file) throws IOException {
   7.115 -        if (!file.canRead()) return null;
   7.116 -        StringBuilder res = new StringBuilder();
   7.117 -        Reader in = new InputStreamReader(new FileInputStream(file));
   7.118 -        int read;
   7.119 -        
   7.120 -        while ((read = in.read()) != (-1)) {
   7.121 -            res.append((char) read);
   7.122 -        }
   7.123 -
   7.124 -        return res.toString();
   7.125 -    }
   7.126 -
   7.127      @Hint(category="general")
   7.128      @TriggerPattern("$1 == null && null == $1")
   7.129      @TriggerCompileTime //XXX: currently not really used
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/cmdline/compiler/test/unit/src/org/netbeans/modules/jackpot30/compiler/HintsAnnotationProcessingTestBase.java	Sun Jan 16 19:22:56 2011 +0100
     8.3 @@ -0,0 +1,219 @@
     8.4 +/*
     8.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     8.6 + *
     8.7 + * Copyright 2009-2010 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 2009-2010 Sun Microsystems, Inc.
    8.41 + */
    8.42 +package org.netbeans.modules.jackpot30.compiler;
    8.43 +
    8.44 +import com.sun.tools.javac.Main;
    8.45 +import java.io.File;
    8.46 +import java.io.FileInputStream;
    8.47 +import java.io.FileOutputStream;
    8.48 +import java.io.IOException;
    8.49 +import java.io.InputStream;
    8.50 +import java.io.InputStreamReader;
    8.51 +import java.io.OutputStream;
    8.52 +import java.io.OutputStreamWriter;
    8.53 +import java.io.Reader;
    8.54 +import java.io.Writer;
    8.55 +import java.util.Arrays;
    8.56 +import java.util.Collections;
    8.57 +import java.util.LinkedList;
    8.58 +import java.util.List;
    8.59 +import org.netbeans.junit.NbTestCase;
    8.60 +import org.openide.filesystems.FileUtil;
    8.61 +import org.openide.util.Exceptions;
    8.62 +
    8.63 +/**
    8.64 + *
    8.65 + * @author lahvac
    8.66 + */
    8.67 +public class HintsAnnotationProcessingTestBase extends NbTestCase {
    8.68 +
    8.69 +    public HintsAnnotationProcessingTestBase(String name) {
    8.70 +        super(name);
    8.71 +    }
    8.72 +
    8.73 +    protected File workDir;
    8.74 +    protected File src;
    8.75 +    protected File sourceOutput;
    8.76 +
    8.77 +    @Override
    8.78 +    protected void setUp() throws Exception {
    8.79 +        super.setUp();
    8.80 +
    8.81 +        clearWorkDir();
    8.82 +
    8.83 +        workDir = getWorkDir();
    8.84 +        sourceOutput = new File(workDir, "src-out");
    8.85 +        sourceOutput.mkdirs();
    8.86 +        src = new File(workDir, "src");
    8.87 +        src.mkdirs();
    8.88 +    }
    8.89 +
    8.90 +    protected void runCompiler(String... fileContentAndExtraOptions) throws Exception {
    8.91 +        List<String> fileAndContent = new LinkedList<String>();
    8.92 +        List<String> extraOptions = new LinkedList<String>();
    8.93 +        List<String> fileContentAndExtraOptionsList = Arrays.asList(fileContentAndExtraOptions);
    8.94 +        int nullPos = fileContentAndExtraOptionsList.indexOf(null);
    8.95 +
    8.96 +        if (nullPos == (-1)) {
    8.97 +            fileAndContent = fileContentAndExtraOptionsList;
    8.98 +            extraOptions = Collections.emptyList();
    8.99 +        } else {
   8.100 +            fileAndContent = fileContentAndExtraOptionsList.subList(0, nullPos);
   8.101 +            extraOptions = fileContentAndExtraOptionsList.subList(nullPos + 1, fileContentAndExtraOptionsList.size());
   8.102 +        }
   8.103 +
   8.104 +        assertTrue(fileAndContent.size() % 2 == 0);
   8.105 +
   8.106 +        List<String> options = new LinkedList<String>();
   8.107 +
   8.108 +        for (int cntr = 0; cntr < fileAndContent.size(); cntr += 2) {
   8.109 +            String file = createAndFill(fileAndContent.get(cntr), fileAndContent.get(cntr + 1)).getAbsolutePath();
   8.110 +
   8.111 +            if (file.endsWith(".java")) {
   8.112 +                options.add(file);
   8.113 +            }
   8.114 +        }
   8.115 +
   8.116 +        if (!extraOptions.contains("-sourcepath")) {
   8.117 +            options.add("-sourcepath");
   8.118 +            options.add(src.getAbsolutePath());
   8.119 +        }
   8.120 +        
   8.121 +        options.add("-s");
   8.122 +        options.add(sourceOutput.getAbsolutePath());
   8.123 +        options.add("-source");
   8.124 +        options.add("1.5");
   8.125 +        options.add("-Xjcov");
   8.126 +        options.addAll(extraOptions);
   8.127 +
   8.128 +        reallyRunCompiler(workDir, options.toArray(new String[0]));
   8.129 +    }
   8.130 +
   8.131 +    protected void reallyRunCompiler(File workDir, String... params) throws Exception {
   8.132 +        String javacJar = System.getProperty("test.javacJar");
   8.133 +
   8.134 +        if (javacJar == null) {
   8.135 +            String oldUserDir = System.getProperty("user.dir");
   8.136 +
   8.137 +            System.setProperty("user.dir", workDir.getAbsolutePath());
   8.138 +
   8.139 +            try {
   8.140 +                assertEquals(0, Main.compile(params));
   8.141 +            } finally {
   8.142 +                System.setProperty("user.dir", oldUserDir);
   8.143 +            }
   8.144 +        } else {
   8.145 +            File compiler = new File(javacJar);
   8.146 +
   8.147 +            assertTrue(compiler.exists());
   8.148 +
   8.149 +            List<String> ll = new LinkedList<String>();
   8.150 +
   8.151 +            ll.add("java");
   8.152 +            ll.add("-Xbootclasspath/p:" + compiler.getAbsolutePath());
   8.153 +            ll.add("com.sun.tools.javac.Main");
   8.154 +            ll.addAll(Arrays.asList(params));
   8.155 +
   8.156 +            try {
   8.157 +                Process p = Runtime.getRuntime().exec(ll.toArray(new String[0]), null, workDir);
   8.158 +
   8.159 +                new CopyStream(p.getInputStream(), System.out).start();
   8.160 +                new CopyStream(p.getErrorStream(), System.err).start();
   8.161 +
   8.162 +                assertEquals(0, p.waitFor());
   8.163 +            } catch (Throwable t) {
   8.164 +                throw new IOException(t);
   8.165 +            }
   8.166 +        }
   8.167 +    }
   8.168 +
   8.169 +    private static final class CopyStream extends Thread {
   8.170 +        private final InputStream ins;
   8.171 +        private final OutputStream out;
   8.172 +
   8.173 +        public CopyStream(InputStream ins, OutputStream out) {
   8.174 +            this.ins = ins;
   8.175 +            this.out = out;
   8.176 +        }
   8.177 +
   8.178 +        @Override
   8.179 +        public void run() {
   8.180 +            try {
   8.181 +                FileUtil.copy(ins, out);
   8.182 +            } catch (IOException ex) {
   8.183 +                Exceptions.printStackTrace(ex);
   8.184 +            } finally {
   8.185 +                try {
   8.186 +                    ins.close();
   8.187 +                } catch (IOException ex) {
   8.188 +                    Exceptions.printStackTrace(ex);
   8.189 +                }
   8.190 +            }
   8.191 +        }
   8.192 +
   8.193 +    }
   8.194 +
   8.195 +    private File createAndFill(String path, String content) throws IOException {
   8.196 +        File source = new File(workDir, path);
   8.197 +
   8.198 +        source.getParentFile().mkdirs();
   8.199 +        
   8.200 +        Writer out = new OutputStreamWriter(new FileOutputStream(source));
   8.201 +
   8.202 +        out.write(content);
   8.203 +
   8.204 +        out.close();
   8.205 +
   8.206 +        return source;
   8.207 +    }
   8.208 +
   8.209 +    protected static String readFully(File file) throws IOException {
   8.210 +        if (!file.canRead()) return null;
   8.211 +        StringBuilder res = new StringBuilder();
   8.212 +        Reader in = new InputStreamReader(new FileInputStream(file));
   8.213 +        int read;
   8.214 +        
   8.215 +        while ((read = in.read()) != (-1)) {
   8.216 +            res.append((char) read);
   8.217 +        }
   8.218 +
   8.219 +        return res.toString();
   8.220 +    }
   8.221 +
   8.222 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/cmdline/compiler/test/unit/src/org/netbeans/modules/jackpot30/compiler/IndexingAnnotationProcessorTest.java	Sun Jan 16 19:22:56 2011 +0100
     9.3 @@ -0,0 +1,120 @@
     9.4 +/*
     9.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     9.6 + *
     9.7 + * Copyright 2011 Sun Microsystems, Inc. All rights reserved.
     9.8 + *
     9.9 + * The contents of this file are subject to the terms of either the GNU
    9.10 + * General Public License Version 2 only ("GPL") or the Common
    9.11 + * Development and Distribution License("CDDL") (collectively, the
    9.12 + * "License"). You may not use this file except in compliance with the
    9.13 + * License. You can obtain a copy of the License at
    9.14 + * http://www.netbeans.org/cddl-gplv2.html
    9.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    9.16 + * specific language governing permissions and limitations under the
    9.17 + * License.  When distributing the software, include this License Header
    9.18 + * Notice in each file and include the License file at
    9.19 + * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
    9.20 + * particular file as subject to the "Classpath" exception as provided
    9.21 + * by Sun in the GPL Version 2 section of the License file that
    9.22 + * accompanied this code. If applicable, add the following below the
    9.23 + * License Header, with the fields enclosed by brackets [] replaced by
    9.24 + * your own identifying information:
    9.25 + * "Portions Copyrighted [year] [name of copyright owner]"
    9.26 + *
    9.27 + * If you wish your version of this file to be governed by only the CDDL
    9.28 + * or only the GPL Version 2, indicate your decision by adding
    9.29 + * "[Contributor] elects to include this software in this distribution
    9.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    9.31 + * single choice of license, a recipient has the option to distribute
    9.32 + * your version of this file under either the CDDL, the GPL Version 2 or
    9.33 + * to extend the choice of license to its licensees as provided above.
    9.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    9.35 + * Version 2 license, then the option applies only if the new code is
    9.36 + * made subject to such option by the copyright holder.
    9.37 + *
    9.38 + * Contributor(s):
    9.39 + *
    9.40 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
    9.41 + */
    9.42 +package org.netbeans.modules.jackpot30.compiler;
    9.43 +
    9.44 +import java.io.File;
    9.45 +import java.util.Arrays;
    9.46 +import java.util.HashSet;
    9.47 +import java.util.Set;
    9.48 +import org.netbeans.api.java.source.ClasspathInfo;
    9.49 +import org.netbeans.api.java.source.CompilationController;
    9.50 +import org.netbeans.api.java.source.JavaSource;
    9.51 +import org.netbeans.api.java.source.Task;
    9.52 +import org.netbeans.modules.jackpot30.impl.indexing.Cache;
    9.53 +import org.netbeans.modules.jackpot30.impl.indexing.FileBasedIndex;
    9.54 +import org.netbeans.modules.jackpot30.impl.pm.BulkSearch;
    9.55 +import org.netbeans.modules.jackpot30.spi.Hacks;
    9.56 +
    9.57 +/**
    9.58 + *
    9.59 + * @author lahvac
    9.60 + */
    9.61 +public class IndexingAnnotationProcessorTest extends HintsAnnotationProcessingTestBase {
    9.62 +    public IndexingAnnotationProcessorTest(String name) {
    9.63 +        super(name);
    9.64 +    }
    9.65 +
    9.66 +    @Override
    9.67 +    protected void setUp() throws Exception {
    9.68 +        super.setUp();
    9.69 +        cache = new File(workDir, "cache");
    9.70 +        Cache.setStandaloneCacheRoot(cache);
    9.71 +    }
    9.72 +
    9.73 +    private File cache;
    9.74 +
    9.75 +    public void testSimpleIndexing() throws Exception {
    9.76 +        runCompiler("src/test/Test1.java",
    9.77 +                    "package test; public class Test1 { private void test() { java.io.File f = null; f.isDirectory(); } }",
    9.78 +                    "src/test/Test2.java",
    9.79 +                    "package test; public class Test2 { private void test() { new javax.swing.ImageIcon((byte[]) null); } }",
    9.80 +                    null,
    9.81 +                    "-A" + IndexingAnnotationProcessor.CACHE_ROOT + "=" + cache.getAbsolutePath());
    9.82 +
    9.83 +        String[] patterns = new String[]{
    9.84 +            "$1.isDirectory()",
    9.85 +            "new ImageIcon($1)"
    9.86 +        };
    9.87 +
    9.88 +        verifyIndex(patterns, "test/Test1.java", "test/Test2.java");
    9.89 +    }
    9.90 +
    9.91 +    public void testNoSourcePath() throws Exception {
    9.92 +        runCompiler("src/test/Test1.java",
    9.93 +                    "package test; public class Test1 { private void test() { java.io.File f = null; f.isDirectory(); } }",
    9.94 +                    "src/test/Test2.java",
    9.95 +                    "package test; public class Test2 { private void test() { new javax.swing.ImageIcon((byte[]) null); } }",
    9.96 +                    null,
    9.97 +                    "-A" + IndexingAnnotationProcessor.CACHE_ROOT + "=" + cache.getAbsolutePath(),
    9.98 +                    "-sourcepath",
    9.99 +                    "");
   9.100 +
   9.101 +        String[] patterns = new String[]{
   9.102 +            "$1.isDirectory()",
   9.103 +            "new ImageIcon($1)"
   9.104 +        };
   9.105 +
   9.106 +        verifyIndex(patterns, "test/Test1.java", "test/Test2.java");
   9.107 +    }
   9.108 +
   9.109 +    private void verifyIndex(final String[] patterns, String... containedIn) throws Exception {
   9.110 +        ClasspathInfo cpInfo = Hacks.createUniversalCPInfo();
   9.111 +        final Set<String> real = new HashSet<String>();
   9.112 +
   9.113 +        JavaSource.create(cpInfo).runUserActionTask(new Task<CompilationController>() {
   9.114 +            public void run(CompilationController parameter) throws Exception {
   9.115 +                real.addAll(FileBasedIndex.get(src.toURI().toURL()).findCandidates(BulkSearch.getDefault().create(parameter, patterns)));
   9.116 +            }
   9.117 +        }, true);
   9.118 +
   9.119 +        Set<String> golden = new HashSet<String>(Arrays.asList(containedIn));
   9.120 +
   9.121 +        assertEquals(golden, real);
   9.122 +    }
   9.123 +}
    10.1 --- a/cmdline/lib/test/unit/src/org/netbeans/modules/jackpot30/cmdline/lib/CreateStandaloneJar.java	Sun Jan 16 19:22:56 2011 +0100
    10.2 +++ b/cmdline/lib/test/unit/src/org/netbeans/modules/jackpot30/cmdline/lib/CreateStandaloneJar.java	Sun Jan 16 19:22:56 2011 +0100
    10.3 @@ -50,8 +50,11 @@
    10.4  import java.io.UnsupportedEncodingException;
    10.5  import java.io.Writer;
    10.6  import java.net.URL;
    10.7 +import java.util.ArrayList;
    10.8  import java.util.Arrays;
    10.9 +import java.util.Collection;
   10.10  import java.util.Enumeration;
   10.11 +import java.util.HashMap;
   10.12  import java.util.HashSet;
   10.13  import java.util.LinkedHashMap;
   10.14  import java.util.LinkedList;
   10.15 @@ -153,15 +156,15 @@
   10.16                  toProcess.add(classFromCP.getInternalName().replace('/', '.'));
   10.17              }
   10.18  
   10.19 -            out.putNextEntry(new ZipEntry(escapeJavaxLang(fileName)));
   10.20 -            out.write(escapeJavaxLang(bytes));
   10.21 +            out.putNextEntry(new ZipEntry(escapeJavaxLang(info, fileName)));
   10.22 +            out.write(escapeJavaxLang(info, bytes));
   10.23  
   10.24              if (COPY_REGISTRATION.contains(fqn) || info.copyMetaInfRegistration.contains(fqn)) {
   10.25                  String serviceName = "META-INF/services/" + fqn;
   10.26                  Enumeration<URL> resources = this.getClass().getClassLoader().getResources(serviceName);
   10.27  
   10.28                  if (resources.hasMoreElements()) {
   10.29 -                    out.putNextEntry(new ZipEntry(escapeJavaxLang(serviceName)));
   10.30 +                    out.putNextEntry(new ZipEntry(escapeJavaxLang(info, serviceName)));
   10.31  
   10.32                      while (resources.hasMoreElements()) {
   10.33                          URL res = resources.nextElement();
   10.34 @@ -179,7 +182,7 @@
   10.35          }
   10.36  
   10.37          bundlesToCopy.addAll(RESOURCES);
   10.38 -        copyResources(out, bundlesToCopy);
   10.39 +        copyResources(out, info, bundlesToCopy);
   10.40  
   10.41          //generated-layer.xml:
   10.42          Enumeration<URL> resources = this.getClass().getClassLoader().getResources("META-INF/generated-layer.xml");
   10.43 @@ -205,17 +208,32 @@
   10.44              }
   10.45          }
   10.46  
   10.47 -        out.putNextEntry(new ZipEntry(escapeJavaxLang("META-INF/generated-layer.xml")));
   10.48 +        out.putNextEntry(new ZipEntry(escapeJavaxLang(info, "META-INF/generated-layer.xml")));
   10.49          XMLUtil.write(main, out, "UTF-8");
   10.50  
   10.51 -        addMETA_INFRegistration(out, "java.lang.SecurityManager", "org.netbeans.modules.masterfs.filebasedfs.utils.FileChangedManager");
   10.52 -        addMETA_INFRegistration(out, "org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation", StandaloneTools.EmptySourceForBinaryQueryImpl.class.getName(), 0);
   10.53 -        addMETA_INFRegistration(out, Provider.class.getName(), StandaloneTools.PreferencesProvider.class.getName(), 0);
   10.54 -        addMETA_INFRegistration(out, MimeDataProvider.class.getName(), StandaloneTools.StandaloneMimeDataProviderImpl.class.getName());
   10.55 -        addMETA_INFRegistration(out, SPI.class.getName(), StandaloneTools.UtilitiesSPIImpl.class.getName());
   10.56 +        List<MetaInfRegistration> registrations = new ArrayList<MetaInfRegistration>();
   10.57  
   10.58 -        for (MetaInfRegistration r : info.metaInf) {
   10.59 -            addMETA_INFRegistration(out, r.apiClassName, r.implClassName, r.pos);
   10.60 +        registrations.add(new MetaInfRegistration("java.lang.SecurityManager", "org.netbeans.modules.masterfs.filebasedfs.utils.FileChangedManager"));
   10.61 +        registrations.add(new MetaInfRegistration("org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation", StandaloneTools.EmptySourceForBinaryQueryImpl.class.getName(), 0));
   10.62 +        registrations.add(new MetaInfRegistration(Provider.class.getName(), StandaloneTools.PreferencesProvider.class.getName(), 0));
   10.63 +        registrations.add(new MetaInfRegistration(MimeDataProvider.class.getName(), StandaloneTools.StandaloneMimeDataProviderImpl.class.getName()));
   10.64 +        registrations.add(new MetaInfRegistration(SPI.class.getName(), StandaloneTools.UtilitiesSPIImpl.class.getName()));
   10.65 +        registrations.addAll(info.metaInf);
   10.66 +
   10.67 +        Map<String, Collection<MetaInfRegistration>> api2Registrations = new HashMap<String, Collection<MetaInfRegistration>>();
   10.68 +
   10.69 +        for (MetaInfRegistration r : registrations) {
   10.70 +            Collection<MetaInfRegistration> regs = api2Registrations.get(r.apiClassName);
   10.71 +
   10.72 +            if (regs == null) {
   10.73 +                api2Registrations.put(r.apiClassName, regs = new ArrayList<MetaInfRegistration>());
   10.74 +            }
   10.75 +
   10.76 +            regs.add(r);
   10.77 +        }
   10.78 +
   10.79 +        for (Entry<String, Collection<MetaInfRegistration>> e : api2Registrations.entrySet()) {
   10.80 +            addMETA_INFRegistration(out, info, e.getValue());
   10.81          }
   10.82  
   10.83          out.close();
   10.84 @@ -231,6 +249,7 @@
   10.85          private final Set<String> additionalRoots = new HashSet<String>();
   10.86          private final List<MetaInfRegistration> metaInf = new LinkedList<MetaInfRegistration>();
   10.87          private final Set<String> copyMetaInfRegistration = new HashSet<String>();
   10.88 +        private       boolean escapeJavaxLang;
   10.89          public Info() {}
   10.90          public Info addAdditionalRoots(String... fqns) {
   10.91              additionalRoots.addAll(Arrays.asList(fqns));
   10.92 @@ -244,6 +263,10 @@
   10.93              copyMetaInfRegistration.addAll(Arrays.asList(registrationsToCopy));
   10.94              return this;
   10.95          }
   10.96 +        public Info setEscapeJavaxLang() {
   10.97 +            this.escapeJavaxLang = true;
   10.98 +            return this;
   10.99 +        }
  10.100      }
  10.101  
  10.102      public static final class MetaInfRegistration {
  10.103 @@ -267,7 +290,7 @@
  10.104  
  10.105      }
  10.106  
  10.107 -    private void copyResources(JarOutputStream out, Set<String> res) throws IOException {
  10.108 +    private void copyResources(JarOutputStream out, Info info, Set<String> res) throws IOException {
  10.109          for (String resource : res) {
  10.110              URL url = this.getClass().getClassLoader().getResource(resource);
  10.111  
  10.112 @@ -275,7 +298,7 @@
  10.113                  continue;
  10.114              }
  10.115              
  10.116 -            out.putNextEntry(new ZipEntry(escapeJavaxLang(resource)));
  10.117 +            out.putNextEntry(new ZipEntry(escapeJavaxLang(info, resource)));
  10.118              out.write(readFile(url));
  10.119          }
  10.120      }
  10.121 @@ -298,15 +321,17 @@
  10.122          return data.toByteArray();
  10.123      }
  10.124  
  10.125 -    private static void addMETA_INFRegistration(JarOutputStream out, String apiClassName, String implClassName) throws IOException {
  10.126 -        addMETA_INFRegistration(out, apiClassName, implClassName, null);
  10.127 -    }
  10.128 +    private static void addMETA_INFRegistration(JarOutputStream out, Info info, Iterable<MetaInfRegistration> registrations) throws IOException {
  10.129 +        String apiClassName = registrations.iterator().next().apiClassName;
  10.130 +        out.putNextEntry(new ZipEntry(escapeJavaxLang(info, "META-INF/services/" + apiClassName)));
  10.131  
  10.132 -    private static void addMETA_INFRegistration(JarOutputStream out, String apiClassName, String implClassName, Integer pos) throws IOException {
  10.133 -        out.putNextEntry(new ZipEntry(escapeJavaxLang("META-INF/services/" + apiClassName)));
  10.134 -        out.write(implClassName.getBytes("UTF-8"));
  10.135 -        if (pos != null) {
  10.136 -            out.write(("\n#position=" + pos.toString() + "\n").getBytes("UTF-8"));
  10.137 +        for (MetaInfRegistration r : registrations) {
  10.138 +            assert apiClassName.equals(r.apiClassName);
  10.139 +            out.write(r.implClassName.getBytes("UTF-8"));
  10.140 +            out.write("\n".getBytes("UTF-8"));
  10.141 +            if (r.pos != null) {
  10.142 +                out.write(("#position=" + r.pos.toString() + "\n").getBytes("UTF-8"));
  10.143 +            }
  10.144          }
  10.145      }
  10.146  
  10.147 @@ -318,7 +343,9 @@
  10.148      }
  10.149              
  10.150  
  10.151 -   private static byte[] escapeJavaxLang(byte[] source) throws UnsupportedEncodingException {
  10.152 +   private static byte[] escapeJavaxLang(Info info, byte[] source) throws UnsupportedEncodingException {
  10.153 +       if (!info.escapeJavaxLang) return source;
  10.154 +
  10.155         for (Entry<String, String> e  : replaceWhat2With.entrySet()) {
  10.156             byte[] replaceSource = e.getKey().getBytes("UTF-8");
  10.157             byte[] replaceTarget = e.getValue().getBytes("UTF-8");
  10.158 @@ -342,7 +369,9 @@
  10.159         return source;
  10.160      }
  10.161  
  10.162 -    private static String escapeJavaxLang(String fileName) throws UnsupportedEncodingException {
  10.163 +    private static String escapeJavaxLang(Info info, String fileName) throws UnsupportedEncodingException {
  10.164 +       if (!info.escapeJavaxLang) return fileName;
  10.165 +
  10.166          for (Entry<String, String> e : replaceWhat2With.entrySet()) {
  10.167              fileName = fileName.replace(e.getKey(), e.getValue());
  10.168          }
    11.1 --- a/cmdline/lib/test/unit/src/org/netbeans/modules/jackpot30/cmdline/lib/CreateStandaloneLibJar.java	Sun Jan 16 19:22:56 2011 +0100
    11.2 +++ b/cmdline/lib/test/unit/src/org/netbeans/modules/jackpot30/cmdline/lib/CreateStandaloneLibJar.java	Sun Jan 16 19:22:56 2011 +0100
    11.3 @@ -54,7 +54,7 @@
    11.4  
    11.5      @Override
    11.6      protected Info computeInfo() {
    11.7 -        return new Info().addAdditionalRoots(NonNBComputer.class.getName());
    11.8 +        return new Info().addAdditionalRoots(NonNBComputer.class.getName()).setEscapeJavaxLang();
    11.9      }
   11.10  
   11.11  }
    12.1 --- a/cmdline/tool/test/unit/src/org/netbeans/modules/jackpot30/cmdline/CreateTool.java	Sun Jan 16 19:22:56 2011 +0100
    12.2 +++ b/cmdline/tool/test/unit/src/org/netbeans/modules/jackpot30/cmdline/CreateTool.java	Sun Jan 16 19:22:56 2011 +0100
    12.3 @@ -60,7 +60,8 @@
    12.4      protected Info computeInfo() {
    12.5          return new Info().addAdditionalRoots(Utilities.SPIImpl.class.getName(), Main.class.getName(), OpenProjectsTrampolineImpl.class.getName(), J2SEProject.class.getName(), DefaultJavaPlatformProvider.class.getName(), ConvertToDiamondBulkHint.class.getName())
    12.6                           .addMetaInfRegistrations(new MetaInfRegistration(Utilities.SPI.class, Utilities.SPIImpl.class))
    12.7 -                         .addMetaInfRegistrations(new MetaInfRegistration(org.netbeans.modules.project.uiapi.OpenProjectsTrampoline.class, OpenProjectsTrampolineImpl.class));
    12.8 +                         .addMetaInfRegistrations(new MetaInfRegistration(org.netbeans.modules.project.uiapi.OpenProjectsTrampoline.class, OpenProjectsTrampolineImpl.class))
    12.9 +                         .setEscapeJavaxLang();
   12.10      }
   12.11  
   12.12  }
    13.1 --- a/server/hudson/src/main/java/org/netbeans/modules/jackpot30/hudson/BuildWrapperImpl.java	Sun Jan 16 19:22:56 2011 +0100
    13.2 +++ b/server/hudson/src/main/java/org/netbeans/modules/jackpot30/hudson/BuildWrapperImpl.java	Sun Jan 16 19:22:56 2011 +0100
    13.3 @@ -46,6 +46,7 @@
    13.4  import hudson.model.AbstractBuild;
    13.5  import hudson.model.AbstractProject;
    13.6  import hudson.model.BuildListener;
    13.7 +import hudson.model.Descriptor;
    13.8  import hudson.model.Run.RunnerAbortedException;
    13.9  import hudson.remoting.Channel;
   13.10  import hudson.tasks.BuildWrapper;
   13.11 @@ -89,6 +90,7 @@
   13.12      private final boolean classpathBasedHintsEnabled;
   13.13      private final boolean classpathBasedHintFixesEnabled;
   13.14      private final boolean hardcodedHintsEnabled;
   13.15 +    private final boolean indexingEnabled;
   13.16      private final Map<String, Boolean> id2Enabled;
   13.17      private final Map<String, Boolean> id2Apply;
   13.18      
   13.19 @@ -118,13 +120,16 @@
   13.20                  }
   13.21              }
   13.22          }
   13.23 +
   13.24 +        indexingEnabled = json.containsKey("indexingEnabled") && json.getBoolean("indexingEnabled");
   13.25      }
   13.26  
   13.27      @DataBoundConstructor
   13.28 -    public BuildWrapperImpl(boolean classpathBasedHintsEnabled, boolean classpathBasedHintFixesEnabled, boolean hardcodedHintsEnabled, Map<String, Boolean> id2Enabled, Map<String, Boolean> id2Apply) {
   13.29 +    public BuildWrapperImpl(boolean classpathBasedHintsEnabled, boolean classpathBasedHintFixesEnabled, boolean hardcodedHintsEnabled, boolean indexingEnabled, Map<String, Boolean> id2Enabled, Map<String, Boolean> id2Apply) {
   13.30          this.classpathBasedHintsEnabled = classpathBasedHintsEnabled;
   13.31          this.classpathBasedHintFixesEnabled = classpathBasedHintFixesEnabled;
   13.32          this.hardcodedHintsEnabled = hardcodedHintsEnabled;
   13.33 +        this.indexingEnabled = indexingEnabled;
   13.34          this.id2Enabled = id2Enabled;
   13.35          this.id2Apply = id2Apply;
   13.36      }
   13.37 @@ -157,6 +162,10 @@
   13.38          return id2Apply.containsKey(id) ? id2Apply.get(id) == Boolean.TRUE : getDescriptor().isHintApplyEnabledByDefault(id);
   13.39      }
   13.40  
   13.41 +    public boolean isIndexingEnabled() {
   13.42 +        return indexingEnabled;
   13.43 +    }
   13.44 +
   13.45      @Override
   13.46      public DescriptorImpl getDescriptor() {
   13.47          return (DescriptorImpl) super.getDescriptor();
   13.48 @@ -169,7 +178,7 @@
   13.49  
   13.50      @Override
   13.51      public Launcher decorateLauncher(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException, RunnerAbortedException {
   13.52 -        return new LauncherWrapper(launcher);
   13.53 +        return new LauncherWrapper(build, launcher);
   13.54      }
   13.55  
   13.56      private static String dumpToString(Map<String, Boolean> id2Include) {
   13.57 @@ -197,10 +206,12 @@
   13.58  
   13.59      private final class LauncherWrapper extends Launcher {
   13.60  
   13.61 +        private final AbstractBuild build;
   13.62          private final Launcher delegate;
   13.63  
   13.64 -        public LauncherWrapper(Launcher delegate) {
   13.65 +        public LauncherWrapper(AbstractBuild build, Launcher delegate) {
   13.66              super(delegate.getListener(), delegate.getChannel());//XXX???
   13.67 +            this.build = build;
   13.68              this.delegate = delegate;
   13.69          }
   13.70  
   13.71 @@ -223,8 +234,20 @@
   13.72                  args.add("-Djackpot30_apply_hc_hints=" + dumpToString(id2Apply));
   13.73              }
   13.74  
   13.75 +            if (indexingEnabled) {
   13.76 +                args.add("-Djackpot30_cache_root=" + ((IndexingBuilder.DescriptorImpl) Descriptor.find(IndexingBuilder.DescriptorImpl.class.getName())).getCacheDir().getAbsolutePath());
   13.77 +                
   13.78 +                try {
   13.79 +                    args.add("-Djackpot30_root=" + new File(build.getWorkspace().toURI()).getAbsolutePath());
   13.80 +                } catch (InterruptedException ex) {
   13.81 +                    throw new IOException(ex);
   13.82 +                }
   13.83 +            }
   13.84 +
   13.85              args.add("-Dbuild.compiler=org.netbeans.modules.jackpot30.compiler.ant.JackpotCompiler");
   13.86  
   13.87 +            System.err.println("args=" + args);
   13.88 +            
   13.89              boolean[] origMasks = ps.masks();
   13.90              boolean[] mask = new boolean[args.size()];
   13.91  
    14.1 --- a/server/hudson/src/main/resources/org/netbeans/modules/jackpot30/hudson/BuildWrapperImpl/config.jelly	Sun Jan 16 19:22:56 2011 +0100
    14.2 +++ b/server/hudson/src/main/resources/org/netbeans/modules/jackpot30/hudson/BuildWrapperImpl/config.jelly	Sun Jan 16 19:22:56 2011 +0100
    14.3 @@ -63,6 +63,12 @@
    14.4      </table>
    14.5    </f:block>
    14.6  
    14.7 +  <f:block>
    14.8 +    <table>
    14.9 +        <f:checkbox name="indexingEnabled" checked="${instance != null ? instance.isIndexingEnabled() : true}"/>
   14.10 +        <label class="attach-previous">Run Indexing</label>
   14.11 +    </table>
   14.12 +  </f:block>
   14.13  <!--  <j:forEach var="d" items="${descriptor.getHints()}" varStatus="loop">
   14.14    <f:entry description="${descriptor.getHintDescription(d)}">
   14.15      <f:checkbox name="${d}" checked="${instance.isHintEnabled(d)}"/>