Ability to cache the remote indices locally
authorJan Lahoda <jlahoda@netbeans.org>
Mon, 16 Jan 2012 23:09:48 +0100
changeset 7278d768d51c409
parent 726 c32594fdc412
child 728 3f9cab74a535
Ability to cache the remote indices locally
.hgignore
remoting/build-indexing-backend
remoting/ide/api/nbproject/genfiles.properties
remoting/ide/api/nbproject/project.xml
remoting/ide/api/src/org/netbeans/modules/jackpot30/remoting/api/LocalServer.java
remoting/ide/api/src/org/netbeans/modules/jackpot30/remoting/api/RemoteIndex.java
remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/Bundle.properties
remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/IndexPanel.form
remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/IndexPanel.java
remoting/ide/kit/nbproject/genfiles.properties
remoting/ide/kit/nbproject/project.xml
remoting/ide/local/build.xml
remoting/ide/local/manifest.mf
remoting/ide/local/nbproject/build-impl.xml
remoting/ide/local/nbproject/genfiles.properties
remoting/ide/local/nbproject/project.properties
remoting/ide/local/nbproject/project.xml
remoting/ide/local/nbproject/suite.properties
remoting/ide/local/src/org/netbeans/modules/jackpot30/remoting/local/Bundle.properties
remoting/ide/local/src/org/netbeans/modules/jackpot30/remoting/local/LocalServerImpl.java
remoting/ide/nbproject/project.properties
remoting/server/web/base.web.api/src/org/netbeans/modules/jackpot30/backend/base/CategoryStorage.java
remoting/server/web/nbindex.web.api/nbproject/project.properties
remoting/server/web/nbindex.web.api/src/org/netbeans/modules/jackpot30/backend/usages/api/DownloadableIndex.java
     1.1 --- a/.hgignore	Mon Jan 16 18:48:12 2012 +0100
     1.2 +++ b/.hgignore	Mon Jan 16 23:09:48 2012 +0100
     1.3 @@ -24,3 +24,4 @@
     1.4  ^remoting/server/tests/cache$
     1.5  ^remoting/server/tests/results$
     1.6  ^remoting/server/hudson/nb-configuration.xml$
     1.7 +^remoting/ide/local/release$
     1.8 \ No newline at end of file
     2.1 --- a/remoting/build-indexing-backend	Mon Jan 16 18:48:12 2012 +0100
     2.2 +++ b/remoting/build-indexing-backend	Mon Jan 16 23:09:48 2012 +0100
     2.3 @@ -1,6 +1,4 @@
     2.4  #!/bin/bash
     2.5 -(cd ide; ant "$@" clean && ant "$@" nbms && cp -r build/updates ../build) || exit 1
     2.6 -
     2.7  rm -rf build
     2.8  mkdir -p build/indexing-backend
     2.9  (cd server/indexer; ant "$@" clean && ant "$@" build-zip && unzip -d ../../build/indexing-backend dist/indexer.zip) || exit 1
    2.10 @@ -16,3 +14,8 @@
    2.11  (cd build; zip -r indexing-backend-shortened.zip `find indexing-backend -type f | grep -v indexing-backend/indexer/enterprise/ | grep -v indexing-backend/indexer/apisupport/  | grep -v indexing-backend/indexer/cnd/   | grep -v indexing-backend/indexer/dlight/   | grep -v indexing-backend/indexer/harness/   | grep -v indexing-backend/indexer/ide/   | grep -v indexing-backend/indexer/java   | grep -v indexing-backend/indexer/nb/   | grep -v indexing-backend/indexer/platform/   | grep -v indexing-backend/indexer/profiler/   | grep -v indexing-backend/indexer/websvccommon/`) || exit 1
    2.12  
    2.13  (cd server/hudson; mvn -Dmaven.test.skip=true clean package && cp target/*.hpi ../../build) || exit
    2.14 +
    2.15 +mkdir -p ide/local/release/index-server
    2.16 +(cd server/web/web.main; cp -r dist/* ../../../ide/local/release/index-server) || exit 1
    2.17 +(cd ide; ant "$@" clean && ant "$@" nbms && cp -r build/updates ../build) || exit 1
    2.18 +
     3.1 --- a/remoting/ide/api/nbproject/genfiles.properties	Mon Jan 16 18:48:12 2012 +0100
     3.2 +++ b/remoting/ide/api/nbproject/genfiles.properties	Mon Jan 16 23:09:48 2012 +0100
     3.3 @@ -3,6 +3,6 @@
     3.4  build.xml.stylesheet.CRC32=a56c6a5b@1.47
     3.5  # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
     3.6  # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
     3.7 -nbproject/build-impl.xml.data.CRC32=73e27a6d
     3.8 +nbproject/build-impl.xml.data.CRC32=e364f985
     3.9  nbproject/build-impl.xml.script.CRC32=33cac223
    3.10 -nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.45
    3.11 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.49
     4.1 --- a/remoting/ide/api/nbproject/project.xml	Mon Jan 16 18:48:12 2012 +0100
     4.2 +++ b/remoting/ide/api/nbproject/project.xml	Mon Jan 16 23:09:48 2012 +0100
     4.3 @@ -16,6 +16,15 @@
     4.4                      </run-dependency>
     4.5                  </dependency>
     4.6                  <dependency>
     4.7 +                    <code-name-base>org.netbeans.api.progress</code-name-base>
     4.8 +                    <build-prerequisite/>
     4.9 +                    <compile-dependency/>
    4.10 +                    <run-dependency>
    4.11 +                        <release-version>1</release-version>
    4.12 +                        <specification-version>1.27</specification-version>
    4.13 +                    </run-dependency>
    4.14 +                </dependency>
    4.15 +                <dependency>
    4.16                      <code-name-base>org.netbeans.modules.options.api</code-name-base>
    4.17                      <build-prerequisite/>
    4.18                      <compile-dependency/>
    4.19 @@ -41,6 +50,14 @@
    4.20                      </run-dependency>
    4.21                  </dependency>
    4.22                  <dependency>
    4.23 +                    <code-name-base>org.openide.execution</code-name-base>
    4.24 +                    <build-prerequisite/>
    4.25 +                    <compile-dependency/>
    4.26 +                    <run-dependency>
    4.27 +                        <specification-version>1.25</specification-version>
    4.28 +                    </run-dependency>
    4.29 +                </dependency>
    4.30 +                <dependency>
    4.31                      <code-name-base>org.openide.explorer</code-name-base>
    4.32                      <build-prerequisite/>
    4.33                      <compile-dependency/>
    4.34 @@ -57,6 +74,14 @@
    4.35                      </run-dependency>
    4.36                  </dependency>
    4.37                  <dependency>
    4.38 +                    <code-name-base>org.openide.io</code-name-base>
    4.39 +                    <build-prerequisite/>
    4.40 +                    <compile-dependency/>
    4.41 +                    <run-dependency>
    4.42 +                        <specification-version>1.30</specification-version>
    4.43 +                    </run-dependency>
    4.44 +                </dependency>
    4.45 +                <dependency>
    4.46                      <code-name-base>org.openide.loaders</code-name-base>
    4.47                      <build-prerequisite/>
    4.48                      <compile-dependency/>
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/remoting/ide/api/src/org/netbeans/modules/jackpot30/remoting/api/LocalServer.java	Mon Jan 16 23:09:48 2012 +0100
     5.3 @@ -0,0 +1,55 @@
     5.4 +/*
     5.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     5.6 + *
     5.7 + * Copyright 2012 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 2012 Sun Microsystems, Inc.
    5.44 + */
    5.45 +package org.netbeans.modules.jackpot30.remoting.api;
    5.46 +
    5.47 +import java.io.IOException;
    5.48 +
    5.49 +/**
    5.50 + *
    5.51 + * @author lahvac
    5.52 + */
    5.53 +public interface LocalServer {
    5.54 +
    5.55 +    public int startLocalServer();
    5.56 +    public boolean downloadIndex(RemoteIndex idx) throws IOException;
    5.57 +
    5.58 +}
     6.1 --- a/remoting/ide/api/src/org/netbeans/modules/jackpot30/remoting/api/RemoteIndex.java	Mon Jan 16 18:48:12 2012 +0100
     6.2 +++ b/remoting/ide/api/src/org/netbeans/modules/jackpot30/remoting/api/RemoteIndex.java	Mon Jan 16 23:09:48 2012 +0100
     6.3 @@ -42,7 +42,6 @@
     6.4  
     6.5  package org.netbeans.modules.jackpot30.remoting.api;
     6.6  
     6.7 -import java.io.File;
     6.8  import java.net.MalformedURLException;
     6.9  import java.net.URL;
    6.10  import java.util.LinkedList;
    6.11 @@ -52,6 +51,7 @@
    6.12  import org.codeviation.pojson.Pojson;
    6.13  import org.netbeans.modules.jackpot30.remotingapi.options.Utils;
    6.14  import org.openide.util.Exceptions;
    6.15 +import org.openide.util.Lookup;
    6.16  import org.openide.util.NbPreferences;
    6.17  
    6.18  /**
    6.19 @@ -62,26 +62,29 @@
    6.20  
    6.21      public final boolean enabled;
    6.22      private final String folder;
    6.23 +    public final UseLocalCache useLocalCache;
    6.24      public final URL    remote;
    6.25      public final String remoteSegment;
    6.26  
    6.27      public static RemoteIndex create(URL localFolder, URL remote, String remoteSegment) {
    6.28 -        return create(true, localFolder, remote, remoteSegment);
    6.29 +        return create(true, UseLocalCache.NEVER, localFolder, remote, remoteSegment);
    6.30      }
    6.31  
    6.32 -    public static RemoteIndex create(boolean enabled, URL localFolder, URL remote, String remoteSegment) {
    6.33 -        return new RemoteIndex(enabled, localFolder.toExternalForm(), remote, remoteSegment);
    6.34 +    public static RemoteIndex create(boolean enabled, UseLocalCache useLocalCache, URL localFolder, URL remote, String remoteSegment) {
    6.35 +        return new RemoteIndex(enabled, useLocalCache, localFolder.toExternalForm(), remote, remoteSegment);
    6.36      }
    6.37  
    6.38      private RemoteIndex() {//used by Pojson
    6.39          this.enabled = true;
    6.40 +        this.useLocalCache = UseLocalCache.NEVER;
    6.41          this.folder = null;
    6.42          this.remote = null;
    6.43          this.remoteSegment = null;
    6.44      }
    6.45  
    6.46 -    private RemoteIndex(boolean enabled, String folder, URL remote, String remoteSegment) {
    6.47 +    private RemoteIndex(boolean enabled, UseLocalCache useLocalCache, String folder, URL remote, String remoteSegment) {
    6.48          this.enabled = enabled;
    6.49 +        this.useLocalCache = useLocalCache;
    6.50          this.folder = folder;
    6.51          this.remote = remote;
    6.52          this.remoteSegment = remoteSegment;
    6.53 @@ -92,6 +95,7 @@
    6.54      }
    6.55  
    6.56      private static final String KEY_REMOTE_INDICES = RemoteIndex.class.getSimpleName();
    6.57 +    private static int localServerPort = -2;
    6.58  
    6.59      public static Iterable<? extends RemoteIndex> loadIndices() {
    6.60          return loadIndices(false);
    6.61 @@ -107,6 +111,20 @@
    6.62                      if (key.startsWith("index")) {
    6.63                          RemoteIndex idx = Pojson.load(RemoteIndex.class, prefs.get(key, null));
    6.64  
    6.65 +                        if (idx.enabled && idx.useLocalCache == UseLocalCache.ALWAYS) {
    6.66 +                            if (localServerPort == (-2)) {
    6.67 +                                localServerPort = Lookup.getDefault().lookup(LocalServer.class).startLocalServer();
    6.68 +                            }
    6.69 +
    6.70 +                            if (localServerPort != (-1)) {
    6.71 +                                try {
    6.72 +                                    idx = new RemoteIndex(true, UseLocalCache.ALWAYS, idx.folder, new URL("http://localhost:" + localServerPort + "/index"), idx.remoteSegment);
    6.73 +                                } catch (MalformedURLException ex) {
    6.74 +                                    Exceptions.printStackTrace(ex);
    6.75 +                                }
    6.76 +                            }
    6.77 +                        }
    6.78 +
    6.79                          if (includeAll || idx.enabled)
    6.80                              result.add(idx);
    6.81                      }
    6.82 @@ -140,4 +158,9 @@
    6.83              Exceptions.printStackTrace(ex);
    6.84          }
    6.85      }
    6.86 +
    6.87 +    public enum UseLocalCache {
    6.88 +        ALWAYS,
    6.89 +        NEVER;
    6.90 +    }
    6.91  }
     7.1 --- a/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/Bundle.properties	Mon Jan 16 18:48:12 2012 +0100
     7.2 +++ b/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/Bundle.properties	Mon Jan 16 23:09:48 2012 +0100
     7.3 @@ -9,3 +9,4 @@
     7.4  IndexPanel.addButton.text=Add Mapping
     7.5  IndexPanel.removeButton.text=Remove Mapping
     7.6  IndexPanel.editButton.text=Edit Mapping
     7.7 +IndexPanel.synchronizeOffline.text=Synchronize Offline
     8.1 --- a/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/IndexPanel.form	Mon Jan 16 18:48:12 2012 +0100
     8.2 +++ b/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/IndexPanel.form	Mon Jan 16 23:09:48 2012 +0100
     8.3 @@ -18,12 +18,13 @@
     8.4        <Group type="103" groupAlignment="0" attributes="0">
     8.5            <Group type="102" alignment="1" attributes="0">
     8.6                <EmptySpace max="-2" attributes="0"/>
     8.7 -              <Component id="jScrollPane1" pref="281" max="32767" attributes="0"/>
     8.8 +              <Component id="jScrollPane1" pref="263" max="32767" attributes="0"/>
     8.9                <EmptySpace max="-2" attributes="0"/>
    8.10 -              <Group type="103" groupAlignment="1" attributes="0">
    8.11 -                  <Component id="removeButton" alignment="1" pref="154" max="32767" attributes="1"/>
    8.12 -                  <Component id="addButton" alignment="1" pref="154" max="32767" attributes="1"/>
    8.13 -                  <Component id="editButton" alignment="1" pref="154" max="32767" attributes="0"/>
    8.14 +              <Group type="103" groupAlignment="0" attributes="0">
    8.15 +                  <Component id="removeButton" alignment="1" max="32767" attributes="1"/>
    8.16 +                  <Component id="addButton" alignment="1" max="32767" attributes="1"/>
    8.17 +                  <Component id="editButton" alignment="1" max="32767" attributes="0"/>
    8.18 +                  <Component id="synchronizeOffline" alignment="0" max="32767" attributes="0"/>
    8.19                </Group>
    8.20                <EmptySpace max="-2" attributes="0"/>
    8.21            </Group>
    8.22 @@ -34,13 +35,15 @@
    8.23            <Group type="102" alignment="0" attributes="0">
    8.24                <EmptySpace max="-2" attributes="0"/>
    8.25                <Group type="103" groupAlignment="0" attributes="0">
    8.26 -                  <Component id="jScrollPane1" alignment="0" pref="306" max="32767" attributes="0"/>
    8.27 -                  <Group type="102" alignment="0" attributes="0">
    8.28 +                  <Component id="jScrollPane1" pref="306" max="32767" attributes="0"/>
    8.29 +                  <Group type="102" attributes="0">
    8.30                        <Component id="addButton" min="-2" max="-2" attributes="0"/>
    8.31                        <EmptySpace max="-2" attributes="0"/>
    8.32                        <Component id="editButton" min="-2" max="-2" attributes="0"/>
    8.33                        <EmptySpace max="-2" attributes="0"/>
    8.34                        <Component id="removeButton" min="-2" max="-2" attributes="0"/>
    8.35 +                      <EmptySpace max="32767" attributes="0"/>
    8.36 +                      <Component id="synchronizeOffline" min="-2" max="-2" attributes="0"/>
    8.37                    </Group>
    8.38                </Group>
    8.39                <EmptySpace max="-2" attributes="0"/>
    8.40 @@ -102,5 +105,15 @@
    8.41          <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="editButtonActionPerformed"/>
    8.42        </Events>
    8.43      </Component>
    8.44 +    <Component class="javax.swing.JButton" name="synchronizeOffline">
    8.45 +      <Properties>
    8.46 +        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
    8.47 +          <ResourceString bundle="org/netbeans/modules/jackpot30/remotingapi/options/Bundle.properties" key="IndexPanel.synchronizeOffline.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;, {arguments})"/>
    8.48 +        </Property>
    8.49 +      </Properties>
    8.50 +      <Events>
    8.51 +        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="synchronizeOfflineActionPerformed"/>
    8.52 +      </Events>
    8.53 +    </Component>
    8.54    </SubComponents>
    8.55  </Form>
     9.1 --- a/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/IndexPanel.java	Mon Jan 16 18:48:12 2012 +0100
     9.2 +++ b/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/IndexPanel.java	Mon Jan 16 23:09:48 2012 +0100
     9.3 @@ -41,15 +41,29 @@
     9.4   */
     9.5  package org.netbeans.modules.jackpot30.remotingapi.options;
     9.6  
     9.7 +import java.io.IOException;
     9.8 +import java.net.URISyntaxException;
     9.9  import java.util.ArrayList;
    9.10 +import java.util.Collection;
    9.11 +import java.util.Iterator;
    9.12  import java.util.List;
    9.13 +import javax.swing.DefaultCellEditor;
    9.14  import javax.swing.JButton;
    9.15 +import javax.swing.JComboBox;
    9.16  import javax.swing.event.ListSelectionEvent;
    9.17  import javax.swing.event.ListSelectionListener;
    9.18  import javax.swing.table.AbstractTableModel;
    9.19 +import org.netbeans.api.progress.ProgressHandle;
    9.20 +import org.netbeans.api.progress.ProgressHandleFactory;
    9.21 +import org.netbeans.modules.jackpot30.remoting.api.LocalServer;
    9.22  import org.netbeans.modules.jackpot30.remoting.api.RemoteIndex;
    9.23 +import org.netbeans.modules.jackpot30.remoting.api.RemoteIndex.UseLocalCache;
    9.24  import org.openide.DialogDescriptor;
    9.25  import org.openide.DialogDisplayer;
    9.26 +import org.openide.execution.ExecutionEngine;
    9.27 +import org.openide.util.Exceptions;
    9.28 +import org.openide.util.Lookup;
    9.29 +import org.openide.windows.InputOutput;
    9.30  
    9.31  final class IndexPanel extends javax.swing.JPanel {
    9.32  
    9.33 @@ -63,6 +77,8 @@
    9.34                  enableDisable();
    9.35              }
    9.36          });
    9.37 +        JComboBox cacheEditor = new JComboBox(UseLocalCache.values());
    9.38 +        indices.setDefaultEditor(UseLocalCache.class, new DefaultCellEditor(cacheEditor));
    9.39          enableDisable();
    9.40      }
    9.41  
    9.42 @@ -79,6 +95,7 @@
    9.43          addButton = new javax.swing.JButton();
    9.44          removeButton = new javax.swing.JButton();
    9.45          editButton = new javax.swing.JButton();
    9.46 +        synchronizeOffline = new javax.swing.JButton();
    9.47  
    9.48          indices.setModel(new javax.swing.table.DefaultTableModel(
    9.49              new Object [][] {
    9.50 @@ -114,18 +131,26 @@
    9.51              }
    9.52          });
    9.53  
    9.54 +        org.openide.awt.Mnemonics.setLocalizedText(synchronizeOffline, org.openide.util.NbBundle.getMessage(IndexPanel.class, "IndexPanel.synchronizeOffline.text", new Object[] {})); // NOI18N
    9.55 +        synchronizeOffline.addActionListener(new java.awt.event.ActionListener() {
    9.56 +            public void actionPerformed(java.awt.event.ActionEvent evt) {
    9.57 +                synchronizeOfflineActionPerformed(evt);
    9.58 +            }
    9.59 +        });
    9.60 +
    9.61          javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
    9.62          this.setLayout(layout);
    9.63          layout.setHorizontalGroup(
    9.64              layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    9.65              .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
    9.66                  .addContainerGap()
    9.67 -                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 281, Short.MAX_VALUE)
    9.68 +                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 263, Short.MAX_VALUE)
    9.69                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
    9.70 -                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
    9.71 -                    .addComponent(removeButton, javax.swing.GroupLayout.DEFAULT_SIZE, 154, Short.MAX_VALUE)
    9.72 -                    .addComponent(addButton, javax.swing.GroupLayout.DEFAULT_SIZE, 154, Short.MAX_VALUE)
    9.73 -                    .addComponent(editButton, javax.swing.GroupLayout.DEFAULT_SIZE, 154, Short.MAX_VALUE))
    9.74 +                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    9.75 +                    .addComponent(removeButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
    9.76 +                    .addComponent(addButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
    9.77 +                    .addComponent(editButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
    9.78 +                    .addComponent(synchronizeOffline, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
    9.79                  .addContainerGap())
    9.80          );
    9.81          layout.setVerticalGroup(
    9.82 @@ -139,7 +164,9 @@
    9.83                          .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
    9.84                          .addComponent(editButton)
    9.85                          .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
    9.86 -                        .addComponent(removeButton)))
    9.87 +                        .addComponent(removeButton)
    9.88 +                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
    9.89 +                        .addComponent(synchronizeOffline)))
    9.90                  .addContainerGap())
    9.91          );
    9.92      }// </editor-fold>//GEN-END:initComponents
    9.93 @@ -159,6 +186,45 @@
    9.94          model.fireTableDataChanged();
    9.95      }//GEN-LAST:event_removeButtonActionPerformed
    9.96  
    9.97 +    private void synchronizeOfflineActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_synchronizeOfflineActionPerformed
    9.98 +        ExecutionEngine.getDefault().execute("Synchronizing remote indices", new Runnable() {
    9.99 +            @Override public void run() {
   9.100 +                TableModelImpl model = (TableModelImpl) indices.getModel();
   9.101 +                Collection<RemoteIndex> indices = new ArrayList<RemoteIndex>(model.indices);
   9.102 +
   9.103 +                for (Iterator<RemoteIndex> it = indices.iterator(); it.hasNext();) {
   9.104 +                    if (it.next().useLocalCache == UseLocalCache.NEVER) {
   9.105 +                        it.remove();
   9.106 +                    }
   9.107 +                }
   9.108 +
   9.109 +                ProgressHandle h = ProgressHandleFactory.createHandle("Synchronizing remote indices");
   9.110 +
   9.111 +                h.start(indices.size());
   9.112 +
   9.113 +                try {
   9.114 +                    int i = 0;
   9.115 +
   9.116 +                    for (RemoteIndex idx : indices) {
   9.117 +                        try {
   9.118 +                            h.progress("Downloading index from " + idx.remote.toURI() + " subindex " + idx.remoteSegment);
   9.119 +                            Lookup.getDefault().lookup(LocalServer.class).downloadIndex(idx);
   9.120 +                        } catch (URISyntaxException ex) {
   9.121 +                            Exceptions.printStackTrace(ex);
   9.122 +                        } catch (IOException ex) {
   9.123 +                            Exceptions.printStackTrace(ex);
   9.124 +                        }
   9.125 +
   9.126 +                        h.progress(++i);
   9.127 +                    }
   9.128 +                } finally {
   9.129 +                    h.finish();
   9.130 +                }
   9.131 +            }
   9.132 +        }, InputOutput.NULL);
   9.133 +
   9.134 +    }//GEN-LAST:event_synchronizeOfflineActionPerformed
   9.135 +
   9.136      private void addEditIndex(boolean edit) {
   9.137          JButton okButton = new JButton("OK");
   9.138          CustomizeRemoteIndex panel = new CustomizeRemoteIndex(okButton);
   9.139 @@ -197,6 +263,17 @@
   9.140              editButton.setEnabled(false);
   9.141              removeButton.setEnabled(false);
   9.142          }
   9.143 +
   9.144 +        if (indices.getModel() instanceof TableModelImpl) {
   9.145 +            TableModelImpl model = (TableModelImpl) indices.getModel();
   9.146 +            boolean enableDownload = false;
   9.147 +
   9.148 +            for (RemoteIndex idx : model.indices) {
   9.149 +                enableDownload |= idx.useLocalCache != UseLocalCache.NEVER;
   9.150 +            }
   9.151 +
   9.152 +            synchronizeOffline.setEnabled(enableDownload);
   9.153 +        }
   9.154      }
   9.155  
   9.156      void load() {
   9.157 @@ -225,6 +302,7 @@
   9.158      private javax.swing.JButton editButton;
   9.159      private javax.swing.JTable indices;
   9.160      private javax.swing.JButton removeButton;
   9.161 +    private javax.swing.JButton synchronizeOffline;
   9.162      // End of variables declaration//GEN-END:variables
   9.163  
   9.164      private static final class TableModelImpl extends AbstractTableModel {
   9.165 @@ -236,7 +314,7 @@
   9.166          }
   9.167  
   9.168          public int getColumnCount() {
   9.169 -            return 4;
   9.170 +            return 5;
   9.171          }
   9.172  
   9.173          public String getColumnName(int columnIndex) {
   9.174 @@ -245,12 +323,13 @@
   9.175                  case 1: return "Local folder";
   9.176                  case 2: return "Remote URL";
   9.177                  case 3: return "Remote project";
   9.178 +                case 4: return "Use local cache";
   9.179                  default: throw new IllegalStateException();
   9.180              }
   9.181          }
   9.182  
   9.183          public Class<?> getColumnClass(int columnIndex) {
   9.184 -            return columnIndex == 0 ? Boolean.class : String.class;
   9.185 +            return columnIndex == 0 ? Boolean.class : columnIndex != 4 ? String.class : UseLocalCache.class;
   9.186          }
   9.187  
   9.188          public Object getValueAt(int rowIndex, int columnIndex) {
   9.189 @@ -261,6 +340,7 @@
   9.190                  case 1: return Utils.toDisplayName(idx.getLocalFolder());
   9.191                  case 2: return idx.remote.toExternalForm();
   9.192                  case 3: return idx.remoteSegment;
   9.193 +                case 4: return idx.useLocalCache;
   9.194                  default: throw new IllegalStateException();
   9.195              }
   9.196          }
   9.197 @@ -269,12 +349,17 @@
   9.198          public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
   9.199              RemoteIndex idx = indices.get(rowIndex);
   9.200  
   9.201 -            indices.set(rowIndex, RemoteIndex.create(aValue instanceof Boolean ? (Boolean) aValue : true, idx.getLocalFolder(), idx.remote, idx.remoteSegment));
   9.202 +            if (columnIndex == 0) {
   9.203 +                idx = RemoteIndex.create(aValue instanceof Boolean ? (Boolean) aValue : true, idx.useLocalCache, idx.getLocalFolder(), idx.remote, idx.remoteSegment);
   9.204 +            } else {
   9.205 +                idx = RemoteIndex.create(idx.enabled, aValue instanceof UseLocalCache ? (UseLocalCache) aValue : UseLocalCache.NEVER, idx.getLocalFolder(), idx.remote, idx.remoteSegment);
   9.206 +            }
   9.207 +            indices.set(rowIndex, idx);
   9.208          }
   9.209  
   9.210          @Override
   9.211          public boolean isCellEditable(int rowIndex, int columnIndex) {
   9.212 -            return columnIndex == 0;
   9.213 +            return columnIndex == 0 || columnIndex == 4;
   9.214          }
   9.215  
   9.216      }
    10.1 --- a/remoting/ide/kit/nbproject/genfiles.properties	Mon Jan 16 18:48:12 2012 +0100
    10.2 +++ b/remoting/ide/kit/nbproject/genfiles.properties	Mon Jan 16 23:09:48 2012 +0100
    10.3 @@ -1,8 +1,8 @@
    10.4 -build.xml.data.CRC32=72164044
    10.5 +build.xml.data.CRC32=fb399e54
    10.6  build.xml.script.CRC32=14f758ae
    10.7 -build.xml.stylesheet.CRC32=a56c6a5b@1.47
    10.8 +build.xml.stylesheet.CRC32=a56c6a5b@2.49
    10.9  # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
   10.10  # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
   10.11 -nbproject/build-impl.xml.data.CRC32=72164044
   10.12 +nbproject/build-impl.xml.data.CRC32=fb399e54
   10.13  nbproject/build-impl.xml.script.CRC32=36b4ac39
   10.14 -nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.47
   10.15 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.49
    11.1 --- a/remoting/ide/kit/nbproject/project.xml	Mon Jan 16 18:48:12 2012 +0100
    11.2 +++ b/remoting/ide/kit/nbproject/project.xml	Mon Jan 16 23:09:48 2012 +0100
    11.3 @@ -26,6 +26,12 @@
    11.4                          <specification-version>1.0</specification-version>
    11.5                      </run-dependency>
    11.6                  </dependency>
    11.7 +                <dependency>
    11.8 +                    <code-name-base>org.netbeans.modules.jackpot30.remoting.local</code-name-base>
    11.9 +                    <run-dependency>
   11.10 +                        <specification-version>1.0</specification-version>
   11.11 +                    </run-dependency>
   11.12 +                </dependency>
   11.13              </module-dependencies>
   11.14              <public-packages/>
   11.15          </data>
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/remoting/ide/local/build.xml	Mon Jan 16 23:09:48 2012 +0100
    12.3 @@ -0,0 +1,8 @@
    12.4 +<?xml version="1.0" encoding="UTF-8"?>
    12.5 +<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
    12.6 +<!-- for some information on what you could do (e.g. targets to override). -->
    12.7 +<!-- If you delete this file and reopen the project it will be recreated. -->
    12.8 +<project name="org.netbeans.modules.jackpot30.remoting.local" default="netbeans" basedir=".">
    12.9 +    <description>Builds, tests, and runs the project org.netbeans.modules.jackpot30.remoting.local.</description>
   12.10 +    <import file="nbproject/build-impl.xml"/>
   12.11 +</project>
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/remoting/ide/local/manifest.mf	Mon Jan 16 23:09:48 2012 +0100
    13.3 @@ -0,0 +1,6 @@
    13.4 +Manifest-Version: 1.0
    13.5 +AutoUpdate-Show-In-Client: false
    13.6 +OpenIDE-Module: org.netbeans.modules.jackpot30.remoting.local
    13.7 +OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/jackpot30/remoting/local/Bundle.properties
    13.8 +OpenIDE-Module-Specification-Version: 1.0
    13.9 +
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/remoting/ide/local/nbproject/build-impl.xml	Mon Jan 16 23:09:48 2012 +0100
    14.3 @@ -0,0 +1,45 @@
    14.4 +<?xml version="1.0" encoding="UTF-8"?>
    14.5 +<!--
    14.6 +*** GENERATED FROM project.xml - DO NOT EDIT  ***
    14.7 +***         EDIT ../build.xml INSTEAD         ***
    14.8 +-->
    14.9 +<project name="org.netbeans.modules.jackpot30.remoting.local-impl" basedir="..">
   14.10 +    <fail message="Please build using Ant 1.7.1 or higher.">
   14.11 +        <condition>
   14.12 +            <not>
   14.13 +                <antversion atleast="1.7.1"/>
   14.14 +            </not>
   14.15 +        </condition>
   14.16 +    </fail>
   14.17 +    <property file="nbproject/private/suite-private.properties"/>
   14.18 +    <property file="nbproject/suite.properties"/>
   14.19 +    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
   14.20 +    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
   14.21 +    <property file="${suite.dir}/nbproject/platform.properties"/>
   14.22 +    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
   14.23 +        <attribute name="name"/>
   14.24 +        <attribute name="value"/>
   14.25 +        <sequential>
   14.26 +            <property name="@{name}" value="${@{value}}"/>
   14.27 +        </sequential>
   14.28 +    </macrodef>
   14.29 +    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
   14.30 +        <attribute name="property"/>
   14.31 +        <attribute name="value"/>
   14.32 +        <sequential>
   14.33 +            <property name="@{property}" value="@{value}"/>
   14.34 +        </sequential>
   14.35 +    </macrodef>
   14.36 +    <property file="${user.properties.file}"/>
   14.37 +    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
   14.38 +    <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
   14.39 +    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
   14.40 +    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
   14.41 +        <condition>
   14.42 +            <not>
   14.43 +                <contains string="${cluster.path.evaluated}" substring="platform"/>
   14.44 +            </not>
   14.45 +        </condition>
   14.46 +    </fail>
   14.47 +    <import file="${harness.dir}/build.xml"/>
   14.48 +</project>
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/remoting/ide/local/nbproject/genfiles.properties	Mon Jan 16 23:09:48 2012 +0100
    15.3 @@ -0,0 +1,8 @@
    15.4 +build.xml.data.CRC32=c99d6905
    15.5 +build.xml.script.CRC32=cee246cf
    15.6 +build.xml.stylesheet.CRC32=a56c6a5b@2.49
    15.7 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
    15.8 +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
    15.9 +nbproject/build-impl.xml.data.CRC32=c99d6905
   15.10 +nbproject/build-impl.xml.script.CRC32=bec8c0f7
   15.11 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.49
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/remoting/ide/local/nbproject/project.properties	Mon Jan 16 23:09:48 2012 +0100
    16.3 @@ -0,0 +1,2 @@
    16.4 +javac.source=1.6
    16.5 +javac.compilerargs=-Xlint -Xlint:-serial
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/remoting/ide/local/nbproject/project.xml	Mon Jan 16 23:09:48 2012 +0100
    17.3 @@ -0,0 +1,71 @@
    17.4 +<?xml version="1.0" encoding="UTF-8"?>
    17.5 +<project xmlns="http://www.netbeans.org/ns/project/1">
    17.6 +    <type>org.netbeans.modules.apisupport.project</type>
    17.7 +    <configuration>
    17.8 +        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
    17.9 +            <code-name-base>org.netbeans.modules.jackpot30.remoting.local</code-name-base>
   17.10 +            <suite-component/>
   17.11 +            <module-dependencies>
   17.12 +                <dependency>
   17.13 +                    <code-name-base>org.netbeans.modules.extexecution</code-name-base>
   17.14 +                    <build-prerequisite/>
   17.15 +                    <compile-dependency/>
   17.16 +                    <run-dependency>
   17.17 +                        <release-version>2</release-version>
   17.18 +                        <specification-version>1.29</specification-version>
   17.19 +                    </run-dependency>
   17.20 +                </dependency>
   17.21 +                <dependency>
   17.22 +                    <code-name-base>org.netbeans.modules.jackpot30.remoting.api</code-name-base>
   17.23 +                    <build-prerequisite/>
   17.24 +                    <compile-dependency/>
   17.25 +                    <run-dependency>
   17.26 +                        <specification-version>1.7</specification-version>
   17.27 +                    </run-dependency>
   17.28 +                </dependency>
   17.29 +                <dependency>
   17.30 +                    <code-name-base>org.netbeans.modules.java.platform</code-name-base>
   17.31 +                    <build-prerequisite/>
   17.32 +                    <compile-dependency/>
   17.33 +                    <run-dependency>
   17.34 +                        <release-version>1</release-version>
   17.35 +                        <specification-version>1.24</specification-version>
   17.36 +                    </run-dependency>
   17.37 +                </dependency>
   17.38 +                <dependency>
   17.39 +                    <code-name-base>org.openide.filesystems</code-name-base>
   17.40 +                    <build-prerequisite/>
   17.41 +                    <compile-dependency/>
   17.42 +                    <run-dependency>
   17.43 +                        <specification-version>7.55</specification-version>
   17.44 +                    </run-dependency>
   17.45 +                </dependency>
   17.46 +                <dependency>
   17.47 +                    <code-name-base>org.openide.modules</code-name-base>
   17.48 +                    <build-prerequisite/>
   17.49 +                    <compile-dependency/>
   17.50 +                    <run-dependency>
   17.51 +                        <specification-version>7.28</specification-version>
   17.52 +                    </run-dependency>
   17.53 +                </dependency>
   17.54 +                <dependency>
   17.55 +                    <code-name-base>org.openide.util</code-name-base>
   17.56 +                    <build-prerequisite/>
   17.57 +                    <compile-dependency/>
   17.58 +                    <run-dependency>
   17.59 +                        <specification-version>8.22</specification-version>
   17.60 +                    </run-dependency>
   17.61 +                </dependency>
   17.62 +                <dependency>
   17.63 +                    <code-name-base>org.openide.util.lookup</code-name-base>
   17.64 +                    <build-prerequisite/>
   17.65 +                    <compile-dependency/>
   17.66 +                    <run-dependency>
   17.67 +                        <specification-version>8.12</specification-version>
   17.68 +                    </run-dependency>
   17.69 +                </dependency>
   17.70 +            </module-dependencies>
   17.71 +            <public-packages/>
   17.72 +        </data>
   17.73 +    </configuration>
   17.74 +</project>
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/remoting/ide/local/nbproject/suite.properties	Mon Jan 16 23:09:48 2012 +0100
    18.3 @@ -0,0 +1,1 @@
    18.4 +suite.dir=${basedir}/..
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/remoting/ide/local/src/org/netbeans/modules/jackpot30/remoting/local/Bundle.properties	Mon Jan 16 23:09:48 2012 +0100
    19.3 @@ -0,0 +1,1 @@
    19.4 +OpenIDE-Module-Name=Jackpot 3.0 Remoting - Local Server
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/remoting/ide/local/src/org/netbeans/modules/jackpot30/remoting/local/LocalServerImpl.java	Mon Jan 16 23:09:48 2012 +0100
    20.3 @@ -0,0 +1,156 @@
    20.4 +/*
    20.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    20.6 + *
    20.7 + * Copyright 2012 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 2012 Sun Microsystems, Inc.
   20.44 + */
   20.45 +package org.netbeans.modules.jackpot30.remoting.local;
   20.46 +
   20.47 +import java.io.BufferedOutputStream;
   20.48 +import java.io.BufferedReader;
   20.49 +import java.io.File;
   20.50 +import java.io.FileOutputStream;
   20.51 +import java.io.IOException;
   20.52 +import java.io.InputStream;
   20.53 +import java.io.InputStreamReader;
   20.54 +import java.io.OutputStream;
   20.55 +import java.net.URL;
   20.56 +import java.util.jar.JarInputStream;
   20.57 +import java.util.zip.ZipEntry;
   20.58 +import org.netbeans.api.extexecution.ExternalProcessBuilder;
   20.59 +import org.netbeans.api.java.platform.JavaPlatform;
   20.60 +import org.netbeans.modules.jackpot30.remoting.api.LocalServer;
   20.61 +import org.netbeans.modules.jackpot30.remoting.api.RemoteIndex;
   20.62 +import org.openide.filesystems.FileObject;
   20.63 +import org.openide.filesystems.FileUtil;
   20.64 +import org.openide.modules.InstalledFileLocator;
   20.65 +import org.openide.modules.Places;
   20.66 +import org.openide.util.Exceptions;
   20.67 +import org.openide.util.lookup.ServiceProvider;
   20.68 +
   20.69 +/**
   20.70 + *
   20.71 + * @author lahvac
   20.72 + */
   20.73 +@ServiceProvider(service=LocalServer.class)
   20.74 +public class LocalServerImpl implements LocalServer {
   20.75 +
   20.76 +    private static final String CACHE_PATH = "remoting-index";
   20.77 +
   20.78 +    private int serverPort = -2;
   20.79 +
   20.80 +    @Override
   20.81 +    public int startLocalServer() {
   20.82 +        File webMain = InstalledFileLocator.getDefault().locate("index-server/web/web.main.jar", null, false);
   20.83 +
   20.84 +        if (webMain == null) return -1;
   20.85 +
   20.86 +        FileObject javaFO = JavaPlatform.getDefault().findTool("java");
   20.87 +        File java = javaFO != null ? FileUtil.toFile(javaFO) : null;
   20.88 +
   20.89 +        if (java == null) return -1;
   20.90 +
   20.91 +        ExternalProcessBuilder epb = new ExternalProcessBuilder(java.getAbsolutePath());
   20.92 +
   20.93 +        epb = epb.addArgument("-Djava.index.useMemCache=false");
   20.94 +        epb = epb.addArgument("-Xbootclasspath/p:" + new File(webMain, "lib/javac-api-nb-7.0-b07.jar").getAbsolutePath() + ":" + new File(webMain, "lib/javac-api-nb-7.0-b07.jar").getAbsolutePath());
   20.95 +        epb = epb.addArgument("-jar");
   20.96 +        epb = epb.addArgument(webMain.getAbsolutePath());
   20.97 +        epb = epb.addArgument("--freeport");
   20.98 +        epb = epb.addArgument(Places.getCacheSubdirectory(CACHE_PATH).getAbsolutePath());
   20.99 +
  20.100 +        try {
  20.101 +            Process running = epb.call();
  20.102 +            BufferedReader br = new BufferedReader(new InputStreamReader(running.getInputStream()));
  20.103 +            String line = br.readLine();
  20.104 +
  20.105 +            if (line != null && line.startsWith("Running on port: ")) {
  20.106 +                return serverPort = Integer.parseInt(line.substring("Running on port: ".length()));
  20.107 +            }
  20.108 +
  20.109 +            running.destroy();
  20.110 +        } catch (IOException ex) {
  20.111 +            Exceptions.printStackTrace(ex);
  20.112 +            return serverPort = -1;
  20.113 +        }
  20.114 +
  20.115 +        return serverPort = -1;
  20.116 +    }
  20.117 +
  20.118 +    @Override
  20.119 +    public boolean downloadIndex(RemoteIndex idx) throws IOException {
  20.120 +        URL url = new URL(idx.remote.toExternalForm() + "/downloadable/index?path=" + idx.remoteSegment);
  20.121 +        InputStream in = url.openStream();
  20.122 +        JarInputStream jis = new JarInputStream(in);
  20.123 +        File cacheDir = Places.getCacheSubdirectory(CACHE_PATH);
  20.124 +        File newTarget = new File(cacheDir, idx.remoteSegment + ".new");
  20.125 +
  20.126 +        ZipEntry ze;
  20.127 +
  20.128 +        while ((ze = jis.getNextEntry()) != null) {
  20.129 +            if (ze.isDirectory()) continue;
  20.130 +
  20.131 +            File targetFile = new File(newTarget, ze.getName());
  20.132 +
  20.133 +            targetFile.getParentFile().mkdirs();
  20.134 +
  20.135 +            OutputStream out = new BufferedOutputStream(new FileOutputStream(targetFile));
  20.136 +
  20.137 +            FileUtil.copy(jis, out);
  20.138 +
  20.139 +            out.close();
  20.140 +        }
  20.141 +
  20.142 +        File target = new File(cacheDir, idx.remoteSegment);
  20.143 +        File old = new File(cacheDir, idx.remoteSegment + ".old");
  20.144 +
  20.145 +        target.renameTo(old);
  20.146 +        newTarget.renameTo(target);
  20.147 +
  20.148 +        FileObject oldFO = FileUtil.toFileObject(old);
  20.149 +
  20.150 +        if (oldFO != null) oldFO.delete();
  20.151 +
  20.152 +        if (serverPort > 0) {
  20.153 +            new URL("http://localhost:" + serverPort + "/index/internal/indexUpdated").openStream().close();
  20.154 +        }
  20.155 +
  20.156 +        return true;
  20.157 +    }
  20.158 +
  20.159 +}
    21.1 --- a/remoting/ide/nbproject/project.properties	Mon Jan 16 18:48:12 2012 +0100
    21.2 +++ b/remoting/ide/nbproject/project.properties	Mon Jan 16 23:09:48 2012 +0100
    21.3 @@ -4,10 +4,12 @@
    21.4      ${project.org.netbeans.modules.jackpot30.ide.usages}:\
    21.5      ${project.org.netbeans.modules.jackpot30.remoting.kit}:\
    21.6      ${project.org.netbeans.modules.jackpot30.cnd.remote.bridge}:\
    21.7 -    ${project.org.netbeans.modules.jackpot30.remoting.downloadable}
    21.8 +    ${project.org.netbeans.modules.jackpot30.remoting.downloadable}:\
    21.9 +    ${project.org.netbeans.modules.jackpot30.remoting.local}
   21.10  project.org.netbeans.modules.jackpot30.cnd.remote.bridge=cnd.remote.bridge
   21.11  project.org.netbeans.modules.jackpot30.ide.usages=usages
   21.12  project.org.netbeans.modules.jackpot30.jumpto=jumpto
   21.13  project.org.netbeans.modules.jackpot30.remoting.api=api
   21.14  project.org.netbeans.modules.jackpot30.remoting.downloadable=downloadable
   21.15  project.org.netbeans.modules.jackpot30.remoting.kit=kit
   21.16 +project.org.netbeans.modules.jackpot30.remoting.local=local
    22.1 --- a/remoting/server/web/base.web.api/src/org/netbeans/modules/jackpot30/backend/base/CategoryStorage.java	Mon Jan 16 18:48:12 2012 +0100
    22.2 +++ b/remoting/server/web/base.web.api/src/org/netbeans/modules/jackpot30/backend/base/CategoryStorage.java	Mon Jan 16 23:09:48 2012 +0100
    22.3 @@ -60,6 +60,7 @@
    22.4  import org.apache.lucene.analysis.KeywordAnalyzer;
    22.5  import org.codeviation.pojson.Pojson;
    22.6  import org.netbeans.modules.parsing.impl.indexing.CacheFolder;
    22.7 +import org.netbeans.modules.parsing.lucene.LuceneIndexFactory;
    22.8  import org.netbeans.modules.parsing.lucene.support.Index;
    22.9  import org.netbeans.modules.parsing.lucene.support.IndexManager;
   22.10  import org.openide.filesystems.FileObject;
   22.11 @@ -185,7 +186,7 @@
   22.12          return displayName;
   22.13      }
   22.14  
   22.15 -    private FileObject getCacheRoot() {
   22.16 +    public FileObject getCacheRoot() {
   22.17          return FileUtil.toFileObject(FileUtil.normalizeFile(new File(cacheRoot, id)));
   22.18      }
   22.19  
    23.1 --- a/remoting/server/web/nbindex.web.api/nbproject/project.properties	Mon Jan 16 18:48:12 2012 +0100
    23.2 +++ b/remoting/server/web/nbindex.web.api/nbproject/project.properties	Mon Jan 16 23:09:48 2012 +0100
    23.3 @@ -28,6 +28,7 @@
    23.4  file.reference.org-netbeans-modules-parsing-api.jar=../../../../server/lib/org-netbeans-modules-parsing-api.jar
    23.5  file.reference.org-netbeans-modules-parsing-lucene.jar=../../../../server/lib/org-netbeans-modules-parsing-lucene.jar
    23.6  file.reference.org-openide-filesystems.jar=../../../../server/lib/org-openide-filesystems.jar
    23.7 +file.reference.org-openide-util.jar=../../../../server/lib/org-openide-util.jar
    23.8  file.reference.util-commons.jar=../../../ide/api/external/util-commons.jar
    23.9  file.reference.util-pojson.jar=../../../ide/api/external/util-pojson.jar
   23.10  includes=**
   23.11 @@ -40,7 +41,8 @@
   23.12      ${file.reference.org-openide-filesystems.jar}:\
   23.13      ${file.reference.org-netbeans-modules-parsing-lucene.jar}:\
   23.14      ${file.reference.util-commons.jar}:\
   23.15 -    ${file.reference.util-pojson.jar}
   23.16 +    ${file.reference.util-pojson.jar}:\
   23.17 +    ${file.reference.org-openide-util.jar}
   23.18  # Space-separated list of extra javac options
   23.19  javac.compilerargs=
   23.20  javac.deprecation=false
    24.1 --- a/remoting/server/web/nbindex.web.api/src/org/netbeans/modules/jackpot30/backend/usages/api/DownloadableIndex.java	Mon Jan 16 18:48:12 2012 +0100
    24.2 +++ b/remoting/server/web/nbindex.web.api/src/org/netbeans/modules/jackpot30/backend/usages/api/DownloadableIndex.java	Mon Jan 16 23:09:48 2012 +0100
    24.3 @@ -42,10 +42,18 @@
    24.4  package org.netbeans.modules.jackpot30.backend.usages.api;
    24.5  
    24.6  import java.io.*;
    24.7 +import java.util.Arrays;
    24.8 +import java.util.Collections;
    24.9 +import java.util.jar.JarOutputStream;
   24.10 +import java.util.zip.ZipEntry;
   24.11 +import java.util.zip.ZipOutputStream;
   24.12  import javax.ws.rs.*;
   24.13  import javax.ws.rs.core.Response;
   24.14  import javax.ws.rs.core.StreamingOutput;
   24.15  import org.netbeans.modules.jackpot30.backend.base.CategoryStorage;
   24.16 +import org.openide.filesystems.FileObject;
   24.17 +import org.openide.filesystems.FileUtil;
   24.18 +import org.openide.util.NbCollections;
   24.19  
   24.20  /**
   24.21   *
   24.22 @@ -81,4 +89,51 @@
   24.23          } ).build();
   24.24      }
   24.25  
   24.26 +    @GET
   24.27 +    @Path("/index")
   24.28 +    @Produces("application/octet-stream")
   24.29 +    public Response index(@QueryParam("path") String segment) throws IOException, InterruptedException {
   24.30 +        CategoryStorage category = CategoryStorage.forId(segment);
   24.31 +        final FileObject idxRoot = category.getCacheRoot();
   24.32 +
   24.33 +        if (idxRoot == null || !idxRoot.canRead()) return Response.status(Response.Status.NOT_FOUND).build();
   24.34 +
   24.35 +        return Response.ok().entity(new StreamingOutput() {
   24.36 +            @Override public void write(OutputStream output) throws IOException, WebApplicationException {
   24.37 +                JarOutputStream out = new JarOutputStream(output);
   24.38 +
   24.39 +                try {
   24.40 +                    for (String rel : Arrays.asList("index", "info", "segments")) {
   24.41 +                        FileObject relFO = idxRoot.getFileObject(rel);
   24.42 +
   24.43 +                        if (relFO == null) return;
   24.44 +
   24.45 +                        Iterable<? extends FileObject> children;
   24.46 +
   24.47 +                        if (relFO.isFolder()) children = NbCollections.iterable(relFO.getChildren(true));
   24.48 +                        else children = Collections.singletonList(relFO);
   24.49 +
   24.50 +                        for (FileObject c : children) {
   24.51 +                            if (c.isFolder()) continue;
   24.52 +
   24.53 +                            out.putNextEntry(new ZipEntry(FileUtil.getRelativePath(idxRoot, c)));
   24.54 +
   24.55 +                            InputStream in = c.getInputStream();
   24.56 +
   24.57 +                            try {
   24.58 +                                FileUtil.copy(in, out);
   24.59 +                            } finally {
   24.60 +                                in.close();
   24.61 +                            }
   24.62 +
   24.63 +                            out.closeEntry();
   24.64 +                        }
   24.65 +                    }
   24.66 +                } finally {
   24.67 +                    out.close();
   24.68 +                }
   24.69 +            }
   24.70 +        } ).build();
   24.71 +    }
   24.72 +
   24.73  }