You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by po...@apache.org on 2017/09/03 17:33:19 UTC

[26/51] [partial] incubator-netbeans-jackpot30 git commit: INFRA-15006 Import for http://bits.netbeans.org/download/apache-donation

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-jackpot30/blob/9ed0a377/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/CacheFolder.java
----------------------------------------------------------------------
diff --git a/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/CacheFolder.java b/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/CacheFolder.java
new file mode 100644
index 0000000..ea01606
--- /dev/null
+++ b/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/CacheFolder.java
@@ -0,0 +1,269 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2008 Sun Microsystems, Inc.
+ */
+
+package org.netbeans.modules.jackpot30.remotingapi;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileSystem;
+import org.openide.filesystems.FileUtil;
+import org.openide.filesystems.URLMapper;
+import org.openide.modules.Places;
+import org.openide.util.Exceptions;
+import org.openide.util.RequestProcessor;
+
+/**
+ *
+ * @author Tomas Zezula
+ */
+public final class CacheFolder {
+
+    private static final Logger LOG = Logger.getLogger(CacheFolder.class.getName());
+    private static final RequestProcessor RP = new RequestProcessor(CacheFolder.class.getName(), 1, false, false);
+    private static final RequestProcessor.Task SAVER = RP.create(new Saver());
+    private static final int SLIDING_WINDOW = 500;
+
+    private static final String SEGMENTS_FILE = "segments";      //NOI18N
+    private static final String SLICE_PREFIX = "s";              //NOI18N
+
+    //@GuardedBy("CacheFolder.class")
+    private static FileObject cacheFolder;
+    //@GuardedBy("CacheFolder.class")
+    private static Properties segments;
+    //@GuardedBy("CacheFolder.class")
+    private static Map<String, String> invertedSegments;
+    //@GuardedBy("CacheFolder.class")
+    private static int index = 0;
+
+
+    //@NotThreadSafe
+    @org.netbeans.api.annotations.common.SuppressWarnings(
+        value="LI_LAZY_INIT_UPDATE_STATIC"
+        /*,justification="Caller already holds a monitor"*/)
+    private static void loadSegments(FileObject folder) throws IOException {
+        assert Thread.holdsLock(CacheFolder.class);
+        if (segments == null) {
+            assert folder != null;
+            segments = new Properties ();
+            invertedSegments = new HashMap<String,String> ();
+            final FileObject segmentsFile =  folder.getFileObject(SEGMENTS_FILE);
+            if (segmentsFile!=null) {
+                final InputStream in = segmentsFile.getInputStream();
+                try {
+                    segments.load (in);
+                } finally {
+                    in.close();
+                }
+            }
+            for (Map.Entry entry : segments.entrySet()) {
+                String segment = (String) entry.getKey();
+                String root = (String) entry.getValue();
+                invertedSegments.put(root,segment);
+                try {
+                    index = Math.max (index,Integer.parseInt(segment.substring(SLICE_PREFIX.length())));
+                } catch (NumberFormatException nfe) {
+                    LOG.log(Level.FINE, null, nfe);
+                }
+            }
+        }
+    }
+
+
+    private static void storeSegments(FileObject folder) throws IOException {
+        assert Thread.holdsLock(CacheFolder.class);
+        assert folder != null;
+        //It's safer to use FileUtil.createData(File) than FileUtil.createData(FileObject, String)
+        //see issue #173094
+        final File _file = FileUtil.toFile(folder);
+        assert _file != null;
+        final FileObject segmentsFile = FileUtil.createData(new File(_file, SEGMENTS_FILE));
+        final OutputStream out = segmentsFile.getOutputStream();
+        try {
+            segments.store(out,null);
+        } finally {
+            out.close();
+        }
+    }
+
+    public static synchronized URL getSourceRootForDataFolder (final FileObject dataFolder) {
+        final FileObject segFolder = dataFolder.getParent();
+        if (segFolder == null || !segFolder.equals(cacheFolder)) {
+            return null;
+        }
+        String source = segments.getProperty(dataFolder.getName());
+        if (source != null) {
+            try {
+                return new URL (source);
+            } catch (IOException ioe) {
+                LOG.log(Level.FINE, null, ioe);
+            }
+        }
+        return null;
+    }
+
+    public static FileObject getDataFolder (final URL root) throws IOException {
+        return getDataFolder(root, false);
+    }
+
+    public static FileObject getDataFolder (final URL root, final boolean onlyIfAlreadyExists) throws IOException {
+        final String rootName = root.toExternalForm();
+        final FileObject _cacheFolder = getCacheFolder();
+        String slice;
+        synchronized (CacheFolder.class) {
+            loadSegments(_cacheFolder);
+            slice = invertedSegments.get (rootName);
+            if (slice == null) {
+                if (onlyIfAlreadyExists) {
+                    return null;
+                }
+                slice = SLICE_PREFIX + (++index);
+                while (segments.getProperty(slice) != null) {
+                    slice = SLICE_PREFIX + (++index);
+                }
+                segments.put (slice,rootName);
+                invertedSegments.put(rootName, slice);
+                SAVER.schedule(SLIDING_WINDOW);
+            }
+        }
+        assert slice != null;
+        if (onlyIfAlreadyExists) {
+            return cacheFolder.getFileObject(slice);
+        } else {
+            return FileUtil.createFolder(_cacheFolder, slice);
+        }
+    }
+
+    public static synchronized Iterable<? extends FileObject> findRootsWithCacheUnderFolder(FileObject folder) throws IOException {
+        URL folderURL = folder.toURL();
+        String prefix = folderURL.toExternalForm();
+        final FileObject _cacheFolder = getCacheFolder();
+        List<FileObject> result = new LinkedList<FileObject>();
+        loadSegments(_cacheFolder);
+        for (Entry<String, String> e : invertedSegments.entrySet()) {
+            if (e.getKey().startsWith(prefix)) {
+                FileObject fo = URLMapper.findFileObject(new URL(e.getKey()));
+
+                if (fo != null) {
+                    result.add(fo);
+                }
+            }
+        }
+
+        return result;
+    }
+
+    public static synchronized FileObject getCacheFolder () {
+        if (cacheFolder == null) {
+            File cache = Places.getCacheSubdirectory("index"); // NOI18N
+            if (!cache.isDirectory()) {
+                throw new IllegalStateException("Indices cache folder " + cache.getAbsolutePath() + " is not a folder"); //NOI18N
+            }
+            if (!cache.canRead()) {
+                throw new IllegalStateException("Can't read from indices cache folder " + cache.getAbsolutePath()); //NOI18N
+            }
+            if (!cache.canWrite()) {
+                throw new IllegalStateException("Can't write to indices cache folder " + cache.getAbsolutePath()); //NOI18N
+            }
+
+            cacheFolder = FileUtil.toFileObject(cache);
+            if (cacheFolder == null) {
+                throw new IllegalStateException("Can't convert indices cache folder " + cache.getAbsolutePath() + " to FileObject"); //NOI18N
+            }
+        }
+        return cacheFolder;
+    }
+
+
+    /**
+     * Only for unit tests! It's used also by CslTestBase, which is not in the
+     * same package, hence the public keyword.
+     *
+     */
+    public static void setCacheFolder (final FileObject folder) {
+        SAVER.schedule(0);
+        SAVER.waitFinished();
+        synchronized (CacheFolder.class) {
+            assert folder != null && folder.canRead() && folder.canWrite();
+            cacheFolder = folder;
+            segments = null;
+            invertedSegments = null;
+            index = 0;
+        }
+    }
+
+    private CacheFolder() {
+        // no-op
+    }
+
+    private static class Saver implements Runnable {
+        @Override
+        public void run() {
+            try {
+                final FileObject cf = getCacheFolder();
+                // #170182 - preventing filesystem events being fired from under the CacheFolder.class lock
+                cf.getFileSystem().runAtomicAction(new FileSystem.AtomicAction() {
+                    @Override
+                    public void run() throws IOException {
+                        synchronized (CacheFolder.class) {
+                            if (segments == null) return ;
+                            storeSegments(cf);
+                        }
+                    }
+                });
+            } catch (IOException ioe) {
+                Exceptions.printStackTrace(ioe);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-jackpot30/blob/9ed0a377/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/Bundle.properties
----------------------------------------------------------------------
diff --git a/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/Bundle.properties b/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/Bundle.properties
new file mode 100644
index 0000000..1c81565
--- /dev/null
+++ b/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/Bundle.properties
@@ -0,0 +1,53 @@
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+#
+# Copyright 2009-2017 Oracle and/or its affiliates. All rights reserved.
+#
+# Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+# Other names may be trademarks of their respective owners.
+#
+# The contents of this file are subject to the terms of either the GNU
+# General Public License Version 2 only ("GPL") or the Common
+# Development and Distribution License("CDDL") (collectively, the
+# "License"). You may not use this file except in compliance with the
+# License. You can obtain a copy of the License at
+# http://www.netbeans.org/cddl-gplv2.html
+# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+# specific language governing permissions and limitations under the
+# License.  When distributing the software, include this License Header
+# Notice in each file and include the License file at
+# nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the GPL Version 2 section of the License file that
+# accompanied this code. If applicable, add the following below the
+# License Header, with the fields enclosed by brackets [] replaced by
+# your own identifying information:
+# "Portions Copyrighted [year] [name of copyright owner]"
+#
+# Contributor(s):
+#
+# The Original Software is NetBeans. The Initial Developer of the Original
+# Software is Sun Microsystems, Inc. Portions Copyright 2009-2010 Sun
+# Microsystems, Inc. All Rights Reserved.
+#
+# If you wish your version of this file to be governed by only the CDDL
+# or only the GPL Version 2, indicate your decision by adding
+# "[Contributor] elects to include this software in this distribution
+# under the [CDDL or GPL Version 2] license." If you do not indicate a
+# single choice of license, a recipient has the option to distribute
+# your version of this file under either the CDDL, the GPL Version 2 or
+# to extend the choice of license to its licensees as provided above.
+# However, if you add GPL Version 2 code and therefore, elected the GPL
+# Version 2 license, then the option applies only if the new code is
+# made subject to such option by the copyright holder.
+AdvancedOption_DisplayName_Index=Jackpot 3.0 Indices
+AdvancedOption_Keywords_Index=index indices jackpot
+CustomizeRemoteIndex.indexURLLabel.text=Index URL:
+CustomizeRemoteIndex.indexURL.text=
+CustomizeRemoteIndex.jLabel1.text=Subindex:
+CustomizeRemoteIndex.folderLabel.text=&Folder:
+CustomizeRemoteIndex.folderChooser.text=Browse
+CustomizeRemoteIndex.folder.text=
+IndexPanel.addButton.text=Add Mapping
+IndexPanel.removeButton.text=Remove Mapping
+IndexPanel.editButton.text=Edit Mapping
+IndexPanel.synchronizeOffline.text=Synchronize Offline

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-jackpot30/blob/9ed0a377/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/CustomizeRemoteIndex.form
----------------------------------------------------------------------
diff --git a/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/CustomizeRemoteIndex.form b/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/CustomizeRemoteIndex.form
new file mode 100644
index 0000000..46368e3
--- /dev/null
+++ b/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/CustomizeRemoteIndex.form
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <NonVisualComponents>
+    <Component class="javax.swing.ButtonGroup" name="buttonGroup1">
+    </Component>
+  </NonVisualComponents>
+  <Properties>
+    <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+      <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
+        <EmptyBorder bottom="12" left="12" right="12" top="12"/>
+      </Border>
+    </Property>
+  </Properties>
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+    <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,53,0,0,2,-37"/>
+  </AuxValues>
+
+  <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
+  <SubComponents>
+    <Container class="javax.swing.JPanel" name="folderPanel">
+      <Constraints>
+        <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+          <GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="17" weightX="1.0" weightY="0.0"/>
+        </Constraint>
+      </Constraints>
+
+      <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
+      <SubComponents>
+        <Component class="javax.swing.JLabel" name="folderLabel">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="org/netbeans/modules/jackpot30/remotingapi/options/Bundle.properties" key="CustomizeRemoteIndex.folderLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+          <Constraints>
+            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+              <GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="6" anchor="17" weightX="0.0" weightY="0.0"/>
+            </Constraint>
+          </Constraints>
+        </Component>
+        <Component class="javax.swing.JButton" name="folderChooser">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="org/netbeans/modules/jackpot30/remotingapi/options/Bundle.properties" key="CustomizeRemoteIndex.folderChooser.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="folderChooserActionPerformed"/>
+          </Events>
+          <Constraints>
+            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+              <GridBagConstraints gridX="2" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="6" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
+            </Constraint>
+          </Constraints>
+        </Component>
+        <Component class="javax.swing.JTextField" name="folder">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="org/netbeans/modules/jackpot30/remotingapi/options/Bundle.properties" key="CustomizeRemoteIndex.folder.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+          <Constraints>
+            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+              <GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="0.0"/>
+            </Constraint>
+          </Constraints>
+        </Component>
+      </SubComponents>
+    </Container>
+    <Component class="javax.swing.JTextArea" name="indexInfo">
+      <Properties>
+        <Property name="columns" type="int" value="20"/>
+        <Property name="editable" type="boolean" value="false"/>
+        <Property name="rows" type="int" value="5"/>
+        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+          <Border info="null"/>
+        </Property>
+      </Properties>
+      <Constraints>
+        <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+          <GridBagConstraints gridX="0" gridY="2" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="6" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
+        </Constraint>
+      </Constraints>
+    </Component>
+    <Container class="javax.swing.JPanel" name="remoteIndexPanel">
+      <Constraints>
+        <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+          <GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="0.0"/>
+        </Constraint>
+      </Constraints>
+
+      <Layout>
+        <DimensionLayout dim="0">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" alignment="0" attributes="0">
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="0" attributes="0">
+                      <Group type="102" alignment="0" attributes="0">
+                          <EmptySpace min="12" pref="12" max="12" attributes="0"/>
+                          <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
+                          <EmptySpace max="-2" attributes="0"/>
+                          <Component id="subIndex" pref="589" max="32767" attributes="0"/>
+                      </Group>
+                      <Group type="102" alignment="0" attributes="0">
+                          <Component id="indexURLLabel" min="-2" max="-2" attributes="0"/>
+                          <EmptySpace max="-2" attributes="0"/>
+                          <Component id="indexURL" min="-2" max="-2" attributes="0"/>
+                      </Group>
+                  </Group>
+                  <EmptySpace max="-2" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+        <DimensionLayout dim="1">
+          <Group type="103" groupAlignment="0" attributes="0">
+              <Group type="102" alignment="0" attributes="0">
+                  <EmptySpace max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="3" attributes="0">
+                      <Component id="indexURLLabel" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="indexURL" alignment="3" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <EmptySpace type="unrelated" max="-2" attributes="0"/>
+                  <Group type="103" groupAlignment="3" attributes="0">
+                      <Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="subIndex" alignment="3" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <EmptySpace max="32767" attributes="0"/>
+              </Group>
+          </Group>
+        </DimensionLayout>
+      </Layout>
+      <SubComponents>
+        <Component class="javax.swing.JTextField" name="indexURL">
+          <Properties>
+            <Property name="columns" type="int" value="40"/>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="org/netbeans/modules/jackpot30/remotingapi/options/Bundle.properties" key="CustomizeRemoteIndex.indexURL.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JLabel" name="indexURLLabel">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="org/netbeans/modules/jackpot30/remotingapi/options/Bundle.properties" key="CustomizeRemoteIndex.indexURLLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+        <Component class="javax.swing.JComboBox" name="subIndex">
+          <Properties>
+            <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
+              <StringArray count="0"/>
+            </Property>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="subIndexActionPerformed"/>
+          </Events>
+        </Component>
+        <Component class="javax.swing.JLabel" name="jLabel1">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="org/netbeans/modules/jackpot30/remotingapi/options/Bundle.properties" key="CustomizeRemoteIndex.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
+      </SubComponents>
+    </Container>
+  </SubComponents>
+</Form>

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-jackpot30/blob/9ed0a377/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/CustomizeRemoteIndex.java
----------------------------------------------------------------------
diff --git a/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/CustomizeRemoteIndex.java b/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/CustomizeRemoteIndex.java
new file mode 100644
index 0000000..7dff967
--- /dev/null
+++ b/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/CustomizeRemoteIndex.java
@@ -0,0 +1,616 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2010-2011 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2010-2011 Sun Microsystems, Inc.
+ */
+package org.netbeans.modules.jackpot30.remotingapi.options;
+
+import java.awt.Component;
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.JList;
+import javax.swing.JTextField;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import org.netbeans.modules.jackpot30.remoting.api.RemoteIndex;
+import org.netbeans.modules.jackpot30.remoting.api.WebUtilities;
+import org.openide.NotificationLineSupport;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.URLMapper;
+import org.openide.util.RequestProcessor;
+
+/**
+ *
+ * @author lahvac
+ */
+public class CustomizeRemoteIndex extends javax.swing.JPanel {
+
+    private final JButton okButton;
+
+    public CustomizeRemoteIndex(JButton okButton) {
+        this.okButton = okButton;
+        initComponents();
+        DocumentListener updateErrorsListener = new DocumentListener() {
+            public void insertUpdate(DocumentEvent e) {
+                validateIndexSelection();
+                updateErrors();
+            }
+            public void removeUpdate(DocumentEvent e) {
+                validateIndexSelection();
+                updateErrors();
+            }
+            public void changedUpdate(DocumentEvent e) {}
+        };
+        folder.getDocument().addDocumentListener(updateErrorsListener);
+        indexURL.getDocument().addDocumentListener(new DocumentListener() {
+            public void insertUpdate(DocumentEvent e) {
+                indexURLUpdated();
+            }
+            public void removeUpdate(DocumentEvent e) {
+                indexURLUpdated();
+            }
+            public void changedUpdate(DocumentEvent e) {
+            }
+        });
+        indexInfo.setFont(UIManager.getFont("Label.font"));
+        indexInfo.setBackground(UIManager.getColor("Label.background"));
+        indexInfo.setDisabledTextColor(UIManager.getColor("Label.foreground"));
+    }
+
+    /** This method is called from within the constructor to
+     * initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is
+     * always regenerated by the Form Editor.
+     */
+    @SuppressWarnings("unchecked")
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+        java.awt.GridBagConstraints gridBagConstraints;
+
+        buttonGroup1 = new javax.swing.ButtonGroup();
+        folderPanel = new javax.swing.JPanel();
+        folderLabel = new javax.swing.JLabel();
+        folderChooser = new javax.swing.JButton();
+        folder = new javax.swing.JTextField();
+        indexInfo = new javax.swing.JTextArea();
+        remoteIndexPanel = new javax.swing.JPanel();
+        indexURL = new javax.swing.JTextField();
+        indexURLLabel = new javax.swing.JLabel();
+        subIndex = new javax.swing.JComboBox();
+        jLabel1 = new javax.swing.JLabel();
+
+        setBorder(javax.swing.BorderFactory.createEmptyBorder(12, 12, 12, 12));
+        setLayout(new java.awt.GridBagLayout());
+
+        folderPanel.setLayout(new java.awt.GridBagLayout());
+
+        org.openide.awt.Mnemonics.setLocalizedText(folderLabel, org.openide.util.NbBundle.getMessage(CustomizeRemoteIndex.class, "CustomizeRemoteIndex.folderLabel.text")); // NOI18N
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
+        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 6);
+        folderPanel.add(folderLabel, gridBagConstraints);
+
+        org.openide.awt.Mnemonics.setLocalizedText(folderChooser, org.openide.util.NbBundle.getMessage(CustomizeRemoteIndex.class, "CustomizeRemoteIndex.folderChooser.text")); // NOI18N
+        folderChooser.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                folderChooserActionPerformed(evt);
+            }
+        });
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.gridx = 2;
+        gridBagConstraints.gridy = 0;
+        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
+        gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 0);
+        folderPanel.add(folderChooser, gridBagConstraints);
+
+        folder.setText(org.openide.util.NbBundle.getMessage(CustomizeRemoteIndex.class, "CustomizeRemoteIndex.folder.text")); // NOI18N
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.gridx = 1;
+        gridBagConstraints.gridy = 0;
+        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+        gridBagConstraints.weightx = 1.0;
+        folderPanel.add(folder, gridBagConstraints);
+
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.gridx = 0;
+        gridBagConstraints.gridy = 0;
+        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
+        gridBagConstraints.weightx = 1.0;
+        add(folderPanel, gridBagConstraints);
+
+        indexInfo.setColumns(20);
+        indexInfo.setEditable(false);
+        indexInfo.setRows(5);
+        indexInfo.setBorder(null);
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.gridx = 0;
+        gridBagConstraints.gridy = 2;
+        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
+        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+        gridBagConstraints.weightx = 1.0;
+        gridBagConstraints.weighty = 1.0;
+        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
+        add(indexInfo, gridBagConstraints);
+
+        indexURL.setColumns(40);
+        indexURL.setText(org.openide.util.NbBundle.getMessage(CustomizeRemoteIndex.class, "CustomizeRemoteIndex.indexURL.text")); // NOI18N
+
+        org.openide.awt.Mnemonics.setLocalizedText(indexURLLabel, org.openide.util.NbBundle.getMessage(CustomizeRemoteIndex.class, "CustomizeRemoteIndex.indexURLLabel.text")); // NOI18N
+
+        subIndex.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                subIndexActionPerformed(evt);
+            }
+        });
+
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(CustomizeRemoteIndex.class, "CustomizeRemoteIndex.jLabel1.text")); // NOI18N
+
+        javax.swing.GroupLayout remoteIndexPanelLayout = new javax.swing.GroupLayout(remoteIndexPanel);
+        remoteIndexPanel.setLayout(remoteIndexPanelLayout);
+        remoteIndexPanelLayout.setHorizontalGroup(
+            remoteIndexPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(remoteIndexPanelLayout.createSequentialGroup()
+                .addContainerGap()
+                .addGroup(remoteIndexPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addGroup(remoteIndexPanelLayout.createSequentialGroup()
+                        .addGap(12, 12, 12)
+                        .addComponent(jLabel1)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addComponent(subIndex, 0, 589, Short.MAX_VALUE))
+                    .addGroup(remoteIndexPanelLayout.createSequentialGroup()
+                        .addComponent(indexURLLabel)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addComponent(indexURL, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
+                .addContainerGap())
+        );
+        remoteIndexPanelLayout.setVerticalGroup(
+            remoteIndexPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(remoteIndexPanelLayout.createSequentialGroup()
+                .addContainerGap()
+                .addGroup(remoteIndexPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(indexURLLabel)
+                    .addComponent(indexURL, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+                .addGroup(remoteIndexPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                    .addComponent(jLabel1)
+                    .addComponent(subIndex, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+        );
+
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.gridx = 0;
+        gridBagConstraints.gridy = 1;
+        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+        gridBagConstraints.weightx = 1.0;
+        add(remoteIndexPanel, gridBagConstraints);
+    }// </editor-fold>//GEN-END:initComponents
+
+    private void folderChooserActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_folderChooserActionPerformed
+        showFileChooser(folder);
+}//GEN-LAST:event_folderChooserActionPerformed
+
+    private void subIndexActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_subIndexActionPerformed
+        subindexSelectionUpdated();
+    }//GEN-LAST:event_subIndexActionPerformed
+
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.ButtonGroup buttonGroup1;
+    private javax.swing.JTextField folder;
+    private javax.swing.JButton folderChooser;
+    private javax.swing.JLabel folderLabel;
+    private javax.swing.JPanel folderPanel;
+    private javax.swing.JTextArea indexInfo;
+    private javax.swing.JTextField indexURL;
+    private javax.swing.JLabel indexURLLabel;
+    private javax.swing.JLabel jLabel1;
+    private javax.swing.JPanel remoteIndexPanel;
+    private javax.swing.JComboBox subIndex;
+    // End of variables declaration//GEN-END:variables
+
+    private void showFileChooser(JTextField folder) {
+        JFileChooser c = new JFileChooser();
+
+        c.setSelectedFile(new File(folder.getText()));
+        c.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+        c.setMultiSelectionEnabled(false);
+        c.setApproveButtonText("Select");
+
+        if (c.showDialog(this, null) == JFileChooser.APPROVE_OPTION) {
+            folder.setText(c.getSelectedFile().getAbsolutePath());
+        }
+//
+//        URL result = FSChooser.select("Select folder", "Select", Utils.fromDisplayName(folder.getText()));
+//
+//        if (result != null) {
+//            folder.setText(Utils.toDisplayName(result));
+//        }
+    }
+
+    private String tempSubIndexSelection;
+    public void setIndex(RemoteIndex index) {
+        URL localFolder = index.getLocalFolder();
+        folder.setText(localFolder != null ? Utils.toDisplayName(localFolder) : "");
+        indexURL.setText(index.remote.toExternalForm());
+        tempSubIndexSelection = index.remoteSegment;
+    }
+
+    private String getSubIndexSelectedItem() {
+        String sel = (String) subIndex.getSelectedItem();
+
+        if (sel == null) {
+            return tempSubIndexSelection;
+        }
+
+        return sel;
+    }
+    
+    public RemoteIndex getIndex() {
+        try {
+            String folderText = folder.getText();
+            return RemoteIndex.create(!folderText.isEmpty() ? Utils.fromDisplayName(folderText) : null, new URL(indexURL.getText()), getSubIndexSelectedItem());
+        } catch (MalformedURLException ex) {
+            throw new IllegalStateException(ex);
+        }
+    }
+
+    private NotificationLineSupport notificationSupport;
+
+    public void setNotificationSupport(NotificationLineSupport notificationSupport) {
+        this.notificationSupport = notificationSupport;
+    }
+
+    private void updateErrors() {
+        notificationSupport.clearMessages();
+
+        String folderText = folder.getText();
+
+        if (!folderText.isEmpty()) {
+            URL folderURL = Utils.fromDisplayName(folderText);
+            FileObject folder = URLMapper.findFileObject(folderURL);
+
+            if (folder == null) {
+                notificationSupport.setErrorMessage("Specified directory does not exist.");
+                okButton.setEnabled(false);
+                return;
+            }
+
+            if (!folder.isFolder()) {
+                notificationSupport.setErrorMessage("Specified directory is not directory.");
+                okButton.setEnabled(false);
+                return ;
+            }
+        }
+
+        if (checkingIndexURL.get()) {
+            notificationSupport.setInformationMessage("Checking index URL");
+            okButton.setEnabled(false);
+            return;
+        }
+
+        if (checkingIndexAgainstFolder.get()) {
+            notificationSupport.setInformationMessage("Checking local folder against the index");
+        }
+
+        String urlError = checkingIndexURLError.get();
+
+        if (urlError != null) {
+            notificationSupport.setErrorMessage(urlError);
+            okButton.setEnabled(false);
+            return;
+        }
+
+        String urlWarning = checkingIndexURLWarning.get();
+
+        if (urlWarning != null) {
+            notificationSupport.setWarningMessage(urlWarning);
+        }
+        
+        okButton.setEnabled(true);
+    }
+
+    private final AtomicBoolean checkingIndexURL = new AtomicBoolean();
+    private final AtomicReference<String> checkingIndexURLContentCopy = new AtomicReference<String>();
+    private final AtomicReference<String> checkingIndexURLError = new AtomicReference<String>();
+    private final AtomicReference<String> checkingIndexURLWarning = new AtomicReference<String>();
+    private final AtomicReference<Collection<? extends String>> indexRandomFiles = new AtomicReference<Collection<? extends String>>();
+
+    private void indexURLUpdated() {
+        indexRandomFiles.set(null);
+        checkingIndexURLContentCopy.set(indexURL.getText());
+        urlCheckerTask.cancel();
+        urlCheckerTask.schedule(50);
+    }
+
+    private static final RequestProcessor WORKER = new RequestProcessor(CustomizeRemoteIndex.class.getName(), 1, false, false);
+    private final RequestProcessor.Task urlCheckerTask = WORKER.create(new Runnable() {
+
+        public void run() {
+            checkingIndexURL.set(true);
+            checkingIndexURLError.set(null);
+            indexRandomFiles.set(null);
+
+            SwingUtilities.invokeLater(new Runnable() {
+                public void run() {
+                    updateErrors();
+                }
+            });
+
+            String urlText = checkingIndexURLContentCopy.get();
+            Collection<? extends String> subindices = null;
+
+            try {
+                URL url = new URL(urlText);
+
+                if (!url.getPath().endsWith("/"))
+                    url = new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getPath() + "/" + (url.getQuery() != null ? "?" + url.getQuery() : ""));
+                
+                subindices = new ArrayList<String>(WebUtilities.requestStringArrayResponse(url.toURI().resolve("list"), new AtomicBoolean()));
+
+                for (Iterator<? extends String> it = subindices.iterator(); it.hasNext();) {
+                    String idx = it.next();
+                    if (idx.trim().isEmpty() || !idx.contains(":")) it.remove();
+                }
+
+                if (subindices.isEmpty()) {
+                   checkingIndexURLError.set("Not an index.");
+                }
+            } catch (URISyntaxException ex) {
+                checkingIndexURLError.set(ex.getLocalizedMessage());
+            } catch (MalformedURLException ex) {
+                checkingIndexURLError.set(ex.getLocalizedMessage());
+            } catch (ThreadDeath td) {
+                throw td;
+            } catch (Throwable t) {//#6541019
+                checkingIndexURLError.set("Invalid URL");
+            }
+            
+            checkingIndexURL.set(false);
+
+            final Collection<? extends String> subindicesFinal = subindices;
+
+            SwingUtilities.invokeLater(new Runnable() {
+                public void run() {
+                    updateErrors();
+
+                    if (subindicesFinal == null || subindicesFinal.isEmpty()) return;
+
+                    DefaultComboBoxModel model = (DefaultComboBoxModel) subIndex.getModel();
+                    String selected = getSubIndexSelectedItem();
+
+                    tempSubIndexSelection = null;
+                    model.removeAllElements();
+
+                    boolean containsSelection = false;
+                    Map<String, String> displayNames = new HashMap<String, String>();
+
+                    for (String subindex : subindicesFinal) {
+                        String[] subindexSplit = subindex.split(":", 2);
+                        if (subindexSplit[0].equals(selected)) containsSelection = true;
+                        model.addElement(subindexSplit[0]);
+                        displayNames.put(subindexSplit[0], subindexSplit[1]);
+                    }
+
+                    if (containsSelection) {
+                        model.setSelectedItem(selected);
+                    }
+
+                    subindexSelectionUpdated();
+                    subIndex.setRenderer(new RendererImpl(displayNames));
+                }
+            });
+        }
+    });
+
+    private final AtomicBoolean checkingIndexAgainstFolder = new AtomicBoolean();
+    private final AtomicReference<String> indexInfoURLContentCopy = new AtomicReference<String>();
+    private final AtomicReference<String> indexInfoSubIndexCopy = new AtomicReference<String>();
+    private final AtomicReference<String> checkingIndexFolderContentCopy = new AtomicReference<String>();
+    private void subindexSelectionUpdated() {
+        indexRandomFiles.set(null);
+        validateIndexSelection();
+    }
+    private void validateIndexSelection() {
+        indexInfoURLContentCopy.set(indexURL.getText());
+        indexInfoSubIndexCopy.set((String) subIndex.getSelectedItem());
+        checkingIndexFolderContentCopy.set(folder.getText());
+        indexInfoTask.cancel();
+        indexInfoTask.schedule(50);
+    }
+
+    private final RequestProcessor.Task indexInfoTask = WORKER.create(new Runnable() {
+
+        public void run() {
+            String localFolder = checkingIndexFolderContentCopy.get();
+
+            if (!localFolder.isEmpty()) {
+            checkingIndexAgainstFolder.set(true);
+            checkingIndexURLWarning.set(null);
+
+            SwingUtilities.invokeLater(new Runnable() {
+                public void run() {
+                    updateErrors();
+                }
+            });
+            
+            String urlText = indexInfoURLContentCopy.get();
+            String subIndex = indexInfoSubIndexCopy.get();
+            URL folderURL = Utils.fromDisplayName(localFolder);
+            FileObject folder = URLMapper.findFileObject(folderURL);
+
+            try {
+                if (folder != null) {
+                Collection<? extends String> random = indexRandomFiles.get();
+
+                if (random == null) {
+                    URL url = new URL(urlText);
+
+                    if (!url.getPath().endsWith("/"))
+                        url = new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getPath() + "/" + (url.getQuery() != null ? "?" + url.getQuery() : ""));
+
+                    indexRandomFiles.set(random = WebUtilities.requestStringArrayResponse(url.toURI().resolve("source/randomfiles?path=" + WebUtilities.escapeForQuery(subIndex))));
+                }
+
+                if (!random.isEmpty()) {
+                    boolean found = matches(folder, random);
+
+                    if (!found) {
+                        if (folder.getParent() != null && matches(folder.getParent(), random)) {
+                            checkingIndexURLWarning.set("The given folder is unlikely to match the index content, parent folder does.");
+                        } else {
+                            StringBuilder matchingChildren = new StringBuilder();
+
+                            for (FileObject c : folder.getChildren()) {
+                                if (matches(c, random)) {
+                                    if (matchingChildren.length() > 0) matchingChildren.append(", ");
+                                    matchingChildren.append(c.getName());
+                                }
+                            }
+
+                            if (matchingChildren.length() > 0) {
+                                checkingIndexURLWarning.set("The given folder is unlikely to match the index content, subfolders: " + matchingChildren.toString() + " do.");
+                            } else {
+                                checkingIndexURLWarning.set("The given folder is unlikely to match the index content.");
+                            }
+                        }
+                    }
+                } else {
+                    //no random files? ignoring for now...
+                }
+                }
+            } catch (URISyntaxException ex) {
+                checkingIndexURLError.set(ex.getLocalizedMessage());
+            } catch (MalformedURLException ex) {
+                checkingIndexURLError.set(ex.getLocalizedMessage());
+            } catch (ThreadDeath td) {
+                throw td;
+            } catch (Throwable t) {//#6541019
+                checkingIndexURLError.set("Invalid URL");
+            } finally {
+                checkingIndexAgainstFolder.set(false);
+            }
+            }
+
+            //XXX: the index currently does not provide the info anyway...
+//            IndexInfo info = null;
+//
+//            try {
+//                URL url = new URL(urlText);
+//
+//                if (!url.getPath().endsWith("/"))
+//                    url = new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getPath() + "/" + (url.getQuery() != null ? "?" + url.getQuery() : ""));
+//
+//                String indexInfoText = WebUtilities.requestStringResponse(url.toURI().resolve("info?path=" + WebUtilities.escapeForQuery(subIndex)));
+//                info = IndexInfo.empty();
+//
+//                if (indexInfoText != null)
+//                    Pojson.update(info, indexInfoText);
+//            } catch (URISyntaxException ex) {
+//                Logger.getLogger(CustomizeRemoteIndex.class.getName()).log(Level.FINE, null, ex);
+//            } catch (MalformedURLException ex) {
+//                Logger.getLogger(CustomizeRemoteIndex.class.getName()).log(Level.FINE, null, ex);
+//            }
+//
+//            final IndexInfo infoFinal = info;
+//
+            SwingUtilities.invokeLater(new Runnable() {
+                public void run() {
+                    updateErrors();
+//                    if (infoFinal != null) {
+//                        indexInfo.setText(toDisplayText(infoFinal));
+//                    } else {
+//                        indexInfo.setText("");
+//                    }
+                }
+            });
+        }
+
+        private boolean matches(FileObject folder, Collection<? extends String> random) {
+            boolean found = false;
+            for (String rel : random) {
+                if (folder.getFileObject(rel) != null) {
+                    found = true;
+                    break;
+                }
+            }
+            return found;
+        }
+    });
+
+//    private static String toDisplayText(IndexInfo info) {
+//        StringBuilder sb = new StringBuilder();
+//
+//        if (info.sourceLocation != null) {
+//            sb.append("Source Location: ").append(info.sourceLocation).append("\n");
+//        }
+//        if (info.lastUpdate >= 0) {
+//            sb.append("Last Update:\t").append(DateFormat.getDateTimeInstance().format(new Date(info.lastUpdate))).append("\n");
+//        }
+//        if (info.totalFiles >= 0) {
+//            sb.append("Indexed Files:\t").append(info.totalFiles).append("\n");
+//        }
+//
+//        return sb.toString();
+//    }
+
+    private static final class RendererImpl extends DefaultListCellRenderer {
+        private final Map<String, String> displayNames;
+        public RendererImpl(Map<String, String> displayNames) {
+            this.displayNames = displayNames;
+        }
+
+        @Override
+        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+            return super.getListCellRendererComponent(list, displayNames.get(value), index, isSelected, cellHasFocus);
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-jackpot30/blob/9ed0a377/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/FSChooser.java
----------------------------------------------------------------------
diff --git a/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/FSChooser.java b/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/FSChooser.java
new file mode 100644
index 0000000..e0c442c
--- /dev/null
+++ b/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/FSChooser.java
@@ -0,0 +1,260 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2011 Sun Microsystems, Inc.
+ */
+package org.netbeans.modules.jackpot30.remotingapi.options;
+
+import java.awt.BorderLayout;
+import java.awt.Dialog;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyVetoException;
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import javax.swing.JButton;
+import javax.swing.JPanel;
+import org.netbeans.modules.jackpot30.remoting.api.FileSystemLister;
+import org.openide.DialogDescriptor;
+import org.openide.DialogDisplayer;
+import org.openide.explorer.ExplorerManager;
+import org.openide.explorer.view.BeanTreeView;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileStateInvalidException;
+import org.openide.filesystems.FileSystem;
+import org.openide.filesystems.FileUtil;
+import org.openide.filesystems.URLMapper;
+import org.openide.loaders.DataFilter;
+import org.openide.loaders.DataFolder;
+import org.openide.loaders.DataObject;
+import org.openide.nodes.AbstractNode;
+import org.openide.nodes.Children;
+import org.openide.nodes.FilterNode;
+import org.openide.nodes.Node;
+import org.openide.util.Exceptions;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.ServiceProvider;
+
+/**
+ *
+ * @author lahvac
+ */
+public class FSChooser {
+
+    public static URL select(String caption, String okButton, URL preselect) {
+        Node n = new RootNode();
+        final ExplorerManager m = new ExplorerManager();
+
+        m.setRootContext(n);
+
+        class P extends JPanel implements ExplorerManager.Provider {
+            public P() {
+                setLayout(new BorderLayout());
+                add(new BeanTreeView(), BorderLayout.CENTER);
+            }
+            @Override public ExplorerManager getExplorerManager() {
+                return m;
+            }
+        }
+
+        //XXX: asynchronously!
+        FileObject toSelect = preselect != null ? URLMapper.findFileObject(preselect) : null;
+
+        toSelect = toSelect != null ? toSelect : homeFO();
+
+        if (toSelect != null) {
+            try {
+                Node toSelectNode = findFileNode(n, toSelect);
+
+                if (toSelectNode == null) {
+                    FileObject home = homeFO();
+
+                    if (home != null) {
+                        toSelectNode = findFileNode(n, home);
+                    }
+                }
+
+                if (toSelectNode != null) {
+                    m.setSelectedNodes(new Node[] {toSelectNode});
+                }
+            } catch (PropertyVetoException ex) {
+                Exceptions.printStackTrace(ex);
+            }
+        }
+
+        final boolean[] accepted = new boolean[1];
+        final Dialog[] d = new Dialog[1];
+        final JButton ok = new JButton(okButton);
+
+        m.addPropertyChangeListener(new PropertyChangeListener() {
+            @Override public void propertyChange(PropertyChangeEvent evt) {
+                ok.setEnabled(m.getSelectedNodes().length == 1);
+            }
+        });
+
+        ok.addActionListener(new ActionListener() {
+            @Override public void actionPerformed(ActionEvent e) {
+                d[0].setVisible(false);
+                accepted[0] = true;
+            }
+        });
+
+        DialogDescriptor dd = new DialogDescriptor(new P(), caption, true, new Object[] {ok, DialogDescriptor.CANCEL_OPTION}, ok, DialogDescriptor.DEFAULT_ALIGN, null, null);
+
+        d[0] = DialogDisplayer.getDefault().createDialog(dd);
+
+        d[0].setVisible(true);
+
+        if (accepted[0]) {
+            try {
+                return m.getSelectedNodes()[0].getLookup().lookup(FileObject.class).getURL();
+            } catch (FileStateInvalidException ex) {
+                Exceptions.printStackTrace(ex);
+                return null;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    private static FileObject homeFO() {
+        return FileUtil.toFileObject(FileUtil.normalizeFile(new File(System.getProperty("user.home"))));
+    }
+
+    private static Node findFileNode(Node root, FileObject file) {
+        for (Node n : root.getChildren().getNodes(true)) {
+            FileObject p = n.getLookup().lookup(FileObject.class);
+
+            if (p == null) {
+                continue;
+            }
+
+            if (FileUtil.isParentOf(p, file)) {
+                return findFileNode(n, file);
+            }
+
+            if (p == file) return n;
+        }
+
+        return null;
+    }
+    
+    private static final class RootNode extends AbstractNode {
+        public RootNode() {
+            super(new RootChildren());
+        }
+    }
+
+    private static final class RootChildren extends Children.Keys<FileSystem> {
+
+        @Override
+        protected Node[] createNodes(FileSystem key) {
+            try {
+                DataFolder f = DataFolder.findFolder(key.getRoot());
+                
+                return new Node[] {
+                    new FSNode(f)
+                };
+            } catch (FileStateInvalidException ex) {
+                Exceptions.printStackTrace(ex);
+                return new Node[0];
+            }
+        }
+
+        @Override
+        protected void addNotify() {
+            List<FileSystem> fss = new ArrayList<FileSystem>();
+
+            for (FileSystemLister l : Lookup.getDefault().lookupAll(FileSystemLister.class)) {
+                fss.addAll(l.getKnownFileSystems());
+            }
+
+            setKeys(fss);
+            
+            super.addNotify();
+        }
+
+        @Override
+        protected void removeNotify() {
+            super.removeNotify();
+
+            setKeys(Collections.<FileSystem>emptyList());
+        }
+    }
+    
+    private static final class FSNode extends FilterNode {
+
+        public FSNode(DataFolder original) throws FileStateInvalidException {
+            super(original.getNodeDelegate(), original.createNodeChildren(new DataFilter() {
+                @Override public boolean acceptDataObject(DataObject obj) {
+                    return obj instanceof DataFolder;
+                }
+            }));
+        }
+    }
+    
+    @ServiceProvider(service=FileSystemLister.class)
+    public static final class LocalFileSystemLister implements FileSystemLister {
+        @Override public Collection<? extends FileSystem> getKnownFileSystems() {
+            Set<FileSystem> fss = new HashSet<FileSystem>();
+
+            for (File f : File.listRoots()) {
+                FileObject fo = FileUtil.toFileObject(f);
+
+                if (fo != null) {
+                    try {
+                        fss.add(fo.getFileSystem());
+                    } catch (FileStateInvalidException ex) {
+                        Exceptions.printStackTrace(ex);
+                    }
+                }
+            }
+
+            return fss;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-jackpot30/blob/9ed0a377/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/IndexOptionsPanelController.java
----------------------------------------------------------------------
diff --git a/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/IndexOptionsPanelController.java b/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/IndexOptionsPanelController.java
new file mode 100644
index 0000000..e7c2024
--- /dev/null
+++ b/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/IndexOptionsPanelController.java
@@ -0,0 +1,113 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2011 Sun Microsystems, Inc.
+ */
+package org.netbeans.modules.jackpot30.remotingapi.options;
+
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import javax.swing.JComponent;
+import org.netbeans.spi.options.OptionsPanelController;
+import org.openide.util.HelpCtx;
+import org.openide.util.Lookup;
+
+@OptionsPanelController.SubRegistration(location = "Editor",
+displayName = "#AdvancedOption_DisplayName_Index",
+keywords = "#AdvancedOption_Keywords_Index",
+keywordsCategory = "Editor/Index")
+public final class IndexOptionsPanelController extends OptionsPanelController {
+
+    private IndexPanel panel;
+    private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
+    private boolean changed;
+
+    public void update() {
+        getPanel().load();
+        changed = false;
+    }
+
+    public void applyChanges() {
+        getPanel().store();
+        changed = false;
+    }
+
+    public void cancel() {
+        // need not do anything special, if no changes have been persisted yet
+    }
+
+    public boolean isValid() {
+        return getPanel().valid();
+    }
+
+    public boolean isChanged() {
+        return changed;
+    }
+
+    public HelpCtx getHelpCtx() {
+        return null; // new HelpCtx("...ID") if you have a help set
+    }
+
+    public JComponent getComponent(Lookup masterLookup) {
+        return getPanel();
+    }
+
+    public void addPropertyChangeListener(PropertyChangeListener l) {
+        pcs.addPropertyChangeListener(l);
+    }
+
+    public void removePropertyChangeListener(PropertyChangeListener l) {
+        pcs.removePropertyChangeListener(l);
+    }
+
+    private IndexPanel getPanel() {
+        if (panel == null) {
+            panel = new IndexPanel(this);
+        }
+        return panel;
+    }
+
+    void changed() {
+        if (!changed) {
+            changed = true;
+            pcs.firePropertyChange(OptionsPanelController.PROP_CHANGED, false, true);
+        }
+        pcs.firePropertyChange(OptionsPanelController.PROP_VALID, null, null);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-jackpot30/blob/9ed0a377/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/IndexPanel.form
----------------------------------------------------------------------
diff --git a/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/IndexPanel.form b/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/IndexPanel.form
new file mode 100644
index 0000000..82cc349
--- /dev/null
+++ b/remoting/ide/api/src/org/netbeans/modules/jackpot30/remotingapi/options/IndexPanel.form
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="1" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jScrollPane1" pref="263" max="32767" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Component id="removeButton" alignment="1" max="32767" attributes="1"/>
+                  <Component id="addButton" alignment="1" max="32767" attributes="1"/>
+                  <Component id="editButton" alignment="1" max="32767" attributes="0"/>
+                  <Component id="synchronizeOffline" alignment="0" max="32767" attributes="0"/>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Component id="jScrollPane1" pref="306" max="32767" attributes="0"/>
+                  <Group type="102" attributes="0">
+                      <Component id="addButton" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="editButton" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="removeButton" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace max="32767" attributes="0"/>
+                      <Component id="synchronizeOffline" min="-2" max="-2" attributes="0"/>
+                  </Group>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Container class="javax.swing.JScrollPane" name="jScrollPane1">
+      <AuxValues>
+        <AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
+        <AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
+        <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
+      </AuxValues>
+
+      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+      <SubComponents>
+        <Component class="javax.swing.JTable" name="indices">
+          <Properties>
+            <Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
+              <Table columnCount="4" rowCount="4">
+                <Column editable="true" title="Title 1" type="java.lang.Object"/>
+                <Column editable="true" title="Title 2" type="java.lang.Object"/>
+                <Column editable="true" title="Title 3" type="java.lang.Object"/>
+                <Column editable="true" title="Title 4" type="java.lang.Object"/>
+              </Table>
+            </Property>
+          </Properties>
+        </Component>
+      </SubComponents>
+    </Container>
+    <Component class="javax.swing.JButton" name="addButton">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/jackpot30/remotingapi/options/Bundle.properties" key="IndexPanel.addButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="addButtonActionPerformed"/>
+      </Events>
+    </Component>
+    <Component class="javax.swing.JButton" name="removeButton">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/jackpot30/remotingapi/options/Bundle.properties" key="IndexPanel.removeButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="removeButtonActionPerformed"/>
+      </Events>
+    </Component>
+    <Component class="javax.swing.JButton" name="editButton">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="org/netbeans/modules/jackpot30/remotingapi/options/Bundle.properties" key="IndexPanel.editButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="editButtonActionPerformed"/>
+      </Events>
+    </Component>
+    <Component class="javax.swing.JButton" name="synchronizeOffline">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <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})"/>
+        </Property>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="synchronizeOfflineActionPerformed"/>
+      </Events>
+    </Component>
+  </SubComponents>
+</Form>