diff --git a/Core/build.xml b/Core/build.xml index a9807f490b..c698835266 100644 --- a/Core/build.xml +++ b/Core/build.xml @@ -123,8 +123,8 @@ tofile="${ext.dir}/sleuthkit-${TSK_VERSION}.jar"/> - + ext/commons-codec-1.11.jar release\modules\ext\commons-codec-1.11.jar + + ext/postgresql-42.2.18.jar + release\modules\ext\postgresql-42.2.18.jar + ext/commons-pool2-2.4.2.jar release\modules\ext\commons-pool2-2.4.2.jar @@ -736,10 +740,6 @@ ext/jai_imageio-1.1.jar release\modules\ext\jai_imageio-1.1.jar - - ext/postgresql-9.4.1211.jre7.jar - release\modules\ext\postgresql-9.4.1211.jre7.jar - ext/junit-3.8.1.jar release\modules\ext\junit-3.8.1.jar diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index 204e475ef3..987323a52b 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -253,3 +253,7 @@ UnpackagePortableCaseProgressDialog.resultLabel.text=resultLabel UnpackagePortableCaseDialog.extractLabel.text=Folder to extract to: UnpackagePortableCaseDialog.caseLabel.text=Portable Case: NewCaseVisualPanel1.caseDataStoredLabel.text_1=Case data will be stored in the following directory: +SolrNotConfiguredDialog.okButton.text=OK +SolrNotConfiguredDialog.title=Solr 8 Server Not Configured +SolrNotConfiguredDialog.EmptyKeywordSearchHostName=Solr 8 connection parameters are not configured. Please go to Tools->Options->Multi User. +SolrNotConfiguredDialog.messageLabel.text=Multi-User cases are enabled but Solr 8 server has not been configured.
\nNew cases can only be created with Solr 8. Please go to Tools->Options->Multi User.\n diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED index f5c18a1640..e59c37fea7 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED @@ -471,3 +471,7 @@ UnpackagePortableCaseProgressDialog.resultLabel.text=resultLabel UnpackagePortableCaseDialog.extractLabel.text=Folder to extract to: UnpackagePortableCaseDialog.caseLabel.text=Portable Case: NewCaseVisualPanel1.caseDataStoredLabel.text_1=Case data will be stored in the following directory: +SolrNotConfiguredDialog.okButton.text=OK +SolrNotConfiguredDialog.title=Solr 8 Server Not Configured +SolrNotConfiguredDialog.EmptyKeywordSearchHostName=Solr 8 connection parameters are not configured. Please go to Tools->Options->Multi User. +SolrNotConfiguredDialog.messageLabel.text=Multi-User cases are enabled but Solr 8 server has not been configured.
\nNew cases can only be created with Solr 8. Please go to Tools->Options->Multi User.\n diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/SolrNotConfiguredDialog.form b/Core/src/org/sleuthkit/autopsy/casemodule/SolrNotConfiguredDialog.form new file mode 100755 index 0000000000..15bf89bc47 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/SolrNotConfiguredDialog.form @@ -0,0 +1,78 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/SolrNotConfiguredDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/SolrNotConfiguredDialog.java new file mode 100755 index 0000000000..3adf647596 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/SolrNotConfiguredDialog.java @@ -0,0 +1,110 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.casemodule; + +import java.awt.Dimension; +import java.awt.Toolkit; +import javax.swing.JFrame; +import org.openide.util.ImageUtilities; +import org.openide.windows.WindowManager; + +/** + * A dialog to notify the user on startup when Solr 8 server is not configured. + */ +class SolrNotConfiguredDialog extends javax.swing.JDialog { + + private static final long serialVersionUID = 1L; + + /** + * Creates new form SolrNotConfiguredDialog + */ + SolrNotConfiguredDialog() { + super((JFrame) WindowManager.getDefault().getMainWindow(), true); + // Center the startup window. + Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); + int width = getSize().width; + int height = getSize().height; + setLocation((screenDimension.width - width) / 2, (screenDimension.height - height) / 2); + initComponents(); + setIconImage(ImageUtilities.loadImage("org/sleuthkit/autopsy/images/warning16.png", false)); + } + + /** + * 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") + // //GEN-BEGIN:initComponents + private void initComponents() { + + okButton = new javax.swing.JButton(); + messageLabel = new javax.swing.JLabel(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + setTitle(org.openide.util.NbBundle.getMessage(SolrNotConfiguredDialog.class, "SolrNotConfiguredDialog.title")); // NOI18N + setModal(true); + setName("toolsNotFound"); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(okButton, org.openide.util.NbBundle.getMessage(SolrNotConfiguredDialog.class, "SolrNotConfiguredDialog.okButton.text")); // NOI18N + okButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + okButtonActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(messageLabel, org.openide.util.NbBundle.getMessage(SolrNotConfiguredDialog.class, "SolrNotConfiguredDialog.messageLabel.text")); // NOI18N + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(0, 15, Short.MAX_VALUE) + .addComponent(messageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 420, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addGap(189, 189, 189) + .addComponent(okButton) + .addGap(0, 193, Short.MAX_VALUE))) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(messageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(okButton) + .addContainerGap()) + ); + + pack(); + }// //GEN-END:initComponents + + private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed + this.dispose(); + }//GEN-LAST:event_okButtonActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel messageLabel; + private javax.swing.JButton okButton; + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/StartupWindowProvider.java b/Core/src/org/sleuthkit/autopsy/casemodule/StartupWindowProvider.java index b532405ef9..9b62bdb0e0 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/StartupWindowProvider.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/StartupWindowProvider.java @@ -23,11 +23,15 @@ import java.util.Iterator; import java.util.logging.Level; import org.netbeans.spi.sendopts.OptionProcessor; import org.openide.util.Lookup; +import org.openide.util.NbBundle; import org.sleuthkit.autopsy.commandlineingest.CommandLineIngestManager; import org.sleuthkit.autopsy.commandlineingest.CommandLineOpenCaseManager; import org.sleuthkit.autopsy.commandlineingest.CommandLineOptionProcessor; import org.sleuthkit.autopsy.commandlineingest.CommandLineStartupWindow; +import org.sleuthkit.autopsy.core.RuntimeProperties; +import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; /** * Provides the start up window to rest of the application. It may return the @@ -76,6 +80,10 @@ public class StartupWindowProvider implements StartupWindowInterface { } } + if (RuntimeProperties.runningWithGUI()) { + checkSolr(); + } + //discover the registered windows Collection startupWindows = Lookup.getDefault().lookupAll(StartupWindowInterface.class); @@ -115,6 +123,21 @@ public class StartupWindowProvider implements StartupWindowInterface { } } + private void checkSolr() { + + // if Multi-User settings are enabled and Solr8 server is not configured, + // display an error message and a dialog + if (UserPreferences.getIsMultiUserModeEnabled() && UserPreferences.getIndexingServerHost().isEmpty()) { + // Solr 8 host name is not configured. This could be the first time user + // runs Autopsy with Solr 8. Display a message. + MessageNotifyUtil.Notify.error(NbBundle.getMessage(CueBannerPanel.class, "SolrNotConfiguredDialog.title"), + NbBundle.getMessage(SolrNotConfiguredDialog.class, "SolrNotConfiguredDialog.EmptyKeywordSearchHostName")); + + SolrNotConfiguredDialog dialog = new SolrNotConfiguredDialog(); + dialog.setVisible(true); + } + } + /** * Checks whether Autopsy is running from command line. There is an * OptionProcessor that is responsible for processing command line inputs. diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/multiusercases/CoordinationServiceUtils.java b/Core/src/org/sleuthkit/autopsy/casemodule/multiusercases/CoordinationServiceUtils.java index d4b0399ff8..c10e6b6fd2 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/multiusercases/CoordinationServiceUtils.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/multiusercases/CoordinationServiceUtils.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019-2019 Basis Technology Corp. + * Copyright 2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresCentralRepo.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresCentralRepo.java index f1afb941bc..e72bfa9359 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresCentralRepo.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresCentralRepo.java @@ -198,11 +198,11 @@ final class PostgresCentralRepo extends RdbmsCentralRepo { if (connectionPool == null) { setupConnectionPool(); } - } - try { - return connectionPool.getConnection(); - } catch (SQLException ex) { - throw new CentralRepoException("Error getting connection from connection pool.", Bundle.PostgresEamDb_connectionFailed_message(), ex); // NON-NLS + try { + return connectionPool.getConnection(); + } catch (SQLException ex) { + throw new CentralRepoException("Error getting connection from connection pool.", Bundle.PostgresEamDb_connectionFailed_message(), ex); // NON-NLS + } } } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/CentralRepoIngestModule.java b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/CentralRepoIngestModule.java index a7c3bd41e0..210e361261 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/CentralRepoIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/CentralRepoIngestModule.java @@ -67,7 +67,7 @@ final class CentralRepoIngestModule implements FileIngestModule { private static final String MODULE_NAME = CentralRepoIngestModuleFactory.getModuleName(); - static final boolean DEFAULT_FLAG_TAGGED_NOTABLE_ITEMS = true; + static final boolean DEFAULT_FLAG_TAGGED_NOTABLE_ITEMS = false; static final boolean DEFAULT_FLAG_PREVIOUS_DEVICES = false; static final boolean DEFAULT_CREATE_CR_PROPERTIES = true; diff --git a/Core/src/org/sleuthkit/autopsy/commandlineingest/UserPreferences.java b/Core/src/org/sleuthkit/autopsy/commandlineingest/UserPreferences.java index 63c59ca852..f797a4cb1b 100755 --- a/Core/src/org/sleuthkit/autopsy/commandlineingest/UserPreferences.java +++ b/Core/src/org/sleuthkit/autopsy/commandlineingest/UserPreferences.java @@ -18,40 +18,14 @@ */ package org.sleuthkit.autopsy.commandlineingest; -import org.openide.util.NbPreferences; - /** * Provides convenient access to a UserPreferences node for user preferences * with default values. */ public final class UserPreferences { - private static final java.util.prefs.Preferences preferences = NbPreferences.forModule(UserPreferences.class); - private static final String COMMAND_LINE_MODE_RESULTS_FOLDER = "CommandLineModeResultsFolder"; // NON-NLS private static final String COMMAND_LINE_MODE_CONTEXT_STRING = "CommandLineModeContext"; // NON-NLS - // Prevent instantiation. - private UserPreferences() { - } - - /** - * Get results folder for command line mode from persistent storage. - * - * @return String Selected output folder. - */ - public static String getCommandLineModeResultsFolder() { - return preferences.get(COMMAND_LINE_MODE_RESULTS_FOLDER, ""); - } - - /** - * Set results folder for command line mode from persistent storage. - * - * @param folder Selected output folder. - */ - public static void setCommandLineModeResultsFolder(String folder) { - preferences.put(COMMAND_LINE_MODE_RESULTS_FOLDER, folder); - } - /** * Get context string for command line mode ingest module settings. * diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/Bundle.properties b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/Bundle.properties index 03e30a6923..dbdc049ee2 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/Bundle.properties @@ -1,20 +1,3 @@ -# Copyright 2020 Basis Technology Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the -# License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an "AS -# IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -# express or implied. See the License for the specific language -# governing permissions and limitations under the License. -# - -DefaultArtifactContentViewer.copyMenuItem.text=Copy -DefaultArtifactContentViewer.selectAllMenuItem.text=Select All MessageArtifactViewer.ccLabel.text=CC: MessageArtifactViewer.rtfbodyScrollPane.TabConstraints.tabTitle=RTF MessageArtifactViewer.toText.text=to list goes here @@ -32,3 +15,19 @@ MessageArtifactViewer.subjectLabel.text=Subject: MessageArtifactViewer.attachmentsPanel.TabConstraints.tabTitle=Attachments MessageArtifactViewer.ccText.text=cc list goes here MessageArtifactViewer.textbodyScrollPane.TabConstraints.tabTitle=Text +DefaultTableArtifactContentViewer.selectAllMenuItem.text=Select All +# Copyright 2020 Basis Technology Corp. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the +# License. You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS +# IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. See the License for the specific language +# governing permissions and limitations under the License. + +DefaultTableArtifactContentViewer.copyMenuItem.text=Copy diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/Bundle.properties-MERGED index 0673318668..e2afbad508 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/Bundle.properties-MERGED @@ -1,18 +1,3 @@ -# Copyright 2020 Basis Technology Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the -# License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an "AS -# IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either -# express or implied. See the License for the specific language -# governing permissions and limitations under the License. -# - CalllogArtifactViewer_cr_disabled_message=Enable Central Repository to view, create and edit personas. CallLogArtifactViewer_heading_metadata=Metadata CallLogArtifactViewer_heading_others=Other Attributes @@ -56,11 +41,15 @@ ContactArtifactViewer_persona_unknown=Unknown ContactArtifactViewer_phones_header=Phone DataContentViewerArtifact.failedToGetAttributes.message=Failed to get some or all attributes from case database DataContentViewerArtifact.failedToGetSourcePath.message=Failed to get source file path from case database -DefaultArtifactContentViewer.attrsTableHeader.sources=Source(s) -DefaultArtifactContentViewer.attrsTableHeader.type=Type -DefaultArtifactContentViewer.attrsTableHeader.value=Value -DefaultArtifactContentViewer.copyMenuItem.text=Copy -DefaultArtifactContentViewer.selectAllMenuItem.text=Select All +DefaultTableArtifactContentViewer.attrsTableHeader.sources=Source(s) +DefaultTableArtifactContentViewer.attrsTableHeader.type=Type +DefaultTableArtifactContentViewer.attrsTableHeader.value=Value +GeneralPurposeArtifactViewer.details.attrHeader=Attributes +GeneralPurposeArtifactViewer.details.dataSource=Data Source +GeneralPurposeArtifactViewer.details.file=File +GeneralPurposeArtifactViewer.details.sourceHeader=Source +GeneralPurposeArtifactViewer.unknown.text=Unknown +GeneralPurposeArtifactViewer_menuitem_copy=Copy MessageAccountPanel.account.justification=Account found in Message artifact MessageAccountPanel_button_create_label=Create MessageAccountPanel_button_view_label=View @@ -87,6 +76,22 @@ MessageArtifactViewer.subjectLabel.text=Subject: MessageArtifactViewer.attachmentsPanel.TabConstraints.tabTitle=Attachments MessageArtifactViewer.ccText.text=cc list goes here MessageArtifactViewer.textbodyScrollPane.TabConstraints.tabTitle=Text +DefaultTableArtifactContentViewer.selectAllMenuItem.text=Select All +# Copyright 2020 Basis Technology Corp. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the +# License. You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS +# IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. See the License for the specific language +# governing permissions and limitations under the License. + +DefaultTableArtifactContentViewer.copyMenuItem.text=Copy PersonaAccountFetcher.account.justification=Account found in Call Log artifact # {0} - Persona count PersonaDisplayTask_persona_count_suffix=(1 of {0}) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/Bundle_ja.properties index baee09ff5a..c76255ef36 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/Bundle_ja.properties @@ -41,8 +41,6 @@ DataContentViewerArtifact.failedToGetSourcePath.message=\u30b1\u30fc\u30b9\u30fb DefaultArtifactContentViewer.attrsTableHeader.sources=\u30bd\u30fc\u30b9 DefaultArtifactContentViewer.attrsTableHeader.type=\u30bf\u30a4\u30d7 DefaultArtifactContentViewer.attrsTableHeader.value=\u5024 -DefaultArtifactContentViewer.copyMenuItem.text=\u30b3\u30d4\u30fc -DefaultArtifactContentViewer.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629e MessageAccountPanel_button_create_label=\u4f5c\u6210 MessageAccountPanel_button_view_label=\u8868\u793a MessageAccountPanel_no_matches=\u4e00\u81f4\u3059\u308b\u3082\u306e\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002 @@ -67,3 +65,5 @@ MessageArtifactViewer.toLabel.text=\u5b9b\u5148\uff1a MessageArtifactViewer.toText.text=\u3053\u3053\u306b\u5b9b\u5148\u30ea\u30b9\u30c8\u3092\u8a18\u5165 MessageArtifactViewer.viewInNewWindowButton.text=\u65b0\u3057\u3044\u30a6\u30a3\u30f3\u30c9\u30a6\u3067\u8868\u793a PersonaDisplayTask_persona_count_suffix=\uff081/{0}\uff09 +DefaultTableArtifactContentViewer.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629e +DefaultTableArtifactContentViewer.copyMenuItem.text=\u30b3\u30d4\u30fc diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java index 13e11d2a2d..fe5e19aff5 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java @@ -44,7 +44,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; * A class to help display a communication artifact in a panel using a * gridbaglayout. */ -public final class CommunicationArtifactViewerHelper { +final class CommunicationArtifactViewerHelper { // Number of columns in the gridbag layout. private final static int MAX_COLS = 4; @@ -68,7 +68,7 @@ public final class CommunicationArtifactViewerHelper { * * @return JLabel Heading label added. */ - public static JLabel addHeader(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String headerString) { + static JLabel addHeader(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String headerString) { Insets savedInsets = constraints.insets; @@ -121,7 +121,7 @@ public final class CommunicationArtifactViewerHelper { * @param valueString Value string to display. * */ - public static void addNameValueRow(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String keyString, String valueString) { + static void addNameValueRow(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String keyString, String valueString) { addKey(panel, gridbagLayout, constraints, keyString); addValue(panel, gridbagLayout, constraints, valueString); } @@ -178,7 +178,7 @@ public final class CommunicationArtifactViewerHelper { * @param gridbagLayout Layout to use. * @param constraints Constraints to use. */ - public static void addPageEndGlue(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints) { + static void addPageEndGlue(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints) { constraints.gridx = 0; diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultArtifactContentViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultTableArtifactContentViewer.form similarity index 85% rename from Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultArtifactContentViewer.form rename to Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultTableArtifactContentViewer.form index a6aa7f13ce..df38743b8b 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultArtifactContentViewer.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultTableArtifactContentViewer.form @@ -11,14 +11,14 @@ - + - + @@ -27,7 +27,7 @@ - + @@ -59,8 +59,11 @@ + + + - + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultArtifactContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultTableArtifactContentViewer.java similarity index 95% rename from Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultArtifactContentViewer.java rename to Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultTableArtifactContentViewer.java index 0c9e41afd6..0c90993a61 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultArtifactContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultTableArtifactContentViewer.java @@ -61,29 +61,29 @@ import org.sleuthkit.autopsy.discovery.ui.AbstractArtifactDetailsPanel; * This class displays a Blackboard artifact as a table of its attributes. */ @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives -public class DefaultArtifactContentViewer extends AbstractArtifactDetailsPanel implements ArtifactContentViewer { +public class DefaultTableArtifactContentViewer extends AbstractArtifactDetailsPanel implements ArtifactContentViewer { @NbBundle.Messages({ - "DefaultArtifactContentViewer.attrsTableHeader.type=Type", - "DefaultArtifactContentViewer.attrsTableHeader.value=Value", - "DefaultArtifactContentViewer.attrsTableHeader.sources=Source(s)", + "DefaultTableArtifactContentViewer.attrsTableHeader.type=Type", + "DefaultTableArtifactContentViewer.attrsTableHeader.value=Value", + "DefaultTableArtifactContentViewer.attrsTableHeader.sources=Source(s)", "DataContentViewerArtifact.failedToGetSourcePath.message=Failed to get source file path from case database", "DataContentViewerArtifact.failedToGetAttributes.message=Failed to get some or all attributes from case database" }) - private final static Logger logger = Logger.getLogger(DefaultArtifactContentViewer.class.getName()); + private final static Logger logger = Logger.getLogger(DefaultTableArtifactContentViewer.class.getName()); private static final long serialVersionUID = 1L; private static final String[] COLUMN_HEADERS = { - Bundle.DefaultArtifactContentViewer_attrsTableHeader_type(), - Bundle.DefaultArtifactContentViewer_attrsTableHeader_value(), - Bundle.DefaultArtifactContentViewer_attrsTableHeader_sources()}; + Bundle.DefaultTableArtifactContentViewer_attrsTableHeader_type(), + Bundle.DefaultTableArtifactContentViewer_attrsTableHeader_value(), + Bundle.DefaultTableArtifactContentViewer_attrsTableHeader_sources()}; private static final int[] COLUMN_WIDTHS = {100, 800, 100}; private static final int CELL_BOTTOM_MARGIN = 5; private static final int CELL_RIGHT_MARGIN = 1; - public DefaultArtifactContentViewer() { + public DefaultTableArtifactContentViewer() { initResultsTable(); initComponents(); resultsTableScrollPane.setViewportView(resultsTable); @@ -201,17 +201,18 @@ public class DefaultArtifactContentViewer extends AbstractArtifactDetailsPanel i selectAllMenuItem = new javax.swing.JMenuItem(); resultsTableScrollPane = new javax.swing.JScrollPane(); - copyMenuItem.setText(org.openide.util.NbBundle.getMessage(DefaultArtifactContentViewer.class, "DefaultArtifactContentViewer.copyMenuItem.text")); // NOI18N + copyMenuItem.setText(org.openide.util.NbBundle.getMessage(DefaultTableArtifactContentViewer.class, "DefaultTableArtifactContentViewer.copyMenuItem.text")); // NOI18N rightClickMenu.add(copyMenuItem); - selectAllMenuItem.setText(org.openide.util.NbBundle.getMessage(DefaultArtifactContentViewer.class, "DefaultArtifactContentViewer.selectAllMenuItem.text")); // NOI18N + selectAllMenuItem.setText(org.openide.util.NbBundle.getMessage(DefaultTableArtifactContentViewer.class, "DefaultTableArtifactContentViewer.selectAllMenuItem.text")); // NOI18N rightClickMenu.add(selectAllMenuItem); - setPreferredSize(new java.awt.Dimension(100, 58)); + setPreferredSize(new java.awt.Dimension(0, 0)); resultsTableScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); resultsTableScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); - resultsTableScrollPane.setPreferredSize(new java.awt.Dimension(620, 34)); + resultsTableScrollPane.setMinimumSize(new java.awt.Dimension(0, 0)); + resultsTableScrollPane.setPreferredSize(new java.awt.Dimension(0, 0)); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.form b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/GeneralPurposeArtifactViewer.form similarity index 87% rename from Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.form rename to Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/GeneralPurposeArtifactViewer.form index 5f3eab1a5f..7fb4b28206 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/GeneralPurposeArtifactViewer.form @@ -1,6 +1,11 @@
+ + + + + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/GeneralPurposeArtifactViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/GeneralPurposeArtifactViewer.java new file mode 100644 index 0000000000..15ef8c4796 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/GeneralPurposeArtifactViewer.java @@ -0,0 +1,383 @@ +/* + * Autopsy + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.contentviewers.artifactviewers; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Toolkit; +import java.awt.datatransfer.StringSelection; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import javax.swing.JLabel; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.JTextPane; +import javax.swing.SwingUtilities; +import org.openide.util.NbBundle; +import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; +import org.sleuthkit.autopsy.discovery.ui.AbstractArtifactDetailsPanel; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * Panel to display the details for an Artifact. + */ +@ServiceProvider(service = ArtifactContentViewer.class) +public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel implements ArtifactContentViewer { + + private static final long serialVersionUID = 1L; + private static final Logger logger = Logger.getLogger(GeneralPurposeArtifactViewer.class.getName()); + // Number of columns in the gridbag layout. + private final static int MAX_COLS = 4; + private final static Insets ROW_INSETS = new java.awt.Insets(0, 12, 0, 0); + private final static Insets HEADER_INSETS = new java.awt.Insets(0, 0, 0, 0); + private final static double GLUE_WEIGHT_X = 1.0; + private final static double TEXT_WEIGHT_X = 0.0; + private final static int LABEL_COLUMN = 0; + private final static int VALUE_COLUMN = 1; + private final static int VALUE_WIDTH = 2; + private final static int LABEL_WIDTH = 1; + private static final Integer[] DEFAULT_ORDERING = new Integer[]{BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_REFERRER.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_HEADERS.getTypeID()}; + private final GridBagLayout gridBagLayout = new GridBagLayout(); + private final GridBagConstraints gridBagConstraints = new GridBagConstraints(); + private final Map orderingMap = new HashMap<>(); + + /** + * Creates new form GeneralPurposeArtifactViewer. + */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + public GeneralPurposeArtifactViewer() { + orderingMap.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID(), DEFAULT_ORDERING); + orderingMap.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID(), DEFAULT_ORDERING); + orderingMap.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID(), DEFAULT_ORDERING); + orderingMap.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID(), DEFAULT_ORDERING); + orderingMap.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID(), DEFAULT_ORDERING); + orderingMap.put(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID(), DEFAULT_ORDERING); + initComponents(); + } + + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + @NbBundle.Messages({"GeneralPurposeArtifactViewer.unknown.text=Unknown"}) + @Override + public void setArtifact(BlackboardArtifact artifact) { + resetComponent(); + if (artifact != null) { + String dataSourceName = Bundle.GeneralPurposeArtifactViewer_unknown_text(); + String sourceFileName = Bundle.GeneralPurposeArtifactViewer_unknown_text(); + Map> attributeMap = new HashMap<>(); + try { + // Get all the attributes and group them by the attributeType + for (BlackboardAttribute bba : artifact.getAttributes()) { + List attrList = attributeMap.get(bba.getAttributeType().getTypeID()); + if (attrList == null) { + attrList = new ArrayList<>(); + } + attrList.add(bba); + attributeMap.put(bba.getAttributeType().getTypeID(), attrList); + } + dataSourceName = artifact.getDataSource().getName(); + sourceFileName = artifact.getParent().getName(); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Unable to get attributes for artifact " + artifact.getArtifactID(), ex); + } + updateView(artifact.getArtifactTypeID(), attributeMap, dataSourceName, sourceFileName); + } + this.setLayout(this.gridBagLayout); + this.revalidate(); + this.repaint(); + } + + /** + * Reset the panel so that it is empty. + */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + private void resetComponent() { + // clear the panel + this.removeAll(); + gridBagConstraints.anchor = GridBagConstraints.FIRST_LINE_START; + gridBagConstraints.gridy = 0; + gridBagConstraints.gridx = LABEL_COLUMN; + gridBagConstraints.weighty = 0.0; + gridBagConstraints.weightx = TEXT_WEIGHT_X; // keep components fixed horizontally. + gridBagConstraints.fill = GridBagConstraints.NONE; + gridBagConstraints.insets = ROW_INSETS; + } + + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + @Override + public Component getComponent() { + // Slap a vertical scrollbar on the panel. + return new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + } + + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + @Override + public boolean isSupported(BlackboardArtifact artifact) { + return (artifact != null) + && (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID() + || artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID() + || artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID() + || artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID()); + } + + @NbBundle.Messages({"GeneralPurposeArtifactViewer.details.attrHeader=Attributes", + "GeneralPurposeArtifactViewer.details.sourceHeader=Source", + "GeneralPurposeArtifactViewer.details.dataSource=Data Source", + "GeneralPurposeArtifactViewer.details.file=File"}) + /** + * 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") + // //GEN-BEGIN:initComponents + private void initComponents() { + + setPreferredSize(new java.awt.Dimension(0, 0)); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 300, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + /** + * Update the view to reflect the current artifact's details. + * + * @param artifactTypeId The BlackboardArtifact type id for the artifact + * being displayed. + * @param attributeMap The map of attributes that exist for the artifact. + * @param dataSourceName The name of the datasource that caused the creation + * of the artifact. + * @param sourceFileName The name of the file that caused the creation of + * the artifact. + */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + private void updateView(Integer artifactTypeId, Map> attributeMap, String dataSourceName, String sourceFileName) { + if (!(artifactTypeId < 1 || artifactTypeId >= Integer.MAX_VALUE)) { + addHeader(Bundle.GeneralPurposeArtifactViewer_details_attrHeader()); + Integer[] orderingArray = orderingMap.get(artifactTypeId); + if (orderingArray == null) { + orderingArray = DEFAULT_ORDERING; + } + for (Integer attrId : orderingArray) { + List attrList = attributeMap.remove(attrId); + if (attrList != null) { + for (BlackboardAttribute bba : attrList) { + addNameValueRow(bba.getAttributeType().getDisplayName(), bba.getDisplayString()); + } + } + } + for (int key : attributeMap.keySet()) { + for (BlackboardAttribute bba : attributeMap.get(key)) { + addNameValueRow(bba.getAttributeType().getDisplayName(), bba.getDisplayString()); + } + } + addHeader(Bundle.GeneralPurposeArtifactViewer_details_sourceHeader()); + addNameValueRow(Bundle.GeneralPurposeArtifactViewer_details_dataSource(), dataSourceName); + addNameValueRow(Bundle.GeneralPurposeArtifactViewer_details_file(), sourceFileName); + // add veritcal glue at the end + addPageEndGlue(); + } + } + + /** + * Adds a new heading to the panel. + * + * @param headerString Heading string to display. + * + * @return JLabel Heading label added. + */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + private JLabel addHeader(String headerString) { + // create label for heading + javax.swing.JLabel headingLabel = new javax.swing.JLabel(); + // add a blank line before the start of new section, unless it's + // the first section + if (gridBagConstraints.gridy != 0) { + gridBagConstraints.gridy++; + add(new javax.swing.JLabel(" "), gridBagConstraints); + addLineEndGlue(); + } + gridBagConstraints.gridy++; + gridBagConstraints.gridx = LABEL_COLUMN;; + // let the header span all of the row + gridBagConstraints.gridwidth = MAX_COLS; + gridBagConstraints.insets = HEADER_INSETS; + // set text + headingLabel.setText(headerString); + // make it large and bold + headingLabel.setFont(headingLabel.getFont().deriveFont(Font.BOLD, headingLabel.getFont().getSize() + 2)); + // add to panel + add(headingLabel, gridBagConstraints); + // reset constraints to normal + gridBagConstraints.gridwidth = LABEL_WIDTH; + // add line end glue + addLineEndGlue(); + gridBagConstraints.insets = ROW_INSETS; + return headingLabel; + } + + /** + * Add a key value row to the specified panel with the specified layout and + * constraints. + * + * @param keyString Key name to display. + * @param valueString Value string to display. + */ + private void addNameValueRow(String keyString, String valueString) { + addKeyAtCol(keyString); + addValueAtCol(valueString); + } + + /** + * Adds a filler/glue at the end of the line to keep the other columns + * aligned, in case the panel is resized. + */ + private void addLineEndGlue() { + // Place the filler just past the last column. + gridBagConstraints.gridx = MAX_COLS; + gridBagConstraints.weightx = GLUE_WEIGHT_X; // take up all the horizontal space + gridBagConstraints.fill = GridBagConstraints.BOTH; + javax.swing.Box.Filler horizontalFiller = new javax.swing.Box.Filler(new Dimension(0, 0), new Dimension(0, 0), new Dimension(32767, 0)); + add(horizontalFiller, gridBagConstraints); + // restore fill & weight + gridBagConstraints.fill = GridBagConstraints.NONE; + gridBagConstraints.weightx = TEXT_WEIGHT_X; + } + + /** + * Adds a filler/glue at the bottom of the panel to keep the data rows + * aligned, in case the panel is resized. + */ + private void addPageEndGlue() { + gridBagConstraints.weighty = 1.0; // take up all the vertical space + gridBagConstraints.fill = GridBagConstraints.VERTICAL; + javax.swing.Box.Filler vertFiller = new javax.swing.Box.Filler(new Dimension(0, 0), new Dimension(0, 0), new Dimension(0, 32767)); + add(vertFiller, gridBagConstraints); + } + + /** + * Adds a label/key to the panel. + * + * @param keyString Key name to display. + * + * @return Label added. + */ + private JLabel addKeyAtCol(String keyString) { + // create label + javax.swing.JLabel keyLabel = new javax.swing.JLabel(); + gridBagConstraints.gridy++; + gridBagConstraints.gridx = LABEL_COLUMN; + gridBagConstraints.gridwidth = LABEL_WIDTH; + // set text + keyLabel.setText(keyString + ": "); + // add to panel + add(keyLabel, gridBagConstraints); + return keyLabel; + } + + /** + * Adds a value string to the panel at specified column. + * + * @param valueString Value string to display. + * + * @return Label added. + */ + private JTextPane addValueAtCol(String valueString) { + // create label, + JTextPane valueField = new JTextPane(); + valueField.setEditable(false); + valueField.setOpaque(false); + gridBagConstraints.gridx = VALUE_COLUMN; + GridBagConstraints cloneConstraints = (GridBagConstraints) gridBagConstraints.clone(); + // let the value span 2 cols + cloneConstraints.gridwidth = VALUE_WIDTH; + cloneConstraints.fill = GridBagConstraints.BOTH; + // set text + valueField.setText(valueString); + // attach a right click menu with Copy option + valueField.addMouseListener(new java.awt.event.MouseAdapter() { + @Override + public void mouseClicked(java.awt.event.MouseEvent evt) { + valueLabelMouseClicked(evt, valueField); + } + }); + // add label to panel + add(valueField, cloneConstraints); + // end the line + addLineEndGlue(); + return valueField; + } + + /** + * Event handler for mouse click event. Attaches a 'Copy' menu item to right + * click. + * + * @param evt Event to check. + * @param valueLabel Label to attach the menu item to. + */ + @NbBundle.Messages({ + "GeneralPurposeArtifactViewer_menuitem_copy=Copy" + }) + private void valueLabelMouseClicked(java.awt.event.MouseEvent evt, JTextPane valueLabel) { + if (SwingUtilities.isRightMouseButton(evt)) { + JPopupMenu popup = new JPopupMenu(); + JMenuItem copyMenu = new JMenuItem(Bundle.CommunicationArtifactViewerHelper_menuitem_copy()); // NON-NLS + copyMenu.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(valueLabel.getText()), null); + } + }); + popup.add(copyMenu); + popup.show(valueLabel, evt.getX(), evt.getY()); + } + } + + + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/coordinationservice/CoordinationService.java b/Core/src/org/sleuthkit/autopsy/coordinationservice/CoordinationService.java index 9bd5710980..bbf41429bf 100644 --- a/Core/src/org/sleuthkit/autopsy/coordinationservice/CoordinationService.java +++ b/Core/src/org/sleuthkit/autopsy/coordinationservice/CoordinationService.java @@ -36,10 +36,9 @@ import org.apache.curator.retry.ExponentialBackoffRetry; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.KeeperException.NoNodeException; -import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.ZooDefs; -import org.apache.zookeeper.ZooKeeper; import org.openide.util.Lookup; +import org.sleuthkit.autopsy.coordinationservice.utils.CoordinationServiceUtils; import org.sleuthkit.autopsy.core.UserPreferences; /** @@ -52,8 +51,6 @@ public final class CoordinationService { private static final int SESSION_TIMEOUT_MILLISECONDS = 300000; private static final int CONNECTION_TIMEOUT_MILLISECONDS = 300000; - private static final int ZOOKEEPER_SESSION_TIMEOUT_MILLIS = 3000; - private static final int ZOOKEEPER_CONNECTION_TIMEOUT_MILLIS = 15000; private static final int PORT_OFFSET = 1000; // When run in Solr, ZooKeeper defaults to Solr port + 1000 private static final String DEFAULT_NAMESPACE_ROOT = "autopsy"; @GuardedBy("CoordinationService.class") @@ -62,37 +59,6 @@ public final class CoordinationService { @GuardedBy("categoryNodeToPath") private final Map categoryNodeToPath; - /** - * Determines if ZooKeeper is accessible with the current settings. Closes - * the connection prior to returning. - * - * @return true if a connection was achieved, false otherwise - * - * @throws InterruptedException - * @throws IOException - */ - private static boolean isZooKeeperAccessible() throws InterruptedException, IOException { - boolean result = false; - Object workerThreadWaitNotifyLock = new Object(); - int zooKeeperServerPort = Integer.valueOf(UserPreferences.getIndexingServerPort()) + PORT_OFFSET; - String connectString = UserPreferences.getIndexingServerHost() + ":" + zooKeeperServerPort; - ZooKeeper zooKeeper = new ZooKeeper(connectString, ZOOKEEPER_SESSION_TIMEOUT_MILLIS, - (WatchedEvent event) -> { - synchronized (workerThreadWaitNotifyLock) { - workerThreadWaitNotifyLock.notify(); - } - }); - synchronized (workerThreadWaitNotifyLock) { - workerThreadWaitNotifyLock.wait(ZOOKEEPER_CONNECTION_TIMEOUT_MILLIS); - } - ZooKeeper.States state = zooKeeper.getState(); - if (state == ZooKeeper.States.CONNECTED || state == ZooKeeper.States.CONNECTEDREADONLY) { - result = true; - } - zooKeeper.close(); - return result; - } - /** * Gets the coordination service for maintaining configuration information * and providing distributed synchronization using a shared hierarchical @@ -141,16 +107,26 @@ public final class CoordinationService { */ private CoordinationService(String rootNodeName) throws InterruptedException, IOException, KeeperException, CoordinationServiceException { - if (false == isZooKeeperAccessible()) { + // read ZK connection info + String hostName = UserPreferences.getZkServerHost(); + String port = UserPreferences.getZkServerPort(); + if (hostName.isEmpty() || port.isEmpty()) { + // use defaults for embedded ZK that runs on Solr server + hostName = UserPreferences.getIndexingServerHost(); + int portInt = Integer.valueOf(UserPreferences.getIndexingServerPort()) + PORT_OFFSET; + port = Integer.toString(portInt); + } + if (false == CoordinationServiceUtils.isZooKeeperAccessible(hostName, port)) { throw new CoordinationServiceException("Unable to access ZooKeeper"); } - + + // We are using ZK for all coordination/locking, so ZK connection info cannot be changed. + // A reboot is required in order to use a different ZK server for coordination services. /* * Connect to ZooKeeper via Curator. */ RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3); - int zooKeeperServerPort = Integer.valueOf(UserPreferences.getIndexingServerPort()) + PORT_OFFSET; - String connectString = UserPreferences.getIndexingServerHost() + ":" + zooKeeperServerPort; + String connectString = hostName + ":" + port; curator = CuratorFrameworkFactory.newClient(connectString, SESSION_TIMEOUT_MILLISECONDS, CONNECTION_TIMEOUT_MILLISECONDS, retryPolicy); curator.start(); diff --git a/Core/src/org/sleuthkit/autopsy/coordinationservice/utils/CoordinationServiceUtils.java b/Core/src/org/sleuthkit/autopsy/coordinationservice/utils/CoordinationServiceUtils.java new file mode 100755 index 0000000000..28f2a340e9 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/coordinationservice/utils/CoordinationServiceUtils.java @@ -0,0 +1,63 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2018 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.coordinationservice.utils; + +import java.io.IOException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.ZooKeeper; + +/** + * A utility class for coordination service and ZooKeeper. This class is in a + * separate package to avoid exposing it as public API. + */ +public final class CoordinationServiceUtils { + + private static final int ZOOKEEPER_SESSION_TIMEOUT_MILLIS = 3000; + private static final int ZOOKEEPER_CONNECTION_TIMEOUT_MILLIS = 15000; + + /** + * Determines if ZooKeeper is accessible with the current settings. Closes + * the connection prior to returning. + * + * @return true if a connection was achieved, false otherwise + * + * @throws InterruptedException + * @throws IOException + */ + public static boolean isZooKeeperAccessible(String hostName, String port) throws InterruptedException, IOException { + boolean result = false; + Object workerThreadWaitNotifyLock = new Object(); + String connectString = hostName + ":" + port; + ZooKeeper zooKeeper = new ZooKeeper(connectString, ZOOKEEPER_SESSION_TIMEOUT_MILLIS, + (WatchedEvent event) -> { + synchronized (workerThreadWaitNotifyLock) { + workerThreadWaitNotifyLock.notify(); + } + }); + synchronized (workerThreadWaitNotifyLock) { + workerThreadWaitNotifyLock.wait(ZOOKEEPER_CONNECTION_TIMEOUT_MILLIS); + } + ZooKeeper.States state = zooKeeper.getState(); + if (state == ZooKeeper.States.CONNECTED || state == ZooKeeper.States.CONNECTEDREADONLY) { + result = true; + } + zooKeeper.close(); + return result; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties index 29a74d2da9..7d172a62c1 100644 --- a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties @@ -21,9 +21,9 @@ ServicesMonitor.statusChange.notify.msg=Status for {0} is {1} ServicesMonitor.nullServiceName.excepton.txt=Requested service name is null ServicesMonitor.unknownServiceName.excepton.txt=Requested service name {0} is unknown ServicesMonitor.KeywordSearchNull=Cannot find Keyword Search service -ServicesMonitor.InvalidPortNumber=Invalid port number. +ServicesMonitor.InvalidPortNumber=Invalid Solr 8 port number. ServicesMonitor.remoteCaseDatabase.displayName.text=Multi-user case database service ServicesMonitor.remoteKeywordSearch.displayName.text=Multi-user keyword search service ServicesMonitor.messaging.displayName.text=Messaging service ServicesMonitor.databaseConnectionInfo.error.msg=Error accessing case database connection info -ServicesMonitor.messagingService.connErr.text=Error accessing messaging service connection info \ No newline at end of file +ServicesMonitor.messagingService.connErr.text=Error accessing messaging service connection info diff --git a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties-MERGED index 55f1219edb..066b653ca1 100755 --- a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties-MERGED @@ -25,7 +25,7 @@ ServicesMonitor.statusChange.notify.msg=Status for {0} is {1} ServicesMonitor.nullServiceName.excepton.txt=Requested service name is null ServicesMonitor.unknownServiceName.excepton.txt=Requested service name {0} is unknown ServicesMonitor.KeywordSearchNull=Cannot find Keyword Search service -ServicesMonitor.InvalidPortNumber=Invalid port number. +ServicesMonitor.InvalidPortNumber=Invalid Solr 8 port number. ServicesMonitor.remoteCaseDatabase.displayName.text=Multi-user case database service ServicesMonitor.remoteKeywordSearch.displayName.text=Multi-user keyword search service ServicesMonitor.messaging.displayName.text=Messaging service diff --git a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java index ec91e09a89..ad45a1e9d7 100644 --- a/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java +++ b/Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java @@ -354,20 +354,33 @@ public class ServicesMonitor { KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class); try { if (kwsService != null) { - int port = Integer.parseUnsignedInt(UserPreferences.getIndexingServerPort()); - kwsService.tryConnect(UserPreferences.getIndexingServerHost(), port); - setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.UP.toString(), ""); + ServiceStatus status = ServiceStatus.DOWN; + // check Solr 8 + String kwsHostName = UserPreferences.getIndexingServerHost(); + if (!kwsHostName.isEmpty()) { + int port = Integer.parseUnsignedInt(UserPreferences.getIndexingServerPort()); + kwsService.tryConnect(UserPreferences.getIndexingServerHost(), port); + status = ServiceStatus.UP; + } + + // check Solr 4 + if (!UserPreferences.getSolr4ServerHost().trim().isEmpty()) { + int port = Integer.parseUnsignedInt(UserPreferences.getSolr4ServerPort().trim()); + kwsService.tryConnect(UserPreferences.getSolr4ServerHost().trim(), port); + status = ServiceStatus.UP; + } + setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.toString(), status.toString(), ""); } else { setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.DOWN.toString(), NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.KeywordSearchNull")); } } catch (NumberFormatException ex) { String rootCause = NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.InvalidPortNumber"); - logger.log(Level.SEVERE, "Unable to connect to messaging server: " + rootCause, ex); //NON-NLS + logger.log(Level.SEVERE, "Unable to connect to Keyword Search server: " + rootCause, ex); //NON-NLS setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.DOWN.toString(), rootCause); } catch (KeywordSearchServiceException ex) { String rootCause = ex.getMessage(); - logger.log(Level.SEVERE, "Unable to connect to messaging server: " + rootCause, ex); //NON-NLS + logger.log(Level.SEVERE, "Unable to connect to Keyword Search server: " + rootCause, ex); //NON-NLS setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.DOWN.toString(), rootCause); } } diff --git a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java index 08c6f8f6d4..e0a23afb82 100644 --- a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java +++ b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java @@ -55,8 +55,12 @@ public final class UserPreferences { public static final String EXTERNAL_DATABASE_USER = "ExternalDatabaseUsername"; //NON-NLS public static final String EXTERNAL_DATABASE_PASSWORD = "ExternalDatabasePassword"; //NON-NLS public static final String EXTERNAL_DATABASE_TYPE = "ExternalDatabaseType"; //NON-NLS - public static final String INDEXING_SERVER_HOST = "IndexingServerHost"; //NON-NLS - public static final String INDEXING_SERVER_PORT = "IndexingServerPort"; //NON-NLS + private static final String SOLR8_SERVER_HOST = "Solr8ServerHost"; //NON-NLS + private static final String SOLR8_SERVER_PORT = "Solr8ServerPort"; //NON-NLS + private static final String SOLR4_SERVER_HOST = "IndexingServerHost"; //NON-NLS + private static final String SOLR4_SERVER_PORT = "IndexingServerPort"; //NON-NLS + private static final String ZK_SERVER_HOST = "ZookeeperServerHost"; //NON-NLS + private static final String ZK_SERVER_PORT = "ZookeeperServerPort"; //NON-NLS private static final String MESSAGE_SERVICE_PASSWORD = "MessageServicePassword"; //NON-NLS private static final String MESSAGE_SERVICE_USER = "MessageServiceUser"; //NON-NLS private static final String MESSAGE_SERVICE_HOST = "MessageServiceHost"; //NON-NLS @@ -326,21 +330,53 @@ public final class UserPreferences { } public static String getIndexingServerHost() { - return preferences.get(INDEXING_SERVER_HOST, ""); + return preferences.get(SOLR8_SERVER_HOST, ""); } public static void setIndexingServerHost(String hostName) { - preferences.put(INDEXING_SERVER_HOST, hostName); + preferences.put(SOLR8_SERVER_HOST, hostName); } public static String getIndexingServerPort() { - return preferences.get(INDEXING_SERVER_PORT, "8983"); + return preferences.get(SOLR8_SERVER_PORT, "8983"); } public static void setIndexingServerPort(int port) { - preferences.putInt(INDEXING_SERVER_PORT, port); + preferences.putInt(SOLR8_SERVER_PORT, port); + } + + public static String getSolr4ServerHost() { + return preferences.get(SOLR4_SERVER_HOST, ""); } + public static void setSolr4ServerHost(String hostName) { + preferences.put(SOLR4_SERVER_HOST, hostName); + } + + public static String getSolr4ServerPort() { + return preferences.get(SOLR4_SERVER_PORT, ""); + } + + public static void setSolr4ServerPort(String port) { + preferences.put(SOLR4_SERVER_PORT, port); + } + + public static String getZkServerHost() { + return preferences.get(ZK_SERVER_HOST, ""); + } + + public static void setZkServerHost(String hostName) { + preferences.put(ZK_SERVER_HOST, hostName); + } + + public static String getZkServerPort() { + return preferences.get(ZK_SERVER_PORT, "9983"); + } + + public static void setZkServerPort(String port) { + preferences.put(ZK_SERVER_PORT, port); + } + public static void setTextTranslatorName(String textTranslatorName) { preferences.put(TEXT_TRANSLATOR_NAME, textTranslatorName); } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties index 38c6af268b..6bae533223 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties @@ -75,14 +75,17 @@ DataResultViewerThumbnail.switchPage.done.errMsg=Error making thumbnails: {0} AboutWindowPanel.actVerboseLogging.text=Activate verbose logging OptionsCategory_Name_Multi_User_Settings=Multi-User OptionsCategory_Keywords_Multi_User_Options=Multi-User Settings -MultiUserSettingsPanel.lbSolrSettings.text=Solr Server Settings MultiUserSettingsPanel.cbEnableMultiUser.text=Enable multi-user cases MultiUserSettingsPanel.lbDatabaseSettings.text=Database Server Settings MultiUserSettingsPanel.validationErrMsg.incomplete=Fill in all values MultiUserSettingsPanel.nonWindowsOs.msg=Multi-user cases are only available on Windows platforms MultiUserSettingsPanel.validationErrMsg.invalidDatabasePort=Invalid database port number MultiUserSettingsPanel.validationErrMsg.invalidMessageServicePort=Invalid message service port number -MultiUserSettingsPanel.validationErrMsg.invalidIndexingServerPort=Invalid Solr server port number +MultiUserSettingsPanel.validationErrMsg.invalidIndexingServerPort=Invalid Solr 8 server port number +MultiUserSettingsPanel.validationErrMsg.invalidSolr4ServerPort=Invalid Solr 4 server port number +MultiUserSettingsPanel.validationErrMsg.invalidZkServerPort=Invalid ZooKeeper server port number +MultiUserSettingsPanel.validationErrMsg.invalidZkServerHostName=ZooKeeper server host name not set +MultiUserSettingsPanel.validationErrMsg.solrNotConfigured=Either Solr 8 or/and Solr 4 server needs to be configured MultiUserSettingsPanel.validationErrMsg.invalidMessgeServiceURI=Message service host and/or port not valid DataContentViewerHex.goToOffsetLabel.text=Jump to Offset DataContentViewerHex.goToOffsetTextField.text= @@ -101,8 +104,6 @@ MultiUserSettingsPanel.tbDbPassword.toolTipText=Password MultiUserSettingsPanel.tbDbPassword.text= MultiUserSettingsPanel.lbTestSolr.text= MultiUserSettingsPanel.bnTestSolr.text=Test -MultiUserSettingsPanel.tbSolrHostname.toolTipText=Hostname or IP Address -MultiUserSettingsPanel.tbSolrPort.toolTipText=Port Number MultiUserSettingsPanel.lbTestMessageService.text= MultiUserSettingsPanel.bnTestMessageService.text=Test MultiUserSettingsPanel.lbMessageServiceSettings.text=ActiveMQ Message Server Settings @@ -118,6 +119,7 @@ MultiUserSettingsPanel.lbTestMessageWarning.text= MultiUserSettingsPanel.lbTestSolrWarning.text= MultiUserSettingsPanel.lbTestDbWarning.text= MultiUserSettingsPanel.KeywordSearchNull=Cannot find keyword search service +MultiUserSettingsPanel.UnableToConnectToZK=Unable to connect to ZooKeeper service MultiUserSettingsPanel.InvalidPortNumber=Invalid port number AutopsyOptionsPanel.agencyLogoImageLabel.toolTipText= SortChooserDialog.label=remove @@ -175,6 +177,19 @@ DataResultViewerTable.pagesLabel.text=Pages: DataResultViewerTable.pageNumLabel.text= DataResultViewerTable.pageLabel.text=Page: DataResultViewerTable.exportCSVButton.text=Save Table as CSV +MultiUserSettingsPanel.tbSolr4Hostname.toolTipText=Solr 4 Hostname or IP Address +MultiUserSettingsPanel.tbSolr4Port.toolTipText=Solr 4 Port Number +MultiUserSettingsPanel.lbZkSettings.text=ZooKeeper Server Settings +MultiUserSettingsPanel.lbSolr4Settings.text=Solr 4 Server Settings +MultiUserSettingsPanel.lbSolr8Settings.text=Solr 8 Server Settings +MultiUserSettingsPanel.tbZkHostname.toolTipText=ZooKeeper Hostname or IP Address +MultiUserSettingsPanel.tbZkPort.toolTipText=ZooKeeper Port Number +MultiUserSettingsPanel.tbSolr8Hostname.toolTipText=Solr 8 Hostname or IP Address +MultiUserSettingsPanel.tbSolr8Port.toolTipText=Solr 8 Port Number +MultiUserSettingsPanel.restartRequiredLabel.text=Application restart required to take effect. +MultiUserSettingsPanel.MustRestart=Autopsy must be restarted for new configuration to take effect +MultiUserSettingsPanel.lbSolrNote1.text=NOTE: Enter Solr 8 and/or Solr 4 server settings. +MultiUserSettingsPanel.lbSolrNote2.text=New cases can only be created with Solr 8. AutopsyOptionsPanel.logoPanel.border.title=Logo AutopsyOptionsPanel.agencyLogoPathFieldValidationLabel.text= AutopsyOptionsPanel.specifyLogoRB.text=Specify a logo @@ -223,3 +238,4 @@ ViewPreferencesPanel.useBestViewerRadioButton.toolTipText=For example, change fr ViewPreferencesPanel.useBestViewerRadioButton.text=Change to the most specific file viewer ViewPreferencesPanel.selectFileLabel.text=When selecting a file: ViewPreferencesPanel.globalSettingsPanel.border.title=Global Settings + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED index 26a86074a4..f577c8e2e7 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED @@ -130,14 +130,17 @@ DataResultViewerThumbnail.switchPage.done.errMsg=Error making thumbnails: {0} AboutWindowPanel.actVerboseLogging.text=Activate verbose logging OptionsCategory_Name_Multi_User_Settings=Multi-User OptionsCategory_Keywords_Multi_User_Options=Multi-User Settings -MultiUserSettingsPanel.lbSolrSettings.text=Solr Server Settings MultiUserSettingsPanel.cbEnableMultiUser.text=Enable multi-user cases MultiUserSettingsPanel.lbDatabaseSettings.text=Database Server Settings MultiUserSettingsPanel.validationErrMsg.incomplete=Fill in all values MultiUserSettingsPanel.nonWindowsOs.msg=Multi-user cases are only available on Windows platforms MultiUserSettingsPanel.validationErrMsg.invalidDatabasePort=Invalid database port number MultiUserSettingsPanel.validationErrMsg.invalidMessageServicePort=Invalid message service port number -MultiUserSettingsPanel.validationErrMsg.invalidIndexingServerPort=Invalid Solr server port number +MultiUserSettingsPanel.validationErrMsg.invalidIndexingServerPort=Invalid Solr 8 server port number +MultiUserSettingsPanel.validationErrMsg.invalidSolr4ServerPort=Invalid Solr 4 server port number +MultiUserSettingsPanel.validationErrMsg.invalidZkServerPort=Invalid ZooKeeper server port number +MultiUserSettingsPanel.validationErrMsg.invalidZkServerHostName=ZooKeeper server host name not set +MultiUserSettingsPanel.validationErrMsg.solrNotConfigured=Either Solr 8 or/and Solr 4 server needs to be configured MultiUserSettingsPanel.validationErrMsg.invalidMessgeServiceURI=Message service host and/or port not valid DataContentViewerHex.goToOffsetLabel.text=Jump to Offset DataContentViewerHex.goToOffsetTextField.text= @@ -156,8 +159,6 @@ MultiUserSettingsPanel.tbDbPassword.toolTipText=Password MultiUserSettingsPanel.tbDbPassword.text= MultiUserSettingsPanel.lbTestSolr.text= MultiUserSettingsPanel.bnTestSolr.text=Test -MultiUserSettingsPanel.tbSolrHostname.toolTipText=Hostname or IP Address -MultiUserSettingsPanel.tbSolrPort.toolTipText=Port Number MultiUserSettingsPanel.lbTestMessageService.text= MultiUserSettingsPanel.bnTestMessageService.text=Test MultiUserSettingsPanel.lbMessageServiceSettings.text=ActiveMQ Message Server Settings @@ -173,6 +174,7 @@ MultiUserSettingsPanel.lbTestMessageWarning.text= MultiUserSettingsPanel.lbTestSolrWarning.text= MultiUserSettingsPanel.lbTestDbWarning.text= MultiUserSettingsPanel.KeywordSearchNull=Cannot find keyword search service +MultiUserSettingsPanel.UnableToConnectToZK=Unable to connect to ZooKeeper service MultiUserSettingsPanel.InvalidPortNumber=Invalid port number AutopsyOptionsPanel.agencyLogoImageLabel.toolTipText= SortChooserDialog.label=remove @@ -232,6 +234,19 @@ DataResultViewerTable.pagesLabel.text=Pages: DataResultViewerTable.pageNumLabel.text= DataResultViewerTable.pageLabel.text=Page: DataResultViewerTable.exportCSVButton.text=Save Table as CSV +MultiUserSettingsPanel.tbSolr4Hostname.toolTipText=Solr 4 Hostname or IP Address +MultiUserSettingsPanel.tbSolr4Port.toolTipText=Solr 4 Port Number +MultiUserSettingsPanel.lbZkSettings.text=ZooKeeper Server Settings +MultiUserSettingsPanel.lbSolr4Settings.text=Solr 4 Server Settings +MultiUserSettingsPanel.lbSolr8Settings.text=Solr 8 Server Settings +MultiUserSettingsPanel.tbZkHostname.toolTipText=ZooKeeper Hostname or IP Address +MultiUserSettingsPanel.tbZkPort.toolTipText=ZooKeeper Port Number +MultiUserSettingsPanel.tbSolr8Hostname.toolTipText=Solr 8 Hostname or IP Address +MultiUserSettingsPanel.tbSolr8Port.toolTipText=Solr 8 Port Number +MultiUserSettingsPanel.restartRequiredLabel.text=Application restart required to take effect. +MultiUserSettingsPanel.MustRestart=Autopsy must be restarted for new configuration to take effect +MultiUserSettingsPanel.lbSolrNote1.text=NOTE: Enter Solr 8 and/or Solr 4 server settings. +MultiUserSettingsPanel.lbSolrNote2.text=New cases can only be created with Solr 8. AutopsyOptionsPanel.logoPanel.border.title=Logo AutopsyOptionsPanel.agencyLogoPathFieldValidationLabel.text= AutopsyOptionsPanel.specifyLogoRB.text=Specify a logo @@ -280,3 +295,4 @@ ViewPreferencesPanel.useBestViewerRadioButton.toolTipText=For example, change fr ViewPreferencesPanel.useBestViewerRadioButton.text=Change to the most specific file viewer ViewPreferencesPanel.selectFileLabel.text=When selecting a file: ViewPreferencesPanel.globalSettingsPanel.border.title=Global Settings + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle_ja.properties index 9dc1ebdd53..5c34ae9bef 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle_ja.properties @@ -170,6 +170,59 @@ HINT_DataContentTopComponent=\u3053\u308c\u306fDataContent\u30a6\u30a3\u30f3\u30 HINT_NodeTableTopComponent=\u3053\u308c\u306fDataResult\u30a6\u30a3\u30f3\u30c9\u30a6\u3067\u3059 INDEX_FOR_LOCAL_HELP=/docs/index.html LBL_Close=\u9589\u3058\u308b +DataContentViewerHex.copyMenuItem.text=\u30b3\u30d4\u30fc +DataContentViewerHex.selectAllMenuItem.text=\u3059\u3079\u3066\u3092\u9078\u629e +DataContentViewerArtifact.totalPageLabel.text=100 +DataContentViewerArtifact.prevPageButton.text= +DataContentViewerArtifact.pageLabel2.text=\u7d50\u679c +DataContentViewerArtifact.nextPageButton.text= +DataContentViewerArtifact.currentPageLabel.text=1 +DataContentViewerArtifact.ofLabel.text=/ +DataContentViewerArtifact.pageLabel.text=\u7d50\u679c: +AdvancedConfigurationDialog.applyButton.text=OK +DataContentViewerHex.goToPageTextField.text= +DataContentViewerHex.goToPageLabel.text=\u30da\u30fc\u30b8\u306b\u79fb\u52d5: +DataResultViewerThumbnail.pageLabel.text=\u30da\u30fc\u30b8: +DataResultViewerThumbnail.pagesLabel.text=\u30da\u30fc\u30b8: +DataResultViewerThumbnail.pagePrevButton.text= +DataResultViewerThumbnail.pageNextButton.text= +DataResultViewerThumbnail.imagesLabel.text=\u30a4\u30e1\u30fc\u30b8: +DataResultViewerThumbnail.imagesRangeLabel.text=- +DataResultViewerThumbnail.pageNumLabel.text=- +DataResultViewerThumbnail.filePathLabel.text=\ \ \ +DataResultViewerThumbnail.goToPageLabel.text=\u30da\u30fc\u30b8\u306b\u79fb\u52d5: +DataResultViewerThumbnail.goToPageField.text= +AdvancedConfigurationDialog.cancelButton.text=\u53d6\u308a\u6d88\u3057 +DataContentViewerArtifact.waitText=\u30c7\u30fc\u30bf\u3092\u691c\u7d22\u3057\u3066\u6e96\u5099\u4e2d\u3067\u3059\u3002\u304a\u5f85\u3061\u304f\u3060\u3055\u3044... +DataContentViewerArtifact.errorText=\u7d50\u679c\u306e\u691c\u7d22\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +DataContentViewerArtifact.title=\u7d50\u679c +DataContentViewerArtifact.toolTip=\u30d5\u30a1\u30a4\u30eb\u3068\u95a2\u9023\u4ed8\u3051\u3089\u308c\u3066\u3044\u308b\u7d50\u679c\u3092\u8868\u793a +DataContentViewerHex.goToPageTextField.msgDlg=1 \u304b\u3089 {0} \u307e\u3067\u306e\u6709\u52b9\u306a\u30da\u30fc\u30b8\u756a\u53f7\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044 +DataContentViewerHex.goToPageTextField.err=\u7121\u52b9\u306a\u30da\u30fc\u30b8\u756a\u53f7\u3067\u3059 +DataContentViewerHex.setDataView.errorText=(\u30aa\u30d5\u30bb\u30c3\u30c8 {0}-{1} \u3092\u8aad\u307f\u8fbc\u3081\u307e\u305b\u3093\u3067\u3057\u305f) +DataContentViewerHex.title=16\u9032\u6570 +DataContentViewerHex.toolTip=\u30d5\u30a1\u30a4\u30eb\u306e\u30d0\u30a4\u30ca\u30ea\u30fc\u30b3\u30f3\u30c6\u30f3\u30c4\u309216\u9032\u6570\u3068\u3057\u3066\u8868\u793a\u3057\u307e\u3059\u3002\u53f3\u5074\u306bASCII\u6587\u5b57\u3068\u3057\u3066\u8868\u793a\u53ef\u80fd\u306a\u30d0\u30a4\u30c8\u304c\u793a\u3055\u308c\u307e\u3059\u3002 +DataResultPanel.pleasewaitNodeDisplayName=\u304a\u5f85\u3061\u304f\u3060\u3055\u3044... +DataResultViewerTable.illegalArgExc.noChildFromParent=\u6307\u5b9a\u3057\u305f\u89aa\u304b\u3089\u5b50\u30ce\u30fc\u30c9\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +DataResultViewerTable.illegalArgExc.childWithoutPropertySet=\u5b50\u30ce\u30fc\u30c9\u306b\u306f\u6b63\u898f\u306ePropertySet\u304c\u3042\u308a\u307e\u305b\u3093\u3002 +DataResultViewerThumbnail.title=\u30b5\u30e0\u30cd\u30a4\u30eb +DataResultViewerThumbnail.goToPageTextField.msgDlg=1 \u304b\u3089 {0} \u307e\u3067\u306e\u6709\u52b9\u306a\u30da\u30fc\u30b8\u756a\u53f7\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044 +DataResultViewerThumbnail.goToPageTextField.err=\u7121\u52b9\u306a\u30da\u30fc\u30b8\u756a\u53f7\u3067\u3059 +DataResultViewerThumbnail.genThumbs=\u30b5\u30e0\u30cd\u30a4\u30eb\u3092\u4f5c\u6210\u4e2d\u3067\u3059... +DataResultViewerThumbnail.pageNumbers.curOfTotal={0} / {1} +GeneralOptionsPanelController.moduleErr=\u30e2\u30b8\u30e5\u30fc\u30eb\u30a8\u30e9\u30fc +GeneralOptionsPanelController.moduleErr.msg=GeneralOptionsPanelController\u66f4\u65b0\u306e\u30ea\u30c3\u30b9\u30f3\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u767a\u751f\u3055\u305b\u307e\u3057\u305f\u3002\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u5224\u65ad\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u4e0d\u5b8c\u5168\u3067\u3042\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 +ProductInformationPanel.verbLoggingEnabled.text=\u8a73\u7d30\u30ed\u30ae\u30f3\u30b0\u304c\u6709\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u3059 +ProductInformationPanel.propertyUnknown.text=\u4e0d\u660e +ProductInformationPanel.getVMValue.text={0} {1} +TableFilterNode.displayName.text=\u540d\u524d +DataResultViewerThumbnail.comboBox.smallThumbnails=\u5c0f\u30b5\u30a4\u30ba\u306e\u30b5\u30e0\u30cd\u30a4\u30eb +DataResultViewerThumbnail.comboBox.mediumThumbnails=\u4e2d\u30b5\u30a4\u30ba\u306e\u30b5\u30e0\u30cd\u30a4\u30eb +DataResultViewerThumbnail.comboBox.largeThumbnails=\u5927\u30b5\u30a4\u30ba\u306e\u30b5\u30e0\u30cd\u30a4\u30eb +DataResultViewerThumbnail.switchPage.done.errMsg=\u6b21\u306e\u30b5\u30e0\u30cd\u30a4\u30eb\u3092\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f: {0} +AboutWindowPanel.actVerboseLogging.text=\u8a73\u7d30\u30ed\u30ae\u30f3\u30b0\u3092\u30a2\u30af\u30c6\u30a3\u30d6\u5316 +OptionsCategory_Name_Multi_User_Settings=\u30de\u30eb\u30c1\u30e6\u30fc\u30b6\u30fc +OptionsCategory_Keywords_Multi_User_Options=\u30de\u30eb\u30c1\u30e6\u30fc\u30b6\u30fc\u8a2d\u5b9a LBL_Copyright=
Autopsy™ \u306f The Sleuth Kit™ \u304a\u3088\u3073\u305d\u306e\u4ed6\u306e\u30c4\u30fc\u30eb\u306b\u57fa\u3065\u304f\u30c7\u30b8\u30bf\u30eb\u79d1\u5b66\u635c\u67fb\u30d7\u30e9\u30c3\u30c8\u30d5\u30a9\u30fc\u30e0\u3002
Copyright © 2003-2020.
LBL_Description=
\n \u88fd\u54c1\u30d0\u30fc\u30b8\u30e7\u30f3\: {0} ({9})
Sleuth Kit\u30d0\u30fc\u30b8\u30e7\u30f3\: {7}
Netbeans RCP\u30d3\u30eb\u30c9\: {8}
Java\: {1}; {2}
\u30b7\u30b9\u30c6\u30e0\: {3}; {4}; {5}
Userdir\: {6}
MultiUserSettingsPanel.InvalidPortNumber=\u7121\u52b9\u306a\u30dd\u30fc\u30c8\u756a\u53f7\u3067\u3059 @@ -195,6 +248,14 @@ MultiUserSettingsPanel.tbDbPassword.toolTipText=\u30d1\u30b9\u30ef\u30fc\u30c9 MultiUserSettingsPanel.tbDbPort.text= MultiUserSettingsPanel.tbDbPort.toolTipText=\u30dd\u30fc\u30c8\u756a\u53f7 MultiUserSettingsPanel.tbDbUsername.text= +MultiUserSettingsPanel.tbDbPassword.toolTipText=\u30d1\u30b9\u30ef\u30fc\u30c9 +MultiUserSettingsPanel.tbDbPassword.text= +MultiUserSettingsPanel.lbTestSolr.text= +MultiUserSettingsPanel.bnTestSolr.text=\u30c6\u30b9\u30c8 +MultiUserSettingsPanel.lbTestMessageService.text= +MultiUserSettingsPanel.bnTestMessageService.text=\u30c6\u30b9\u30c8 +MultiUserSettingsPanel.lbMessageServiceSettings.text=ActiveMQ\u30e1\u30c3\u30bb\u30fc\u30b8\u30b5\u30fc\u30d3\u30b9\u8a2d\u5b9a +MultiUserSettingsPanel.tbMsgPort.toolTipText=\u30dd\u30fc\u30c8\u756a\u53f7 MultiUserSettingsPanel.tbDbUsername.toolTipText=\u30e6\u30fc\u30b6\u30fc\u540d MultiUserSettingsPanel.tbMsgHostname.text= MultiUserSettingsPanel.tbMsgHostname.toolTipText=\u30db\u30b9\u30c8\u540d\u307e\u305f\u306fIP\u30a2\u30c9\u30ec\u30b9 @@ -239,6 +300,18 @@ ViewPreferencesPanel.maxResultsLabel.toolTipText=\n\u3053\u306e\u5024\u309 ViewPreferencesPanel.maxResultsLabel.text=\u30c6\u30fc\u30d6\u30eb\u3067\u8868\u793a\u3059\u308b\u6700\u5927\u7d50\u679c\u6570: ViewPreferencesPanel.fileNameTranslationColumnCheckbox.text=\u7d50\u679c\u30d3\u30e5\u30fc\u30ef\u30fc\u306b\u30d5\u30a1\u30a4\u30eb\u540d\u7ffb\u8a33\u7528\u5217\u3092\u8ffd\u52a0 ViewPreferencesPanel.scoColumnsWrapAroundText.text=\u975e\u8868\u793a\u306b\u3059\u308b\u3068\u8aad\u8fbc\u307f\u304c\u65e9\u304f\u306a\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 +ViewPreferencesPanel.scoColumnsLabel.text=\u6b21\u306e\u305f\u3081\u306e\u5217\u3092\u8ffd\u52a0\u3057\u306a\u3044: +MultiUserSettingsPanel.tbSolr4Port.toolTipText=\u30dd\u30fc\u30c8\u756a\u53f7 +MultiUserSettingsPanel.lbZkSettings.text=Solr\u8a2d\u5b9a +MultiUserSettingsPanel.lbSolr4Settings.text=Solr\u8a2d\u5b9a +MultiUserSettingsPanel.lbSolr8Settings.text=Solr\u8a2d\u5b9a +MultiUserSettingsPanel.tbZkPort.toolTipText=\u30dd\u30fc\u30c8\u756a\u53f7 +MultiUserSettingsPanel.tbSolr8Hostname.toolTipText=\u30db\u30b9\u30c8\u540d\u307e\u305f\u306fIP\u30a2\u30c9\u30ec\u30b9 +MultiUserSettingsPanel.tbSolr8Port.toolTipText=\u30dd\u30fc\u30c8\u756a\u53f7 +MultiUserSettingsPanel.lbSolrNote1.text=Solr\u8a2d\u5b9a +MultiUserSettingsPanel.lbSolrNote2.text=Solr\u8a2d\u5b9a +ViewPreferencesPanel.selectFileLabel.text=\u30d5\u30a1\u30a4\u30eb\u9078\u629e\u6642\: +ViewPreferencesPanel.translateTextLabel.text=\u30c6\u30ad\u30b9\u30c8\u3092\u7ffb\u8a33\: ViewPreferencesPanel.translateTextLabel.text=\u30c6\u30ad\u30b9\u30c8\u3092\u7ffb\u8a33: ViewPreferencesPanel.scoColumnsCheckbox.text=S(\u30b9\u30b3\u30a2)\u3001C(\u30b3\u30e1\u30f3\u30c8)\u3001O(\u767a\u751f) ViewPreferencesPanel.scoColumnsLabel.text=\u6b21\u306e\u305f\u3081\u306e\u5217\u3092\u8ffd\u52a0\u3057\u306a\u3044: diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java index b015dbf3ad..b6a1373236 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java @@ -41,7 +41,7 @@ import org.sleuthkit.datamodel.TskException; import java.util.Collections; import java.util.HashSet; import org.sleuthkit.autopsy.contentviewers.artifactviewers.ArtifactContentViewer; -import org.sleuthkit.autopsy.contentviewers.artifactviewers.DefaultArtifactContentViewer; +import org.sleuthkit.autopsy.contentviewers.artifactviewers.DefaultTableArtifactContentViewer; /** * Instances of this class display the BlackboardArtifacts associated with the @@ -372,7 +372,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat return viewer; } } - return new DefaultArtifactContentViewer(); + return new DefaultTableArtifactContentViewer(); } /** diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index c79c8e613c..48e7427172 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -434,7 +434,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { } setColumnWidths(); - + /* * Load column sorting information from preferences file and apply it to * columns. @@ -460,26 +460,27 @@ public class DataResultViewerTable extends AbstractDataResultViewer { * If one of the child nodes of the root node is to be selected, select * it. */ - SwingUtilities.invokeLater(() -> { - if (rootNode instanceof TableFilterNode) { - NodeSelectionInfo selectedChildInfo = ((TableFilterNode) rootNode).getChildNodeSelectionInfo(); - if (null != selectedChildInfo) { - Node[] childNodes = rootNode.getChildren().getNodes(true); - for (int i = 0; i < childNodes.length; ++i) { - Node childNode = childNodes[i]; - if (selectedChildInfo.matches(childNode)) { + if (rootNode instanceof TableFilterNode) { + NodeSelectionInfo selectedChildInfo = ((TableFilterNode) rootNode).getChildNodeSelectionInfo(); + if (null != selectedChildInfo) { + Node[] childNodes = rootNode.getChildren().getNodes(true); + for (int i = 0; i < childNodes.length; ++i) { + Node childNode = childNodes[i]; + if (selectedChildInfo.matches(childNode)) { + SwingUtilities.invokeLater(() -> { try { - this.getExplorerManager().setSelectedNodes(new Node[]{childNode}); + this.getExplorerManager().setExploredContextAndSelection(this.rootNode, new Node[]{childNode}); } catch (PropertyVetoException ex) { LOGGER.log(Level.SEVERE, "Failed to select node specified by selected child info", ex); } - break; - } + }); + + break; } - ((TableFilterNode) rootNode).setChildNodeSelectionInfo(null); } + ((TableFilterNode) rootNode).setChildNodeSelectionInfo(null); } - }); + } /* * The table setup is done, so any added/removed events can now be @@ -516,7 +517,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { protected void setColumnWidths() { if (rootNode.getChildren().getNodesCount() != 0) { final Graphics graphics = outlineView.getGraphics(); - + if (graphics != null) { // Current width of the outlineView double outlineViewWidth = outlineView.getSize().getWidth(); @@ -526,10 +527,10 @@ public class DataResultViewerTable extends AbstractDataResultViewer { int margin = 4; int padding = 8; - + int totalColumnWidth = 0; - int cntMaxSizeColumns =0; - + int cntMaxSizeColumns = 0; + // Calulate the width for each column keeping track of the number // of columns that were set to columnwidthLimit. for (int column = 0; column < outline.getModel().getColumnCount(); column++) { @@ -552,40 +553,40 @@ public class DataResultViewerTable extends AbstractDataResultViewer { columnWidth = Math.min(columnWidth, columnWidthLimit); columnWidths.add(columnWidth); - + totalColumnWidth += columnWidth; - - if( columnWidth == columnWidthLimit) { + + if (columnWidth == columnWidthLimit) { cntMaxSizeColumns++; } } - + // Figure out how much extra, if any can be given to the columns // so that the table is as wide as outlineViewWidth. If cntMaxSizeColumns // is greater than 0 divide the extra space between the columns // that could use more space. Otherwise divide evenly amoung // all columns. int extraWidth = 0; - + if (totalColumnWidth < outlineViewWidth) { - if (cntMaxSizeColumns > 0) { - extraWidth = (int) ((outlineViewWidth - totalColumnWidth)/cntMaxSizeColumns); + if (cntMaxSizeColumns > 0) { + extraWidth = (int) ((outlineViewWidth - totalColumnWidth) / cntMaxSizeColumns); } else { - extraWidth = (int) ((outlineViewWidth - totalColumnWidth)/columnWidths.size()); + extraWidth = (int) ((outlineViewWidth - totalColumnWidth) / columnWidths.size()); } } - - for(int column = 0; column < columnWidths.size(); column++) { + + for (int column = 0; column < columnWidths.size(); column++) { int columnWidth = columnWidths.get(column); - - if(cntMaxSizeColumns > 0) { - if(columnWidth >= ((column == 0) ? 350 : 300)) { + + if (cntMaxSizeColumns > 0) { + if (columnWidth >= ((column == 0) ? 350 : 300)) { columnWidth += extraWidth; } } else { columnWidth += extraWidth; } - + outline.getColumnModel().getColumn(column).setPreferredWidth(columnWidth); } } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.form index be29f511dd..97273e1dbb 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.form @@ -16,14 +16,14 @@ - + - + @@ -47,11 +47,12 @@ - - + + + @@ -63,12 +64,15 @@ - - - - - - + + + + + + + + + @@ -92,7 +96,7 @@ - + @@ -116,7 +120,7 @@ - + @@ -252,17 +256,30 @@ - + - - + + + + + + - + + - - - + + + + + + + + + + + @@ -273,19 +290,35 @@ + + + + - - - + + + - + - - - + + + + + + + + + + + + + + + @@ -293,39 +326,39 @@ - + - + - + - + - + - + - + - + - + @@ -356,6 +389,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -376,7 +510,7 @@ - + @@ -398,9 +532,9 @@ - - - + + + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.java index 0fe9e9c731..bec42f0dc1 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.java @@ -32,10 +32,14 @@ import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.events.MessageServiceConnectionInfo; import org.sleuthkit.autopsy.coreutils.Logger; import java.awt.Cursor; +import java.io.IOException; import java.util.logging.Level; import javax.swing.ImageIcon; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; import org.openide.util.ImageUtilities; import org.openide.util.Lookup; +import org.sleuthkit.autopsy.coordinationservice.utils.CoordinationServiceUtils; import org.sleuthkit.autopsy.core.UserPreferencesException; import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.events.MessageServiceException; @@ -60,6 +64,17 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { private static final String INVALID_DB_PORT_MSG = NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.validationErrMsg.invalidDatabasePort"); private static final String INVALID_MESSAGE_SERVICE_PORT_MSG = NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.validationErrMsg.invalidMessageServicePort"); private static final String INVALID_INDEXING_SERVER_PORT_MSG = NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.validationErrMsg.invalidIndexingServerPort"); + private static final String INVALID_SOLR4_SERVER_PORT_MSG = NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.validationErrMsg.invalidSolr4ServerPort"); + private static final String SOLR_SERVER_NOT_CONFIGURED_MSG = NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.validationErrMsg.solrNotConfigured"); + private static final String INVALID_ZK_SERVER_HOST_MSG = NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.validationErrMsg.invalidZkServerHostName"); + private static final String INVALID_ZK_SERVER_PORT_MSG = NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.validationErrMsg.invalidZkServerPort"); + private static final String SOLR8_HOST_NAME_OR_IP_PROMPT = NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbSolr8Hostname.toolTipText"); + private static final String SOLR8_PORT_PROMPT = NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbSolr8Port.toolTipText"); + private static final String SOLR4_HOST_NAME_OR_IP_PROMPT = NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbSolr4Hostname.toolTipText"); + private static final String SOLR4_PORT_PROMPT = NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbSolr4Port.toolTipText"); + private static final String ZK_HOST_NAME_OR_IP_PROMPT = NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbZkHostname.toolTipText"); + private static final String ZK_PORT_PROMPT = NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbZkPort.toolTipText"); + private static final long serialVersionUID = 1L; private final MultiUserSettingsPanelController controller; private final Collection textBoxes = new ArrayList<>(); @@ -91,8 +106,12 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { textPrompts.add(new TextPrompt(PORT_PROMPT, tbMsgPort)); textPrompts.add(new TextPrompt(USER_NAME_PROMPT_OPT, tbMsgUsername)); textPrompts.add(new TextPrompt(PASSWORD_PROMPT_OPT, tbMsgPassword)); - textPrompts.add(new TextPrompt(HOST_NAME_OR_IP_PROMPT, tbSolrHostname)); - textPrompts.add(new TextPrompt(PORT_PROMPT, tbSolrPort)); + textPrompts.add(new TextPrompt(SOLR8_HOST_NAME_OR_IP_PROMPT, tbSolr8Hostname)); + textPrompts.add(new TextPrompt(SOLR8_PORT_PROMPT, tbSolr8Port)); + textPrompts.add(new TextPrompt(SOLR4_HOST_NAME_OR_IP_PROMPT, tbSolr4Hostname)); + textPrompts.add(new TextPrompt(SOLR4_PORT_PROMPT, tbSolr4Port)); + textPrompts.add(new TextPrompt(ZK_HOST_NAME_OR_IP_PROMPT, tbZkHostname)); + textPrompts.add(new TextPrompt(ZK_PORT_PROMPT, tbZkPort)); configureTextPrompts(textPrompts); /* @@ -104,8 +123,12 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { tbDbUsername.getDocument().putProperty("statusIcon", lbTestDatabase); tbDbPassword.getDocument().putProperty("statusIcon", lbTestDatabase); - tbSolrHostname.getDocument().putProperty("statusIcon", lbTestSolr); - tbSolrPort.getDocument().putProperty("statusIcon", lbTestSolr); + tbSolr8Hostname.getDocument().putProperty("statusIcon", lbTestSolr); + tbSolr8Port.getDocument().putProperty("statusIcon", lbTestSolr); + tbSolr4Hostname.getDocument().putProperty("statusIcon", lbTestSolr); + tbSolr4Port.getDocument().putProperty("statusIcon", lbTestSolr); + tbZkHostname.getDocument().putProperty("statusIcon", lbTestSolr); + tbZkPort.getDocument().putProperty("statusIcon", lbTestSolr); tbMsgHostname.getDocument().putProperty("statusIcon", lbTestMessageService); tbMsgPort.getDocument().putProperty("statusIcon", lbTestMessageService); @@ -122,8 +145,15 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { textBoxes.add(tbMsgPort); textBoxes.add(tbMsgUsername); textBoxes.add(tbMsgPassword); - textBoxes.add(tbSolrHostname); - textBoxes.add(tbSolrPort); + textBoxes.add(tbSolr8Hostname); + textBoxes.add(tbSolr8Port); + textBoxes.add(tbSolr4Hostname); + textBoxes.add(tbSolr4Port); + textBoxes.add(tbZkHostname); + textBoxes.add(tbZkPort); + + // as the user enters Solr 8 settings, we fill in the ZK settings with the embedded Solr 8 ZK connection info. + tbSolr8Hostname.getDocument().addDocumentListener(new MyDocumentListener()); addDocumentListeners(textBoxes, textBoxChangedListener); goodIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/images/good.png", false)); @@ -178,12 +208,20 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { lbTestDatabase = new javax.swing.JLabel(); lbTestDbWarning = new javax.swing.JLabel(); pnSolrSettings = new javax.swing.JPanel(); - lbSolrSettings = new javax.swing.JLabel(); - tbSolrHostname = new javax.swing.JTextField(); - tbSolrPort = new javax.swing.JTextField(); + lbSolr8Settings = new javax.swing.JLabel(); + tbSolr8Hostname = new javax.swing.JTextField(); + tbSolr8Port = new javax.swing.JTextField(); bnTestSolr = new javax.swing.JButton(); lbTestSolr = new javax.swing.JLabel(); lbTestSolrWarning = new javax.swing.JLabel(); + tbSolr4Hostname = new javax.swing.JTextField(); + tbSolr4Port = new javax.swing.JTextField(); + lbSolr4Settings = new javax.swing.JLabel(); + lbZkSettings = new javax.swing.JLabel(); + tbZkHostname = new javax.swing.JTextField(); + tbZkPort = new javax.swing.JTextField(); + lbSolrNote1 = new javax.swing.JLabel(); + lbSolrNote2 = new javax.swing.JLabel(); pnMessagingSettings = new javax.swing.JPanel(); lbMessageServiceSettings = new javax.swing.JLabel(); tbMsgHostname = new javax.swing.JTextField(); @@ -241,7 +279,7 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { .addComponent(tbDbHostname) .addGroup(pnDatabaseSettingsLayout.createSequentialGroup() .addComponent(lbDatabaseSettings) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 231, Short.MAX_VALUE) .addComponent(bnTestDatabase) .addGap(18, 18, 18) .addComponent(lbTestDatabase, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)) @@ -260,7 +298,7 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { .addGroup(pnDatabaseSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(bnTestDatabase) .addComponent(lbTestDatabase, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lbDatabaseSettings)) + .addComponent(lbDatabaseSettings, javax.swing.GroupLayout.Alignment.TRAILING)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(tbDbHostname, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -276,14 +314,14 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { pnSolrSettings.setBorder(javax.swing.BorderFactory.createEtchedBorder()); - lbSolrSettings.setFont(lbSolrSettings.getFont().deriveFont(lbSolrSettings.getFont().getSize()+1f)); - org.openide.awt.Mnemonics.setLocalizedText(lbSolrSettings, org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.lbSolrSettings.text")); // NOI18N + lbSolr8Settings.setFont(lbSolr8Settings.getFont().deriveFont(lbSolr8Settings.getFont().getSize()+1f)); + org.openide.awt.Mnemonics.setLocalizedText(lbSolr8Settings, org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.lbSolr8Settings.text")); // NOI18N - tbSolrHostname.setFont(tbSolrHostname.getFont().deriveFont(tbSolrHostname.getFont().getSize()+1f)); - tbSolrHostname.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbSolrHostname.toolTipText")); // NOI18N + tbSolr8Hostname.setFont(tbSolr8Hostname.getFont().deriveFont(tbSolr8Hostname.getFont().getSize()+1f)); + tbSolr8Hostname.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbSolr8Hostname.toolTipText")); // NOI18N - tbSolrPort.setFont(tbSolrPort.getFont().deriveFont(tbSolrPort.getFont().getSize()+1f)); - tbSolrPort.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbSolrPort.toolTipText")); // NOI18N + tbSolr8Port.setFont(tbSolr8Port.getFont().deriveFont(tbSolr8Port.getFont().getSize()+1f)); + tbSolr8Port.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbSolr8Port.toolTipText")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(bnTestSolr, org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.bnTestSolr.text")); // NOI18N bnTestSolr.addActionListener(new java.awt.event.ActionListener() { @@ -297,6 +335,30 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { lbTestSolrWarning.setForeground(new java.awt.Color(255, 0, 0)); org.openide.awt.Mnemonics.setLocalizedText(lbTestSolrWarning, org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.lbTestSolrWarning.text")); // NOI18N + tbSolr4Hostname.setFont(tbSolr4Hostname.getFont().deriveFont(tbSolr4Hostname.getFont().getSize()+1f)); + tbSolr4Hostname.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbSolr4Hostname.toolTipText")); // NOI18N + + tbSolr4Port.setFont(tbSolr4Port.getFont().deriveFont(tbSolr4Port.getFont().getSize()+1f)); + tbSolr4Port.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbSolr4Port.toolTipText")); // NOI18N + + lbSolr4Settings.setFont(lbSolr4Settings.getFont().deriveFont(lbSolr4Settings.getFont().getSize()+1f)); + org.openide.awt.Mnemonics.setLocalizedText(lbSolr4Settings, org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.lbSolr4Settings.text")); // NOI18N + + lbZkSettings.setFont(lbZkSettings.getFont().deriveFont(lbZkSettings.getFont().getSize()+1f)); + org.openide.awt.Mnemonics.setLocalizedText(lbZkSettings, org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.lbZkSettings.text")); // NOI18N + + tbZkHostname.setFont(tbZkHostname.getFont().deriveFont(tbZkHostname.getFont().getSize()+1f)); + tbZkHostname.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbZkHostname.toolTipText")); // NOI18N + + tbZkPort.setFont(tbZkPort.getFont().deriveFont(tbZkPort.getFont().getSize()+1f)); + tbZkPort.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbZkPort.toolTipText")); // NOI18N + + lbSolrNote1.setFont(lbSolrNote1.getFont().deriveFont(lbSolrNote1.getFont().getSize()+1f)); + org.openide.awt.Mnemonics.setLocalizedText(lbSolrNote1, org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.lbSolrNote1.text")); // NOI18N + + lbSolrNote2.setFont(lbSolrNote2.getFont().deriveFont(lbSolrNote2.getFont().getSize()+1f)); + org.openide.awt.Mnemonics.setLocalizedText(lbSolrNote2, org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.lbSolrNote2.text")); // NOI18N + javax.swing.GroupLayout pnSolrSettingsLayout = new javax.swing.GroupLayout(pnSolrSettings); pnSolrSettings.setLayout(pnSolrSettingsLayout); pnSolrSettingsLayout.setHorizontalGroup( @@ -304,37 +366,66 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { .addGroup(pnSolrSettingsLayout.createSequentialGroup() .addContainerGap() .addGroup(pnSolrSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(tbSolrHostname) + .addComponent(tbSolr8Hostname) .addGroup(pnSolrSettingsLayout.createSequentialGroup() - .addComponent(lbSolrSettings) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(pnSolrSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(lbSolr8Settings) + .addComponent(lbSolrNote1) + .addComponent(lbSolrNote2)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 57, Short.MAX_VALUE) .addComponent(bnTestSolr) - .addGap(18, 18, 18) - .addComponent(lbTestSolr, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addComponent(tbSolrPort) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(lbTestSolr, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(3, 3, 3)) + .addComponent(tbSolr8Port) + .addComponent(tbSolr4Hostname) + .addComponent(tbSolr4Port) + .addComponent(tbZkHostname) + .addComponent(tbZkPort) .addGroup(pnSolrSettingsLayout.createSequentialGroup() - .addComponent(lbTestSolrWarning) + .addGroup(pnSolrSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(lbTestSolrWarning) + .addComponent(lbSolr4Settings) + .addComponent(lbZkSettings)) .addGap(0, 0, Short.MAX_VALUE))) .addContainerGap()) ); pnSolrSettingsLayout.setVerticalGroup( pnSolrSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(pnSolrSettingsLayout.createSequentialGroup() - .addContainerGap() + .addGap(8, 8, 8) + .addComponent(lbSolrNote1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lbSolrNote2) + .addGap(20, 20, 20) .addGroup(pnSolrSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnSolrSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(bnTestSolr, javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(lbSolrSettings)) - .addComponent(lbTestSolr, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(pnSolrSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(lbSolr8Settings) + .addComponent(bnTestSolr)) + .addComponent(lbTestSolr, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(tbSolrHostname, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(tbSolr8Hostname, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(tbSolr8Port, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(18, 18, 18) + .addComponent(lbSolr4Settings, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(tbSolr4Hostname, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(tbSolr4Port, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(lbZkSettings) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(tbZkHostname, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(tbZkPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(tbSolrPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(lbTestSolrWarning, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap()) ); + tbSolr4Port.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbSolr4Port.toolTipText")); // NOI18N + pnMessagingSettings.setBorder(javax.swing.BorderFactory.createEtchedBorder()); lbMessageServiceSettings.setFont(lbMessageServiceSettings.getFont().deriveFont((float)12)); @@ -378,7 +469,7 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { .addComponent(tbMsgHostname) .addGroup(pnMessagingSettingsLayout.createSequentialGroup() .addComponent(lbMessageServiceSettings) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 229, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(bnTestMessageService) .addGap(18, 18, 18) .addComponent(lbTestMessageService, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)) @@ -395,8 +486,8 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { .addGroup(pnMessagingSettingsLayout.createSequentialGroup() .addContainerGap() .addGroup(pnMessagingSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(pnMessagingSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(bnTestMessageService, javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(pnMessagingSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(bnTestMessageService) .addComponent(lbMessageServiceSettings)) .addComponent(lbTestMessageService, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -436,10 +527,11 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { .addComponent(cbEnableMultiUser) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(tbOops)) - .addComponent(pnSolrSettings, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(pnDatabaseSettings, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(pnMessagingSettings, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addContainerGap()) + .addComponent(pnMessagingSettings, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pnSolrSettings, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(39, 39, 39)) ); pnOverallPanelLayout.setVerticalGroup( pnOverallPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -448,12 +540,13 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { .addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(cbEnableMultiUser)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pnDatabaseSettings, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pnSolrSettings, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pnMessagingSettings, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(39, Short.MAX_VALUE)) + .addGroup(pnOverallPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addGroup(pnOverallPanelLayout.createSequentialGroup() + .addComponent(pnDatabaseSettings, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(18, 18, 18) + .addComponent(pnMessagingSettings, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(pnSolrSettings, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap(201, Short.MAX_VALUE)) ); jScrollPane.setViewportView(pnOverallPanel); @@ -462,13 +555,13 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 555, Short.MAX_VALUE) + .addComponent(jScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 1191, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addComponent(jScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 537, Short.MAX_VALUE) + .addComponent(jScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 695, Short.MAX_VALUE) .addContainerGap()) ); }// //GEN-END:initComponents @@ -477,7 +570,7 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { * Enables/disables the multi-user settings, based upon input provided * * @param textFields The text fields to enable/disable. - * @param enabled True means enable, false means disable. + * @param enabled True means enable, false means disable. */ private static void enableMultiUserComponents(Collection textFields, boolean enabled) { for (JTextField textField : textFields) { @@ -570,8 +663,31 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class); try { if (kwsService != null) { - int port = Integer.parseInt(tbSolrPort.getText().trim()); - kwsService.tryConnect(tbSolrHostname.getText().trim(), port); + // test Solr 8 connectivity + if (!tbSolr8Port.getText().trim().isEmpty() && !tbSolr8Hostname.getText().trim().isEmpty()) { + int port = Integer.parseInt(tbSolr8Port.getText().trim()); + kwsService.tryConnect(tbSolr8Hostname.getText().trim(), port); + } + + // test Solr 4 conenctivity + if (!tbSolr4Port.getText().trim().isEmpty() && !tbSolr4Hostname.getText().trim().isEmpty()) { + int port = Integer.parseInt(tbSolr4Port.getText().trim()); + kwsService.tryConnect(tbSolr4Hostname.getText().trim(), port); + } + + // test ZooKeeper connectivity (ZK settings are mandatory) + if (tbZkPort.getText().trim().isEmpty() || tbZkHostname.getText().trim().isEmpty()) { + lbTestSolr.setIcon(badIcon); + lbTestSolrWarning.setText(NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.UnableToConnectToZK")); + return; + } + + if (false == CoordinationServiceUtils.isZooKeeperAccessible(tbZkHostname.getText().trim(), tbZkPort.getText().trim())) { + lbTestSolr.setIcon(badIcon); + lbTestSolrWarning.setText(NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.UnableToConnectToZK")); + return; + } + lbTestSolr.setIcon(goodIcon); lbTestSolrWarning.setText(""); } else { @@ -584,6 +700,10 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { } catch (KeywordSearchServiceException ex) { lbTestSolr.setIcon(badIcon); lbTestSolrWarning.setText(ex.getMessage()); + } catch (InterruptedException | IOException ex) { + // ZK exceptions + lbTestSolr.setIcon(badIcon); + lbTestSolrWarning.setText(ex.getMessage()); } finally { setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } @@ -617,14 +737,7 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { logger.log(Level.SEVERE, "Error accessing case database connection info", ex); //NON-NLS } - String indexingServerHost = UserPreferences.getIndexingServerHost().trim(); - if (!indexingServerHost.isEmpty()) { - tbSolrHostname.setText(indexingServerHost); - } - String indexingServerPort = UserPreferences.getIndexingServerPort().trim(); - if (portNumberIsValid(indexingServerPort)) { - tbSolrPort.setText(indexingServerPort); - } + populateSolrAndZkSettings(); lbTestDatabase.setIcon(null); lbTestSolr.setIcon(null); @@ -638,6 +751,54 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { this.valid(); // trigger validation to enable buttons based on current settings } + private void populateSolrAndZkSettings() { + + String indexingServerHost = UserPreferences.getIndexingServerHost().trim(); + if (!indexingServerHost.isEmpty()) { + tbSolr8Hostname.setText(indexingServerHost); + } + String indexingServerPort = UserPreferences.getIndexingServerPort().trim(); + if (portNumberIsValid(indexingServerPort)) { + tbSolr8Port.setText(indexingServerPort); + } + + String solr4ServerHost = UserPreferences.getSolr4ServerHost().trim(); + if (!solr4ServerHost.isEmpty()) { + tbSolr4Hostname.setText(solr4ServerHost); + } + String solr4ServerPort = UserPreferences.getSolr4ServerPort().trim(); + if (portNumberIsValid(solr4ServerPort)) { + tbSolr4Port.setText(solr4ServerPort); + } + + // if there are existing valid ZK settings, use those + String zkServerPort = UserPreferences.getZkServerPort().trim(); + if (portNumberIsValid(zkServerPort)) { + tbZkPort.setText(zkServerPort); // gets default ZK port, which is Solr port number + 1000 + } + String zkServerHost = UserPreferences.getZkServerHost().trim(); + if (!zkServerHost.isEmpty()) { + tbZkHostname.setText(zkServerHost); + return; + } + + // If there are no previous Solr 4 settings, use Solr 8 settings + // to fill in the ZK settings with the embedded Solr 8 ZK connection info. + if (solr4ServerHost.isEmpty() && !indexingServerHost.isEmpty()) { + tbZkHostname.setText(indexingServerHost); + tbZkPort.setText(zkServerPort); // gets default ZK port, which is Solr port number + 1000 + return; + } + + // If there are existing Solr 4 settings and no Solr 8 settings, + // pre-populate the ZK settings with the Solr 4 embedded ZK settings. + if (!solr4ServerHost.isEmpty() && indexingServerHost.isEmpty()) { + tbZkHostname.setText(solr4ServerHost); + tbZkPort.setText(zkServerPort); // gets default ZK port, which is Solr port number + 1000 + return; + } + } + /** * Tests whether or not values have been entered in all of the database * settings text fields. @@ -652,14 +813,31 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { } /** - * Tests whether or not values have been entered in all of the Solr settings - * text fields. + * Tests whether or not values have been entered in all of the mandatory + * Solr settings text fields. Test optional settings for completeness. * * @return True or false. */ private boolean solrFieldsArePopulated() { - return !tbSolrHostname.getText().trim().isEmpty() - && !tbSolrPort.getText().trim().isEmpty(); + + // either Solr 8 or/and Solr 4 seetings must be specified + boolean solrConfigured = false; + + // check if Solr 8 settings are set + if (!tbSolr8Hostname.getText().trim().isEmpty() + && !tbSolr8Port.getText().trim().isEmpty()) { + solrConfigured = true; + } + + // check if Solr 4 settings are set + if (!tbSolr4Hostname.getText().trim().isEmpty() + && !tbSolr4Port.getText().trim().isEmpty()) { + solrConfigured = true; + } + + // ZK settings are mandatory + return (solrConfigured && !tbZkHostname.getText().trim().isEmpty() + && !tbZkPort.getText().trim().isEmpty()); } /** @@ -680,8 +858,6 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { boolean isPwSet = (tbMsgPassword.getPassword().length != 0); return (isUserSet == isPwSet); } - - void store() { boolean prevSelected = UserPreferences.getIsMultiUserModeEnabled(); @@ -694,11 +870,18 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { boolean multiUserCasesEnabled = cbEnableMultiUser.isSelected(); UserPreferences.setIsMultiUserModeEnabled(multiUserCasesEnabled); - + CaseDbConnectionInfo info = null; - + if (multiUserCasesEnabled == true) { + // Check if aplication restart is required. + boolean needsRestart = false; + // don't check if entring multi user data for the first time + if (prevSelected == true) { + needsRestart = isRestartRequired(); + } + /* * Currently only supporting multi-user cases with PostgreSQL case * databases. @@ -735,37 +918,63 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { logger.log(Level.SEVERE, "Error saving messaging service connection info", ex); //NON-NLS } - UserPreferences.setIndexingServerHost(tbSolrHostname.getText().trim()); - UserPreferences.setIndexingServerPort(Integer.parseInt(tbSolrPort.getText().trim())); + UserPreferences.setIndexingServerHost(tbSolr8Hostname.getText().trim()); + String solr8port = tbSolr8Port.getText().trim(); + if (!solr8port.isEmpty()) { + UserPreferences.setIndexingServerPort(Integer.parseInt(solr8port)); + } + UserPreferences.setSolr4ServerHost(tbSolr4Hostname.getText().trim()); + UserPreferences.setSolr4ServerPort(tbSolr4Port.getText().trim()); + UserPreferences.setZkServerHost(tbZkHostname.getText().trim()); + UserPreferences.setZkServerPort(tbZkPort.getText().trim()); + + if (needsRestart) { + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(this, + NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.MustRestart"), + NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.restartRequiredLabel.text"), + JOptionPane.WARNING_MESSAGE); + }); + } } // trigger changes to whether or not user can use multi user settings for central repository - if (prevSelected != multiUserCasesEnabled || !areCaseDbConnectionEqual(prevConn, info)) + if (prevSelected != multiUserCasesEnabled || !areCaseDbConnectionEqual(prevConn, info)) { GlobalSettingsPanel.onMultiUserChange(this, prevSelected, multiUserCasesEnabled); + } + } + + private boolean isRestartRequired() { + // if ZK was previously configured + if (!UserPreferences.getZkServerHost().isEmpty()) { + // Restart is required any time ZK info has changed + if (!(tbZkHostname.getText().trim().equalsIgnoreCase(UserPreferences.getZkServerHost())) + || !(tbZkPort.getText().trim().equals(UserPreferences.getZkServerPort()))) { + return true; + } + } + return false; } private static boolean arePropsEqual(Object a, Object b) { if (a == null || b == null) { return (a == null && b == null); - } - else { + } else { return a.equals(b); } } - - private static boolean areCaseDbConnectionEqual(CaseDbConnectionInfo a, CaseDbConnectionInfo b) { + + private static boolean areCaseDbConnectionEqual(CaseDbConnectionInfo a, CaseDbConnectionInfo b) { if (a == null || b == null) { return (a == null && b == null); } - return - arePropsEqual(a.getDbType(), b.getDbType()) && - arePropsEqual(a.getHost(), b.getHost()) && - arePropsEqual(a.getPassword(), b.getPassword()) && - arePropsEqual(a.getPort(), b.getPort()) && - arePropsEqual(a.getUserName(), b.getUserName()); - } - + return arePropsEqual(a.getDbType(), b.getDbType()) + && arePropsEqual(a.getHost(), b.getHost()) + && arePropsEqual(a.getPassword(), b.getPassword()) + && arePropsEqual(a.getPort(), b.getPort()) + && arePropsEqual(a.getUserName(), b.getUserName()); + } /** * Validates that the form is filled out correctly for our usage. @@ -849,11 +1058,55 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { * @return True or false. */ boolean indexingServerSettingsAreValid() { - if (!portNumberIsValid(tbSolrPort.getText().trim())) { + + String solr8Port = tbSolr8Port.getText().trim(); + if (!solr8Port.isEmpty() && !portNumberIsValid(solr8Port)) { + // if the port is specified, it has to be valid tbOops.setText(INVALID_INDEXING_SERVER_PORT_MSG); return false; } + String solr4Port = tbSolr4Port.getText().trim(); + if (!solr4Port.isEmpty() && !portNumberIsValid(solr4Port)) { + // if the port is specified, it has to be valid + tbOops.setText(INVALID_SOLR4_SERVER_PORT_MSG); + return false; + } + + // either Solr 8 or/and Solr 4 seetings must be specified + boolean solrConfigured = false; + + // check if Solr 8 settings are set + if (!tbSolr8Hostname.getText().trim().isEmpty() + && !tbSolr8Port.getText().trim().isEmpty()) { + solrConfigured = true; + } + + // check if Solr 4 settings are set + if (!tbSolr4Hostname.getText().trim().isEmpty() + && !tbSolr4Port.getText().trim().isEmpty()) { + solrConfigured = true; + } + + if (!solrConfigured) { + tbOops.setText(SOLR_SERVER_NOT_CONFIGURED_MSG); + return false; + } + + // ZK settings are mandatory + if (tbZkHostname.getText().trim().isEmpty()) { + tbOops.setText(INVALID_ZK_SERVER_HOST_MSG); + return false; + } + + // ZK settings are mandatory + String zkPort = tbZkPort.getText().trim(); + if (zkPort.isEmpty() || !portNumberIsValid(zkPort)) { + // if the port is specified, it has to be valid + tbOops.setText(INVALID_ZK_SERVER_PORT_MSG); + return false; + } + return true; } @@ -885,13 +1138,17 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { private javax.swing.JScrollPane jScrollPane; private javax.swing.JLabel lbDatabaseSettings; private javax.swing.JLabel lbMessageServiceSettings; - private javax.swing.JLabel lbSolrSettings; + private javax.swing.JLabel lbSolr4Settings; + private javax.swing.JLabel lbSolr8Settings; + private javax.swing.JLabel lbSolrNote1; + private javax.swing.JLabel lbSolrNote2; private javax.swing.JLabel lbTestDatabase; private javax.swing.JLabel lbTestDbWarning; private javax.swing.JLabel lbTestMessageService; private javax.swing.JLabel lbTestMessageWarning; private javax.swing.JLabel lbTestSolr; private javax.swing.JLabel lbTestSolrWarning; + private javax.swing.JLabel lbZkSettings; private javax.swing.JPanel pnDatabaseSettings; private javax.swing.JPanel pnMessagingSettings; private javax.swing.JPanel pnOverallPanel; @@ -905,8 +1162,12 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { private javax.swing.JTextField tbMsgPort; private javax.swing.JTextField tbMsgUsername; private javax.swing.JTextField tbOops; - private javax.swing.JTextField tbSolrHostname; - private javax.swing.JTextField tbSolrPort; + private javax.swing.JTextField tbSolr4Hostname; + private javax.swing.JTextField tbSolr4Port; + private javax.swing.JTextField tbSolr8Hostname; + private javax.swing.JTextField tbSolr8Port; + private javax.swing.JTextField tbZkHostname; + private javax.swing.JTextField tbZkPort; // End of variables declaration//GEN-END:variables /** @@ -942,4 +1203,22 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { controller.changed(); } } + + private class MyDocumentListener implements DocumentListener { + + @Override + public void changedUpdate(DocumentEvent e) { + tbZkHostname.setText(tbSolr8Hostname.getText().trim()); + } + + @Override + public void removeUpdate(DocumentEvent e) { + tbZkHostname.setText(tbSolr8Hostname.getText().trim()); + } + + @Override + public void insertUpdate(DocumentEvent e) { + tbZkHostname.setText(tbSolr8Hostname.getText().trim()); + } + }; } diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/PlatformUtil.java b/Core/src/org/sleuthkit/autopsy/coreutils/PlatformUtil.java index e729248b47..9aae3292c3 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/PlatformUtil.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/PlatformUtil.java @@ -170,6 +170,7 @@ public class PlatformUtil { return javaPath; } + // by default, use Java that came with Autopsy File jrePath = new File(getInstallPath() + File.separator + "jre"); if (jrePath.exists() && jrePath.isDirectory()) { System.out.println( @@ -177,10 +178,12 @@ public class PlatformUtil { "PlatformUtil.jrePath.jreDir.msg", jrePath.getAbsolutePath())); javaPath = jrePath.getAbsolutePath() + File.separator + "bin" + File.separator + "java"; //NON-NLS + } else if (System.getProperty("java.home") != null && !(System.getProperty("java.home").isEmpty())) { + // if OS knows where Java is located + return System.getProperty("java.home") + File.separator + "bin" + File.separator + "java"; //NON-NLS } else { //else use system installed java in PATH env variable javaPath = "java"; //NON-NLS - } System.out.println(NbBundle.getMessage(PlatformUtil.class, "PlatformUtil.jrePath.usingJavaPath.msg", javaPath)); diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/TextUtil.java b/Core/src/org/sleuthkit/autopsy/coreutils/TextUtil.java index f2eed8e474..53b19ee310 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/TextUtil.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/TextUtil.java @@ -71,12 +71,19 @@ public class TextUtil { * have chosen to ignore the extended planes above Unicode BMP for the time * being. The net result of this is some non-BMP characters may be * interspersed with '^' characters in Autopsy. + * + * Strip all non-characters + * http://unicode.org/cldr/utility/list-unicodeset.jsp?a=[:Noncharacter_Code_Point=True:] + * and non-printable control characters except tabulator, new line and carriage return * * @param ch the character to test * * @return Returns true if the character is valid UTF-8, false if not. */ public static boolean isValidSolrUTF8(char ch) { - return ((ch <= 0xFDD0 || ch >= 0xFDEF) && (ch > 0x1F || ch == 0x9 || ch == 0xA || ch == 0xD) && (ch != 0xFFFF) && (ch != 0xFFFE)); + return ((ch <= 0xFDD0 || ch >= 0xFDEF) // 0xfdd0 - 0xfdef + && (ch > 0x1F || ch == 0x9 || ch == 0xA || ch == 0xD) + && (ch % 0x10000 != 0xFFFF) // 0xffff - 0x10ffff range step 0x10000 + && (ch % 0x10000 != 0xFFFE)); // 0xfffe - 0x10fffe range } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java index 34a6859292..efdfb12c48 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java @@ -982,7 +982,21 @@ public class BlackboardArtifactNode extends AbstractContentNode + + + @@ -34,6 +37,12 @@ + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index 6235761d6e..9aa41b3c20 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -52,7 +52,7 @@ class ArtifactsListPanel extends JPanel { @ThreadConfined(type = ThreadConfined.ThreadType.AWT) ArtifactsListPanel(BlackboardArtifact.ARTIFACT_TYPE artifactType) { tableModel = new DomainArtifactTableModel(artifactType); - initComponents(); + initComponents(); jTable1.getRowSorter().toggleSortOrder(0); jTable1.getRowSorter().toggleSortOrder(0); } @@ -153,8 +153,11 @@ class ArtifactsListPanel extends JPanel { jTable1 = new javax.swing.JTable(); setOpaque(false); + setPreferredSize(new java.awt.Dimension(300, 0)); jScrollPane1.setBorder(null); + jScrollPane1.setMinimumSize(new java.awt.Dimension(0, 0)); + jScrollPane1.setPreferredSize(new java.awt.Dimension(0, 0)); jTable1.setAutoCreateRowSorter(true); jTable1.setModel(tableModel); @@ -311,6 +314,10 @@ class ArtifactsListPanel extends JPanel { return bba.getDisplayString(); } else if (columnIndex == 1 && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL.getTypeID() && !StringUtils.isBlank(bba.getDisplayString())) { return bba.getDisplayString(); + } else if (columnIndex == 1 && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID() && !StringUtils.isBlank(bba.getDisplayString())) { + return bba.getDisplayString(); + } else if (columnIndex == 1 && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT.getTypeID() && !StringUtils.isBlank(bba.getDisplayString())) { + return bba.getDisplayString(); } } return Bundle.ArtifactsListPanel_value_noValue(); @@ -339,7 +346,6 @@ class ArtifactsListPanel extends JPanel { } } } - // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JTable jTable1; // End of variables declaration//GEN-END:variables diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java index 9a47e164cf..371c99fae7 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsWorker.java @@ -76,5 +76,4 @@ class ArtifactsWorker extends SwingWorker, Void> { } DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.ArtifactSearchResultEvent(artifactType, listOfArtifacts)); } - } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED index a5305503b5..6c9f511ba6 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED @@ -151,7 +151,3 @@ VideoThumbnailPanel.nameLabel.more.text=\ and {0} more # {1} - units VideoThumbnailPanel.sizeLabel.text=Size: {0} {1} VideoThumbnailPanel.terraBytes.text=TB -WebHistoryDetailsPanel.details.attrHeader=Attributes -WebHistoryDetailsPanel.details.dataSource=Data Source -WebHistoryDetailsPanel.details.file=File -WebHistoryDetailsPanel.details.sourceHeader=Source diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryDialog.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryDialog.java index 565dad8a88..e3ebba7a3d 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryDialog.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryDialog.java @@ -118,10 +118,7 @@ final class DiscoveryDialog extends javax.swing.JDialog { @Override public void itemStateChanged(ItemEvent event) { if (event.getStateChange() == ItemEvent.SELECTED) { - SwingUtilities.invokeLater(() -> { - getSelectedFilterPanel().setLastGroupingAttributeType(groupByCombobox.getItemAt(groupByCombobox.getSelectedIndex())); - }); - + getSelectedFilterPanel().setLastGroupingAttributeType(groupByCombobox.getItemAt(groupByCombobox.getSelectedIndex())); } } }); @@ -129,9 +126,7 @@ final class DiscoveryDialog extends javax.swing.JDialog { @Override public void itemStateChanged(ItemEvent event) { if (event.getStateChange() == ItemEvent.SELECTED) { - SwingUtilities.invokeLater(() -> { - getSelectedFilterPanel().setLastSortingMethod(orderByCombobox.getItemAt(orderByCombobox.getSelectedIndex())); - }); + getSelectedFilterPanel().setLastSortingMethod(orderByCombobox.getItemAt(orderByCombobox.getSelectedIndex())); } } }); @@ -139,9 +134,7 @@ final class DiscoveryDialog extends javax.swing.JDialog { @Override public void itemStateChanged(ItemEvent event) { if (event.getStateChange() == ItemEvent.SELECTED) { - SwingUtilities.invokeLater(() -> { - getSelectedFilterPanel().setLastGroupSortingAlg(groupSortingComboBox.getItemAt(groupSortingComboBox.getSelectedIndex())); - }); + getSelectedFilterPanel().setLastGroupSortingAlg(groupSortingComboBox.getItemAt(groupSortingComboBox.getSelectedIndex())); } } }); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java index 371f329f00..994f17c390 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryTopComponent.java @@ -56,12 +56,12 @@ public final class DiscoveryTopComponent extends TopComponent { private static final long serialVersionUID = 1L; private static final String PREFERRED_ID = "DiscoveryTc"; // NON-NLS private static final int ANIMATION_INCREMENT = 30; - private volatile static int resultsAreaSize = 250; + private volatile static int previousDividerLocation = 250; private final GroupListPanel groupListPanel; private final ResultsPanel resultsPanel; private String selectedDomainTabName; private Type searchType; - private int dividerLocation = -1; + private int dividerLocation = JSplitPane.UNDEFINED_CONDITION; private SwingAnimator animator = null; /** @@ -87,9 +87,13 @@ public final class DiscoveryTopComponent extends TopComponent { public void propertyChange(PropertyChangeEvent evt) { if (evt.getPropertyName().equalsIgnoreCase(JSplitPane.DIVIDER_LOCATION_PROPERTY)) { //Only change the saved location when it was a manual change by the user and not the animation or the window opening initially - if ((animator == null || !animator.isRunning()) && evt.getNewValue() instanceof Integer - && ((int) evt.getNewValue() + 5) < (rightSplitPane.getHeight() - rightSplitPane.getDividerSize())) { - resultsAreaSize = (int) evt.getNewValue(); + if ((animator == null || !animator.isRunning()) + && evt.getNewValue() instanceof Integer + && evt.getOldValue() instanceof Integer + && ((int) evt.getNewValue() + 5) < (rightSplitPane.getHeight() - rightSplitPane.getDividerSize()) + && (JSplitPane.UNDEFINED_CONDITION != (int) evt.getNewValue()) + && ((int) evt.getOldValue() != JSplitPane.UNDEFINED_CONDITION)) { + previousDividerLocation = (int) evt.getNewValue(); } } @@ -160,6 +164,7 @@ public final class DiscoveryTopComponent extends TopComponent { if (rightSplitPane.getBottomComponent() instanceof DomainDetailsPanel) { selectedDomainTabName = ((DomainDetailsPanel) rightSplitPane.getBottomComponent()).getSelectedTabName(); } + rightSplitPane.setDividerLocation(JSplitPane.UNDEFINED_CONDITION); super.componentClosed(); } @@ -350,6 +355,7 @@ public final class DiscoveryTopComponent extends TopComponent { @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private String validateLastSelectedType(DiscoveryEventUtils.SearchCompleteEvent searchCompleteEvent) { String typeFilteredOn = selectedDomainTabName; + for (AbstractFilter filter : searchCompleteEvent.getFilters()) { if (filter instanceof ArtifactTypeFilter) { for (ARTIFACT_TYPE type : ((ArtifactTypeFilter) filter).getTypes()) { @@ -396,8 +402,8 @@ public final class DiscoveryTopComponent extends TopComponent { @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @Override public boolean hasTerminated() { - if (dividerLocation != JSplitPane.UNDEFINED_CONDITION && dividerLocation < resultsAreaSize) { - dividerLocation = resultsAreaSize; + if (dividerLocation != JSplitPane.UNDEFINED_CONDITION && dividerLocation < previousDividerLocation) { + dividerLocation = previousDividerLocation; animator = null; return true; } @@ -448,7 +454,7 @@ public final class DiscoveryTopComponent extends TopComponent { @Override public void paintComponent(Graphics g) { if (animator != null && animator.isRunning() && (dividerLocation == JSplitPane.UNDEFINED_CONDITION - || (dividerLocation <= getHeight() && dividerLocation >= resultsAreaSize))) { + || (dividerLocation <= getHeight() && dividerLocation >= previousDividerLocation))) { setDividerLocation(dividerLocation); } super.paintComponent(g); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.form index 1e93e06f86..fbd55756e9 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.form +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.form @@ -1,6 +1,14 @@ + + + + + + + + @@ -17,6 +25,14 @@ + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java index 295107ef78..453785181c 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainArtifactsTabPanel.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.discovery.ui; +import org.sleuthkit.autopsy.contentviewers.artifactviewers.GeneralPurposeArtifactViewer; import com.google.common.eventbus.Subscribe; import java.util.logging.Level; import javax.swing.JPanel; @@ -25,7 +26,7 @@ import javax.swing.JScrollPane; import javax.swing.SwingUtilities; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; -import org.sleuthkit.autopsy.contentviewers.artifactviewers.DefaultArtifactContentViewer; +import org.sleuthkit.autopsy.contentviewers.artifactviewers.DefaultTableArtifactContentViewer; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils; @@ -75,19 +76,17 @@ final class DomainArtifactsTabPanel extends JPanel { private void setRightComponent() { switch (artifactType) { case TSK_WEB_HISTORY: - rightPanel = new WebHistoryDetailsPanel(); - break; case TSK_WEB_COOKIE: case TSK_WEB_SEARCH_QUERY: case TSK_WEB_BOOKMARK: - rightPanel = new DefaultArtifactContentViewer(); + rightPanel = new GeneralPurposeArtifactViewer(); break; case TSK_WEB_DOWNLOAD: case TSK_WEB_CACHE: rightPanel = new ContentViewerDetailsPanel(); break; default: - rightPanel = new DefaultArtifactContentViewer(); + rightPanel = new DefaultTableArtifactContentViewer(); break; } if (rightPanel != null) { @@ -98,7 +97,7 @@ final class DomainArtifactsTabPanel extends JPanel { /** * Get the status of the panel which indicates if it is populated. * - * @return The ArtifactRetrievalStatuss of the panel. + * @return The ArtifactRetrievalStatus of the panel. */ @ThreadConfined(type = ThreadConfined.ThreadType.AWT) ArtifactRetrievalStatus getStatus() { @@ -126,24 +125,24 @@ final class DomainArtifactsTabPanel extends JPanel { */ @Subscribe void handleArtifactSearchResultEvent(DiscoveryEventUtils.ArtifactSearchResultEvent artifactresultEvent) { - SwingUtilities.invokeLater(() -> { - if (artifactType == artifactresultEvent.getArtifactType()) { + if (artifactType == artifactresultEvent.getArtifactType()) { + SwingUtilities.invokeLater(() -> { listPanel.removeListSelectionListener(listener); listPanel.addArtifacts(artifactresultEvent.getListOfArtifacts()); + status = ArtifactRetrievalStatus.POPULATED; + setEnabled(!listPanel.isEmpty()); listPanel.addSelectionListener(listener); listPanel.selectFirst(); + revalidate(); + repaint(); try { DiscoveryEventUtils.getDiscoveryEventBus().unregister(this); } catch (IllegalArgumentException notRegistered) { logger.log(Level.INFO, "Attempting to unregister tab which was not registered"); // attempting to remove a tab that was never registered } - status = ArtifactRetrievalStatus.POPULATED; - setEnabled(!listPanel.isEmpty()); - validate(); - repaint(); - } - }); + }); + } } /** @@ -167,7 +166,12 @@ final class DomainArtifactsTabPanel extends JPanel { jSplitPane1 = new javax.swing.JSplitPane(); + setMinimumSize(new java.awt.Dimension(0, 0)); + setPreferredSize(new java.awt.Dimension(0, 0)); setLayout(new java.awt.BorderLayout()); + + jSplitPane1.setMinimumSize(new java.awt.Dimension(0, 0)); + jSplitPane1.setPreferredSize(new java.awt.Dimension(0, 0)); add(jSplitPane1, java.awt.BorderLayout.CENTER); }// //GEN-END:initComponents diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.form b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.form index 162d346225..b6e16aff08 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.form @@ -3,6 +3,12 @@ + + + + + + @@ -20,6 +26,14 @@ + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java index 6fd407cbaf..dd98d1c15d 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java @@ -96,22 +96,21 @@ final class DomainDetailsPanel extends JPanel { * Run the worker which retrieves the list of artifacts for the domain to * populate the details area. */ + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private void runDomainWorker() { - SwingUtilities.invokeLater(() -> { - Component selectedComponent = jTabbedPane1.getSelectedComponent(); - if (selectedComponent instanceof DomainArtifactsTabPanel) { - if (detailsWorker != null && !detailsWorker.isDone()) { - detailsWorker.cancel(true); - } - DomainArtifactsTabPanel selectedTab = (DomainArtifactsTabPanel) selectedComponent; - if (selectedTab.getStatus() == DomainArtifactsTabPanel.ArtifactRetrievalStatus.UNPOPULATED) { - selectedTab.setStatus(DomainArtifactsTabPanel.ArtifactRetrievalStatus.POPULATING); - DiscoveryEventUtils.getDiscoveryEventBus().register(selectedTab); - detailsWorker = new ArtifactsWorker(selectedTab.getArtifactType(), domain); - detailsWorker.execute(); - } + Component selectedComponent = jTabbedPane1.getSelectedComponent(); + if (selectedComponent instanceof DomainArtifactsTabPanel) { + if (detailsWorker != null && !detailsWorker.isDone()) { + detailsWorker.cancel(true); } - }); + DomainArtifactsTabPanel selectedTab = (DomainArtifactsTabPanel) selectedComponent; + if (selectedTab.getStatus() == DomainArtifactsTabPanel.ArtifactRetrievalStatus.UNPOPULATED) { + DiscoveryEventUtils.getDiscoveryEventBus().register(selectedTab); + selectedTab.setStatus(DomainArtifactsTabPanel.ArtifactRetrievalStatus.POPULATING); + detailsWorker = new ArtifactsWorker(selectedTab.getArtifactType(), domain); + detailsWorker.execute(); + } + } } /** @@ -122,8 +121,8 @@ final class DomainDetailsPanel extends JPanel { */ @Subscribe void handlePopulateDomainTabsEvent(DiscoveryEventUtils.PopulateDomainTabsEvent populateEvent) { + domain = populateEvent.getDomain(); SwingUtilities.invokeLater(() -> { - domain = populateEvent.getDomain(); resetTabsStatus(); selectTab(); runDomainWorker(); @@ -172,7 +171,12 @@ final class DomainDetailsPanel extends JPanel { jTabbedPane1 = new javax.swing.JTabbedPane(); setEnabled(false); + setMinimumSize(new java.awt.Dimension(0, 0)); + setPreferredSize(new java.awt.Dimension(0, 0)); setLayout(new java.awt.BorderLayout()); + + jTabbedPane1.setMinimumSize(new java.awt.Dimension(0, 0)); + jTabbedPane1.setPreferredSize(new java.awt.Dimension(0, 0)); add(jTabbedPane1, java.awt.BorderLayout.CENTER); }// //GEN-END:initComponents diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/FileDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/FileDetailsPanel.java index 9230459d6d..ac7eb05f6d 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/FileDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/FileDetailsPanel.java @@ -70,20 +70,18 @@ final class FileDetailsPanel extends javax.swing.JPanel { @Override public void mousePressed(MouseEvent e) { if (SwingUtilities.isRightMouseButton(e)) { - SwingUtilities.invokeLater(() -> { - instancesList.setSelectedIndex(instancesList.locationToIndex(e.getPoint())); - Set files = new HashSet<>(); - files.add(instancesList.getSelectedValue()); - JPopupMenu menu = new JPopupMenu(); - menu.add(new ViewContextAction(Bundle.ResultsPanel_viewFileInDir_name(), instancesList.getSelectedValue())); - menu.add(new ExternalViewerAction(Bundle.ResultsPanel_openInExternalViewer_name(), new FileNode(instancesList.getSelectedValue()))); - menu.add(ViewFileInTimelineAction.createViewFileAction(instancesList.getSelectedValue())); - menu.add(new DiscoveryExtractAction(files)); - menu.add(AddContentTagAction.getInstance().getMenuForContent(files)); - menu.add(DeleteFileContentTagAction.getInstance().getMenuForFiles(files)); - menu.add(AddContentToHashDbAction.getInstance().getMenuForFiles(files)); - menu.show(instancesList, e.getPoint().x, e.getPoint().y); - }); + instancesList.setSelectedIndex(instancesList.locationToIndex(e.getPoint())); + Set files = new HashSet<>(); + files.add(instancesList.getSelectedValue()); + JPopupMenu menu = new JPopupMenu(); + menu.add(new ViewContextAction(Bundle.ResultsPanel_viewFileInDir_name(), instancesList.getSelectedValue())); + menu.add(new ExternalViewerAction(Bundle.ResultsPanel_openInExternalViewer_name(), new FileNode(instancesList.getSelectedValue()))); + menu.add(ViewFileInTimelineAction.createViewFileAction(instancesList.getSelectedValue())); + menu.add(new DiscoveryExtractAction(files)); + menu.add(AddContentTagAction.getInstance().getMenuForContent(files)); + menu.add(DeleteFileContentTagAction.getInstance().getMenuForFiles(files)); + menu.add(AddContentToHashDbAction.getInstance().getMenuForFiles(files)); + menu.show(instancesList, e.getPoint().x, e.getPoint().y); } } }); @@ -91,14 +89,12 @@ final class FileDetailsPanel extends javax.swing.JPanel { @Override public void valueChanged(ListSelectionEvent e) { if (!e.getValueIsAdjusting()) { - SwingUtilities.invokeLater(() -> { - AbstractFile file = getSelectedFile(); - if (file != null) { - dataContentPanel.setNode(new TableFilterNode(new FileNode(file), false)); - } else { - dataContentPanel.setNode(null); - } - }); + AbstractFile file = getSelectedFile(); + if (file != null) { + dataContentPanel.setNode(new TableFilterNode(new FileNode(file), false)); + } else { + dataContentPanel.setNode(null); + } } } }; @@ -127,8 +123,8 @@ final class FileDetailsPanel extends javax.swing.JPanel { */ @Subscribe void handlePopulateInstancesListEvent(DiscoveryEventUtils.PopulateInstancesListEvent populateEvent) { + List files = populateEvent.getInstances(); SwingUtilities.invokeLater(() -> { - List files = populateEvent.getInstances(); if (files.isEmpty()) { //if there are no files currently remove the current items without removing listener to cause content viewer to reset instancesListModel.removeAllElements(); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/GroupListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/GroupListPanel.java index 5a3b5393af..f4c9fab4a5 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/GroupListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/GroupListPanel.java @@ -69,10 +69,8 @@ final class GroupListPanel extends javax.swing.JPanel { */ @Subscribe void handleSearchStartedEvent(DiscoveryEventUtils.SearchStartedEvent searchStartedEvent) { - SwingUtilities.invokeLater(() -> { - type = searchStartedEvent.getType(); - groupKeyList.setListData(new GroupKey[0]); - }); + type = searchStartedEvent.getType(); + groupKeyList.setListData(new GroupKey[0]); } @Messages({"GroupsListPanel.noFileResults.message.text=No files were found for the selected filters.\n\n" @@ -94,29 +92,27 @@ final class GroupListPanel extends javax.swing.JPanel { */ @Subscribe void handleSearchCompleteEvent(DiscoveryEventUtils.SearchCompleteEvent searchCompleteEvent) { + groupMap = searchCompleteEvent.getGroupMap(); + searchfilters = searchCompleteEvent.getFilters(); + groupingAttribute = searchCompleteEvent.getGroupingAttr(); + groupSort = searchCompleteEvent.getGroupSort(); + resultSortMethod = searchCompleteEvent.getResultSort(); + groupKeyList.setListData(groupMap.keySet().toArray(new GroupKey[groupMap.keySet().size()])); SwingUtilities.invokeLater(() -> { - groupMap = searchCompleteEvent.getGroupMap(); - searchfilters = searchCompleteEvent.getFilters(); - groupingAttribute = searchCompleteEvent.getGroupingAttr(); - groupSort = searchCompleteEvent.getGroupSort(); - resultSortMethod = searchCompleteEvent.getResultSort(); - groupKeyList.setListData(groupMap.keySet().toArray(new GroupKey[groupMap.keySet().size()])); - SwingUtilities.invokeLater(() -> { - if (groupKeyList.getModel().getSize() > 0) { - groupKeyList.setSelectedIndex(0); - } else if (type == DOMAIN) { - JOptionPane.showMessageDialog(DiscoveryTopComponent.getTopComponent(), - Bundle.GroupsListPanel_noDomainResults_message_text(), - Bundle.GroupsListPanel_noResults_title_text(), - JOptionPane.PLAIN_MESSAGE); - } else { - JOptionPane.showMessageDialog(DiscoveryTopComponent.getTopComponent(), - Bundle.GroupsListPanel_noFileResults_message_text(), - Bundle.GroupsListPanel_noResults_title_text(), - JOptionPane.PLAIN_MESSAGE); - } - setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - }); + if (groupKeyList.getModel().getSize() > 0) { + groupKeyList.setSelectedIndex(0); + } else if (type == DOMAIN) { + JOptionPane.showMessageDialog(DiscoveryTopComponent.getTopComponent(), + Bundle.GroupsListPanel_noDomainResults_message_text(), + Bundle.GroupsListPanel_noResults_title_text(), + JOptionPane.PLAIN_MESSAGE); + } else { + JOptionPane.showMessageDialog(DiscoveryTopComponent.getTopComponent(), + Bundle.GroupsListPanel_noFileResults_message_text(), + Bundle.GroupsListPanel_noResults_title_text(), + JOptionPane.PLAIN_MESSAGE); + } + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); }); } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsPanel.java index b6aad696ce..1132311e29 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ResultsPanel.java @@ -182,12 +182,12 @@ final class ResultsPanel extends javax.swing.JPanel { */ @Subscribe void handlePageRetrievedEvent(DiscoveryEventUtils.PageRetrievedEvent pageRetrievedEvent) { + //send populateMesage + if (pageRetrievedEvent.getType() != DOMAIN) { + DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.PopulateInstancesListEvent(getInstancesForSelected())); + } + currentPage = pageRetrievedEvent.getPageNumber(); SwingUtilities.invokeLater(() -> { - //send populateMesage - if (pageRetrievedEvent.getType() != DOMAIN) { - DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.PopulateInstancesListEvent(getInstancesForSelected())); - } - currentPage = pageRetrievedEvent.getPageNumber(); updateControls(); resetResultViewer(); if (null != pageRetrievedEvent.getType()) { @@ -214,20 +214,17 @@ final class ResultsPanel extends javax.swing.JPanel { } resultsViewerPanel.revalidate(); resultsViewerPanel.repaint(); - } - ); + }); } @Subscribe void handleCancelBackgroundTasksEvent(DiscoveryEventUtils.CancelBackgroundTasksEvent cancelEvent) { - SwingUtilities.invokeLater(() -> { - for (SwingWorker thumbWorker : resultContentWorkers) { - if (!thumbWorker.isDone()) { - thumbWorker.cancel(true); - } + for (SwingWorker thumbWorker : resultContentWorkers) { + if (!thumbWorker.isDone()) { + thumbWorker.cancel(true); } - resultContentWorkers.clear(); - }); + } + resultContentWorkers.clear(); } /** @@ -336,14 +333,14 @@ final class ResultsPanel extends javax.swing.JPanel { */ @Subscribe void handleGroupSelectedEvent(DiscoveryEventUtils.GroupSelectedEvent groupSelectedEvent) { + searchFilters = groupSelectedEvent.getFilters(); + groupingAttribute = groupSelectedEvent.getGroupingAttr(); + groupSort = groupSelectedEvent.getGroupSort(); + fileSortMethod = groupSelectedEvent.getResultSort(); + selectedGroupKey = groupSelectedEvent.getGroupKey(); + resultType = groupSelectedEvent.getResultType(); + groupSize = groupSelectedEvent.getGroupSize(); SwingUtilities.invokeLater(() -> { - searchFilters = groupSelectedEvent.getFilters(); - groupingAttribute = groupSelectedEvent.getGroupingAttr(); - groupSort = groupSelectedEvent.getGroupSort(); - fileSortMethod = groupSelectedEvent.getResultSort(); - selectedGroupKey = groupSelectedEvent.getGroupKey(); - resultType = groupSelectedEvent.getResultType(); - groupSize = groupSelectedEvent.getGroupSize(); resetResultViewer(); setPage(0); }); @@ -357,9 +354,9 @@ final class ResultsPanel extends javax.swing.JPanel { */ @Subscribe void handleNoResultsEvent(DiscoveryEventUtils.NoResultsEvent noResultsEvent) { + groupSize = 0; + currentPage = 0; SwingUtilities.invokeLater(() -> { - groupSize = 0; - currentPage = 0; updateControls(); videoThumbnailViewer.clearViewer(); imageThumbnailViewer.clearViewer(); diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java deleted file mode 100644 index deaef104f5..0000000000 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/WebHistoryDetailsPanel.java +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Autopsy - * - * Copyright 2020 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.discovery.ui; - -import java.awt.Component; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import javax.swing.JScrollPane; -import org.openide.util.NbBundle; -import org.openide.util.lookup.ServiceProvider; -import org.sleuthkit.autopsy.contentviewers.artifactviewers.ArtifactContentViewer; -import org.sleuthkit.autopsy.contentviewers.artifactviewers.CommunicationArtifactViewerHelper; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.ThreadConfined; -import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.TskCoreException; - -/** - * Panel to display the details for a Web History Artifact. - */ -@ServiceProvider(service = ArtifactContentViewer.class) -public class WebHistoryDetailsPanel extends AbstractArtifactDetailsPanel implements ArtifactContentViewer { - - private static final long serialVersionUID = 1L; - private static final Logger logger = Logger.getLogger(WebHistoryDetailsPanel.class.getName()); - private BlackboardArtifact webHistoryArtifact; - private final GridBagLayout gridBagLayout = new GridBagLayout(); - private final List urlList = new ArrayList<>(); - private final List dateAccessedList = new ArrayList<>(); - private final List referrerUrlList = new ArrayList<>(); - private final List titleList = new ArrayList<>(); - private final List programNameList = new ArrayList<>(); - private final List domainList = new ArrayList<>(); - private final List otherList = new ArrayList<>(); - private final GridBagConstraints gridBagConstraints = new GridBagConstraints(); - private String dataSourceName; - private String sourceFileName; - - /** - * Creates new form WebHistoryDetailsPanel. - */ - @ThreadConfined(type = ThreadConfined.ThreadType.AWT) - public WebHistoryDetailsPanel() { - initComponents(); - } - - @ThreadConfined(type = ThreadConfined.ThreadType.AWT) - @Override - public void setArtifact(BlackboardArtifact artifact) { - resetComponent(); - if (artifact != null) { - try { - extractArtifactData(artifact); - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Unable to get attributes for artifact " + artifact.getArtifactID(), ex); - } - updateView(); - } - this.setLayout(this.gridBagLayout); - this.revalidate(); - this.repaint(); - } - - /** - * Extracts data from the artifact to be displayed in the panel. - * - * @param artifact Artifact to show. - * - * @throws TskCoreException - */ - @ThreadConfined(type = ThreadConfined.ThreadType.AWT) - private void extractArtifactData(BlackboardArtifact artifact) throws TskCoreException { - - webHistoryArtifact = artifact; - // Get all the attributes and group them by the section panels they go in - for (BlackboardAttribute bba : webHistoryArtifact.getAttributes()) { - if (bba.getAttributeType().getTypeName().startsWith("TSK_URL")) { - urlList.add(bba); - } else if (bba.getAttributeType().getTypeName().startsWith("TSK_PROG_NAME")) { - programNameList.add(bba); - } else if (bba.getAttributeType().getTypeName().startsWith("TSK_DOMAIN")) { - domainList.add(bba); - } else if (bba.getAttributeType().getTypeName().startsWith("TSK_REFERRER")) { - referrerUrlList.add(bba); - } else if (bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME_ACCESSED")) { - dateAccessedList.add(bba); - } else if (bba.getAttributeType().getTypeName().startsWith("TSK_TITLE")) { - titleList.add(bba); - } else { - otherList.add(bba); - } - - } - - dataSourceName = webHistoryArtifact.getDataSource().getName(); - sourceFileName = webHistoryArtifact.getParent().getName(); - } - - /** - * Reset the panel so that it is empty. - */ - @ThreadConfined(type = ThreadConfined.ThreadType.AWT) - private void resetComponent() { - // clear the panel - this.removeAll(); - gridBagConstraints.anchor = GridBagConstraints.FIRST_LINE_START; - gridBagConstraints.gridy = 0; - gridBagConstraints.gridx = 0; - gridBagConstraints.weighty = 0.0; - gridBagConstraints.weightx = 0.0; // keep components fixed horizontally. - gridBagConstraints.insets = new java.awt.Insets(0, 12, 0, 0); - gridBagConstraints.fill = GridBagConstraints.NONE; - webHistoryArtifact = null; - dataSourceName = null; - sourceFileName = null; - urlList.clear(); - dateAccessedList.clear(); - referrerUrlList.clear(); - titleList.clear(); - programNameList.clear(); - domainList.clear(); - otherList.clear(); - } - - @ThreadConfined(type = ThreadConfined.ThreadType.AWT) - @Override - public Component getComponent() { - // Slap a vertical scrollbar on the panel. - return new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - } - - @ThreadConfined(type = ThreadConfined.ThreadType.AWT) - @Override - public boolean isSupported(BlackboardArtifact artifact) { - return (artifact != null) - && (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID()); - } - - @NbBundle.Messages({"WebHistoryDetailsPanel.details.attrHeader=Attributes", - "WebHistoryDetailsPanel.details.sourceHeader=Source", - "WebHistoryDetailsPanel.details.dataSource=Data Source", - "WebHistoryDetailsPanel.details.file=File"}) - /** - * 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") - // //GEN-BEGIN:initComponents - private void initComponents() { - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 400, Short.MAX_VALUE) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 300, Short.MAX_VALUE) - ); - }// //GEN-END:initComponents - - /** - * Update the view to reflect the current artifact's details. - */ - @ThreadConfined(type = ThreadConfined.ThreadType.AWT) - private void updateView() { - CommunicationArtifactViewerHelper.addHeader(this, gridBagLayout, gridBagConstraints, Bundle.WebHistoryDetailsPanel_details_attrHeader()); - - for (BlackboardAttribute bba : this.titleList) { - CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); - } - for (BlackboardAttribute bba : dateAccessedList) { - CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); - } - for (BlackboardAttribute bba : domainList) { - CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); - } - for (BlackboardAttribute bba : urlList) { - CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); - } - for (BlackboardAttribute bba : referrerUrlList) { - CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); - } - for (BlackboardAttribute bba : programNameList) { - CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); - } - for (BlackboardAttribute bba : otherList) { - CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, bba.getAttributeType().getDisplayName(), bba.getDisplayString()); - } - CommunicationArtifactViewerHelper.addHeader(this, gridBagLayout, gridBagConstraints, Bundle.WebHistoryDetailsPanel_details_sourceHeader()); - CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, Bundle.WebHistoryDetailsPanel_details_dataSource(), dataSourceName); - CommunicationArtifactViewerHelper.addNameValueRow(this, gridBagLayout, gridBagConstraints, Bundle.WebHistoryDetailsPanel_details_file(), sourceFileName); - // add veritcal glue at the end - CommunicationArtifactViewerHelper.addPageEndGlue(this, gridBagLayout, this.gridBagConstraints); - } - - - // Variables declaration - do not modify//GEN-BEGIN:variables - // End of variables declaration//GEN-END:variables -} diff --git a/Core/src/org/sleuthkit/autopsy/modules/yara/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/yara/Bundle.properties-MERGED index 8f898ba127..60811049aa 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/yara/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/yara/Bundle.properties-MERGED @@ -1,5 +1,5 @@ -Yara_Module_Description=With the YARA ingest module you use YARA rule files to search files for textual or binary patterns. -Yara_Module_Name=YARA +Yara_Module_Description=The YARA Analyzer uses YARA to search files for textual or binary patterns. +Yara_Module_Name=YARA Analyzer YaraIngestModule_no_ruleSets=Unable to run YARA ingest, list of YARA rule sets was empty. YaraIngestModule_windows_error_msg=The YARA ingest module is only available on 64bit Windows. YaraIngestModule_yarac_not_found=Unable to compile YARA rules files. Unable to find executable at. diff --git a/Core/src/org/sleuthkit/autopsy/modules/yara/YaraIngestHelper.java b/Core/src/org/sleuthkit/autopsy/modules/yara/YaraIngestHelper.java index 4b71a62351..e8f57657f9 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/yara/YaraIngestHelper.java +++ b/Core/src/org/sleuthkit/autopsy/modules/yara/YaraIngestHelper.java @@ -227,9 +227,12 @@ final class YaraIngestHelper { ProcessBuilder builder = new ProcessBuilder(commandList); try { - ExecUtil.execute(builder); + int result = ExecUtil.execute(builder); + if(result != 0) { + throw new IngestModuleException(String.format("Failed to compile Yara rules file %s. Compile error %d", file.toString(), result)); + } } catch (SecurityException | IOException ex) { - throw new IngestModuleException(String.format("Failed to compile Yara rules file", file.toString()), ex); + throw new IngestModuleException(String.format("Failed to compile Yara rules file, %s", file.toString()), ex); } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/yara/YaraIngestJobSettings.java b/Core/src/org/sleuthkit/autopsy/modules/yara/YaraIngestJobSettings.java index b115bba90f..c30f6a6a4d 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/yara/YaraIngestJobSettings.java +++ b/Core/src/org/sleuthkit/autopsy/modules/yara/YaraIngestJobSettings.java @@ -77,6 +77,15 @@ public final class YaraIngestJobSettings implements IngestModuleIngestJobSetting selectedRuleSetNames.add(set.getName()); } } + + /** + * Returns if there are selected Rule Sets. + * + * @return True if there is at least one selected rule. + */ + boolean hasSelectedRuleSets() { + return selectedRuleSetNames != null && !selectedRuleSetNames.isEmpty(); + } /** * Process only executable Files. diff --git a/Core/src/org/sleuthkit/autopsy/modules/yara/YaraIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/yara/YaraIngestModule.java index c8deff0936..40d4c4abb7 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/yara/YaraIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/yara/YaraIngestModule.java @@ -97,7 +97,11 @@ public class YaraIngestModule extends FileIngestModuleAdapter { tempRuleSetDir.toFile().mkdir(); } - YaraIngestHelper.compileRules(settings.getSelectedRuleSetNames(), tempRuleSetDir); + if(settings.hasSelectedRuleSets()) { + YaraIngestHelper.compileRules(settings.getSelectedRuleSetNames(), tempRuleSetDir); + } else { + logger.log(Level.INFO, "YARA ingest module: No rule set was selected for this ingest job."); + } } } @@ -116,6 +120,10 @@ public class YaraIngestModule extends FileIngestModuleAdapter { @Override public ProcessResult process(AbstractFile file) { + if(!settings.hasSelectedRuleSets()) { + return ProcessResult.OK; + } + if (settings.onlyExecutableFiles()) { String extension = file.getNameExtension(); if (!extension.equals("exe")) { diff --git a/Core/src/org/sleuthkit/autopsy/modules/yara/YaraIngestModuleFactory.java b/Core/src/org/sleuthkit/autopsy/modules/yara/YaraIngestModuleFactory.java index 1abf8aaa0f..2330f5f448 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/yara/YaraIngestModuleFactory.java +++ b/Core/src/org/sleuthkit/autopsy/modules/yara/YaraIngestModuleFactory.java @@ -37,8 +37,8 @@ import org.sleuthkit.autopsy.modules.yara.ui.YaraIngestSettingsPanel; public class YaraIngestModuleFactory extends IngestModuleFactoryAdapter { @Messages({ - "Yara_Module_Name=YARA", - "Yara_Module_Description=With the YARA ingest module you use YARA rule files to search files for textual or binary patterns." + "Yara_Module_Name=YARA Analyzer", + "Yara_Module_Description=The YARA Analyzer uses YARA to search files for textual or binary patterns." }) @Override diff --git a/Core/src/org/sleuthkit/autopsy/modules/yara/rules/RuleSetManager.java b/Core/src/org/sleuthkit/autopsy/modules/yara/rules/RuleSetManager.java index eab2f80819..a40d69a07b 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/yara/rules/RuleSetManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/yara/rules/RuleSetManager.java @@ -45,6 +45,10 @@ public class RuleSetManager { */ public RuleSet createRuleSet(String name) throws RuleSetException { + if(name == null || name.isEmpty()) { + throw new RuleSetException("YARA rule set name cannot be null or empty string" ); + } + if (isRuleSetExists(name)) { throw new RuleSetException(String.format("Yara rule set with name %s already exits.", name)); } diff --git a/Core/src/org/sleuthkit/autopsy/modules/yara/ui/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/yara/ui/Bundle.properties-MERGED index f152cf959b..6b8d6f9b7b 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/yara/ui/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/yara/ui/Bundle.properties-MERGED @@ -15,6 +15,7 @@ YaraIngestSettingsPanel.allFilesButton.text=All Files YaraIngestSettingsPanel.allFilesButton.toolTipText= YaraIngestSettingsPanel.executableFilesButton.text=Only Executable Files RuleSetDetailsPanel.refreshButton.text=Refresh File List +YaraRuleSetOptionPanel_badName2_msg=Rule set is invalid.\nRule set names must be non-empty string and unique. # {0} - rule set name YaraRuleSetOptionPanel_badName_msg=Rule set name {0} already exists.\nRule set names must be unique. YaraRuleSetOptionPanel_badName_title=Create Rule Set diff --git a/Core/src/org/sleuthkit/autopsy/modules/yara/ui/YaraRuleSetOptionPanel.java b/Core/src/org/sleuthkit/autopsy/modules/yara/ui/YaraRuleSetOptionPanel.java index 937dc504a3..71d4749cae 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/yara/ui/YaraRuleSetOptionPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/yara/ui/YaraRuleSetOptionPanel.java @@ -93,7 +93,8 @@ public class YaraRuleSetOptionPanel extends javax.swing.JPanel { "YaraRuleSetOptionPanel_new_rule_set_name_title=Rule Set Name", "# {0} - rule set name", "YaraRuleSetOptionPanel_badName_msg=Rule set name {0} already exists.\nRule set names must be unique.", - "YaraRuleSetOptionPanel_badName_title=Create Rule Set" + "YaraRuleSetOptionPanel_badName_title=Create Rule Set", + "YaraRuleSetOptionPanel_badName2_msg=Rule set is invalid.\nRule set names must be non-empty string and unique.", }) /** * Handle the new rule set action. Prompt the user for a rule set name, @@ -103,6 +104,15 @@ public class YaraRuleSetOptionPanel extends javax.swing.JPanel { String value = JOptionPane.showInputDialog(this, Bundle.YaraRuleSetOptionPanel_new_rule_set_name_msg(), Bundle.YaraRuleSetOptionPanel_new_rule_set_name_title()); + + if(value == null || value.isEmpty()) { + JOptionPane.showMessageDialog(this, + Bundle.YaraRuleSetOptionPanel_badName2_msg(), + Bundle.YaraRuleSetOptionPanel_badName_title(), + JOptionPane.ERROR_MESSAGE); + return; + } + try { ruleSetPanel.addRuleSet(manager.createRuleSet(value)); } catch (RuleSetException ex) { @@ -110,7 +120,7 @@ public class YaraRuleSetOptionPanel extends javax.swing.JPanel { Bundle.YaraRuleSetOptionPanel_badName_msg(value), Bundle.YaraRuleSetOptionPanel_badName_title(), JOptionPane.ERROR_MESSAGE); - logger.log(Level.WARNING, "Failed to create new rule set, user provide existing name.", ex); + logger.log(Level.WARNING, "Failed to create new rule set, user provided existing name.", ex); } } diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/PortableCaseReportModule.java b/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/PortableCaseReportModule.java index 7221ee4a55..4cdfde2f79 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/PortableCaseReportModule.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/PortableCaseReportModule.java @@ -41,6 +41,8 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -60,6 +62,7 @@ import org.sleuthkit.autopsy.coreutils.FileTypeUtils.FileTypeCategory; import org.sleuthkit.autopsy.report.ReportProgressPanel; import org.sleuthkit.caseuco.CaseUcoExporter; import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.Account; import org.sleuthkit.datamodel.Blackboard.BlackboardException; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifactTag; @@ -81,6 +84,9 @@ import org.sleuthkit.datamodel.TskDataException; import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.Volume; import org.sleuthkit.datamodel.VolumeSystem; +import org.sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper; +import org.sleuthkit.datamodel.blackboardutils.attributes.BlackboardJsonAttrUtil; +import org.sleuthkit.datamodel.blackboardutils.attributes.MessageAttachments; /** * Creates a portable case from tagged files @@ -883,6 +889,9 @@ public class PortableCaseReportModule implements ReportModule { // Copy the artifact BlackboardArtifact newArtifact = copyArtifact(newContentId, tag.getArtifact()); + + // Copy any attachments + copyAttachments(newArtifact, tag.getArtifact(), portableSkCase.getAbstractFileById(newContentId)); // Tag the artfiact if (!oldTagNameToNewTagName.containsKey(tag.getName())) { @@ -932,6 +941,11 @@ public class PortableCaseReportModule implements ReportModule { if (oldAttr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) { continue; } + + // Attachments will be handled later + if (oldAttr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ATTACHMENTS.getTypeID()) { + continue; + } BlackboardAttribute.Type newAttributeType = getNewAttributeType(oldAttr); switch (oldAttr.getValueType()) { @@ -1142,6 +1156,61 @@ public class PortableCaseReportModule implements ReportModule { newIdToContent.put(newContent.getId(), newContent); return oldIdToNewContent.get(content.getId()).getId(); } + + /** + * Copy attachments to the portable case. + * + * @param newArtifact The new artifact in the portable case. Should be complete apart from the TSK_ATTACHMENTS attribute. + * @param oldArtifact The old artifact. + * @param newFile The new file in the portable case associated with the artifact. + * + * @throws TskCoreException + */ + private void copyAttachments(BlackboardArtifact newArtifact, BlackboardArtifact oldArtifact, AbstractFile newFile) throws TskCoreException { + // Get the attachments from TSK_ATTACHMENTS attribute. + BlackboardAttribute attachmentsAttr = oldArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ATTACHMENTS)); + if (attachmentsAttr != null) { + try { + MessageAttachments msgAttachments = BlackboardJsonAttrUtil.fromAttribute(attachmentsAttr, MessageAttachments.class); + + Collection oldFileAttachments = msgAttachments.getFileAttachments(); + List newFileAttachments = new ArrayList<>(); + for (MessageAttachments.FileAttachment oldFileAttachment : oldFileAttachments) { + long attachedFileObjId = oldFileAttachment.getObjectId(); + if (attachedFileObjId >= 0) { + // Copy the attached file and save to the MessageAttachments object + AbstractFile attachedFile = currentCase.getSleuthkitCase().getAbstractFileById(attachedFileObjId); + if (attachedFile == null) { + throw new TskCoreException("Error loading file with object ID " + attachedFileObjId + " from portable case"); + } + long newFileID = copyContent(attachedFile); + newFileAttachments.add(new MessageAttachments.FileAttachment(portableSkCase.getAbstractFileById(newFileID))); + } + } + + // Get the name of the module(s) that created the attachment + String newSourceStr = ""; + List oldSources = attachmentsAttr.getSources(); + if (! oldSources.isEmpty()) { + newSourceStr = String.join(",", oldSources); + } + + // Add the attachment. The account type specified in the constructor will not be used. + CommunicationArtifactsHelper communicationArtifactsHelper = new CommunicationArtifactsHelper(currentCase.getSleuthkitCase(), + newSourceStr, newFile, Account.Type.EMAIL); + communicationArtifactsHelper.addAttachments(newArtifact, new MessageAttachments(newFileAttachments, msgAttachments.getUrlAttachments())); + } + catch (BlackboardJsonAttrUtil.InvalidJsonException ex) { + throw new TskCoreException(String.format("Unable to parse json for MessageAttachments object in artifact: %s", oldArtifact.getName()), ex); + } + } else { // backward compatibility - email message attachments are derived files, children of the message. + for (Content childContent : oldArtifact.getChildren()) { + if (childContent instanceof AbstractFile) { + copyContent(childContent); + } + } + } + } /** * Return the subfolder name for this file based on MIME type diff --git a/Experimental/ivy.xml b/Experimental/ivy.xml index c1e0e8c1d6..64f4b305bf 100644 --- a/Experimental/ivy.xml +++ b/Experimental/ivy.xml @@ -6,7 +6,7 @@ - + diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties index becf3c5a2b..4e5ec81f78 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties @@ -39,7 +39,6 @@ AutoIngestSettingsPanel.MustRestart=Autopsy must be restarted for new configurat AutoIngestSettingsPanel.nodePanel.TabConstraints.tabTitle=Node Configuration AutoIngestSettingsPanel.NodeStatusLogging.text=Node Status Logging Settings AutoIngestSettingsPanel.restartRequiredLabel.text=Application restart required to take effect. -AutoIngestSettingsPanel.restartRequiredLabel.text=Application restart required AutoIngestSettingsPanel.ResultsDirectoryUnspecified=Shared cases folder must be set AutoIngestSettingsPanel.tbOops.text= AutoIngestSettingsPanel.validationErrMsg.incomplete=Fill in all values diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties-MERGED b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties-MERGED index 337e80b346..08f4718734 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties-MERGED +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties-MERGED @@ -39,7 +39,6 @@ AutoIngestSettingsPanel.MustRestart=Autopsy must be restarted for new configurat AutoIngestSettingsPanel.nodePanel.TabConstraints.tabTitle=Node Configuration AutoIngestSettingsPanel.NodeStatusLogging.text=Node Status Logging Settings AutoIngestSettingsPanel.restartRequiredLabel.text=Application restart required to take effect. -AutoIngestSettingsPanel.restartRequiredLabel.text=Application restart required AutoIngestSettingsPanel.ResultsDirectoryUnspecified=Shared cases folder must be set AutoIngestSettingsPanel.tbOops.text= AutoIngestSettingsPanel.validationErrMsg.incomplete=Fill in all values diff --git a/KeywordSearch/build.xml b/KeywordSearch/build.xml index 1a43a00cf8..00aae9272b 100644 --- a/KeywordSearch/build.xml +++ b/KeywordSearch/build.xml @@ -26,13 +26,21 @@ + + + + + - + - - + + + + + diff --git a/KeywordSearch/ivy.xml b/KeywordSearch/ivy.xml index ee86821bd8..2bc97f2078 100644 --- a/KeywordSearch/ivy.xml +++ b/KeywordSearch/ivy.xml @@ -7,28 +7,37 @@ - - + + - + + - - - - + + + + + + + + + + + + - + diff --git a/KeywordSearch/nbproject/project.properties b/KeywordSearch/nbproject/project.properties index cb9aad54ab..3253bc2010 100644 --- a/KeywordSearch/nbproject/project.properties +++ b/KeywordSearch/nbproject/project.properties @@ -1,27 +1,70 @@ -file.reference.annotations-12.0.jar=release\\modules\\ext\\annotations-12.0.jar -file.reference.commons-beanutils-1.9.2.jar=release\\modules\\ext\\commons-beanutils-1.9.2.jar -file.reference.commons-collections-3.2.2.jar=release\\modules\\ext\\commons-collections-3.2.2.jar +file.reference.boilerpipe-1.1.0.jar=release/modules/ext/boilerpipe-1.1.0.jar +file.reference.bzip2-0.9.1.jar=release/modules/ext/bzip2-0.9.1.jar +file.reference.c3p0-0.9.1.1.jar=release/modules/ext/c3p0-0.9.1.1.jar +file.reference.cdm-4.5.5.jar=release/modules/ext/cdm-4.5.5.jar +file.reference.cleartk-util-2.0.0.jar=release/modules/ext/cleartk-util-2.0.0.jar +file.reference.commons-beanutils-1.9.2.jar=release/modules/ext/commons-beanutils-1.9.2.jar +file.reference.commons-collections-3.2.2.jar=release/modules/ext/commons-collections-3.2.2.jar file.reference.commons-digester-1.8.1.jar=release\\modules\\ext\\commons-digester-1.8.1.jar -file.reference.commons-io-2.3.jar=release\\modules\\ext\\commons-io-2.3.jar -file.reference.commons-lang-2.4.jar=release\\modules\\ext\\commons-lang-2.4.jar -file.reference.commons-logging-1.2.jar=release\\modules\\ext\\commons-logging-1.2.jar -file.reference.commons-validator-1.5.1.jar=release\\modules\\ext\\commons-validator-1.5.1.jar -file.reference.guava-18.0.jar=release\\modules\\ext\\guava-18.0.jar -file.reference.httpclient-4.5.6.jar=release\\modules\\ext\\httpclient-4.5.6.jar -file.reference.httpcore-4.4.10.jar=release\\modules\\ext\\httpcore-4.4.10.jar -file.reference.httpmime-4.5.6.jar=release\\modules\\ext\\httpmime-4.5.6.jar -file.reference.icu4j-3.8.jar=release\\modules\\ext\\icu4j-3.8.jar +file.reference.commons-exec-1.3.jar=release/modules/ext/commons-exec-1.3.jar +file.reference.commons-io-2.6.jar=release/modules/ext/commons-io-2.6.jar +file.reference.commons-lang-2.6.jar=release/modules/ext/commons-lang-2.6.jar +file.reference.commons-logging-1.2.jar=release/modules/ext/commons-logging-1.2.jar +file.reference.commons-validator-1.5.1.jar=release/modules/ext/commons-validator-1.5.1.jar +file.reference.ehcache-core-2.6.2.jar=release/modules/ext/ehcache-core-2.6.2.jar +file.reference.findstructapi-0.0.1.jar=release/modules/ext/findstructapi-0.0.1.jar +file.reference.grib-4.5.5.jar=release/modules/ext/grib-4.5.5.jar +file.reference.guava-18.0.jar=release/modules/ext/guava-18.0.jar +file.reference.httpclient-4.5.10.jar=release/modules/ext/httpclient-4.5.10.jar +file.reference.httpcore-4.4.12.jar=release/modules/ext/httpcore-4.4.12.jar +file.reference.httpmime-4.5.10.jar=release/modules/ext/httpmime-4.5.10.jar +file.reference.httpservices-4.5.5.jar=release/modules/ext/httpservices-4.5.5.jar +file.reference.icu4j-3.8.jar=release/modules/ext/icu4j-3.8.jar +file.reference.java-libpst-0.8.1.jar=release/modules/ext/java-libpst-0.8.1.jar +file.reference.jcip-annotations-1.0.jar=release/modules/ext/jcip-annotations-1.0.jar +file.reference.jcommander-1.35.jar=release/modules/ext/jcommander-1.35.jar +file.reference.jdom-1.0.jar=release/modules/ext/jdom-1.0.jar file.reference.jericho-html-3.3.jar=release\\modules\\ext\\jericho-html-3.3.jar -file.reference.jsonic-1.2.11.jar=release\\modules\\ext\\jsonic-1.2.11.jar +file.reference.joda-time-2.2.jar=release/modules/ext/joda-time-2.2.jar +file.reference.json-simple-1.1.1.jar=release/modules/ext/json-simple-1.1.1.jar +file.reference.juniversalchardet-1.0.3.jar=release/modules/ext/juniversalchardet-1.0.3.jar file.reference.language-detector-0.6.jar=release\\modules\\ext\\language-detector-0.6.jar -file.reference.noggit-0.5.jar=release\\modules\\ext\\noggit-0.5.jar -file.reference.slf4j-api-1.7.6.jar=release\\modules\\ext\\slf4j-api-1.7.6.jar -file.reference.solr-solrj-4.9.1.jar=release\\modules\\ext\\solr-solrj-4.9.1.jar -file.reference.wstx-asl-3.2.7.jar=release\\modules\\ext\\wstx-asl-3.2.7.jar -file.reference.zookeeper-3.4.6.jar=release\\modules\\ext\\zookeeper-3.4.6.jar +file.reference.libsvm-3.1.jar=release/modules/ext/libsvm-3.1.jar +file.reference.log4j-1.2.17.jar=release/modules/ext/log4j-1.2.17.jar +file.reference.lucene-core-4.0.0.jar=release/modules/ext/lucene-core-4.0.0.jar +file.reference.lucene-queries-4.0.0.jar=release/modules/ext/lucene-queries-4.0.0.jar +file.reference.lucene-sandbox-4.0.0.jar=release/modules/ext/lucene-sandbox-4.0.0.jar +file.reference.netcdf4-4.5.5.jar=release/modules/ext/netcdf4-4.5.5.jar +file.reference.openaifsm-0.0.1.jar=release/modules/ext/openaifsm-0.0.1.jar +file.reference.opennlp-maxent-3.0.3.jar=release/modules/ext/opennlp-maxent-3.0.3.jar +file.reference.poi-4.0.1.jar=release/modules/ext/poi-4.0.1.jar +file.reference.poi-ooxml-4.0.1.jar=release/modules/ext/poi-ooxml-4.0.1.jar +file.reference.poi-ooxml-schemas-4.0.1.jar=release/modules/ext/poi-ooxml-schemas-4.0.1.jar +file.reference.poi-scratchpad-4.0.1.jar=release/modules/ext/poi-scratchpad-4.0.1.jar +file.reference.protobuf-java-2.5.0.jar=release/modules/ext/protobuf-java-2.5.0.jar +file.reference.quartz-2.2.0.jar=release/modules/ext/quartz-2.2.0.jar +file.reference.slf4j-api-1.7.25.jar=release/modules/ext/slf4j-api-1.7.25.jar +file.reference.solr-solrj-8.6.2.jar=release/modules/ext/solr-solrj-8.6.2.jar +file.reference.solr-solrj-8.6.3.jar=release/modules/ext/solr-solrj-8.6.3.jar +file.reference.sqlwrapper-0.0.1.jar=release/modules/ext/sqlwrapper-0.0.1.jar +file.reference.stax2-api-3.1.4.jar=release/modules/ext/stax2-api-3.1.4.jar +file.reference.tagsoup-1.2.1.jar=release/modules/ext/tagsoup-1.2.1.jar +file.reference.tika-core-1.20.jar=release/modules/ext/tika-core-1.20.jar +file.reference.tika-parsers-1.20.jar=release/modules/ext/tika-parsers-1.20.jar +file.reference.udunits-4.5.5.jar=release/modules/ext/udunits-4.5.5.jar +file.reference.vorbis-java-core-0.8.jar=release/modules/ext/vorbis-java-core-0.8.jar +file.reference.vorbis-java-tika-0.8.jar=release/modules/ext/vorbis-java-tika-0.8.jar +file.reference.woodstox-core-asl-4.4.1.jar=release/modules/ext/woodstox-core-asl-4.4.1.jar +file.reference.xmlbeans-2.6.0.jar=release/modules/ext/xmlbeans-2.6.0.jar +file.reference.xmpcore-5.1.3.jar=release/modules/ext/xmpcore-5.1.3.jar +file.reference.zookeeper-3.5.7.jar=release/modules/ext/zookeeper-3.5.7.jar +file.reference.annotations-12.0.jar=release\\modules\\ext\\annotations-12.0.jar +file.reference.jsonic-1.2.11.jar=release\\modules\\ext\\jsonic-1.2.11.jar javac.source=11 javac.compilerargs=-Xlint -Xlint:-serial license.file=../LICENSE-2.0.txt nbm.homepage=http://www.sleuthkit.org/autopsy/ nbm.needs.restart=true +source.reference.commons-validator-1.5.1.jar=release/modules/ext/commons-validator-1.5.1-sources.jar +source.reference.solr-solrj-8.6.2.jar=release/modules/ext/solr-solrj-8.6.2-sources.jar spec.version.base=6.6 diff --git a/KeywordSearch/nbproject/project.xml b/KeywordSearch/nbproject/project.xml index c6f056f5a4..618855997e 100644 --- a/KeywordSearch/nbproject/project.xml +++ b/KeywordSearch/nbproject/project.xml @@ -142,21 +142,6 @@ - com.ctc.wstx.api - com.ctc.wstx.cfg - com.ctc.wstx.compat - com.ctc.wstx.dom - com.ctc.wstx.dtd - com.ctc.wstx.ent - com.ctc.wstx.evt - com.ctc.wstx.exc - com.ctc.wstx.io - com.ctc.wstx.msv - com.ctc.wstx.sax - com.ctc.wstx.sr - com.ctc.wstx.stax - com.ctc.wstx.sw - com.ctc.wstx.util org.apache.commons.logging.impl org.apache.http org.apache.http.annotation @@ -201,9 +186,6 @@ org.apache.http.protocol org.apache.http.ssl org.apache.http.util - org.apache.jute - org.apache.jute.compiler - org.apache.jute.compiler.generated org.apache.solr.client.solrj org.apache.solr.client.solrj.beans org.apache.solr.client.solrj.impl @@ -218,17 +200,13 @@ org.apache.zookeeper org.apache.zookeeper.client org.apache.zookeeper.common - org.apache.zookeeper.data org.apache.zookeeper.jmx - org.apache.zookeeper.proto org.apache.zookeeper.server org.apache.zookeeper.server.auth org.apache.zookeeper.server.persistence org.apache.zookeeper.server.quorum org.apache.zookeeper.server.quorum.flexible - org.apache.zookeeper.server.upgrade org.apache.zookeeper.server.util - org.apache.zookeeper.txn org.apache.zookeeper.version org.apache.zookeeper.version.util org.codehaus.stax2 @@ -236,92 +214,187 @@ org.codehaus.stax2.io org.codehaus.stax2.ri org.codehaus.stax2.validation - org.noggit org.sleuthkit.autopsy.keywordsearch - ext/guava-18.0.jar - release\modules\ext\guava-18.0.jar - - - ext/zookeeper-3.4.6.jar - release\modules\ext\zookeeper-3.4.6.jar + ext/findstructapi-0.0.1.jar + release/modules/ext/findstructapi-0.0.1.jar ext/commons-digester-1.8.1.jar release\modules\ext\commons-digester-1.8.1.jar - ext/httpmime-4.5.6.jar - release\modules\ext\httpmime-4.5.6.jar + ext/jcommander-1.35.jar + release/modules/ext/jcommander-1.35.jar - ext/httpclient-4.5.6.jar - release\modules\ext\httpclient-4.5.6.jar + ext/vorbis-java-core-0.8.jar + release/modules/ext/vorbis-java-core-0.8.jar - ext/commons-validator-1.5.1.jar - release\modules\ext\commons-validator-1.5.1.jar + ext/lucene-sandbox-4.0.0.jar + release/modules/ext/lucene-sandbox-4.0.0.jar - ext/commons-lang-2.4.jar - release\modules\ext\commons-lang-2.4.jar - - - ext/commons-logging-1.2.jar - release\modules\ext\commons-logging-1.2.jar + ext/httpmime-4.5.10.jar + release/modules/ext/httpmime-4.5.10.jar ext/jericho-html-3.3.jar release\modules\ext\jericho-html-3.3.jar - ext/httpcore-4.4.10.jar - release\modules\ext\httpcore-4.4.10.jar + ext/netcdf4-4.5.5.jar + release/modules/ext/netcdf4-4.5.5.jar - ext/slf4j-api-1.7.6.jar - release\modules\ext\slf4j-api-1.7.6.jar + ext/cdm-4.5.5.jar + release/modules/ext/cdm-4.5.5.jar - ext/commons-beanutils-1.9.2.jar - release\modules\ext\commons-beanutils-1.9.2.jar + ext/httpservices-4.5.5.jar + release/modules/ext/httpservices-4.5.5.jar - ext/commons-io-2.3.jar - release\modules\ext\commons-io-2.3.jar + ext/java-libpst-0.8.1.jar + release/modules/ext/java-libpst-0.8.1.jar - ext/wstx-asl-3.2.7.jar - release\modules\ext\wstx-asl-3.2.7.jar + ext/protobuf-java-2.5.0.jar + release/modules/ext/protobuf-java-2.5.0.jar - ext/annotations-12.0.jar - release\modules\ext\annotations-12.0.jar + ext/lucene-queries-4.0.0.jar + release/modules/ext/lucene-queries-4.0.0.jar - ext/commons-collections-3.2.2.jar - release\modules\ext\commons-collections-3.2.2.jar + ext/boilerpipe-1.1.0.jar + release/modules/ext/boilerpipe-1.1.0.jar - ext/noggit-0.5.jar - release\modules\ext\noggit-0.5.jar + ext/juniversalchardet-1.0.3.jar + release/modules/ext/juniversalchardet-1.0.3.jar + + + ext/commons-lang-2.6.jar + release/modules/ext/commons-lang-2.6.jar + + + ext/quartz-2.2.0.jar + release/modules/ext/quartz-2.2.0.jar + + + ext/libsvm-3.1.jar + release/modules/ext/libsvm-3.1.jar + + + ext/slf4j-api-1.7.25.jar + release/modules/ext/slf4j-api-1.7.25.jar ext/icu4j-3.8.jar - release\modules\ext\icu4j-3.8.jar + release/modules/ext/icu4j-3.8.jar - ext/jsonic-1.2.11.jar - release\modules\ext\jsonic-1.2.11.jar + ext/poi-4.0.1.jar + release/modules/ext/poi-4.0.1.jar ext/language-detector-0.6.jar release\modules\ext\language-detector-0.6.jar - ext/solr-solrj-4.9.1.jar - release\modules\ext\solr-solrj-4.9.1.jar + ext/guava-18.0.jar + release/modules/ext/guava-18.0.jar + + + ext/joda-time-2.2.jar + release/modules/ext/joda-time-2.2.jar + + + ext/jcip-annotations-1.0.jar + release/modules/ext/jcip-annotations-1.0.jar + + + ext/commons-validator-1.5.1.jar + release/modules/ext/commons-validator-1.5.1.jar + + + ext/commons-logging-1.2.jar + release\modules\ext\commons-logging-1.2.jar + + + ext/bzip2-0.9.1.jar + release/modules/ext/bzip2-0.9.1.jar + + + ext/cleartk-util-2.0.0.jar + release/modules/ext/cleartk-util-2.0.0.jar + + + ext/grib-4.5.5.jar + release/modules/ext/grib-4.5.5.jar + + + ext/httpcore-4.4.12.jar + release/modules/ext/httpcore-4.4.12.jar + + + ext/jdom-1.0.jar + release/modules/ext/jdom-1.0.jar + + + ext/commons-beanutils-1.9.2.jar + release/modules/ext/commons-beanutils-1.9.2.jar + + + ext/ehcache-core-2.6.2.jar + release/modules/ext/ehcache-core-2.6.2.jar + + + ext/poi-ooxml-schemas-4.0.1.jar + release/modules/ext/poi-ooxml-schemas-4.0.1.jar + + + ext/zookeeper-3.5.7.jar + release/modules/ext/zookeeper-3.5.7.jar + + + ext/commons-collections-3.2.2.jar + release/modules/ext/commons-collections-3.2.2.jar + + + ext/commons-io-2.6.jar + release/modules/ext/commons-io-2.6.jar + + + ext/annotations-12.0.jar + release\modules\ext\annotations-12.0.jar + + + ext/openaifsm-0.0.1.jar + release/modules/ext/openaifsm-0.0.1.jar + + + ext/stax2-api-3.1.4.jar + release/modules/ext/stax2-api-3.1.4.jar + + + ext/httpclient-4.5.10.jar + release/modules/ext/httpclient-4.5.10.jar + + + ext/solr-solrj-8.6.3.jar + release/modules/ext/solr-solrj-8.6.3.jar + + + ext/vorbis-java-tika-0.8.jar + release/modules/ext/vorbis-java-tika-0.8.jar + + + ext/xmpcore-5.1.3.jar + release/modules/ext/xmpcore-5.1.3.jar diff --git a/KeywordSearch/solr/bin/autopsy-solr.cmd b/KeywordSearch/solr/bin/autopsy-solr.cmd new file mode 100755 index 0000000000..018a626694 --- /dev/null +++ b/KeywordSearch/solr/bin/autopsy-solr.cmd @@ -0,0 +1,2032 @@ +@REM set JAVA_HOME=C:\Program Files\ojdkbuild\java-1.8.0-openjdk-1.8.0.222-1 +@REM set SOLR_SERVER_DIR=C:\Bitnami\solr-8.2.0-2/apache-solr/server +set SOLR_PORT=8983 +set STOP_PORT=8079 + +@REM +@REM Licensed to the Apache Software Foundation (ASF) under one or more +@REM contributor license agreements. See the NOTICE file distributed with +@REM this work for additional information regarding copyright ownership. +@REM The ASF licenses this file to You under the Apache License, Version 2.0 +@REM (the "License"); you may not use this file except in compliance with +@REM the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, software +@REM distributed under the License is distributed on an "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@REM See the License for the specific language governing permissions and +@REM limitations under the License. + + +IF "%OS%"=="Windows_NT" setlocal enabledelayedexpansion enableextensions + +set "PASS_TO_RUN_EXAMPLE=" + +REM Determine top-level Solr directory +set SDIR=%~dp0 +IF "%SDIR:~-1%"=="\" set SDIR=%SDIR:~0,-1% +set SOLR_TIP=%SDIR%\.. +pushd %SOLR_TIP% +set SOLR_TIP=%CD% +popd + +REM Used to report errors before exiting the script +set SCRIPT_ERROR= +set NO_USER_PROMPT=0 + +REM Allow user to import vars from an include file +REM vars set in the include file can be overridden with +REM command line args +IF "%SOLR_INCLUDE%"=="" set "SOLR_INCLUDE=%SOLR_TIP%\bin\autopsy-solr.in.cmd" +IF EXIST "%SOLR_INCLUDE%" CALL "%SOLR_INCLUDE%" + +set "DEFAULT_SERVER_DIR=%SOLR_TIP%\server" + +REM Select HTTP OR HTTPS related configurations +set SOLR_URL_SCHEME=http +set "SOLR_JETTY_CONFIG=--module=http" +set "SOLR_SSL_OPTS= " + +IF DEFINED SOLR_HADOOP_CREDENTIAL_PROVIDER_PATH ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dhadoop.security.credential.provider.path=%SOLR_HADOOP_CREDENTIAL_PROVIDER_PATH%" +) + +IF NOT DEFINED SOLR_SSL_ENABLED ( + IF DEFINED SOLR_SSL_KEY_STORE ( + set "SOLR_SSL_ENABLED=true" + ) ELSE ( + set "SOLR_SSL_ENABLED=false" + ) +) + +IF "%SOLR_SSL_ENABLED%"=="true" ( + set "SOLR_JETTY_CONFIG=--lib="%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*"" + if !JAVA_MAJOR_VERSION! GEQ 9 ( + set "SOLR_JETTY_CONFIG=!SOLR_JETTY_CONFIG! --module=https" + ) else ( + set "SOLR_JETTY_CONFIG=!SOLR_JETTY_CONFIG! --module=https8" + ) + set SOLR_URL_SCHEME=https + IF DEFINED SOLR_SSL_KEY_STORE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dsolr.jetty.keystore=%SOLR_SSL_KEY_STORE%" + ) + + IF DEFINED SOLR_SSL_KEY_STORE_TYPE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dsolr.jetty.keystore.type=%SOLR_SSL_KEY_STORE_TYPE%" + ) + + IF DEFINED SOLR_SSL_TRUST_STORE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dsolr.jetty.truststore=%SOLR_SSL_TRUST_STORE%" + ) + IF DEFINED SOLR_SSL_TRUST_STORE_TYPE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dsolr.jetty.truststore.type=%SOLR_SSL_TRUST_STORE_TYPE%" + ) + + IF DEFINED SOLR_SSL_NEED_CLIENT_AUTH ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dsolr.jetty.ssl.needClientAuth=%SOLR_SSL_NEED_CLIENT_AUTH%" + ) + IF DEFINED SOLR_SSL_WANT_CLIENT_AUTH ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dsolr.jetty.ssl.wantClientAuth=%SOLR_SSL_WANT_CLIENT_AUTH%" + ) + + IF DEFINED SOLR_SSL_CLIENT_KEY_STORE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.keyStore=%SOLR_SSL_CLIENT_KEY_STORE%" + + IF DEFINED SOLR_SSL_CLIENT_KEY_STORE_TYPE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.keyStoreType=%SOLR_SSL_CLIENT_KEY_STORE_TYPE%" + ) + ) ELSE ( + IF DEFINED SOLR_SSL_KEY_STORE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.keyStore=%SOLR_SSL_KEY_STORE%" + ) + IF DEFINED SOLR_SSL_KEY_STORE_TYPE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.keyStoreType=%SOLR_SSL_KEY_STORE_TYPE%" + ) + ) + + IF DEFINED SOLR_SSL_CLIENT_TRUST_STORE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.trustStore=%SOLR_SSL_CLIENT_TRUST_STORE%" + + IF DEFINED SOLR_SSL_CLIENT_TRUST_STORE_TYPE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.trustStoreType=%SOLR_SSL_CLIENT_TRUST_STORE_TYPE%" + ) + ) ELSE ( + IF DEFINED SOLR_SSL_TRUST_STORE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.trustStore=%SOLR_SSL_TRUST_STORE%" + ) + IF DEFINED SOLR_SSL_TRUST_STORE_TYPE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.trustStoreType=%SOLR_SSL_TRUST_STORE_TYPE%" + ) + ) + IF DEFINED SOLR_SSL_CHECK_PEER_NAME ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dsolr.ssl.checkPeerName=%SOLR_SSL_CHECK_PEER_NAME%" + ) +) ELSE ( + set SOLR_SSL_OPTS= +) + +REM Authentication options + +IF NOT DEFINED SOLR_AUTH_TYPE ( + IF DEFINED SOLR_AUTHENTICATION_OPTS ( + echo WARNING: SOLR_AUTHENTICATION_OPTS variable configured without associated SOLR_AUTH_TYPE variable + echo Please configure SOLR_AUTH_TYPE variable with the authentication type to be used. + echo Currently supported authentication types are [kerberos, basic] + ) +) + +IF DEFINED SOLR_AUTH_TYPE ( + IF DEFINED SOLR_AUTHENTICATION_CLIENT_BUILDER ( + echo WARNING: SOLR_AUTHENTICATION_CLIENT_BUILDER and SOLR_AUTH_TYPE variables are configured together + echo Use SOLR_AUTH_TYPE variable to configure authentication type to be used + echo Currently supported authentication types are [kerberos, basic] + echo The value of SOLR_AUTHENTICATION_CLIENT_BUILDER configuration variable will be ignored + ) +) + +IF DEFINED SOLR_AUTH_TYPE ( + IF /I "%SOLR_AUTH_TYPE%" == "basic" ( + set SOLR_AUTHENTICATION_CLIENT_BUILDER="org.apache.solr.client.solrj.impl.PreemptiveBasicAuthClientBuilderFactory" + ) ELSE ( + IF /I "%SOLR_AUTH_TYPE%" == "kerberos" ( + set SOLR_AUTHENTICATION_CLIENT_BUILDER="org.apache.solr.client.solrj.impl.PreemptiveBasicAuthClientBuilderFactory" + ) ELSE ( + echo ERROR: Value specified for SOLR_AUTH_TYPE configuration variable is invalid. + goto err + ) + ) +) + +IF DEFINED SOLR_AUTHENTICATION_CLIENT_CONFIGURER ( + echo WARNING: Found unsupported configuration variable SOLR_AUTHENTICATION_CLIENT_CONFIGURER + echo Please start using SOLR_AUTH_TYPE instead +) +IF DEFINED SOLR_AUTHENTICATION_CLIENT_BUILDER ( + set AUTHC_CLIENT_BUILDER_ARG="-Dsolr.httpclient.builder.factory=%SOLR_AUTHENTICATION_CLIENT_BUILDER%" +) +set "AUTHC_OPTS=%AUTHC_CLIENT_BUILDER_ARG% %SOLR_AUTHENTICATION_OPTS%" + +REM Set the SOLR_TOOL_HOST variable for use when connecting to a running Solr instance +IF NOT "%SOLR_HOST%"=="" ( + set "SOLR_TOOL_HOST=%SOLR_HOST%" +) ELSE ( + set "SOLR_TOOL_HOST=localhost" +) +IF "%SOLR_JETTY_HOST%"=="" ( + set SOLR_JETTY_HOST=0.0.0.0 +) + +REM Verify Java is available +IF DEFINED SOLR_JAVA_HOME set "JAVA_HOME=%SOLR_JAVA_HOME%" +REM Try to detect JAVA_HOME from the registry +IF NOT DEFINED JAVA_HOME ( + FOR /F "skip=2 tokens=2*" %%A IN ('REG QUERY "HKLM\Software\JavaSoft\Java Runtime Environment" /v CurrentVersion') DO set CurVer=%%B + FOR /F "skip=2 tokens=2*" %%A IN ('REG QUERY "HKLM\Software\JavaSoft\Java Runtime Environment\!CurVer!" /v JavaHome') DO ( + set "JAVA_HOME=%%B" + ) +) +IF NOT DEFINED JAVA_HOME goto need_java_home +set JAVA_HOME=%JAVA_HOME:"=% +IF %JAVA_HOME:~-1%==\ SET JAVA_HOME=%JAVA_HOME:~0,-1% +IF NOT EXIST "%JAVA_HOME%\bin\java.exe" ( + set "SCRIPT_ERROR=java.exe not found in %JAVA_HOME%\bin. Please set JAVA_HOME to a valid JRE / JDK directory." + goto err +) +set "JAVA=%JAVA_HOME%\bin\java" +CALL :resolve_java_info +IF !JAVA_MAJOR_VERSION! LSS 8 ( + set "SCRIPT_ERROR=Java 1.8 or later is required to run Solr. Current Java version is: !JAVA_VERSION_INFO! (detected major: !JAVA_MAJOR_VERSION!)" + goto err +) + +set FIRST_ARG=%1 + +IF [%1]==[] goto usage + +IF "%1"=="-help" goto usage +IF "%1"=="-usage" goto usage +IF "%1"=="-h" goto usage +IF "%1"=="--help" goto usage +IF "%1"=="/?" goto usage +IF "%1"=="-i" goto get_info +IF "%1"=="-info" goto get_info +IF "%1"=="status" goto get_info +IF "%1"=="version" goto get_version +IF "%1"=="-v" goto get_version +IF "%1"=="-version" goto get_version +IF "%1"=="assert" goto run_assert +IF "%1"=="autoscaling" goto run_autoscaling + +REM Only allow the command to be the first argument, assume start if not supplied +IF "%1"=="start" goto set_script_cmd +IF "%1"=="stop" goto set_script_cmd +IF "%1"=="restart" goto set_script_cmd +IF "%1"=="healthcheck" ( + REM healthcheck uses different arg parsing strategy + set SCRIPT_CMD=healthcheck + SHIFT + goto parse_healthcheck_args +) +IF "%1"=="create" ( + set SCRIPT_CMD=create + SHIFT + goto parse_create_args +) +IF "%1"=="create_core" ( + set SCRIPT_CMD=create_core + SHIFT + goto parse_create_args +) +IF "%1"=="create_collection" ( + set SCRIPT_CMD=create_collection + SHIFT + goto parse_create_args +) +IF "%1"=="delete" ( + set SCRIPT_CMD=delete + SHIFT + goto parse_delete_args +) +IF "%1"=="zk" ( + set SCRIPT_CMD=zk + SHIFT + set ZK_RECURSE=false + goto parse_zk_args +) +IF "%1"=="auth" ( + set SCRIPT_CMD=auth + SHIFT + goto run_auth +) +IF "%1"=="config" ( + REM config uses different arg parsing strategy + set SCRIPT_CMD=config + SHIFT + set CONFIG_ARGS= + goto parse_config_args +) + +goto parse_args + +:usage +IF NOT "%SCRIPT_ERROR%"=="" ECHO %SCRIPT_ERROR% +IF [%FIRST_ARG%]==[] goto script_usage +IF "%FIRST_ARG%"=="-help" goto script_usage +IF "%FIRST_ARG%"=="-usage" goto script_usage +IF "%FIRST_ARG%"=="-h" goto script_usage +IF "%FIRST_ARG%"=="--help" goto script_usage +IF "%FIRST_ARG%"=="/?" goto script_usage +IF "%SCRIPT_CMD%"=="start" goto start_usage +IF "%SCRIPT_CMD%"=="restart" goto start_usage +IF "%SCRIPT_CMD%"=="stop" goto stop_usage +IF "%SCRIPT_CMD%"=="healthcheck" goto healthcheck_usage +IF "%SCRIPT_CMD%"=="create" goto create_usage +IF "%SCRIPT_CMD%"=="create_core" goto create_core_usage +IF "%SCRIPT_CMD%"=="create_collection" goto create_collection_usage +IF "%SCRIPT_CMD%"=="delete" goto delete_usage +IF "%SCRIPT_CMD%"=="zk" goto zk_usage +IF "%SCRIPT_CMD%"=="auth" goto auth_usage +IF "%SCRIPT_CMD%"=="status" goto status_usage +goto done + +:script_usage +@echo. +@echo Usage: solr COMMAND OPTIONS +@echo where COMMAND is one of: start, stop, restart, healthcheck, create, create_core, create_collection, delete, version, zk, auth, assert, config, autoscaling +@echo. +@echo Standalone server example (start Solr running in the background on port 8984): +@echo. +@echo solr start -p 8984 +@echo. +@echo SolrCloud example (start Solr running in SolrCloud mode using localhost:2181 to connect to Zookeeper, with 1g max heap size and remote Java debug options enabled): +@echo. +@echo solr start -c -m 1g -z localhost:2181 -a "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=1044" +@echo. +@echo Omit '-z localhost:2181' from the above command if you have defined ZK_HOST in solr.in.cmd. +@echo. +@echo Pass -help after any COMMAND to see command-specific usage information, +@echo such as: solr start -help or solr stop -help +@echo. +goto done + +:start_usage +@echo. +@echo Usage: solr %SCRIPT_CMD% [-f] [-c] [-h hostname] [-p port] [-d directory] [-z zkHost] [-m memory] [-e example] [-s solr.solr.home] [-t solr.data.home] [-a "additional-options"] [-V] +@echo. +@echo -f Start Solr in foreground; default starts Solr in the background +@echo and sends stdout / stderr to solr-PORT-console.log +@echo. +@echo -c or -cloud Start Solr in SolrCloud mode; if -z not supplied and ZK_HOST not defined in +@echo solr.in.cmd, an embedded ZooKeeper instance is started on Solr port+1000, +@echo such as 9983 if Solr is bound to 8983 +@echo. +@echo -h host Specify the hostname for this Solr instance +@echo. +@echo -p port Specify the port to start the Solr HTTP listener on; default is 8983 +@echo " The specified port (SOLR_PORT) will also be used to determine the stop port" +@echo " STOP_PORT=(\$SOLR_PORT-1000) and JMX RMI listen port RMI_PORT=(\$SOLR_PORT+10000). " +@echo " For instance, if you set -p 8985, then the STOP_PORT=7985 and RMI_PORT=18985" +@echo. +@echo -d dir Specify the Solr server directory; defaults to server +@echo. +@echo -z zkHost Zookeeper connection string; only used when running in SolrCloud mode using -c +@echo If neither ZK_HOST is defined in solr.in.cmd nor the -z parameter is specified, +@echo an embedded ZooKeeper instance will be launched. +@echo. +@echo -m memory Sets the min (-Xms) and max (-Xmx) heap size for the JVM, such as: -m 4g +@echo results in: -Xms4g -Xmx4g; by default, this script sets the heap size to 512m +@echo. +@echo -s dir Sets the solr.solr.home system property; Solr will create core directories under +@echo this directory. This allows you to run multiple Solr instances on the same host +@echo while reusing the same server directory set using the -d parameter. If set, the +@echo specified directory should contain a solr.xml file, unless solr.xml exists in Zookeeper. +@echo This parameter is ignored when running examples (-e), as the solr.solr.home depends +@echo on which example is run. The default value is server/solr. If passed a relative dir +@echo validation with the current dir will be done before trying the default server/^ +@echo. +@echo -t dir Sets the solr.data.home system property, where Solr will store index data in ^/data subdirectories. +@echo If not set, Solr uses solr.solr.home for both config and data. +@echo. +@echo -e example Name of the example to run; available examples: +@echo cloud: SolrCloud example +@echo techproducts: Comprehensive example illustrating many of Solr's core capabilities +@echo dih: Data Import Handler +@echo schemaless: Schema-less example +@echo. +@echo -a opts Additional parameters to pass to the JVM when starting Solr, such as to setup +@echo Java debug options. For example, to enable a Java debugger to attach to the Solr JVM +@echo you could pass: -a "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=18983" +@echo In most cases, you should wrap the additional parameters in double quotes. +@echo. +@echo -j opts Additional parameters to pass to Jetty when starting Solr. +@echo For example, to add configuration folder that jetty should read +@echo you could pass: -j "--include-jetty-dir=/etc/jetty/custom/server/" +@echo In most cases, you should wrap the additional parameters in double quotes. +@echo. +@echo -noprompt Don't prompt for input; accept all defaults when running examples that accept user input +@echo. +@echo -v and -q Verbose (-v) or quiet (-q) logging. Sets default log level to DEBUG or WARN instead of INFO +@echo. +@echo -V/-verbose Verbose messages from this script +@echo. +goto done + +:status_usage +@echo. +@echo Usage: solr status +@echo. +@echo NOTE: This command will show the status of all running Solr servers +@echo. +goto done + +:stop_usage +@echo. +@echo Usage: solr stop [-k key] [-p port] [-V] +@echo. +@echo -k key Stop key; default is solrrocks +@echo. +@echo -p port Specify the port the Solr HTTP listener is bound to +@echo. +@echo -all Find and stop all running Solr servers on this host +@echo. +@echo -V/-verbose Verbose messages from this script +@echo. +@echo NOTE: To see if any Solr servers are running, do: solr status +@echo. +goto done + +:healthcheck_usage +@echo. +@echo Usage: solr healthcheck [-c collection] [-z zkHost] [-V] +@echo. +@echo Can be run from remote (non-Solr^) hosts, as long as a proper ZooKeeper connection is provided +@echo. +@echo -c collection Collection to run healthcheck against. +@echo. +@echo -z zkHost Zookeeper connection string; unnecessary if ZK_HOST is defined in solr.in.cmd; +@echo otherwise, default is localhost:9983 +@echo. +@echo -V Enable more verbose output +@echo. +goto done + +:create_usage +echo. +echo Usage: solr create [-c name] [-d confdir] [-n confname] [-shards #] [-replicationFactor #] [-p port] [-V] +echo. +echo Create a core or collection depending on whether Solr is running in standalone (core) or SolrCloud +echo mode (collection). In other words, this action detects which mode Solr is running in, and then takes +echo the appropriate action (either create_core or create_collection). For detailed usage instructions, do: +echo. +echo bin\solr create_core -help +echo. +echo or +echo. +echo bin\solr create_collection -help +echo. +goto done + +:delete_usage +echo. +echo Usage: solr delete [-c name] [-deleteConfig true^|false] [-p port] [-V] +echo. +echo Deletes a core or collection depending on whether Solr is running in standalone (core) or SolrCloud +echo mode (collection). If you're deleting a collection in SolrCloud mode, the default behavior is to also +echo delete the configuration directory from Zookeeper so long as it is not being used by another collection. +echo You can override this behavior by passing -deleteConfig false when running this command. +echo. +echo Can be run on remote (non-Solr^) hosts, as long as a valid SOLR_HOST is provided in solr.in.cmd +echo. +echo -c name Name of core to delete +echo. +echo -deleteConfig boolean Delete the configuration directory from Zookeeper; default is true +echo. +echo -p port Port of a local Solr instance where you want to delete the core/collection +echo If not specified, the script will search the local system for a running +echo Solr instance and will use the port of the first server it finds. +echo. +echo -V Enables more verbose output. +echo. +goto done + +:create_core_usage +echo. +echo Usage: solr create_core [-c ^] [-d confdir] [-p port] [-V] +echo. +echo When a configSet is used, this can be run from any host. If pointing at a non-configSet directory, this +echo must be run from the host that you wish to create the core on. +echo. +echo -c ^ Name of core to create +echo. +echo -d confdir Configuration directory to copy when creating the new core, built-in options are: +echo. +echo _default: Minimal configuration, which supports enabling/disabling field-guessing support +echo sample_techproducts_configs: Example configuration with many optional features enabled to +echo demonstrate the full power of Solr +echo. +echo If not specified, default is: _default +echo. +echo Alternatively, you can pass the path to your own configuration directory instead of using +echo one of the built-in configurations, such as: bin\solr create_core -c mycore -d c:/tmp/myconfig +echo. +echo -p port Port of a local Solr instance where you want to create the new core +echo If not specified, the script will search the local system for a running +echo Solr instance and will use the port of the first server it finds. +echo. +echo -V Enable more verbose output. +echo. +goto done + +:create_collection_usage +echo. +echo Usage: solr create_collection [-c collection] [-d confdir] [-n confname] [-shards #] [-replicationFactor #] [-p port] [-V] +echo. +echo Can be run from remote (non-Solr^) hosts, as long as a valid SOLR_HOST is provided in solr.in.cmd. +echo. +echo -c ^ Name of collection to create +echo. +echo -d ^ Configuration directory to copy when creating the new collection, built-in options are: +echo. +echo _default: Minimal configuration, which supports enabling/disabling field-guessing support +echo sample_techproducts_configs: Example configuration with many optional features enabled to +echo demonstrate the full power of Solr +echo. +echo If not specified, default is: _default +echo. +echo Alternatively, you can pass the path to your own configuration directory instead of using +echo one of the built-in configurations, such as: bin\solr create_collection -c mycoll -d c:/tmp/myconfig +echo. +echo By default the script will upload the specified confdir directory into Zookeeper using the same +echo name as the collection (-c) option. Alternatively, if you want to reuse an existing directory +echo or create a confdir in Zookeeper that can be shared by multiple collections, use the -n option +echo. +echo -n configName Name the configuration directory in Zookeeper; by default, the configuration +echo will be uploaded to Zookeeper using the collection name (-c), but if you want +echo to use an existing directory or override the name of the configuration in +echo Zookeeper, then use the -c option. +echo. +echo -shards # Number of shards to split the collection into; default is 1 +echo. +echo -replicationFactor # Number of copies of each document in the collection, default is 1 (no replication) +echo. +echo -p port Port of a local Solr instance where you want to create the new collection +echo If not specified, the script will search the local system for a running +echo Solr instance and will use the port of the first server it finds. +echo. +echo -V Enable more verbose output. +echo. +goto done + +:zk_usage +set ZK_FULL=true +goto zk_short_usage +:zk_full_usage +echo Can be run on remote (non-Solr^) hosts, as long as valid ZK_HOST information is provided. +echo Be sure to check the Solr logs in case of errors. +echo. +echo -z zkHost Optional Zookeeper connection string for all commands. If specified it +echo overrides the 'ZK_HOST=...'' defined in solr.in.cmd. +echo. +echo -V Enable more verbose output. +echo. +echo upconfig uploads a configset from the local machine to Zookeeper. (Backcompat: -upconfig) +echo. +echo downconfig downloads a configset from Zookeeper to the local machine. (Backcompat: -downconfig) +echo. +echo -n configName Name of the configset in Zookeeper that will be the destination of +echo 'upconfig' and the source for 'downconfig'. +echo. +echo -d confdir The local directory the configuration will be uploaded from for +echo 'upconfig' or downloaded to for 'downconfig'. If 'confdir' is a child of +echo ...solr/server/solr/configsets' then the configs will be copied from/to +echo that directory. Otherwise it is interpreted as a simple local path. +echo. +echo cp copies files or folders to/from Zookeeper or Zokeeper -^> Zookeeper +echo -r Recursively copy ^ to ^. Command will fail if ^ has children and +echo -r is not specified. Optional +echo. +echo. ^, ^ : [file:][/]path/to/local/file or zk:/path/to/zk/node +echo NOTE: ^ and ^ may both be Zookeeper resources prefixed by 'zk:' +echo When ^ is a zk resource, ^ may be '.' +echo If ^ ends with '/', then ^ will be a local folder or parent znode and the last +echo element of the ^ path will be appended unless ^ also ends in a slash. +echo ^ may be zk:, which may be useful when using the cp -r form to backup/restore +echo the entire zk state. +echo You must enclose local paths that end in a wildcard in quotes or just +echo end the local path in a slash. That is, +echo 'bin/solr zk cp -r /some/dir/ zk:/ -z localhost:2181' is equivalent to +echo 'bin/solr zk cp -r ^"/some/dir/*^" zk:/ -z localhost:2181' +echo but 'bin/solr zk cp -r /some/dir/* zk:/ -z localhost:2181' will throw an error. +echo. +echo Here's an example of backup/restore for a ZK configuration: +echo to copy to local: 'bin/solr zk cp -r zk:/ /some/dir -z localhost:2181' +echo to restore to ZK: 'bin/solr zk cp -r /some/dir/ zk:/ -z localhost:2181' +echo. +echo The 'file:' prefix is stripped, thus 'file:/wherever' specifies an absolute local path and +echo 'file:somewhere' specifies a relative local path. All paths on Zookeeper are absolute. +echo. +echo Zookeeper nodes CAN have data, so moving a single file to a parent znode +echo will overlay the data on the parent Znode so specifying the trailing slash +echo can be important. +echo. +echo Wildcards are supported when copying from local, trailing only and must be quoted. +echo. +echo rm deletes files or folders on Zookeeper +echo -r Recursively delete if ^ is a directory. Command will fail if ^ +echo has children and -r is not specified. Optional +echo ^ : [zk:]/path/to/zk/node. ^ may not be the root ('/') +echo. +echo mv moves (renames) znodes on Zookeeper +echo ^, ^ : Zookeeper nodes, the 'zk:' prefix is optional. +echo If ^ ends with '/', then ^ will be a parent znode +echo and the last element of the ^ path will be appended. +echo Zookeeper nodes CAN have data, so moving a single file to a parent znode +echo will overlay the data on the parent Znode so specifying the trailing slash +echo is important. +echo. +echo ls lists the znodes on Zookeeper +echo -r recursively descends the path listing all znodes. Optional +echo ^: The Zookeeper path to use as the root. +echo. +echo Only the node names are listed, not data +echo. +echo mkroot makes a znode in Zookeeper with no data. Can be used to make a path of arbitrary +echo depth but primarily intended to create a 'chroot'. +echo. +echo ^: The Zookeeper path to create. Leading slash is assumed if not present. +echo Intermediate nodes are created as needed if not present. +echo. + +goto done + +:zk_short_usage +IF NOT "!ERROR_MSG!"=="" ( + echo ERROR: !ERROR_MSG! + echo. +) +echo Usage: solr zk upconfig^|downconfig -d ^ -n ^ [-z zkHost] +echo solr zk cp [-r] ^ ^ [-z zkHost] +echo solr zk rm [-r] ^ [-z zkHost] +echo solr zk mv ^ ^ [-z zkHost] +echo solr zk ls [-r] ^ [-z zkHost] +echo solr zk mkroot ^ [-z zkHost] +echo. +IF "%ZK_FULL%"=="true" ( + goto zk_full_usage +) ELSE ( + echo Type bin/solr zk -help for full usage help +) +goto done + +:auth_usage +echo Usage: solr auth enable [-type basicAuth] -credentials user:pass [-blockUnknown ^] [-updateIncludeFileOnly ^] [-V] +echo solr auth enable [-type basicAuth] -prompt ^ [-blockUnknown ^] [-updateIncludeFileOnly ^] [-V] +echo solr auth disable [-updateIncludeFileOnly ^] [-V] +echo. +echo Updates or enables/disables authentication. Must be run on the machine hosting Solr. +echo. +echo -type ^ The authentication mechanism to enable. Defaults to 'basicAuth'. +echo. +echo -credentials ^ The username and password of the initial user +echo Note: only one of -prompt or -credentials must be provided +echo. +echo -prompt ^ Prompts the user to provide the credentials +echo Note: only one of -prompt or -credentials must be provided +echo. +echo -blockUnknown ^ When true, this blocks out access to unauthenticated users. When not provided, +echo this defaults to false (i.e. unauthenticated users can access all endpoints, except the +echo operations like collection-edit, security-edit, core-admin-edit etc.^). Check the reference +echo guide for Basic Authentication for more details. +echo. +echo -updateIncludeFileOnly ^ Only update the solr.in.sh or solr.in.cmd file, and skip actual enabling/disabling" +echo authentication (i.e. don't update security.json^)" +echo. +echo -z zkHost Zookeeper connection string. Unnecessary if ZK_HOST is defined in solr.in.cmd. +echo. +echo -d ^ Specify the Solr server directory" +echo. +echo -s ^ Specify the Solr home directory. This is where any credentials or authentication" +echo configuration files (e.g. basicAuth.conf^) would be placed." +echo. +echo -V Enable more verbose output +echo. +goto done + +REM Really basic command-line arg parsing +:parse_args + +set "arg=%~1" +set "firstTwo=%arg:~0,2%" +IF "%SCRIPT_CMD%"=="" set SCRIPT_CMD=start +IF [%1]==[] goto process_script_cmd +IF "%1"=="-help" goto usage +IF "%1"=="-usage" goto usage +IF "%1"=="/?" goto usage +IF "%1"=="-f" goto set_foreground_mode +IF "%1"=="-foreground" goto set_foreground_mode +IF "%1"=="-V" goto set_verbose +IF "%1"=="-verbose" goto set_verbose +IF "%1"=="-v" goto set_debug +IF "%1"=="-q" goto set_warn +IF "%1"=="-c" goto set_cloud_mode +IF "%1"=="-cloud" goto set_cloud_mode +IF "%1"=="-d" goto set_server_dir +IF "%1"=="-dir" goto set_server_dir +IF "%1"=="-s" goto set_solr_home_dir +IF "%1"=="-t" goto set_solr_data_dir +IF "%1"=="-solr.home" goto set_solr_home_dir +IF "%1"=="-e" goto set_example +IF "%1"=="-example" goto set_example +IF "%1"=="-h" goto set_host +IF "%1"=="-host" goto set_host +IF "%1"=="-m" goto set_memory +IF "%1"=="-memory" goto set_memory +IF "%1"=="-p" goto set_port +IF "%1"=="-port" goto set_port +IF "%1"=="-z" goto set_zookeeper +IF "%1"=="-zkhost" goto set_zookeeper +IF "%1"=="-zkHost" goto set_zookeeper +IF "%1"=="-a" goto set_addl_opts +IF "%1"=="-addlopts" goto set_addl_opts +IF "%1"=="-j" goto set_addl_jetty_config +IF "%1"=="-jettyconfig" goto set_addl_jetty_config +IF "%1"=="-noprompt" goto set_noprompt +IF "%1"=="-k" goto set_stop_key +IF "%1"=="-key" goto set_stop_key +IF "%1"=="-all" goto set_stop_all +IF "%firstTwo%"=="-D" goto set_passthru +IF NOT "%1"=="" goto invalid_cmd_line +goto invalid_cmd_line + +:set_script_cmd +set SCRIPT_CMD=%1 +SHIFT +goto parse_args + +:set_foreground_mode +set FG=1 +SHIFT +goto parse_args + +:set_verbose +set verbose=1 +set "PASS_TO_RUN_EXAMPLE=--verbose !PASS_TO_RUN_EXAMPLE!" +SHIFT +goto parse_args + +:set_debug +set SOLR_LOG_LEVEL=DEBUG +SHIFT +goto parse_args + +:set_warn +set SOLR_LOG_LEVEL=WARN +SHIFT +goto parse_args + +:set_cloud_mode +set SOLR_MODE=solrcloud +SHIFT +goto parse_args + +:set_server_dir + +set "arg=%~2" +IF "%arg%"=="" ( + set SCRIPT_ERROR=Directory name is required! + goto invalid_cmd_line +) +set firstChar=%arg:~0,1% +IF "%firstChar%"=="-" ( + set SCRIPT_ERROR=Expected directory but found %2 instead! + goto invalid_cmd_line +) + +REM See if they are using a short-hand name relative from the Solr tip directory +IF EXIST "%SOLR_TIP%\%~2" ( + set "SOLR_SERVER_DIR=%SOLR_TIP%\%~2" +) ELSE ( + set "SOLR_SERVER_DIR=%~2" +) +SHIFT +SHIFT +goto parse_args + +:set_solr_home_dir + +set "arg=%~2" +IF "%arg%"=="" ( + set SCRIPT_ERROR=Directory name is required! + goto invalid_cmd_line +) + +set firstChar=%arg:~0,1% +IF "%firstChar%"=="-" ( + set SCRIPT_ERROR=Expected directory but found %2 instead! + goto invalid_cmd_line +) +set "SOLR_HOME=%~2" +SHIFT +SHIFT +goto parse_args + +:set_solr_data_dir + +set "arg=%~2" +IF "%arg%"=="" ( + set SCRIPT_ERROR=Directory name is required! + goto invalid_cmd_line +) + +set firstChar=%arg:~0,1% +IF "%firstChar%"=="-" ( + set SCRIPT_ERROR=Expected directory but found %2 instead! + goto invalid_cmd_line +) +set "SOLR_DATA_HOME=%~2" +SHIFT +SHIFT +goto parse_args + +:set_example + +set "arg=%~2" +IF "%arg%"=="" ( + set SCRIPT_ERROR=Example name is required! + goto invalid_cmd_line +) + +set firstChar=%arg:~0,1% +IF "%firstChar%"=="-" ( + set SCRIPT_ERROR=Expected example name but found %2 instead! + goto invalid_cmd_line +) + +set EXAMPLE=%~2 +SHIFT +SHIFT +goto parse_args + +:set_memory + +set "arg=%~2" +IF "%arg%"=="" ( + set SCRIPT_ERROR=Memory setting is required! + goto invalid_cmd_line +) + +set firstChar=%arg:~0,1% +IF "%firstChar%"=="-" ( + set SCRIPT_ERROR=Expected memory setting but found %2 instead! + goto invalid_cmd_line +) + +set SOLR_HEAP=%~2 +set "PASS_TO_RUN_EXAMPLE=-m %~2 !PASS_TO_RUN_EXAMPLE!" +SHIFT +SHIFT +goto parse_args + +:set_host +set "arg=%~2" +IF "%arg%"=="" ( + set SCRIPT_ERROR=Hostname is required! + goto invalid_cmd_line +) + +set firstChar=%arg:~0,1% +IF "%firstChar%"=="-" ( + set SCRIPT_ERROR=Expected hostname but found %2 instead! + goto invalid_cmd_line +) + +set SOLR_HOST=%~2 +set "PASS_TO_RUN_EXAMPLE=-h %~2 !PASS_TO_RUN_EXAMPLE!" +SHIFT +SHIFT +goto parse_args + +:set_port +set "arg=%~2" +IF "%arg%"=="" ( + set SCRIPT_ERROR=Port is required! + goto invalid_cmd_line +) + +set firstChar=%arg:~0,1% +IF "%firstChar%"=="-" ( + set SCRIPT_ERROR=Expected port but found %2 instead! + goto invalid_cmd_line +) + +set SOLR_PORT=%~2 +set "PASS_TO_RUN_EXAMPLE=-p %~2 !PASS_TO_RUN_EXAMPLE!" +SHIFT +SHIFT +goto parse_args + +:set_stop_key +set "arg=%~2" +IF "%arg%"=="" ( + set SCRIPT_ERROR=Stop key is required! + goto invalid_cmd_line +) + +set firstChar=%arg:~0,1% +IF "%firstChar%"=="-" ( + set SCRIPT_ERROR=Expected stop key but found %2 instead! + goto invalid_cmd_line +) +set STOP_KEY=%~2 +SHIFT +SHIFT +goto parse_args + +:set_stop_all +set STOP_ALL=1 +SHIFT +goto parse_args + +:set_zookeeper + +set "arg=%~2" +IF "%arg%"=="" ( + set SCRIPT_ERROR=Zookeeper connection string is required! + goto invalid_cmd_line +) + +set firstChar=%arg:~0,1% +IF "%firstChar%"=="-" ( + set SCRIPT_ERROR=Expected Zookeeper connection string but found %2 instead! + goto invalid_cmd_line +) + +set "ZK_HOST=%~2" +set "PASS_TO_RUN_EXAMPLE=-z %~2 !PASS_TO_RUN_EXAMPLE!" +SHIFT +SHIFT +goto parse_args + +:set_addl_opts +set "arg=%~2" +set "SOLR_ADDL_ARGS=%~2" +SHIFT +SHIFT +goto parse_args + +:set_addl_jetty_config +set "arg=%~2" +set "SOLR_JETTY_ADDL_CONFIG=%~2" +SHIFT +SHIFT +goto parse_args + +:set_passthru +set "PASSTHRU=%~1=%~2" +IF NOT "%SOLR_OPTS%"=="" ( + set "SOLR_OPTS=%SOLR_OPTS% %PASSTHRU%" +) ELSE ( + set "SOLR_OPTS=%PASSTHRU%" +) +set "PASS_TO_RUN_EXAMPLE=%PASSTHRU% !PASS_TO_RUN_EXAMPLE!" +SHIFT +SHIFT +goto parse_args + +:set_noprompt +set NO_USER_PROMPT=1 +set "PASS_TO_RUN_EXAMPLE=-noprompt !PASS_TO_RUN_EXAMPLE!" + +SHIFT +goto parse_args + +REM Perform the requested command after processing args +:process_script_cmd + +IF "%verbose%"=="1" ( + CALL :safe_echo "Using Solr root directory: %SOLR_TIP%" + CALL :safe_echo "Using Java: %JAVA%" + "%JAVA%" -version + @echo. +) + +IF NOT "%SOLR_HOST%"=="" ( + set SOLR_HOST_ARG=-Dhost=%SOLR_HOST% +) ELSE ( + set SOLR_HOST_ARG= +) + +IF "%SOLR_SERVER_DIR%"=="" set "SOLR_SERVER_DIR=%DEFAULT_SERVER_DIR%" + +IF NOT EXIST "%SOLR_SERVER_DIR%" ( + set "SCRIPT_ERROR=Solr server directory %SOLR_SERVER_DIR% not found!" + goto err +) + +IF NOT "%EXAMPLE%"=="" goto run_example + +:start_solr +IF "%SOLR_HOME%"=="" set "SOLR_HOME=%SOLR_SERVER_DIR%\solr" +IF EXIST "%cd%\%SOLR_HOME%" set "SOLR_HOME=%cd%\%SOLR_HOME%" + +IF NOT EXIST "%SOLR_HOME%\" ( + IF EXIST "%SOLR_SERVER_DIR%\%SOLR_HOME%" ( + set "SOLR_HOME=%SOLR_SERVER_DIR%\%SOLR_HOME%" + ) ELSE ( + set "SCRIPT_ERROR=Solr home directory %SOLR_HOME% not found!" + goto err + ) +) + +IF "%STOP_KEY%"=="" set STOP_KEY=solrrocks + +@REM This is quite hacky, but examples rely on a different log4j2.xml +@REM so that we can write logs for examples to %SOLR_HOME%\..\logs +@REM IF [%SOLR_LOGS_DIR%] == [] ( +@REM set "SOLR_LOGS_DIR=%SOLR_SERVER_DIR%\logs" +@REM ) ELSE ( +@REM set SOLR_LOGS_DIR=%SOLR_LOGS_DIR:"=% +@REM ) + +set "SOLR_LOGS_DIR=%APPDATA%\autopsy\var\log\solr" + +set "EXAMPLE_DIR=%SOLR_TIP%\example" +set TMP_SOLR_HOME=!SOLR_HOME:%EXAMPLE_DIR%=! +IF NOT "%TMP_SOLR_HOME%"=="%SOLR_HOME%" ( + set "SOLR_LOGS_DIR=%SOLR_HOME%\..\logs" + set "LOG4J_CONFIG=file:///%SOLR_SERVER_DIR%\resources\log4j2.xml" +) + +set IS_RESTART=0 +IF "%SCRIPT_CMD%"=="restart" ( + IF "%SOLR_PORT%"=="" ( + set "SCRIPT_ERROR=Must specify the port when trying to restart Solr." + goto err + ) + set SCRIPT_CMD=stop + set IS_RESTART=1 +) + +@REM stop logic here +IF "%SCRIPT_CMD%"=="stop" ( + IF "%SOLR_PORT%"=="" ( + IF "%STOP_ALL%"=="1" ( + set found_it=0 + for /f "usebackq" %%i in (`dir /b "%SOLR_LOGS_DIR%" ^| findstr /i "^solr-.*\.port$"`) do ( + set SOME_SOLR_PORT= + For /F "delims=" %%J In ('type "%SOLR_TIP%\bin\%%i"') do set SOME_SOLR_PORT=%%~J + if NOT "!SOME_SOLR_PORT!"=="" ( + for /f "tokens=2,5" %%j in ('netstat -aon ^| find "TCP " ^| find ":0 " ^| find ":!SOME_SOLR_PORT! "') do ( + @REM j is the ip:port and k is the pid + IF NOT "%%k"=="0" ( + IF "%%j"=="%SOLR_JETTY_HOST%:!SOME_SOLR_PORT!" ( + set found_it=1 + @echo Stopping Solr process %%k running on port !SOME_SOLR_PORT! + IF "%STOP_PORT%"=="" set /A STOP_PORT=!SOME_SOLR_PORT! - 1000 + "%JAVA%" %SOLR_SSL_OPTS% -Djetty.home="%SOLR_SERVER_DIR%" -jar "%SOLR_SERVER_DIR%\start.jar" STOP.PORT=!STOP_PORT! STOP.KEY=%STOP_KEY% --stop + del "%SOLR_LOGS_DIR%"\solr-!SOME_SOLR_PORT!.port + timeout /T 5 + REM Kill it if it is still running after the graceful shutdown + For /f "tokens=2,5" %%M in ('netstat -nao ^| find "TCP " ^| find ":0 " ^| find ":!SOME_SOLR_PORT! "') do ( + IF "%%N"=="%%k" ( + IF "%%M"=="%SOLR_JETTY_HOST%:!SOME_SOLR_PORT!" ( + @echo Forcefully killing process %%N + taskkill /f /PID %%N + ) + ) + ) + ) + ) + ) + ) + ) + if "!found_it!"=="0" echo No Solr nodes found to stop. + ) ELSE ( + set "SCRIPT_ERROR=Must specify the port when trying to stop Solr, or use -all to stop all running nodes on this host." + goto err + ) + ) ELSE ( + set found_it=0 + For /f "tokens=2,5" %%M in ('netstat -nao ^| find "TCP " ^| find ":0 " ^| find ":%SOLR_PORT% "') do ( + IF NOT "%%N"=="0" ( + IF "%%M"=="%SOLR_JETTY_HOST%:%SOLR_PORT%" ( + set found_it=1 + @echo Stopping Solr process %%N running on port %SOLR_PORT% + IF "%STOP_PORT%"=="" set /A STOP_PORT=%SOLR_PORT% - 1000 + "%JAVA%" %SOLR_SSL_OPTS% -Djetty.home="%SOLR_SERVER_DIR%" -jar "%SOLR_SERVER_DIR%\start.jar" %SOLR_JETTY_CONFIG% STOP.PORT=!STOP_PORT! STOP.KEY=%STOP_KEY% --stop + del "%SOLR_LOGS_DIR%"\solr-%SOLR_PORT%.port + timeout /T 5 + REM Kill it if it is still running after the graceful shutdown + For /f "tokens=2,5" %%j in ('netstat -nao ^| find "TCP " ^| find ":0 " ^| find ":%SOLR_PORT% "') do ( + IF "%%N"=="%%k" ( + IF "%%j"=="%SOLR_JETTY_HOST%:%SOLR_PORT%" ( + @echo Forcefully killing process %%N + taskkill /f /PID %%N + ) + ) + ) + ) + ) + ) + if "!found_it!"=="0" echo No Solr found running on port %SOLR_PORT% + ) + + IF "!IS_RESTART!"=="0" goto done +) + +IF "!IS_RESTART!"=="1" set SCRIPT_CMD=start + +IF "%SOLR_PORT%"=="" set SOLR_PORT=8983 +IF "%STOP_PORT%"=="" set /A STOP_PORT=%SOLR_PORT% - 1000 + +IF "%SCRIPT_CMD%"=="start" ( + REM see if Solr is already running using netstat + For /f "tokens=2,5" %%j in ('netstat -aon ^| find "TCP " ^| find ":0 " ^| find ":%SOLR_PORT% "') do ( + IF NOT "%%k"=="0" ( + IF "%%j"=="%SOLR_JETTY_HOST%:%SOLR_PORT%" ( + set "SCRIPT_ERROR=Process %%k is already listening on port %SOLR_PORT%. If this is Solr, please stop it first before starting (or use restart). If this is not Solr, then please choose a different port using -p PORT" + goto err + ) + ) + ) +) + +@REM determine if -server flag is supported by current JVM +"%JAVA%" -server -version > nul 2>&1 +IF ERRORLEVEL 1 ( + set IS_JDK=false + set "SERVEROPT=" + @echo WARNING: You are using a JRE without support for -server option. Please upgrade to latest JDK for best performance + @echo. +) ELSE ( + set IS_JDK=true + set "SERVEROPT=-server" +) +if !JAVA_MAJOR_VERSION! LSS 9 ( + "%JAVA%" -d64 -version > nul 2>&1 + IF ERRORLEVEL 1 ( + set "IS_64BIT=false" + @echo WARNING: 32-bit Java detected. Not recommended for production. Point your JAVA_HOME to a 64-bit JDK + @echo. + ) ELSE ( + set IS_64bit=true + ) +) ELSE ( + set IS_64bit=true +) + +REM Clean up and rotate logs. Default to false since 7.4 as log4j2 handles startup rotation +IF [%SOLR_LOG_PRESTART_ROTATION%] == [] ( + set SOLR_LOG_PRESTART_ROTATION=false +) +IF [%SOLR_LOG_PRESTART_ROTATION%] == [true] ( + REM Enable any of these if you require old remove/archive behavior + REM call :run_utils "-remove_old_solr_logs 7" || echo "Failed removing old solr logs" + REM call :run_utils "-archive_gc_logs" || echo "Failed archiving old GC logs" + REM call :run_utils "-archive_console_logs" || echo "Failed archiving old console logs" + call :run_utils "-rotate_solr_logs 9" || echo "Failed rotating old solr logs" +) + +IF NOT "%ZK_HOST%"=="" set SOLR_MODE=solrcloud + +IF "%SOLR_MODE%"=="solrcloud" ( + IF "%ZK_CLIENT_TIMEOUT%"=="" set "ZK_CLIENT_TIMEOUT=15000" + + set "CLOUD_MODE_OPTS=-DzkClientTimeout=!ZK_CLIENT_TIMEOUT!" + + IF NOT "%ZK_HOST%"=="" ( + set "CLOUD_MODE_OPTS=!CLOUD_MODE_OPTS! -DzkHost=%ZK_HOST%" + ) ELSE ( + IF "%verbose%"=="1" echo Configuring SolrCloud to launch an embedded Zookeeper using -DzkRun + set "CLOUD_MODE_OPTS=!CLOUD_MODE_OPTS! -DzkRun" + ) + IF EXIST "%SOLR_HOME%\collection1\core.properties" set "CLOUD_MODE_OPTS=!CLOUD_MODE_OPTS! -Dbootstrap_confdir=./solr/collection1/conf -Dcollection.configName=myconf -DnumShards=1" +) ELSE ( + set CLOUD_MODE_OPTS= + IF NOT EXIST "%SOLR_HOME%\solr.xml" ( + set "SCRIPT_ERROR=Solr home directory %SOLR_HOME% must contain solr.xml!" + goto err + ) +) + +REM These are useful for attaching remove profilers like VisualVM/JConsole +IF "%ENABLE_REMOTE_JMX_OPTS%"=="true" ( + IF "!RMI_PORT!"=="" set RMI_PORT=1%SOLR_PORT% + set REMOTE_JMX_OPTS=-Dcom.sun.management.jmxremote ^ +-Dcom.sun.management.jmxremote.local.only=false ^ +-Dcom.sun.management.jmxremote.ssl=false ^ +-Dcom.sun.management.jmxremote.authenticate=false ^ +-Dcom.sun.management.jmxremote.port=!RMI_PORT! ^ +-Dcom.sun.management.jmxremote.rmi.port=!RMI_PORT! + + IF NOT "%SOLR_HOST%"=="" set REMOTE_JMX_OPTS=%REMOTE_JMX_OPTS% -Djava.rmi.server.hostname=%SOLR_HOST% +) ELSE ( + set REMOTE_JMX_OPTS= +) + +IF NOT "%SOLR_HEAP%"=="" set SOLR_JAVA_MEM=-Xms%SOLR_HEAP% -Xmx%SOLR_HEAP% +IF "%SOLR_JAVA_MEM%"=="" set SOLR_JAVA_MEM=-Xms512m -Xmx512m +IF "%SOLR_JAVA_STACK_SIZE%"=="" set SOLR_JAVA_STACK_SIZE=-Xss256k +set SOLR_OPTS=%SOLR_JAVA_STACK_SIZE% %SOLR_OPTS% +IF "%SOLR_TIMEZONE%"=="" set SOLR_TIMEZONE=UTC + +IF "%GC_TUNE%"=="" ( + set GC_TUNE=-XX:+UseG1GC ^ + -XX:+PerfDisableSharedMem ^ + -XX:+ParallelRefProcEnabled ^ + -XX:MaxGCPauseMillis=250 ^ + -XX:+UseLargePages ^ + -XX:+AlwaysPreTouch +) + +if !JAVA_MAJOR_VERSION! GEQ 9 ( + IF NOT "%GC_LOG_OPTS%"=="" ( + echo ERROR: On Java 9 you cannot set GC_LOG_OPTS, only default GC logging is available. Exiting + GOTO :eof + ) + set GC_LOG_OPTS="-Xlog:gc*:file=\"!SOLR_LOGS_DIR!\solr_gc.log\":time,uptime:filecount=9,filesize=20M" +) else ( + IF "%GC_LOG_OPTS%"=="" ( + rem Set defaults for Java 8 + set GC_LOG_OPTS=-verbose:gc ^ + -XX:+PrintHeapAtGC ^ + -XX:+PrintGCDetails ^ + -XX:+PrintGCDateStamps ^ + -XX:+PrintGCTimeStamps ^ + -XX:+PrintTenuringDistribution ^ + -XX:+PrintGCApplicationStoppedTime + ) + if "%JAVA_VENDOR%" == "IBM J9" ( + set GC_LOG_OPTS=!GC_LOG_OPTS! "-Xverbosegclog:!SOLR_LOGS_DIR!\solr_gc.log" -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=9 -XX:GCLogFileSize=20M + ) else ( + set GC_LOG_OPTS=!GC_LOG_OPTS! "-Xloggc:!SOLR_LOGS_DIR!\solr_gc.log" -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=9 -XX:GCLogFileSize=20M + ) +) + +IF "%verbose%"=="1" ( + @echo Starting Solr using the following settings: + CALL :safe_echo " JAVA = %JAVA%" + CALL :safe_echo " SOLR_SERVER_DIR = %SOLR_SERVER_DIR%" + CALL :safe_echo " SOLR_HOME = %SOLR_HOME%" + @echo SOLR_HOST = %SOLR_HOST% + @echo SOLR_PORT = %SOLR_PORT% + @echo STOP_PORT = %STOP_PORT% + @echo SOLR_JAVA_MEM = %SOLR_JAVA_MEM% + @echo GC_TUNE = !GC_TUNE! + @echo GC_LOG_OPTS = %GC_LOG_OPTS% + @echo SOLR_TIMEZONE = %SOLR_TIMEZONE% + + IF "%SOLR_MODE%"=="solrcloud" ( + @echo CLOUD_MODE_OPTS = %CLOUD_MODE_OPTS% + ) + + IF NOT "%SOLR_OPTS%"=="" ( + @echo SOLR_OPTS = %SOLR_OPTS% + ) + + IF NOT "%SOLR_ADDL_ARGS%"=="" ( + CALL :safe_echo " SOLR_ADDL_ARGS = %SOLR_ADDL_ARGS%" + ) + + IF NOT "%SOLR_JETTY_ADDL_CONFIG%"=="" ( + CALL :safe_echo " SOLR_JETTY_ADDL_CONFIG = %SOLR_JETTY_ADDL_CONFIG%" + ) + + IF "%ENABLE_REMOTE_JMX_OPTS%"=="true" ( + @echo RMI_PORT = !RMI_PORT! + @echo REMOTE_JMX_OPTS = %REMOTE_JMX_OPTS% + ) + + IF NOT "%SOLR_LOG_LEVEL%"=="" ( + @echo SOLR_LOG_LEVEL = !SOLR_LOG_LEVEL! + ) + + IF NOT "%SOLR_DATA_HOME%"=="" ( + @echo SOLR_DATA_HOME = !SOLR_DATA_HOME! + ) + + @echo. +) + +set START_OPTS=-Duser.timezone=%SOLR_TIMEZONE% +set START_OPTS=%START_OPTS% !GC_TUNE! %GC_LOG_OPTS% +IF NOT "!CLOUD_MODE_OPTS!"=="" set "START_OPTS=%START_OPTS% !CLOUD_MODE_OPTS!" +IF NOT "%REMOTE_JMX_OPTS%"=="" set "START_OPTS=%START_OPTS% %REMOTE_JMX_OPTS%" +IF NOT "%SOLR_ADDL_ARGS%"=="" set "START_OPTS=%START_OPTS% %SOLR_ADDL_ARGS%" +IF NOT "%SOLR_HOST_ARG%"=="" set "START_OPTS=%START_OPTS% %SOLR_HOST_ARG%" +IF NOT "%SOLR_OPTS%"=="" set "START_OPTS=%START_OPTS% %SOLR_OPTS%" +IF "%SOLR_SSL_ENABLED%"=="true" ( + set "SSL_PORT_PROP=-Dsolr.jetty.https.port=%SOLR_PORT%" + set "START_OPTS=%START_OPTS% %SOLR_SSL_OPTS% !SSL_PORT_PROP!" +) +IF NOT "%SOLR_LOG_LEVEL%"=="" set "START_OPTS=%START_OPTS% -Dsolr.log.level=%SOLR_LOG_LEVEL%" + +set SOLR_LOGS_DIR_QUOTED="%SOLR_LOGS_DIR%" +set SOLR_DATA_HOME_QUOTED="%SOLR_DATA_HOME%" + +set "START_OPTS=%START_OPTS% -Dsolr.log.dir=%SOLR_LOGS_DIR_QUOTED%" +IF NOT "%SOLR_DATA_HOME%"=="" set "START_OPTS=%START_OPTS% -Dsolr.data.home=%SOLR_DATA_HOME_QUOTED%" +IF NOT DEFINED LOG4J_CONFIG set "LOG4J_CONFIG=file:///%SOLR_SERVER_DIR%\resources\log4j2.xml" + +cd /d "%SOLR_SERVER_DIR%" + +IF NOT EXIST "%SOLR_LOGS_DIR%" ( + mkdir "%SOLR_LOGS_DIR%" +) +copy /Y NUL "%SOLR_LOGS_DIR%\.writable" > NUL 2>&1 && set WRITEOK=1 +IF DEFINED WRITEOK ( + del "%SOLR_LOGS_DIR%\.writable" +) else ( + echo "ERROR: Logs directory %SOLR_LOGS_DIR% is not writable or could not be created. Exiting" + GOTO :eof +) +echo " contexts etc lib modules resources scripts solr solr-webapp " > "%TEMP%\solr-pattern.txt" +findstr /i /C:" %SOLR_LOGS_DIR% " "%TEMP%\solr-pattern.txt" 1>nul +if %ERRORLEVEL% == 0 ( + echo "ERROR: Logs directory %SOLR_LOGS_DIR% is invalid. Reserved for the system. Exiting" + GOTO :eof +) + +IF NOT EXIST "%SOLR_LOGS_DIR%\tmp" ( + mkdir "%SOLR_LOGS_DIR%\tmp" +) + +IF "%DEFAULT_CONFDIR%"=="" set "DEFAULT_CONFDIR=%SOLR_SERVER_DIR%\solr\configsets\_default\conf" + +IF "%FG%"=="1" ( + REM run solr in the foreground + title "Solr-%SOLR_PORT%" + echo %SOLR_PORT%>"%SOLR_LOGS_DIR%"\solr-%SOLR_PORT%.port + "%JAVA%" %SERVEROPT% %SOLR_JAVA_MEM% %START_OPTS% ^ + -Dlog4j.configurationFile="%LOG4J_CONFIG%" -DSTOP.PORT=!STOP_PORT! -DSTOP.KEY=%STOP_KEY% ^ + -Dsolr.solr.home="%SOLR_HOME%" -Dsolr.install.dir="%SOLR_TIP%" -Dsolr.default.confdir="%DEFAULT_CONFDIR%" ^ + -Djetty.host=%SOLR_JETTY_HOST% -Djetty.port=%SOLR_PORT% -Djetty.home="%SOLR_SERVER_DIR%" ^ + -Djava.io.tmpdir="%SOLR_LOGS_DIR%\tmp" -jar start.jar %SOLR_JETTY_CONFIG% "%SOLR_JETTY_ADDL_CONFIG%" +) ELSE ( + START /B "Solr-%SOLR_PORT%" /D "%SOLR_SERVER_DIR%" ^ + "%JAVA%" %SERVEROPT% %SOLR_JAVA_MEM% %START_OPTS% ^ + -Dlog4j.configurationFile="%LOG4J_CONFIG%" -DSTOP.PORT=!STOP_PORT! -DSTOP.KEY=%STOP_KEY% ^ + -Dsolr.log.muteconsole ^ + -Dsolr.solr.home="%SOLR_HOME%" -Dsolr.install.dir="%SOLR_TIP%" -Dsolr.default.confdir="%DEFAULT_CONFDIR%" ^ + -Djetty.host=%SOLR_JETTY_HOST% -Djetty.port=%SOLR_PORT% -Djetty.home="%SOLR_SERVER_DIR%" ^ + -Djava.io.tmpdir="%SOLR_LOGS_DIR%\tmp" -jar start.jar %SOLR_JETTY_CONFIG% "%SOLR_JETTY_ADDL_CONFIG%" > "!SOLR_LOGS_DIR!\solr-%SOLR_PORT%-console.log" + echo %SOLR_PORT%>"%SOLR_LOGS_DIR%"\solr-%SOLR_PORT%.port + + REM now wait to see Solr come online ... + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" -Dsolr.default.confdir="%DEFAULT_CONFDIR%"^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI status -maxWaitSecs 30 -solr !SOLR_URL_SCHEME!://%SOLR_TOOL_HOST%:%SOLR_PORT%/solr +) + +goto done + +:run_example +REM Run the requested example + +"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI run_example -script "%SDIR%\solr.cmd" -e %EXAMPLE% -d "%SOLR_SERVER_DIR%" ^ + -urlScheme !SOLR_URL_SCHEME! !PASS_TO_RUN_EXAMPLE! + +REM End of run_example +goto done + +:get_info +REM Find all Java processes, correlate with those listening on a port +REM and then try to contact via that port using the status tool +for /f "usebackq" %%i in (`dir /b "%SOLR_LOGS_DIR%" ^| findstr /i "^solr-.*\.port$"`) do ( + set SOME_SOLR_PORT= + For /F "Delims=" %%J In ('type "%SOLR_TIP%\bin\%%i"') do set SOME_SOLR_PORT=%%~J + if NOT "!SOME_SOLR_PORT!"=="" ( + for /f "tokens=2,5" %%j in ('netstat -aon ^| find "TCP " ^| find ":0 " ^| find ":!SOME_SOLR_PORT! "') do ( + IF NOT "%%k"=="0" ( + if "%%j"=="%SOLR_JETTY_HOST%:!SOME_SOLR_PORT!" ( + @echo. + set has_info=1 + echo Found Solr process %%k running on port !SOME_SOLR_PORT! + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI status -solr !SOLR_URL_SCHEME!://%SOLR_TOOL_HOST%:!SOME_SOLR_PORT!/solr + @echo. + ) + ) + ) + ) +) +if NOT "!has_info!"=="1" echo No running Solr nodes found. +set has_info= +goto done + +:parse_healthcheck_args +IF [%1]==[] goto run_healthcheck +IF "%1"=="-V" goto set_healthcheck_verbose +IF "%1"=="-c" goto set_healthcheck_collection +IF "%1"=="-collection" goto set_healthcheck_collection +IF "%1"=="-z" goto set_healthcheck_zk +IF "%1"=="-zkhost" goto set_healthcheck_zk +IF "%1"=="-zkHost" goto set_healthcheck_zk +IF "%1"=="-help" goto usage +IF "%1"=="-usage" goto usage +IF "%1"=="/?" goto usage +goto run_healthcheck + +:set_healthcheck_verbose +set HEALTHCHECK_VERBOSE="-verbose" +SHIFT +goto parse_healthcheck_args + +:set_healthcheck_collection +set HEALTHCHECK_COLLECTION=%~2 +SHIFT +SHIFT +goto parse_healthcheck_args + +:set_healthcheck_zk +set ZK_HOST=%~2 +SHIFT +SHIFT +goto parse_healthcheck_args + +:run_healthcheck +IF NOT DEFINED HEALTHCHECK_COLLECTION goto healthcheck_usage +IF NOT DEFINED HEALTHCHECK_VERBOSE set "HEALTHCHECK_VERBOSE=" +IF NOT DEFINED HEALTHCHECK_ZK_HOST set "HEALTHCHECK_ZK_HOST=localhost:9983" +echo ZK_HOST: !ZK_HOST! +"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI healthcheck -collection !HEALTHCHECK_COLLECTION! -zkHost !ZK_HOST! %HEALTHCHECK_VERBOSE% +goto done + +:run_assert +"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI %* +if errorlevel 1 ( + exit /b 1 +) +goto done + +:run_autoscaling +"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI %* +goto done + +:parse_config_args +IF [%1]==[] goto run_config +IF "%1"=="-z" goto set_config_zk +IF "%1"=="-zkhost" goto set_config_zk +IF "%1"=="-zkHost" goto set_config_zk +IF "%1"=="-s" goto set_config_url_scheme +IF "%1"=="-scheme" goto set_config_url_scheme +set "CONFIG_ARGS=!CONFIG_ARGS! %1" +SHIFT +goto parse_config_args + +:set_config_zk +set ZK_HOST=%~2 +SHIFT +SHIFT +goto parse_config_args + +:set_config_url_scheme +set SOLR_URL_SCHEME=%~2 +SHIFT +SHIFT +goto parse_config_args + +:run_config +IF NOT "!ZK_HOST!"=="" SET "CONFIG_ARGS=!CONFIG_ARGS! -z !ZK_HOST!" +IF NOT "!SOLR_URL_SCHEME!"=="" SET "CONFIG_ARGS=!CONFIG_ARGS! -scheme !SOLR_URL_SCHEME!" + +"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI config !CONFIG_ARGS! +if errorlevel 1 ( + exit /b 1 +) +goto done + +:get_version +"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI version +goto done + +:run_utils +set "TOOL_CMD=%~1" +set q="-q" +IF "%verbose%"=="1" set q="" +"%JAVA%" %SOLR_SSL_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI utils -s "%DEFAULT_SERVER_DIR%" -l "%SOLR_LOGS_DIR%" %q:"=% %TOOL_CMD% +if errorlevel 1 ( + exit /b 1 +) +goto done + +:parse_create_args +IF [%1]==[] goto run_create +IF "%1"=="-V" goto set_create_verbose +IF "%1"=="-c" goto set_create_name +IF "%1"=="-core" goto set_create_name +IF "%1"=="-collection" goto set_create_name +IF "%1"=="-d" goto set_create_confdir +IF "%1"=="-confdir" goto set_create_confdir +IF "%1"=="-n" goto set_create_confname +IF "%1"=="-confname" goto set_create_confname +IF "%1"=="-s" goto set_create_shards +IF "%1"=="-shards" goto set_create_shards +IF "%1"=="-rf" goto set_create_rf +IF "%1"=="-replicationFactor" goto set_create_rf +IF "%1"=="-p" goto set_create_port +IF "%1"=="-port" goto set_create_port +IF "%1"=="-help" goto usage +IF "%1"=="-usage" goto usage +IF "%1"=="/?" goto usage +goto run_create + + +:set_create_verbose +set CREATE_VERBOSE="-verbose" +SHIFT +goto parse_create_args + +:set_create_name +set CREATE_NAME=%~2 +SHIFT +SHIFT +goto parse_create_args + +:set_create_confdir +set CREATE_CONFDIR=%~2 +SHIFT +SHIFT +goto parse_create_args + +:set_create_confname +set CREATE_CONFNAME=%~2 +SHIFT +SHIFT +goto parse_create_args + +:set_create_port +set CREATE_PORT=%~2 +SHIFT +SHIFT +goto parse_create_args + +:set_create_shards +set CREATE_NUM_SHARDS=%~2 +SHIFT +SHIFT +goto parse_create_args + +:set_create_rf +set CREATE_REPFACT=%~2 +SHIFT +SHIFT +goto parse_create_args + +:run_create +IF "!CREATE_NAME!"=="" ( + set "SCRIPT_ERROR=Name (-c) is a required parameter for %SCRIPT_CMD%" + goto invalid_cmd_line +) +IF NOT DEFINED CREATE_VERBOSE set "CREATE_VERBOSE=" +IF "!CREATE_CONFDIR!"=="" set CREATE_CONFDIR=_default +IF "!CREATE_NUM_SHARDS!"=="" set CREATE_NUM_SHARDS=1 +IF "!CREATE_REPFACT!"=="" set CREATE_REPFACT=1 +IF "!CREATE_CONFNAME!"=="" set CREATE_CONFNAME=!CREATE_NAME! + +REM Find a port that Solr is running on +if "!CREATE_PORT!"=="" ( + for /f "usebackq" %%i in (`dir /b "%SOLR_LOGS_DIR%" ^| findstr /i "^solr-.*\.port$"`) do ( + set SOME_SOLR_PORT= + For /F "Delims=" %%J In ('type "%SOLR_TIP%\bin\%%i"') do set SOME_SOLR_PORT=%%~J + if NOT "!SOME_SOLR_PORT!"=="" ( + for /f "tokens=2,5" %%j in ('netstat -aon ^| find "TCP " ^| find ":0 " ^| find ":!SOME_SOLR_PORT! "') do ( + IF NOT "%%k"=="0" set CREATE_PORT=!SOME_SOLR_PORT! + ) + ) + ) +) +if "!CREATE_PORT!"=="" ( + set "SCRIPT_ERROR=Could not find a running Solr instance on this host! Please use the -p option to specify the port." + goto err +) + +if "!CREATE_CONFDIR!"=="_default" ( + echo WARNING: Using _default configset with data driven schema functionality. NOT RECOMMENDED for production use. + echo To turn off: bin\solr config -c !CREATE_NAME! -p !CREATE_PORT! -action set-user-property -property update.autoCreateFields -value false +) + +if "%SCRIPT_CMD%"=="create_core" ( + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI create_core -name !CREATE_NAME! -solrUrl !SOLR_URL_SCHEME!://%SOLR_TOOL_HOST%:!CREATE_PORT!/solr ^ + -confdir !CREATE_CONFDIR! -configsetsDir "%SOLR_TIP%\server\solr\configsets" %CREATE_VERBOSE% +) else ( + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" -Dsolr.default.confdir="%DEFAULT_CONFDIR%"^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI create -name !CREATE_NAME! -shards !CREATE_NUM_SHARDS! -replicationFactor !CREATE_REPFACT! ^ + -confname !CREATE_CONFNAME! -confdir !CREATE_CONFDIR! -configsetsDir "%SOLR_TIP%\server\solr\configsets" ^ + -solrUrl !SOLR_URL_SCHEME!://%SOLR_TOOL_HOST%:!CREATE_PORT!/solr %CREATE_VERBOSE% +) + +goto done + +:parse_delete_args +IF [%1]==[] goto run_delete +IF "%1"=="-V" goto set_delete_verbose +IF "%1"=="-c" goto set_delete_name +IF "%1"=="-core" goto set_delete_name +IF "%1"=="-collection" goto set_delete_name +IF "%1"=="-p" goto set_delete_port +IF "%1"=="-port" goto set_delete_port +IF "%1"=="-deleteConfig" goto set_delete_config +IF "%1"=="-help" goto usage +IF "%1"=="-usage" goto usage +IF "%1"=="/?" goto usage +goto run_delete + +:set_delete_verbose +set DELETE_VERBOSE="-verbose" +SHIFT +goto parse_delete_args + +:set_delete_name +set DELETE_NAME=%~2 +SHIFT +SHIFT +goto parse_delete_args + +:set_delete_port +set DELETE_PORT=%~2 +SHIFT +SHIFT +goto parse_delete_args + +:set_delete_config +set DELETE_CONFIG=%~2 +SHIFT +SHIFT +goto parse_delete_args + +:run_delete +IF NOT DEFINED DELETE_VERBOSE set "DELETE_VERBOSE=" +IF "!DELETE_NAME!"=="" ( + set "SCRIPT_ERROR=Name (-c) is a required parameter for %SCRIPT_CMD%" + goto invalid_cmd_line +) + +REM Find a port that Solr is running on +if "!DELETE_PORT!"=="" ( + for /f "usebackq" %%i in (`dir /b "%SOLR_LOGS_DIR%" ^| findstr /i "^solr-.*\.port$"`) do ( + set SOME_SOLR_PORT= + For /F "Delims=" %%J In ('type "%SOLR_TIP%\bin\%%i"') do set SOME_SOLR_PORT=%%~J + if NOT "!SOME_SOLR_PORT!"=="" ( + for /f "tokens=2,5" %%j in ('netstat -aon ^| find "TCP " ^| find ":0 " ^| find ":!SOME_SOLR_PORT! "') do ( + IF NOT "%%k"=="0" set DELETE_PORT=!SOME_SOLR_PORT! + ) + ) + ) +) +if "!DELETE_PORT!"=="" ( + set "SCRIPT_ERROR=Could not find a running Solr instance on this host! Please use the -p option to specify the port." + goto err +) + +if "!DELETE_CONFIG!"=="" ( + set DELETE_CONFIG=true +) + +"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ +-Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ +-classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ +org.apache.solr.util.SolrCLI delete -name !DELETE_NAME! -deleteConfig !DELETE_CONFIG! ^ +-solrUrl !SOLR_URL_SCHEME!://%SOLR_TOOL_HOST%:!DELETE_PORT!/solr %DELETE_VERBOSE% + +goto done + +REM Clumsy to do the state machine thing for -d and -n, but that's required for back-compat +:parse_zk_args +IF "%1"=="-upconfig" ( + goto set_zk_op +) ELSE IF "%1"=="-V" ( + goto set_zk_verbose +) ELSE IF "%1"=="upconfig" ( + goto set_zk_op +) ELSE IF "%1"=="-downconfig" ( + goto set_zk_op +) ELSE IF "%1"=="downconfig" ( + goto set_zk_op +) ELSE IF "%1"=="cp" ( + goto set_zk_op +) ELSE IF "%1"=="mv" ( + goto set_zk_op +) ELSE IF "%1"=="rm" ( + goto set_zk_op +) ELSE IF "%1"=="ls" ( + goto set_zk_op +) ELSE IF "%1"=="mkroot" ( + goto set_zk_op +) ELSE IF "%1"=="-n" ( + goto set_config_name +) ELSE IF "%1"=="-r" ( + goto set_zk_recurse +) ELSE IF "%1"=="-configname" ( + goto set_config_name +) ELSE IF "%1"=="-d" ( + goto set_configdir +) ELSE IF "%1"=="-confdir" ( + goto set_configdir +) ELSE IF "%1"=="-z" ( + goto set_config_zk +) ELSE IF "%1"=="/?" ( + goto zk_usage +) ELSE IF "%1"=="-h" ( + goto zk_usage +) ELSE IF "%1"=="-help" ( + goto zk_usage +) ELSE IF "!ZK_SRC!"=="" ( + if not "%~1"=="" ( + goto set_zk_src + ) +) ELSE IF "!ZK_DST!"=="" ( + IF "%ZK_OP%"=="cp" ( + goto set_zk_dst + ) + IF "%ZK_OP%"=="mv" ( + goto set_zk_dst + ) + set ZK_DST="_" +) ELSE IF NOT "%1"=="" ( + set ERROR_MSG="Unrecognized or misplaced zk argument %1%" + goto zk_short_usage +) +goto run_zk + +:set_zk_op +set ZK_OP=%~1 +SHIFT +goto parse_zk_args + +:set_zk_verbose +set ZK_VERBOSE="-verbose" +SHIFT +goto parse_zk_args + +:set_config_name +set CONFIGSET_NAME=%~2 +SHIFT +SHIFT +goto parse_zk_args + +:set_configdir +set CONFIGSET_DIR=%~2 +SHIFT +SHIFT +goto parse_zk_args + +:set_config_zk +set ZK_HOST=%~2 +SHIFT +SHIFT +goto parse_zk_args + +:set_zk_src +set ZK_SRC=%~1 +SHIFT +goto parse_zk_args + +:set_zk_dst +set ZK_DST=%~1 +SHIFT +goto parse_zk_args + +:set_zk_recurse +set ZK_RECURSE="true" +SHIFT +goto parse_zk_args + +:run_zk +IF "!ZK_OP!"=="" ( + set "ERROR_MSG=Invalid command specified for zk sub-command" + goto zk_short_usage +) + +IF "!ZK_HOST!"=="" ( + set "ERROR_MSG=Must specify -z zkHost" + goto zk_short_usage +) + +IF "!ZK_OP!"=="-upconfig" ( + set ZK_OP="upconfig" +) +IF "!ZK_OP!"=="-downconfig" ( + set ZK_OP="downconfig" +) + +IF "!ZK_OP!"=="upconfig" ( + IF "!CONFIGSET_NAME!"=="" ( + set ERROR_MSG="-n option must be set for upconfig" + goto zk_short_usage + ) + IF "!CONFIGSET_DIR!"=="" ( + set ERROR_MSG="The -d option must be set for upconfig." + goto zk_short_usage + ) + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI !ZK_OP! -confname !CONFIGSET_NAME! -confdir !CONFIGSET_DIR! -zkHost !ZK_HOST! %ZK_VERBOSE%^ + -configsetsDir "%SOLR_TIP%/server/solr/configsets" +) ELSE IF "!ZK_OP!"=="downconfig" ( + IF "!CONFIGSET_NAME!"=="" ( + set ERROR_MSG="-n option must be set for downconfig" + goto zk_short_usage + ) + IF "!CONFIGSET_DIR!"=="" ( + set ERROR_MSG="The -d option must be set for downconfig." + goto zk_short_usage + ) + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI !ZK_OP! -confname !CONFIGSET_NAME! -confdir !CONFIGSET_DIR! -zkHost !ZK_HOST! %ZK_VERBOSE% +) ELSE IF "!ZK_OP!"=="cp" ( + IF "%ZK_SRC%"=="" ( + set ERROR_MSG=" must be specified for 'cp' command" + goto zk_short_usage + ) + IF "%ZK_DST%"=="" ( + set ERROR_MSG= must be specified for 'cp' command" + goto zk_short_usage + ) + IF NOT "!ZK_SRC:~0,3!"=="zk:" ( + IF NOT "!%ZK_DST:~0,3!"=="zk:" ( + set ERROR_MSG="At least one of src or dst must be prefixed by 'zk:'" + goto zk_short_usage + ) + ) + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI !ZK_OP! -zkHost !ZK_HOST! -src !ZK_SRC! -dst !ZK_DST! -recurse !ZK_RECURSE! %ZK_VERBOSE% +) ELSE IF "!ZK_OP!"=="mv" ( + IF "%ZK_SRC%"=="" ( + set ERROR_MSG=" must be specified for 'mv' command" + goto zk_short_usage + ) + IF "%ZK_DST%"=="" ( + set ERROR_MSG=" must be specified for 'mv' command" + goto zk_short_usage + ) + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI !ZK_OP! -zkHost !ZK_HOST! -src !ZK_SRC! -dst !ZK_DST! %ZK_VERBOSE% +) ELSE IF "!ZK_OP!"=="rm" ( + IF "%ZK_SRC"=="" ( + set ERROR_MSG="Zookeeper path to remove must be specified when using the 'rm' command" + goto zk_short_usage + ) + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI !ZK_OP! -zkHost !ZK_HOST! -path !ZK_SRC! -recurse !ZK_RECURSE! %ZK_VERBOSE% +) ELSE IF "!ZK_OP!"=="ls" ( + IF "%ZK_SRC"=="" ( + set ERROR_MSG="Zookeeper path to remove must be specified when using the 'ls' command" + goto zk_short_usage + ) + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI !ZK_OP! -zkHost !ZK_HOST! -path !ZK_SRC! -recurse !ZK_RECURSE! %ZK_VERBOSE% +) ELSE IF "!ZK_OP!"=="mkroot" ( + IF "%ZK_SRC"=="" ( + set ERROR_MSG="Zookeeper path to create must be specified when using the 'mkroot' command" + goto zk_short_usage + ) + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%SOLR_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI !ZK_OP! -zkHost !ZK_HOST! -path !ZK_SRC! %ZK_VERBOSE% +) ELSE ( + set ERROR_MSG="Unknown zk option !ZK_OP!" + goto zk_short_usage +) +goto done + + +:run_auth +IF "%1"=="-help" goto usage +IF "%1"=="-usage" goto usage + +REM Options parsing. +REM Note: With the following technique of parsing, it is not possible +REM to have an option without a value. +set "AUTH_PARAMS=%1" +set "option=" +for %%a in (%*) do ( + if not defined option ( + set arg=%%a + if "!arg:~0,1!" equ "-" set "option=!arg!" + ) else ( + set "option!option!=%%a" + if "!option!" equ "-d" set "SOLR_SERVER_DIR=%%a" + if "!option!" equ "-s" set "SOLR_HOME=%%a" + if not "!option!" equ "-s" if not "!option!" equ "-d" ( + set "AUTH_PARAMS=!AUTH_PARAMS! !option! %%a" + ) + set "option=" + ) +) +IF "%SOLR_SERVER_DIR%"=="" set "SOLR_SERVER_DIR=%DEFAULT_SERVER_DIR%" +IF NOT EXIST "%SOLR_SERVER_DIR%" ( + set "SCRIPT_ERROR=Solr server directory %SOLR_SERVER_DIR% not found!" + goto err +) +IF "%SOLR_HOME%"=="" set "SOLR_HOME=%SOLR_SERVER_DIR%\solr" +IF EXIST "%cd%\%SOLR_HOME%" set "SOLR_HOME=%cd%\%SOLR_HOME%" +IF NOT EXIST "%SOLR_HOME%\" ( + IF EXIST "%SOLR_SERVER_DIR%\%SOLR_HOME%" ( + set "SOLR_HOME=%SOLR_SERVER_DIR%\%SOLR_HOME%" + ) ELSE ( + set "SCRIPT_ERROR=Solr home directory %SOLR_HOME% not found!" + goto err + ) +) + +if "!AUTH_PORT!"=="" ( + for /f "usebackq" %%i in (`dir /b "%SOLR_TIP%\bin" ^| findstr /i "^solr-.*\.port$"`) do ( + set SOME_SOLR_PORT= + For /F "Delims=" %%J In ('type "%SOLR_TIP%\bin\%%i"') do set SOME_SOLR_PORT=%%~J + if NOT "!SOME_SOLR_PORT!"=="" ( + for /f "tokens=2,5" %%j in ('netstat -aon ^| find "TCP " ^| find ":0 " ^| find ":!SOME_SOLR_PORT! "') do ( + IF NOT "%%k"=="0" set AUTH_PORT=!SOME_SOLR_PORT! + ) + ) + ) +) +"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI auth %AUTH_PARAMS% -solrIncludeFile "%SOLR_INCLUDE%" -authConfDir "%SOLR_HOME%" ^ + -solrUrl !SOLR_URL_SCHEME!://%SOLR_TOOL_HOST%:!AUTH_PORT!/solr +goto done + + +:invalid_cmd_line +@echo. +IF "!SCRIPT_ERROR!"=="" ( + @echo Invalid command-line option: %1 +) ELSE ( + @echo ERROR: !SCRIPT_ERROR! +) +@echo. +IF "%FIRST_ARG%"=="start" ( + goto start_usage +) ELSE IF "%FIRST_ARG:~0,1%" == "-" ( + goto start_usage +) ELSE IF "%FIRST_ARG%"=="restart" ( + goto start_usage +) ELSE IF "%FIRST_ARG%"=="stop" ( + goto stop_usage +) ELSE IF "%FIRST_ARG%"=="healthcheck" ( + goto healthcheck_usage +) ELSE IF "%FIRST_ARG%"=="create" ( + goto create_usage +) ELSE IF "%FIRST_ARG%"=="create_core" ( + goto create_core_usage +) ELSE IF "%FIRST_ARG%"=="create_collection" ( + goto create_collection_usage +) ELSE IF "%FIRST_ARG%"=="zk" ( + goto zk_short_usage +) ELSE IF "%FIRST_ARG%"=="auth" ( + goto auth_usage +) ELSE IF "%FIRST_ARG%"=="status" ( + goto status_usage +) ELSE ( + goto script_usage +) + +:need_java_home +@echo Please set the JAVA_HOME environment variable to the path where you installed Java 1.8+ +goto done + +:need_java_vers +@echo Java 1.8 or later is required to run Solr. +goto done + +:err +@echo. +@echo ERROR: !SCRIPT_ERROR! +@echo. +exit /b 1 + +:done +ENDLOCAL +exit /b 0 + +REM Tests what Java we have and sets some global variables +:resolve_java_info + +CALL :resolve_java_vendor + +set JAVA_MAJOR_VERSION=0 +set JAVA_VERSION_INFO= +set JAVA_BUILD=0 + +FOR /f "usebackq tokens=3" %%a IN (`^""%JAVA%" -version 2^>^&1 ^| findstr "version"^"`) do ( + set JAVA_VERSION_INFO=%%a + REM Remove surrounding quotes + set JAVA_VERSION_INFO=!JAVA_VERSION_INFO:"=! + + REM Extract the major Java version, e.g. 7, 8, 9, 10 ... + for /f "tokens=1,2 delims=._-" %%a in ("!JAVA_VERSION_INFO!") do ( + if %%a GEQ 9 ( + set JAVA_MAJOR_VERSION=%%a + ) else ( + set JAVA_MAJOR_VERSION=%%b + ) + ) + + REM Don't look for "_{build}" if we're on IBM J9. + if NOT "%JAVA_VENDOR%" == "IBM J9" ( + for /f "delims=_ tokens=2" %%a in ("!JAVA_VERSION_INFO!") do ( + set /a JAVA_BUILD=%%a + ) + ) +) +GOTO :eof + +REM Set which JVM vendor we have +:resolve_java_vendor +"%JAVA%" -version 2>&1 | findstr /i "IBM J9" > nul +if %ERRORLEVEL% == 1 ( set "JAVA_VENDOR=Oracle" ) else ( set "JAVA_VENDOR=IBM J9" ) + +set JAVA_VENDOR_OUT= +GOTO :eof + +REM Safe echo which does not mess with () in strings +:safe_echo +set "eout=%1" +set eout=%eout:"=% +echo !eout! +GOTO :eof diff --git a/KeywordSearch/solr/bin/autopsy-solr.in.cmd b/KeywordSearch/solr/bin/autopsy-solr.in.cmd new file mode 100755 index 0000000000..295059b83a --- /dev/null +++ b/KeywordSearch/solr/bin/autopsy-solr.in.cmd @@ -0,0 +1,173 @@ +@REM +@REM Licensed to the Apache Software Foundation (ASF) under one or more +@REM contributor license agreements. See the NOTICE file distributed with +@REM this work for additional information regarding copyright ownership. +@REM The ASF licenses this file to You under the Apache License, Version 2.0 +@REM (the "License"); you may not use this file except in compliance with +@REM the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, software +@REM distributed under the License is distributed on an "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@REM See the License for the specific language governing permissions and +@REM limitations under the License. + +@REM @echo off + +REM Settings here will override settings in existing env vars or in bin/solr. The default shipped state +REM of this file is completely commented. + +REM By default the script will use JAVA_HOME to determine which java +REM to use, but you can set a specific path for Solr to use without +REM affecting other Java applications on your server/workstation. +REM set SOLR_JAVA_HOME= + +REM Increase Java Min/Max Heap as needed to support your indexing / query needs +REM set SOLR_JAVA_MEM=-Xms512m -Xmx512m + +REM Configure verbose GC logging: +REM For Java 8: if this is set, additional params will be added to specify the log file & rotation +REM For Java 9 or higher: GC_LOG_OPTS is currently not supported. If you set it, the startup script will exit with failure. +REM set GC_LOG_OPTS=-verbose:gc -XX:+PrintHeapAtGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+PrintTenuringDistribution -XX:+PrintGCApplicationStoppedTime + +REM Various GC settings have shown to work well for a number of common Solr workloads. +REM See solr.cmd GC_TUNE for the default list. +REM set GC_TUNE=-XX:SurvivorRatio=4 +REM set GC_TUNE=%GC_TUNE% -XX:TargetSurvivorRatio=90 +REM set GC_TUNE=%GC_TUNE% -XX:MaxTenuringThreshold=8 +REM set GC_TUNE=%GC_TUNE% -XX:+UseConcMarkSweepGC +REM set GC_TUNE=%GC_TUNE% -XX:ConcGCThreads=4 +REM set GC_TUNE=%GC_TUNE% -XX:ParallelGCThreads=4 +REM set GC_TUNE=%GC_TUNE% -XX:+CMSScavengeBeforeRemark +REM set GC_TUNE=%GC_TUNE% -XX:PretenureSizeThreshold=64m +REM set GC_TUNE=%GC_TUNE% -XX:+UseCMSInitiatingOccupancyOnly +REM set GC_TUNE=%GC_TUNE% -XX:CMSInitiatingOccupancyFraction=50 +REM set GC_TUNE=%GC_TUNE% -XX:CMSMaxAbortablePrecleanTime=6000 +REM set GC_TUNE=%GC_TUNE% -XX:+CMSParallelRemarkEnabled +REM set GC_TUNE=%GC_TUNE% -XX:+ParallelRefProcEnabled +REM set GC_TUNE=%GC_TUNE% -XX:-OmitStackTraceInFastThrow etc. + +REM Set the ZooKeeper connection string if using an external ZooKeeper ensemble +REM e.g. host1:2181,host2:2181/chroot +REM Leave empty if not using SolrCloud +REM set ZK_HOST= + +REM Set the ZooKeeper client timeout (for SolrCloud mode) +REM set ZK_CLIENT_TIMEOUT=15000 + +REM By default the start script uses "localhost"; override the hostname here +REM for production SolrCloud environments to control the hostname exposed to cluster state +REM set SOLR_HOST=192.168.1.1 + +REM By default Solr will try to connect to Zookeeper with 30 seconds in timeout; override the timeout if needed +REM set SOLR_WAIT_FOR_ZK=30 + +REM By default the start script uses UTC; override the timezone if needed +REM set SOLR_TIMEZONE=UTC + +REM Set to true to activate the JMX RMI connector to allow remote JMX client applications +REM to monitor the JVM hosting Solr; set to "false" to disable that behavior +REM (false is recommended in production environments) +REM set ENABLE_REMOTE_JMX_OPTS=false + +REM The script will use SOLR_PORT+10000 for the RMI_PORT or you can set it here +REM set RMI_PORT=18983 + +REM Anything you add to the SOLR_OPTS variable will be included in the java +REM start command line as-is, in ADDITION to other options. If you specify the +REM -a option on start script, those options will be appended as well. Examples: +set SOLR_OPTS=%SOLR_OPTS% -Dbootstrap_confdir=../solr/configsets/AutopsyConfig/conf -Dcollection.configName=AutopsyConfig -Dsolr.default.confdir=../solr/configsets/AutopsyConfig/conf + +REM Path to a directory for Solr to store cores and their data. By default, Solr will use server\solr +REM If solr.xml is not stored in ZooKeeper, this directory needs to contain solr.xml +REM set SOLR_HOME= + +REM Path to a directory that Solr will use as root for data folders for each core. +REM If not set, defaults to /data. Overridable per core through 'dataDir' core property +REM set SOLR_DATA_HOME= + +REM Changes the logging level. Valid values: ALL, TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF. Default is INFO +REM This is an alternative to changing the rootLogger in log4j2.xml +REM set SOLR_LOG_LEVEL=INFO + +REM Location where Solr should write logs to. Absolute or relative to solr start dir +REM set SOLR_LOGS_DIR=logs + +REM Enables log rotation before starting Solr. Setting SOLR_LOG_PRESTART_ROTATION=true will let Solr take care of pre +REM start rotation of logs. This is false by default as log4j2 handles this for us. If you choose to use another log +REM framework that cannot do startup rotation, you may want to enable this to let Solr rotate logs on startup. +REM set SOLR_LOG_PRESTART_ROTATION=false + +REM Set the host interface to listen on. Jetty will listen on all interfaces (0.0.0.0) by default. +REM This must be an IPv4 ("a.b.c.d") or bracketed IPv6 ("[x::y]") address, not a hostname! +REM set SOLR_JETTY_HOST=0.0.0.0 + +REM Sets the port Solr binds to, default is 8983 +REM set SOLR_PORT=8983 + +REM Enables HTTPS. It is implictly true if you set SOLR_SSL_KEY_STORE. Use this config +REM to enable https module with custom jetty configuration. +REM set SOLR_SSL_ENABLED=true +REM Uncomment to set SSL-related system properties +REM Be sure to update the paths to the correct keystore for your environment +REM set SOLR_SSL_KEY_STORE=etc/solr-ssl.keystore.jks +REM set SOLR_SSL_KEY_STORE_PASSWORD=secret +REM set SOLR_SSL_TRUST_STORE=etc/solr-ssl.keystore.jks +REM set SOLR_SSL_TRUST_STORE_PASSWORD=secret +REM Require clients to authenticate +REM set SOLR_SSL_NEED_CLIENT_AUTH=false +REM Enable clients to authenticate (but not require) +REM set SOLR_SSL_WANT_CLIENT_AUTH=false +REM SSL Certificates contain host/ip "peer name" information that is validated by default. Setting +REM this to false can be useful to disable these checks when re-using a certificate on many hosts +REM set SOLR_SSL_CHECK_PEER_NAME=true +REM Override Key/Trust Store types if necessary +REM set SOLR_SSL_KEY_STORE_TYPE=JKS +REM set SOLR_SSL_TRUST_STORE_TYPE=JKS + +REM Uncomment if you want to override previously defined SSL values for HTTP client +REM otherwise keep them commented and the above values will automatically be set for HTTP clients +REM set SOLR_SSL_CLIENT_KEY_STORE= +REM set SOLR_SSL_CLIENT_KEY_STORE_PASSWORD= +REM set SOLR_SSL_CLIENT_TRUST_STORE= +REM set SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD= +REM set SOLR_SSL_CLIENT_KEY_STORE_TYPE= +REM set SOLR_SSL_CLIENT_TRUST_STORE_TYPE= + +REM Sets path of Hadoop credential provider (hadoop.security.credential.provider.path property) and +REM enables usage of credential store. +REM Credential provider should store the following keys: +REM * solr.jetty.keystore.password +REM * solr.jetty.truststore.password +REM Set the two below if you want to set specific store passwords for HTTP client +REM * javax.net.ssl.keyStorePassword +REM * javax.net.ssl.trustStorePassword +REM More info: https://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-common/CredentialProviderAPI.html +REM set SOLR_HADOOP_CREDENTIAL_PROVIDER_PATH=localjceks://file/home/solr/hadoop-credential-provider.jceks +REM set SOLR_OPTS=" -Dsolr.ssl.credential.provider.chain=hadoop" + +REM Settings for authentication +REM Please configure only one of SOLR_AUTHENTICATION_CLIENT_BUILDER or SOLR_AUTH_TYPE parameters +REM set SOLR_AUTHENTICATION_CLIENT_BUILDER=org.apache.solr.client.solrj.impl.PreemptiveBasicAuthClientBuilderFactory +REM set SOLR_AUTH_TYPE=basic +REM set SOLR_AUTHENTICATION_OPTS="-Dbasicauth=solr:SolrRocks" + +REM Settings for ZK ACL +REM set SOLR_ZK_CREDS_AND_ACLS=-DzkACLProvider=org.apache.solr.common.cloud.VMParamsAllAndReadonlyDigestZkACLProvider ^ +REM -DzkCredentialsProvider=org.apache.solr.common.cloud.VMParamsSingleSetCredentialsDigestZkCredentialsProvider ^ +REM -DzkDigestUsername=admin-user -DzkDigestPassword=CHANGEME-ADMIN-PASSWORD ^ +REM -DzkDigestReadonlyUsername=readonly-user -DzkDigestReadonlyPassword=CHANGEME-READONLY-PASSWORD +REM set SOLR_OPTS=%SOLR_OPTS% %SOLR_ZK_CREDS_AND_ACLS% + +REM When running Solr in non-cloud mode and if planning to do distributed search (using the "shards" parameter), the +REM list of hosts needs to be whitelisted or Solr will forbid the request. The whitelist can be configured in solr.xml, +REM or if you are using the OOTB solr.xml, can be specified using the system property "solr.shardsWhitelist". Alternatively +REM host checking can be disabled by using the system property "solr.disable.shardsWhitelist" +REM set SOLR_OPTS="%SOLR_OPTS% -Dsolr.shardsWhitelist=http://localhost:8983,http://localhost:8984" + +REM For a visual indication in the Admin UI of what type of environment this cluster is, configure +REM a -Dsolr.environment property below. Valid values are prod, stage, test, dev, with an optional +REM label or color, e.g. -Dsolr.environment=test,label=Functional+test,color=brown +REM SOLR_OPTS="$SOLR_OPTS -Dsolr.environment=prod" diff --git a/KeywordSearch/solr/bin/init.d/solr b/KeywordSearch/solr/bin/init.d/solr new file mode 100755 index 0000000000..e73e0d6830 --- /dev/null +++ b/KeywordSearch/solr/bin/init.d/solr @@ -0,0 +1,78 @@ +#!/bin/sh +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +### BEGIN INIT INFO +# Provides: solr +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Description: Controls Apache Solr as a Service +### END INIT INFO + +# Example of a very simple *nix init script that delegates commands to the bin/solr script +# Typical usage is to do: +# +# cp bin/init.d/solr /etc/init.d/solr +# chmod 755 /etc/init.d/solr +# chown root:root /etc/init.d/solr +# update-rc.d solr defaults +# update-rc.d solr enable + +# Where you extracted the Solr distribution bundle +SOLR_INSTALL_DIR="/opt/solr" + +if [ ! -d "$SOLR_INSTALL_DIR" ]; then + echo "$SOLR_INSTALL_DIR not found! Please check the SOLR_INSTALL_DIR setting in your $0 script." + exit 1 +fi + +# Path to an include file that defines environment specific settings to override default +# variables used by the bin/solr script. It's highly recommended to define this script so +# that you can keep the Solr binary files separated from live files (pid, logs, index data, etc) +# see bin/solr.in.sh for an example +SOLR_ENV="/etc/default/solr.in.sh" + +if [ ! -f "$SOLR_ENV" ]; then + echo "$SOLR_ENV not found! Please check the SOLR_ENV setting in your $0 script." + exit 1 +fi + +# Specify the user to run Solr as; if not set, then Solr will run as root. +# Running Solr as root is not recommended for production environments +RUNAS="solr" + +# verify the specified run as user exists +runas_uid="`id -u "$RUNAS"`" +if [ $? -ne 0 ]; then + echo "User $RUNAS not found! Please create the $RUNAS user before running this script." + exit 1 +fi + +case "$1" in + start|stop|restart|status) + SOLR_CMD="$1" + ;; + *) + echo "Usage: $0 {start|stop|restart|status}" + exit +esac + +if [ -n "$RUNAS" ]; then + su -c "SOLR_INCLUDE=\"$SOLR_ENV\" \"$SOLR_INSTALL_DIR/bin/solr\" $SOLR_CMD" - "$RUNAS" +else + SOLR_INCLUDE="$SOLR_ENV" "$SOLR_INSTALL_DIR/bin/solr" "$SOLR_CMD" +fi diff --git a/KeywordSearch/solr/bin/install_solr_service.sh b/KeywordSearch/solr/bin/install_solr_service.sh new file mode 100755 index 0000000000..6cfb6a578e --- /dev/null +++ b/KeywordSearch/solr/bin/install_solr_service.sh @@ -0,0 +1,370 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +if [[ $EUID -ne 0 ]]; then + echo -e "\nERROR: This script must be run as root\n" 1>&2 + exit 1 +fi + +print_usage() { + ERROR_MSG="$1" + + if [ "$ERROR_MSG" != "" ]; then + echo -e "\nERROR: $ERROR_MSG\n" 1>&2 + fi + + echo "" + echo "Usage: install_solr_service.sh [OPTIONS]" + echo "" + echo " The first argument to the script must be a path to a Solr distribution archive, such as solr-5.0.0.tgz" + echo " (only .tgz or .zip are supported formats for the archive)" + echo "" + echo " Supported OPTIONS include:" + echo "" + echo " -d Directory for live / writable Solr files, such as logs, pid files, and index data; defaults to /var/solr" + echo "" + echo " -i Directory to extract the Solr installation archive; defaults to /opt/" + echo " The specified path must exist prior to using this script." + echo "" + echo " -p Port Solr should bind to; default is 8983" + echo "" + echo " -s Service name; defaults to solr" + echo "" + echo " -u User to own the Solr files and run the Solr process as; defaults to solr" + echo " This script will create the specified user account if it does not exist." + echo "" + echo " -f Upgrade Solr. Overwrite symlink and init script of previous installation." + echo "" + echo " -n Do not start Solr service after install, and do not abort on missing Java" + echo "" + echo " NOTE: Must be run as the root user" + echo "" +} # end print_usage + +print_error() { + echo $1 + exit 1 +} + +# Locate *NIX distribution by looking for match from various detection strategies +# We start with /etc/os-release, as this will also work for Docker containers +for command in "grep -E \"^NAME=\" /etc/os-release" \ + "lsb_release -i" \ + "cat /proc/version" \ + "uname -a" ; do + distro_string=$(eval $command 2>/dev/null) + unset distro + if [[ ${distro_string,,} == *"debian"* ]]; then + distro=Debian + elif [[ ${distro_string,,} == *"red hat"* ]]; then + distro=RedHat + elif [[ ${distro_string,,} == *"centos"* ]]; then + distro=CentOS + elif [[ ${distro_string,,} == *"ubuntu"* ]]; then + distro=Ubuntu + elif [[ ${distro_string,,} == *"suse"* ]]; then + distro=SUSE + elif [[ ${distro_string,,} == *"darwin"* ]]; then + echo "Sorry, this script does not support macOS. You'll need to setup Solr as a service manually using the documentation provided in the Solr Reference Guide." + echo "You could also try installing via Homebrew (http://brew.sh/), e.g. brew install solr" + exit 1 + fi + if [[ $distro ]] ; then break ; fi +done +if [[ ! $distro ]] ; then + echo -e "\nERROR: Unable to auto-detect your *NIX distribution!\nYou'll need to setup Solr as a service manually using the documentation provided in the Solr Reference Guide.\n" 1>&2 + exit 1 +fi + +if [ -z "$1" ]; then + print_usage "Must specify the path to the Solr installation archive, such as solr-5.0.0.tgz" + exit 1 +fi + +SOLR_ARCHIVE=$1 +if [ ! -f "$SOLR_ARCHIVE" ]; then + print_usage "Specified Solr installation archive $SOLR_ARCHIVE not found!" + exit 1 +fi + +# strip off path info +SOLR_INSTALL_FILE=${SOLR_ARCHIVE##*/} +is_tar=true +if [ ${SOLR_INSTALL_FILE: -4} == ".tgz" ]; then + SOLR_DIR=${SOLR_INSTALL_FILE%.tgz} +elif [ ${SOLR_INSTALL_FILE: -4} == ".zip" ]; then + SOLR_DIR=${SOLR_INSTALL_FILE%.zip} + is_tar=false +else + print_usage "Solr installation archive $SOLR_ARCHIVE is invalid, expected a .tgz or .zip file!" + exit 1 +fi + +SOLR_START=true +if [ $# -gt 1 ]; then + shift + while true; do + case $1 in + -i) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "Directory path is required when using the $1 option!" + exit 1 + fi + SOLR_EXTRACT_DIR=$2 + shift 2 + ;; + -d) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "Directory path is required when using the $1 option!" + exit 1 + fi + SOLR_VAR_DIR="$2" + shift 2 + ;; + -u) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "Username is required when using the $1 option!" + exit 1 + fi + SOLR_USER="$2" + shift 2 + ;; + -s) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "Service name is required when using the $1 option!" + exit 1 + fi + SOLR_SERVICE="$2" + shift 2 + ;; + -p) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "Port is required when using the $1 option!" + exit 1 + fi + SOLR_PORT="$2" + shift 2 + ;; + -f) + SOLR_UPGRADE="YES" + shift 1 + ;; + -n) + SOLR_START=false + shift 1 + ;; + -help|-usage) + print_usage "" + exit 0 + ;; + --) + shift + break + ;; + *) + if [ "$1" != "" ]; then + print_usage "Unrecognized or misplaced argument: $1!" + exit 1 + else + break # out-of-args, stop looping + fi + ;; + esac + done +fi + +# Test for availability of needed tools +if [[ $is_tar ]] ; then + tar --version &>/dev/null || print_error "Script requires the 'tar' command" +else + unzip -hh &>/dev/null || print_error "Script requires the 'unzip' command" +fi +if [[ $SOLR_START == "true" ]] ; then + service --version &>/dev/null || service --help &>/dev/null || print_error "Script requires the 'service' command" + java -version &>/dev/null || print_error "Solr requires java, please install or set JAVA_HOME properly" +fi +lsof -h &>/dev/null || echo "We recommend installing the 'lsof' command for more stable start/stop of Solr" + + +if [ -z "$SOLR_EXTRACT_DIR" ]; then + SOLR_EXTRACT_DIR=/opt +fi + +if [ ! -d "$SOLR_EXTRACT_DIR" ]; then + print_usage "Installation directory $SOLR_EXTRACT_DIR not found! Please create it before running this script." + exit 1 +fi + +if [ -z "$SOLR_SERVICE" ]; then + SOLR_SERVICE=solr +fi + +if [ -z "$SOLR_VAR_DIR" ]; then + SOLR_VAR_DIR="/var/$SOLR_SERVICE" +fi + +if [ -z "$SOLR_USER" ]; then + SOLR_USER=solr +fi + +if [ -z "$SOLR_PORT" ]; then + SOLR_PORT=8983 +fi + +if [ -z "$SOLR_UPGRADE" ]; then + SOLR_UPGRADE=NO +fi + +if [ ! "$SOLR_UPGRADE" = "YES" ]; then + if [ -f "/etc/init.d/$SOLR_SERVICE" ]; then + print_usage "/etc/init.d/$SOLR_SERVICE already exists! Perhaps Solr is already setup as a service on this host? To upgrade Solr use the -f option." + exit 1 + fi + + if [ -e "$SOLR_EXTRACT_DIR/$SOLR_SERVICE" ]; then + print_usage "$SOLR_EXTRACT_DIR/$SOLR_SERVICE already exists! Please move this directory / link or choose a different service name using the -s option." + exit 1 + fi +fi + +# stop running instance +if [ -f "/etc/init.d/$SOLR_SERVICE" ]; then + echo -e "\nStopping Solr instance if exists ...\n" + service "$SOLR_SERVICE" stop +fi + +# create user if not exists +solr_uid="`id -u "$SOLR_USER"`" +if [ $? -ne 0 ]; then + echo "Creating new user: $SOLR_USER" + if [ "$distro" == "RedHat" ] || [ "$distro" == "CentOS" ] ; then + adduser --system -U -m --home-dir "$SOLR_VAR_DIR" "$SOLR_USER" + elif [ "$distro" == "SUSE" ]; then + useradd --system -U -m --home-dir "$SOLR_VAR_DIR" "$SOLR_USER" + else + adduser --system --shell /bin/bash --group --disabled-password --home "$SOLR_VAR_DIR" "$SOLR_USER" + fi +fi + +# extract +SOLR_INSTALL_DIR="$SOLR_EXTRACT_DIR/$SOLR_DIR" +if [ ! -d "$SOLR_INSTALL_DIR" ]; then + + echo -e "\nExtracting $SOLR_ARCHIVE to $SOLR_EXTRACT_DIR\n" + + if $is_tar ; then + tar zxf "$SOLR_ARCHIVE" -C "$SOLR_EXTRACT_DIR" + else + unzip -q "$SOLR_ARCHIVE" -d "$SOLR_EXTRACT_DIR" + fi + + if [ ! -d "$SOLR_INSTALL_DIR" ]; then + echo -e "\nERROR: Expected directory $SOLR_INSTALL_DIR not found after extracting $SOLR_ARCHIVE ... script fails.\n" 1>&2 + exit 1 + fi + + chown -R root: "$SOLR_INSTALL_DIR" + find "$SOLR_INSTALL_DIR" -type d -print0 | xargs -0 chmod 0755 + find "$SOLR_INSTALL_DIR" -type f -print0 | xargs -0 chmod 0644 + chmod -R 0755 "$SOLR_INSTALL_DIR/bin" +else + echo -e "\nWARNING: $SOLR_INSTALL_DIR already exists! Skipping extract ...\n" +fi + +# create a symlink for easier scripting +if [ -h "$SOLR_EXTRACT_DIR/$SOLR_SERVICE" ]; then + echo -e "\nRemoving old symlink $SOLR_EXTRACT_DIR/$SOLR_SERVICE ...\n" + rm "$SOLR_EXTRACT_DIR/$SOLR_SERVICE" +fi +if [ -e "$SOLR_EXTRACT_DIR/$SOLR_SERVICE" ]; then + echo -e "\nWARNING: $SOLR_EXTRACT_DIR/$SOLR_SERVICE is not symlink! Skipping symlink update ...\n" +else + echo -e "\nInstalling symlink $SOLR_EXTRACT_DIR/$SOLR_SERVICE -> $SOLR_INSTALL_DIR ...\n" + ln -s "$SOLR_INSTALL_DIR" "$SOLR_EXTRACT_DIR/$SOLR_SERVICE" +fi + +# install init.d script +echo -e "\nInstalling /etc/init.d/$SOLR_SERVICE script ...\n" +cp "$SOLR_INSTALL_DIR/bin/init.d/solr" "/etc/init.d/$SOLR_SERVICE" +chmod 0744 "/etc/init.d/$SOLR_SERVICE" +chown root: "/etc/init.d/$SOLR_SERVICE" +# do some basic variable substitution on the init.d script +sed_expr1="s#SOLR_INSTALL_DIR=.*#SOLR_INSTALL_DIR=\"$SOLR_EXTRACT_DIR/$SOLR_SERVICE\"#" +sed_expr2="s#SOLR_ENV=.*#SOLR_ENV=\"/etc/default/$SOLR_SERVICE.in.sh\"#" +sed_expr3="s#RUNAS=.*#RUNAS=\"$SOLR_USER\"#" +sed_expr4="s#Provides:.*#Provides: $SOLR_SERVICE#" +sed -i -e "$sed_expr1" -e "$sed_expr2" -e "$sed_expr3" -e "$sed_expr4" "/etc/init.d/$SOLR_SERVICE" + +# install/move configuration +if [ ! -d /etc/default ]; then + mkdir /etc/default + chown root: /etc/default + chmod 0755 /etc/default +fi +if [ -f "$SOLR_VAR_DIR/solr.in.sh" ]; then + echo -e "\nMoving existing $SOLR_VAR_DIR/solr.in.sh to /etc/default/$SOLR_SERVICE.in.sh ...\n" + mv "$SOLR_VAR_DIR/solr.in.sh" "/etc/default/$SOLR_SERVICE.in.sh" +elif [ -f "/etc/default/$SOLR_SERVICE.in.sh" ]; then + echo -e "\n/etc/default/$SOLR_SERVICE.in.sh already exist. Skipping install ...\n" +else + echo -e "\nInstalling /etc/default/$SOLR_SERVICE.in.sh ...\n" + cp "$SOLR_INSTALL_DIR/bin/solr.in.sh" "/etc/default/$SOLR_SERVICE.in.sh" + mv "$SOLR_INSTALL_DIR/bin/solr.in.sh" "$SOLR_INSTALL_DIR/bin/solr.in.sh.orig" + mv "$SOLR_INSTALL_DIR/bin/solr.in.cmd" "$SOLR_INSTALL_DIR/bin/solr.in.cmd.orig" + echo "SOLR_PID_DIR=\"$SOLR_VAR_DIR\" +SOLR_HOME=\"$SOLR_VAR_DIR/data\" +LOG4J_PROPS=\"$SOLR_VAR_DIR/log4j2.xml\" +SOLR_LOGS_DIR=\"$SOLR_VAR_DIR/logs\" +SOLR_PORT=\"$SOLR_PORT\" +" >> "/etc/default/$SOLR_SERVICE.in.sh" +fi +chown root:${SOLR_USER} "/etc/default/$SOLR_SERVICE.in.sh" +chmod 0640 "/etc/default/$SOLR_SERVICE.in.sh" + +# install data directories and files +mkdir -p "$SOLR_VAR_DIR/data" +mkdir -p "$SOLR_VAR_DIR/logs" +if [ -f "$SOLR_VAR_DIR/data/solr.xml" ]; then + echo -e "\n$SOLR_VAR_DIR/data/solr.xml already exists. Skipping install ...\n" +else + cp "$SOLR_INSTALL_DIR/server/solr/"{solr.xml,zoo.cfg} "$SOLR_VAR_DIR/data/" +fi +if [ -f "$SOLR_VAR_DIR/log4j2.xml" ]; then + echo -e "\n$SOLR_VAR_DIR/log4j2.xml already exists. Skipping install ...\n" +else + cp "$SOLR_INSTALL_DIR/server/resources/log4j2.xml" "$SOLR_VAR_DIR/log4j2.xml" +fi +chown -R "$SOLR_USER:" "$SOLR_VAR_DIR" +find "$SOLR_VAR_DIR" -type d -print0 | xargs -0 chmod 0750 +find "$SOLR_VAR_DIR" -type f -print0 | xargs -0 chmod 0640 + +# configure autostart of service +if [[ "$distro" == "RedHat" || "$distro" == "CentOS" || "$distro" == "SUSE" ]]; then + chkconfig "$SOLR_SERVICE" on +else + update-rc.d "$SOLR_SERVICE" defaults +fi +echo "Service $SOLR_SERVICE installed." +echo "Customize Solr startup configuration in /etc/default/$SOLR_SERVICE.in.sh" + +# start service +if [[ $SOLR_START == "true" ]] ; then + service "$SOLR_SERVICE" start + sleep 5 + service "$SOLR_SERVICE" status +else + echo "Not starting Solr service (option -n given). Start manually with 'service $SOLR_SERVICE start'" +fi diff --git a/KeywordSearch/solr/bin/oom_solr.sh b/KeywordSearch/solr/bin/oom_solr.sh new file mode 100755 index 0000000000..5ecba6bc30 --- /dev/null +++ b/KeywordSearch/solr/bin/oom_solr.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +SOLR_PORT=$1 +SOLR_LOGS_DIR=$2 +SOLR_PID=`ps auxww | grep start.jar | grep $SOLR_PORT | grep -v grep | awk '{print $2}' | sort -r` +if [ -z "$SOLR_PID" ]; then + echo "Couldn't find Solr process running on port $SOLR_PORT!" + exit +fi +NOW=$(date +"%F_%H_%M_%S") +( +echo "Running OOM killer script for process $SOLR_PID for Solr on port $SOLR_PORT" +kill -9 $SOLR_PID +echo "Killed process $SOLR_PID" +) | tee $SOLR_LOGS_DIR/solr_oom_killer-$SOLR_PORT-$NOW.log diff --git a/KeywordSearch/solr/bin/post b/KeywordSearch/solr/bin/post new file mode 100755 index 0000000000..4c629d1059 --- /dev/null +++ b/KeywordSearch/solr/bin/post @@ -0,0 +1,239 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# ====== Common code copied/adapted from bin/solr (TODO: centralize/share this kind of thing across bin/solr, etc) + +THIS_SCRIPT="$0" + +# Resolve symlinks to this script +while [ -h "$THIS_SCRIPT" ] ; do + ls=`ls -ld "$THIS_SCRIPT"` + # Drop everything prior to -> + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + THIS_SCRIPT="$link" + else + THIS_SCRIPT=`dirname "$THIS_SCRIPT"`/"$link" + fi +done + +SOLR_TIP=`dirname "$THIS_SCRIPT"`/.. +SOLR_TIP=`cd "$SOLR_TIP"; pwd` + +if [ -n "$SOLR_JAVA_HOME" ]; then + JAVA="$SOLR_JAVA_HOME/bin/java" +elif [ -n "$JAVA_HOME" ]; then + for java in "$JAVA_HOME"/bin/amd64/java "$JAVA_HOME"/bin/java; do + if [ -x "$java" ]; then + JAVA="$java" + break + fi + done +else + JAVA=java +fi + +# test that Java exists and is executable on this server +"$JAVA" -version >/dev/null 2>&1 || { echo >&2 "Java is required to run this tool! Please install Java 8 or greater before running this script."; exit 1; } + + +# ===== post specific code + +TOOL_JAR=("$SOLR_TIP/dist"/solr-core-*.jar) + +function print_usage() { + echo "" + echo 'Usage: post -c [OPTIONS] ' + echo " or post -help" + echo "" + echo " collection name defaults to DEFAULT_SOLR_COLLECTION if not specified" + echo "" + echo "OPTIONS" + echo "=======" + echo " Solr options:" + echo " -url (overrides collection, host, and port)" + echo " -host (default: localhost)" + echo " -p or -port (default: 8983)" + echo " -commit yes|no (default: yes)" + echo " -u or -user (sets BasicAuth credentials)" + # optimize intentionally omitted, but can be used as '-optimize yes' (default: no) + echo "" + echo " Web crawl options:" + echo " -recursive (default: 1)" + echo " -delay (default: 10)" + echo "" + echo " Directory crawl options:" + echo " -delay (default: 0)" + echo "" + echo " stdin/args options:" + echo " -type (default: application/xml)" + echo "" + echo " Other options:" + echo " -filetypes [,,...] (default: xml,json,jsonl,csv,pdf,doc,docx,ppt,pptx,xls,xlsx,odt,odp,ods,ott,otp,ots,rtf,htm,html,txt,log)" + echo " -params \"=[&=...]\" (values must be URL-encoded; these pass through to Solr update request)" + echo " -out yes|no (default: no; yes outputs Solr response to console)" + echo " -format solr (sends application/json content as Solr commands to /update instead of /update/json/docs)" + echo "" + echo "" + echo "Examples:" + echo "" + echo "* JSON file: $THIS_SCRIPT -c wizbang events.json" + echo "* XML files: $THIS_SCRIPT -c records article*.xml" + echo "* CSV file: $THIS_SCRIPT -c signals LATEST-signals.csv" + echo "* Directory of files: $THIS_SCRIPT -c myfiles ~/Documents" + echo "* Web crawl: $THIS_SCRIPT -c gettingstarted http://lucene.apache.org/solr -recursive 1 -delay 1" + echo "* Standard input (stdin): echo '{"commit": {}}' | $THIS_SCRIPT -c my_collection -type application/json -out yes -d" + echo "* Data as string: $THIS_SCRIPT -c signals -type text/csv -out yes -d $'id,value\n1,0.47'" + echo "" +} # end print_usage + +if [[ $# -eq 1 && ("$1" == "-help" || "$1" == "-h" || "$1" == "-usage") ]]; then + print_usage + exit +fi + + +COLLECTION="$DEFAULT_SOLR_COLLECTION" +PROPS=('-Dauto=yes') +RECURSIVE="" +FILES=() +URLS=() +ARGS=() + +while [ $# -gt 0 ]; do + # TODO: natively handle the optional parameters to SPT + # but for now they can be specified as bin/post -c collection-name delay=5 http://lucidworks.com + + if [[ -d "$1" ]]; then + # Directory +# echo "$1: DIRECTORY" + RECURSIVE=yes + FILES+=("$1") + elif [[ -f "$1" ]]; then + # File +# echo "$1: FILE" + FILES+=("$1") + elif [[ "$1" == http* ]]; then + # URL +# echo "$1: URL" + URLS+=("$1") + else + if [[ "$1" == -* ]]; then + if [[ "$1" == "-c" ]]; then + # Special case, pull out collection name + shift + COLLECTION="$1" + elif [[ "$1" == "-p" ]]; then + # -p alias for -port for convenience and compatibility with `bin/solr start` + shift + PROPS+=("-Dport=$1") + elif [[ ("$1" == "-d" || "$1" == "--data" || "$1" == "-") ]]; then + if [[ ! -t 0 ]]; then + MODE="stdin" + else + # when no stdin exists and -d specified, the rest of the arguments + # are assumed to be strings to post as-is + MODE="args" + shift + if [[ $# -gt 0 ]]; then + ARGS=("$@") + shift $# + else + # SPT needs a valid args string, useful for 'bin/post -c foo -d' to force a commit + ARGS+=("") + fi + fi + elif [[ ("$1" == "-u" || "$1" == "-user") ]]; then + shift + PROPS+=("-Dbasicauth=$1") + else + if [[ "$1" == -D* ]] ; then + PROPS+=("$1") + if [[ "${1:2:4}" == "url=" ]]; then + SOLR_URL=${1:6} + fi + else + key="${1:1}" + shift + # echo "$1: PROP" + PROPS+=("-D$key=$1") + if [[ "$key" == "url" ]]; then + SOLR_URL=$1 + fi + fi + fi + else + echo -e "\nUnrecognized argument: $1\n" + echo -e "If this was intended to be a data file, it does not exist relative to $PWD\n" + exit 1 + fi + fi + shift +done + +# Check for errors +if [[ $COLLECTION == "" && $SOLR_URL == "" ]]; then + echo -e "\nCollection or URL must be specified. Use -c or set DEFAULT_SOLR_COLLECTION in your environment, or use -url instead.\n" + echo -e "See '$THIS_SCRIPT -h' for usage instructions.\n" + exit 1 +fi + +# Unsupported: bin/post -c foo +if [[ ${#FILES[@]} == 0 && ${#URLS[@]} == 0 && $MODE != "stdin" && $MODE != "args" ]]; then + echo -e "\nNo files, directories, URLs, -d strings, or stdin were specified.\n" + echo -e "See '$THIS_SCRIPT -h' for usage instructions.\n" + exit 1 +fi + +# SPT does not support mixing different data mode types, just files, just URLs, just stdin, or just argument strings. +# The following are unsupported constructs: +# bin/post -c foo existing_file.csv http://example.com +# echo '' | bin/post -c foo existing_file.csv +# bin/post -c foo existing_file.csv -d 'anything' +if [[ (${#FILES[@]} != 0 && ${#URLS[@]} != 0 && $MODE != "stdin" && $MODE != "args") + || ((${#FILES[@]} != 0 || ${#URLS[@]} != 0) && ($MODE == "stdin" || $MODE == "args")) ]]; then + echo -e "\nCombining files/directories, URLs, stdin, or args is not supported. Post them separately.\n" + exit 1 +fi + +PARAMS="" + +# TODO: let's simplify this +if [[ $MODE != "stdin" && $MODE != "args" ]]; then + if [[ $FILES != "" ]]; then + MODE="files" + PARAMS=("${FILES[@]}") + fi + + if [[ $URLS != "" ]]; then + MODE="web" + PARAMS=("${URLS[@]}") + fi +else + PARAMS=("${ARGS[@]}") +fi + +PROPS+=("-Dc=$COLLECTION" "-Ddata=$MODE") +if [[ -n "$RECURSIVE" ]]; then + PROPS+=('-Drecursive=yes') +fi + +echo "$JAVA" -classpath "${TOOL_JAR[0]}" "${PROPS[@]}" org.apache.solr.util.SimplePostTool "${PARAMS[@]}" +"$JAVA" -classpath "${TOOL_JAR[0]}" "${PROPS[@]}" org.apache.solr.util.SimplePostTool "${PARAMS[@]}" + +# post smoker: +# bin/post -c signals -out yes -type application/json -d '[{"id": 2, "val": 0.47}]' +# bin/post -c signals -out yes -params "wt=json" -d '1' diff --git a/KeywordSearch/solr/bin/postlogs b/KeywordSearch/solr/bin/postlogs new file mode 100755 index 0000000000..8925dd6346 --- /dev/null +++ b/KeywordSearch/solr/bin/postlogs @@ -0,0 +1,33 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +############################################################################################ +# +# A command line tool for indexing Solr logs in the out-of-the-box log format. +# +# First build the Solr distribution. Then run postlogs from inside the Solr distribution +# home directory as described below: +# +# parameters: +# +# -- baseUrl: Example http://localhost:8983/solr/collection1 +# -- rootDir: All files found at or below the root will be indexed +# +# Sample syntax: ./bin/postlogs http://localhost:8983/solr/collection1 /user/foo/logs"); +# +# +############################################################################################ + +java -classpath dist/*:dist/solrj-lib/*: org.apache.solr.util.SolrLogPostTool $1 $2 diff --git a/KeywordSearch/solr/bin/solr b/KeywordSearch/solr/bin/solr new file mode 100755 index 0000000000..e178bcd17d --- /dev/null +++ b/KeywordSearch/solr/bin/solr @@ -0,0 +1,2291 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# CONTROLLING STARTUP: +# +# Use solr -help to see available command-line options. In addition +# to passing command-line options, this script looks for an include +# file named solr.in.sh to set environment variables. Specifically, +# the following locations are searched in this order: +# +# ./ +# $HOME/.solr.in.sh +# /usr/share/solr +# /usr/local/share/solr +# /var/solr/ +# /opt/solr +# +# Another option is to specify the full path to the include file in the +# environment. For example: +# +# $ SOLR_INCLUDE=/path/to/solr.in.sh solr start +# +# Note: This is particularly handy for running multiple instances on a +# single installation, or for quick tests. +# +# Finally, developers and enthusiasts who frequently run from an SVN +# checkout, and do not want to locally modify bin/solr.in.sh, can put +# a customized include file at ~/.solr.in.sh. +# +# If you would rather configure startup entirely from the environment, you +# can disable the include by exporting an empty SOLR_INCLUDE, or by +# ensuring that no include files exist in the aforementioned search list. + +SOLR_SCRIPT="$0" +verbose=false +THIS_OS=`uname -s` + +# What version of Java is required to run this version of Solr. +JAVA_VER_REQ="8" + +stop_all=false + +# for now, we don't support running this script from cygwin due to problems +# like not having lsof, ps auxww, curl, and awkward directory handling +if [ "${THIS_OS:0:6}" == "CYGWIN" ]; then + echo -e "This script does not support cygwin due to severe limitations and lack of adherence\nto BASH standards, such as lack of lsof, curl, and ps options.\n\nPlease use the native solr.cmd script on Windows!" + exit 1 +fi + +# Resolve symlinks to this script +while [ -h "$SOLR_SCRIPT" ] ; do + ls=`ls -ld "$SOLR_SCRIPT"` + # Drop everything prior to -> + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + SOLR_SCRIPT="$link" + else + SOLR_SCRIPT=`dirname "$SOLR_SCRIPT"`/"$link" + fi +done + +SOLR_TIP=`dirname "$SOLR_SCRIPT"`/.. +SOLR_TIP=`cd "$SOLR_TIP"; pwd` +DEFAULT_SERVER_DIR="$SOLR_TIP/server" + +# If an include wasn't specified in the environment, then search for one... +if [ -z "$SOLR_INCLUDE" ]; then + # Locations (in order) to use when searching for an include file. + for include in "`dirname "$0"`/solr.in.sh" \ + "$HOME/.solr.in.sh" \ + /usr/share/solr/solr.in.sh \ + /usr/local/share/solr/solr.in.sh \ + /etc/default/solr.in.sh \ + /opt/solr/solr.in.sh; do + if [ -r "$include" ]; then + SOLR_INCLUDE="$include" + . "$include" + break + fi + done +elif [ -r "$SOLR_INCLUDE" ]; then + . "$SOLR_INCLUDE" +fi + +if [ -z "$SOLR_PID_DIR" ]; then + SOLR_PID_DIR="$SOLR_TIP/bin" +fi + +if [ -n "$SOLR_JAVA_HOME" ]; then + JAVA="$SOLR_JAVA_HOME/bin/java" + JSTACK="$SOLR_JAVA_HOME/bin/jstack" +elif [ -n "$JAVA_HOME" ]; then + for java in "$JAVA_HOME"/bin/amd64 "$JAVA_HOME"/bin; do + if [ -x "$java/java" ]; then + JAVA="$java/java" + if [ -x "$java/jstack" ]; then + JSTACK="$java/jstack" + else + echo >&2 "The currently defined JAVA_HOME ($JAVA_HOME) refers to a location" + echo >&2 "where java was found but jstack was not found. Continuing." + fi + break + fi + done + if [ -z "$JAVA" ]; then + echo >&2 "The currently defined JAVA_HOME ($JAVA_HOME) refers" + echo >&2 "to a location where Java could not be found. Aborting." + echo >&2 "Either fix the JAVA_HOME variable or remove it from the" + echo >&2 "environment so that the system PATH will be searched." + exit 1 + fi +else + JAVA=java + JSTACK=jstack +fi + +if [ -z "$SOLR_STOP_WAIT" ]; then + SOLR_STOP_WAIT=180 +fi +# test that Java exists, is executable and correct version +JAVA_VER=$("$JAVA" -version 2>&1) +if [[ $? -ne 0 ]] ; then + echo >&2 "Java not found, or an error was encountered when running java." + echo >&2 "A working Java $JAVA_VER_REQ JRE is required to run Solr!" + echo >&2 "Please install latest version of Java $JAVA_VER_REQ or set JAVA_HOME properly." + echo >&2 "Command that we tried: '${JAVA} -version', with response:" + echo >&2 "${JAVA_VER}" + echo >&2 + echo >&2 "Debug information:" + echo >&2 "JAVA_HOME: ${JAVA_HOME:-N/A}" + echo >&2 "Active Path:" + echo >&2 "${PATH}" + exit 1 +else + JAVA_VER_NUM=$(echo $JAVA_VER | head -1 | awk -F '"' '/version/ {print $2}' | sed -e's/^1\.//' | sed -e's/[._-].*$//') + if [[ "$JAVA_VER_NUM" -lt "$JAVA_VER_REQ" ]] ; then + echo >&2 "Your current version of Java is too old to run this version of Solr." + echo >&2 "We found major version $JAVA_VER_NUM, using command '${JAVA} -version', with response:" + echo >&2 "${JAVA_VER}" + echo >&2 + echo >&2 "Please install latest version of Java $JAVA_VER_REQ or set JAVA_HOME properly." + echo >&2 + echo >&2 "Debug information:" + echo >&2 "JAVA_HOME: ${JAVA_HOME:-N/A}" + echo >&2 "Active Path:" + echo >&2 "${PATH}" + exit 1 + fi + JAVA_VENDOR="Oracle" + if [ "`echo $JAVA_VER | grep -i "IBM J9"`" != "" ]; then + JAVA_VENDOR="IBM J9" + fi +fi + + +# Select HTTP OR HTTPS related configurations +SOLR_URL_SCHEME=http +SOLR_JETTY_CONFIG=() +SOLR_SSL_OPTS="" + +if [ -n "$SOLR_HADOOP_CREDENTIAL_PROVIDER_PATH" ]; then + SOLR_SSL_OPTS+=" -Dhadoop.security.credential.provider.path=$SOLR_HADOOP_CREDENTIAL_PROVIDER_PATH" +fi + +if [ -z "$SOLR_SSL_ENABLED" ]; then + if [ -n "$SOLR_SSL_KEY_STORE" ]; then + SOLR_SSL_ENABLED="true" # implicitly from earlier behaviour + else + SOLR_SSL_ENABLED="false" + fi +fi +if [ "$SOLR_SSL_ENABLED" == "true" ]; then + if [[ "$JAVA_VER_NUM" -lt "9" ]] ; then + echo >&2 "HTTP/2 + SSL is not support in Java 8. " + echo >&2 "Configure Solr with HTTP/1.1 + SSL" + SOLR_JETTY_CONFIG+=("--module=https8") + else + SOLR_JETTY_CONFIG+=("--module=https") + fi + + SOLR_JETTY_CONFIG+=("--lib=$DEFAULT_SERVER_DIR/solr-webapp/webapp/WEB-INF/lib/*") + SOLR_URL_SCHEME=https + if [ -n "$SOLR_SSL_KEY_STORE" ]; then + SOLR_SSL_OPTS+=" -Dsolr.jetty.keystore=$SOLR_SSL_KEY_STORE" + fi + if [ -n "$SOLR_SSL_KEY_STORE_PASSWORD" ]; then + export SOLR_SSL_KEY_STORE_PASSWORD=$SOLR_SSL_KEY_STORE_PASSWORD + fi + if [ -n "$SOLR_SSL_KEY_STORE_TYPE" ]; then + SOLR_SSL_OPTS+=" -Dsolr.jetty.keystore.type=$SOLR_SSL_KEY_STORE_TYPE" + fi + + if [ -n "$SOLR_SSL_TRUST_STORE" ]; then + SOLR_SSL_OPTS+=" -Dsolr.jetty.truststore=$SOLR_SSL_TRUST_STORE" + fi + if [ -n "$SOLR_SSL_TRUST_STORE_PASSWORD" ]; then + export SOLR_SSL_TRUST_STORE_PASSWORD=$SOLR_SSL_TRUST_STORE_PASSWORD + fi + if [ -n "$SOLR_SSL_TRUST_STORE_TYPE" ]; then + SOLR_SSL_OPTS+=" -Dsolr.jetty.truststore.type=$SOLR_SSL_TRUST_STORE_TYPE" + fi + + if [ -z "$SOLR_SSL_CLIENT_HOSTNAME_VERIFICATION" ] ; then + SOLR_SSL_OPTS+=" -Dsolr.jetty.ssl.verifyClientHostName=HTTPS" + fi + + if [ -n "$SOLR_SSL_NEED_CLIENT_AUTH" ]; then + SOLR_SSL_OPTS+=" -Dsolr.jetty.ssl.needClientAuth=$SOLR_SSL_NEED_CLIENT_AUTH" + fi + if [ -n "$SOLR_SSL_WANT_CLIENT_AUTH" ]; then + SOLR_SSL_OPTS+=" -Dsolr.jetty.ssl.wantClientAuth=$SOLR_SSL_WANT_CLIENT_AUTH" + fi + + if [ -n "$SOLR_SSL_CLIENT_KEY_STORE" ]; then + SOLR_SSL_OPTS+=" -Djavax.net.ssl.keyStore=$SOLR_SSL_CLIENT_KEY_STORE" + + if [ -n "$SOLR_SSL_CLIENT_KEY_STORE_PASSWORD" ]; then + export SOLR_SSL_CLIENT_KEY_STORE_PASSWORD=$SOLR_SSL_CLIENT_KEY_STORE_PASSWORD + fi + if [ -n "$SOLR_SSL_CLIENT_KEY_STORE_TYPE" ]; then + SOLR_SSL_OPTS+=" -Djavax.net.ssl.keyStoreType=$SOLR_SSL_CLIENT_KEY_STORE_TYPE" + fi + else + if [ -n "$SOLR_SSL_KEY_STORE" ]; then + SOLR_SSL_OPTS+=" -Djavax.net.ssl.keyStore=$SOLR_SSL_KEY_STORE" + fi + if [ -n "$SOLR_SSL_KEY_STORE_TYPE" ]; then + SOLR_SSL_OPTS+=" -Djavax.net.ssl.keyStoreType=$SOLR_SSL_KEY_STORE_TYPE" + fi + fi + + if [ -n "$SOLR_SSL_CHECK_PEER_NAME" ]; then + SOLR_SSL_OPTS+=" -Dsolr.ssl.checkPeerName=$SOLR_SSL_CHECK_PEER_NAME" + fi + + if [ -n "$SOLR_SSL_CLIENT_TRUST_STORE" ]; then + SOLR_SSL_OPTS+=" -Djavax.net.ssl.trustStore=$SOLR_SSL_CLIENT_TRUST_STORE" + + if [ -n "$SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD" ]; then + export SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD=$SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD + fi + if [ -n "$SOLR_SSL_CLIENT_TRUST_STORE_TYPE" ]; then + SOLR_SSL_OPTS+=" -Djavax.net.ssl.trustStoreType=$SOLR_SSL_CLIENT_TRUST_STORE_TYPE" + fi + else + if [ -n "$SOLR_SSL_TRUST_STORE" ]; then + SOLR_SSL_OPTS+=" -Djavax.net.ssl.trustStore=$SOLR_SSL_TRUST_STORE" + fi + + if [ -n "$SOLR_SSL_TRUST_STORE_TYPE" ]; then + SOLR_SSL_OPTS+=" -Djavax.net.ssl.trustStoreType=$SOLR_SSL_TRUST_STORE_TYPE" + fi + fi +else + SOLR_JETTY_CONFIG+=("--module=http") +fi + +# Requestlog options +if [ "$SOLR_REQUESTLOG_ENABLED" == "true" ]; then + SOLR_JETTY_CONFIG+=("--module=requestlog") +fi + +# Authentication options +if [ -z "$SOLR_AUTH_TYPE" ] && [ -n "$SOLR_AUTHENTICATION_OPTS" ]; then + echo "WARNING: SOLR_AUTHENTICATION_OPTS environment variable configured without associated SOLR_AUTH_TYPE variable" + echo " Please configure SOLR_AUTH_TYPE environment variable with the authentication type to be used." + echo " Currently supported authentication types are [kerberos, basic]" +fi + +if [ -n "$SOLR_AUTH_TYPE" ] && [ -n "$SOLR_AUTHENTICATION_CLIENT_BUILDER" ]; then + echo "WARNING: SOLR_AUTHENTICATION_CLIENT_BUILDER and SOLR_AUTH_TYPE environment variables are configured together." + echo " Use SOLR_AUTH_TYPE environment variable to configure authentication type to be used. " + echo " Currently supported authentication types are [kerberos, basic]" + echo " The value of SOLR_AUTHENTICATION_CLIENT_BUILDER environment variable will be ignored" +fi + +if [ -n "$SOLR_AUTH_TYPE" ]; then + case "$(echo $SOLR_AUTH_TYPE | awk '{print tolower($0)}')" in + basic) + SOLR_AUTHENTICATION_CLIENT_BUILDER="org.apache.solr.client.solrj.impl.PreemptiveBasicAuthClientBuilderFactory" + ;; + kerberos) + SOLR_AUTHENTICATION_CLIENT_BUILDER="org.apache.solr.client.solrj.impl.Krb5HttpClientBuilder" + ;; + *) + echo "ERROR: Value specified for SOLR_AUTH_TYPE environment variable is invalid." + exit 1 + esac +fi + +if [ "$SOLR_AUTHENTICATION_CLIENT_CONFIGURER" != "" ]; then + echo "WARNING: Found unsupported configuration variable SOLR_AUTHENTICATION_CLIENT_CONFIGURER" + echo " Please start using SOLR_AUTH_TYPE instead" +fi +if [ "$SOLR_AUTHENTICATION_CLIENT_BUILDER" != "" ]; then + AUTHC_CLIENT_BUILDER_ARG="-Dsolr.httpclient.builder.factory=$SOLR_AUTHENTICATION_CLIENT_BUILDER" +fi +AUTHC_OPTS="$AUTHC_CLIENT_BUILDER_ARG $SOLR_AUTHENTICATION_OPTS" + +# Set the SOLR_TOOL_HOST variable for use when connecting to a running Solr instance +if [ "$SOLR_HOST" != "" ]; then + SOLR_TOOL_HOST="$SOLR_HOST" +else + SOLR_TOOL_HOST="localhost" +fi + +function print_usage() { + CMD="$1" + ERROR_MSG="$2" + + if [ "$ERROR_MSG" != "" ]; then + echo -e "\nERROR: $ERROR_MSG\n" + fi + + if [ -z "$CMD" ]; then + echo "" + echo "Usage: solr COMMAND OPTIONS" + echo " where COMMAND is one of: start, stop, restart, status, healthcheck, create, create_core, create_collection, delete, version, zk, auth, assert, config, autoscaling, export" + echo "" + echo " Standalone server example (start Solr running in the background on port 8984):" + echo "" + echo " ./solr start -p 8984" + echo "" + echo " SolrCloud example (start Solr running in SolrCloud mode using localhost:2181 to connect to Zookeeper, with 1g max heap size and remote Java debug options enabled):" + echo "" + echo " ./solr start -c -m 1g -z localhost:2181 -a \"-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=1044\"" + echo "" + echo " Omit '-z localhost:2181' from the above command if you have defined ZK_HOST in solr.in.sh." + echo "" + echo "Pass -help after any COMMAND to see command-specific usage information," + echo " such as: ./solr start -help or ./solr stop -help" + echo "" + elif [[ "$CMD" == "start" || "$CMD" == "restart" ]]; then + echo "" + echo "Usage: solr $CMD [-f] [-c] [-h hostname] [-p port] [-d directory] [-z zkHost] [-m memory] [-e example] [-s solr.solr.home] [-t solr.data.home] [-a \"additional-options\"] [-V]" + echo "" + echo " -f Start Solr in foreground; default starts Solr in the background" + echo " and sends stdout / stderr to solr-PORT-console.log" + echo "" + echo " -c or -cloud Start Solr in SolrCloud mode; if -z not supplied and ZK_HOST not defined in" + echo " solr.in.sh, an embedded ZooKeeper instance is started on Solr port+1000," + echo " such as 9983 if Solr is bound to 8983" + echo "" + echo " -h Specify the hostname for this Solr instance" + echo "" + echo " -p Specify the port to start the Solr HTTP listener on; default is 8983" + echo " The specified port (SOLR_PORT) will also be used to determine the stop port" + echo " STOP_PORT=(\$SOLR_PORT-1000) and JMX RMI listen port RMI_PORT=(\$SOLR_PORT+10000). " + echo " For instance, if you set -p 8985, then the STOP_PORT=7985 and RMI_PORT=18985" + echo "" + echo " -d Specify the Solr server directory; defaults to server" + echo "" + echo " -z Zookeeper connection string; only used when running in SolrCloud mode using -c" + echo " If neither ZK_HOST is defined in solr.in.sh nor the -z parameter is specified," + echo " an embedded ZooKeeper instance will be launched." + echo "" + echo " -m Sets the min (-Xms) and max (-Xmx) heap size for the JVM, such as: -m 4g" + echo " results in: -Xms4g -Xmx4g; by default, this script sets the heap size to 512m" + echo "" + echo " -s Sets the solr.solr.home system property; Solr will create core directories under" + echo " this directory. This allows you to run multiple Solr instances on the same host" + echo " while reusing the same server directory set using the -d parameter. If set, the" + echo " specified directory should contain a solr.xml file, unless solr.xml exists in Zookeeper." + echo " This parameter is ignored when running examples (-e), as the solr.solr.home depends" + echo " on which example is run. The default value is server/solr. If passed relative dir," + echo " validation with current dir will be done, before trying default server/" + echo "" + echo " -t Sets the solr.data.home system property, where Solr will store index data in /data subdirectories." + echo " If not set, Solr uses solr.solr.home for config and data." + echo "" + echo " -e Name of the example to run; available examples:" + echo " cloud: SolrCloud example" + echo " techproducts: Comprehensive example illustrating many of Solr's core capabilities" + echo " dih: Data Import Handler" + echo " schemaless: Schema-less example" + echo "" + echo " -a Additional parameters to pass to the JVM when starting Solr, such as to setup" + echo " Java debug options. For example, to enable a Java debugger to attach to the Solr JVM" + echo " you could pass: -a \"-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=18983\"" + echo " In most cases, you should wrap the additional parameters in double quotes." + echo "" + echo " -j Additional parameters to pass to Jetty when starting Solr." + echo " For example, to add configuration folder that jetty should read" + echo " you could pass: -j \"--include-jetty-dir=/etc/jetty/custom/server/\"" + echo " In most cases, you should wrap the additional parameters in double quotes." + echo "" + echo " -noprompt Don't prompt for input; accept all defaults when running examples that accept user input" + echo "" + echo " -v and -q Verbose (-v) or quiet (-q) logging. Sets default log level to DEBUG or WARN instead of INFO" + echo "" + echo " -V/-verbose Verbose messages from this script" + echo "" + elif [ "$CMD" == "stop" ]; then + echo "" + echo "Usage: solr stop [-k key] [-p port] [-V]" + echo "" + echo " -k Stop key; default is solrrocks" + echo "" + echo " -p Specify the port the Solr HTTP listener is bound to" + echo "" + echo " -all Find and stop all running Solr servers on this host" + echo "" + echo " -V/-verbose Verbose messages from this script" + echo "" + echo " NOTE: To see if any Solr servers are running, do: solr status" + echo "" + elif [ "$CMD" == "healthcheck" ]; then + echo "" + echo "Usage: solr healthcheck [-c collection] [-z zkHost] [-V]" + echo "" + echo "Can be run from remote (non-Solr) hosts, as long as a proper ZooKeeper connection is provided" + echo "" + echo " -c Collection to run healthcheck against." + echo "" + echo " -z Zookeeper connection string; unnecessary if ZK_HOST is defined in solr.in.sh;" + echo " otherwise, default is localhost:9983" + echo "" + echo " -V Enable more verbose output" + echo "" + elif [ "$CMD" == "status" ]; then + echo "" + echo "Usage: solr status" + echo "" + echo " This command will show the status of all running Solr servers." + echo " It can only detect those Solr servers running on the current host." + echo "" + elif [ "$CMD" == "create" ]; then + echo "" + echo "Usage: solr create [-c name] [-d confdir] [-n configName] [-shards #] [-replicationFactor #] [-p port] [-V]" + echo "" + echo " Create a core or collection depending on whether Solr is running in standalone (core) or SolrCloud" + echo " mode (collection). In other words, this action detects which mode Solr is running in, and then takes" + echo " the appropriate action (either create_core or create_collection). For detailed usage instructions, do:" + echo "" + echo " bin/solr create_core -help" + echo "" + echo " or" + echo "" + echo " bin/solr create_collection -help" + echo "" + elif [ "$CMD" == "delete" ]; then + echo "" + echo "Usage: solr delete [-c name] [-deleteConfig true|false] [-p port] [-V]" + echo "" + echo " Deletes a core or collection depending on whether Solr is running in standalone (core) or SolrCloud" + echo " mode (collection). If you're deleting a collection in SolrCloud mode, the default behavior is to also" + echo " delete the configuration directory from Zookeeper so long as it is not being used by another collection." + echo " You can override this behavior by passing -deleteConfig false when running this command." + echo "" + echo " Can be run on remote (non-Solr) hosts, as long as a valid SOLR_HOST is provided in solr.in.sh" + echo "" + echo " -c Name of the core / collection to delete" + echo "" + echo " -deleteConfig Delete the configuration directory from Zookeeper; default is true" + echo "" + echo " -p Port of a local Solr instance where you want to delete the core/collection" + echo " If not specified, the script will search the local system for a running" + echo " Solr instance and will use the port of the first server it finds." + echo "" + echo " -V Enables more verbose output." + echo "" + elif [ "$CMD" == "create_core" ]; then + echo "" + echo "Usage: solr create_core [-c core] [-d confdir] [-p port] [-V]" + echo "" + echo "When a configSet is used, this can be run from remote (non-Solr) hosts. If pointing at a non-configSet directory, this" + echo "must be run from the host that you wish to create the core on" + echo "" + echo " -c Name of core to create" + echo "" + echo " -d Configuration directory to copy when creating the new core, built-in options are:" + echo "" + echo " _default: Minimal configuration, which supports enabling/disabling field-guessing support" + echo " sample_techproducts_configs: Example configuration with many optional features enabled to" + echo " demonstrate the full power of Solr" + echo "" + echo " If not specified, default is: _default" + echo "" + echo " Alternatively, you can pass the path to your own configuration directory instead of using" + echo " one of the built-in configurations, such as: bin/solr create_core -c mycore -d /tmp/myconfig" + echo "" + echo " -p Port of a local Solr instance where you want to create the new core" + echo " If not specified, the script will search the local system for a running" + echo " Solr instance and will use the port of the first server it finds." + echo "" + echo " -V Enable more verbose output." + echo "" + elif [ "$CMD" == "create_collection" ]; then + echo "" + echo "Usage: solr create_collection [-c collection] [-d confdir] [-n configName] [-shards #] [-replicationFactor #] [-p port] [-V]" + echo "" + echo "Can be run from remote (non-Solr) hosts, as long as a valid SOLR_HOST is provided in solr.in.sh" + echo " -c Name of collection to create" + echo "" + echo " -d Configuration directory to copy when creating the new collection, built-in options are:" + echo "" + echo " _default: Minimal configuration, which supports enabling/disabling field-guessing support" + echo " sample_techproducts_configs: Example configuration with many optional features enabled to" + echo " demonstrate the full power of Solr" + echo "" + echo " If not specified, default is: _default" + echo "" + echo " Alternatively, you can pass the path to your own configuration directory instead of using" + echo " one of the built-in configurations, such as: bin/solr create_collection -c mycoll -d /tmp/myconfig" + echo "" + echo " By default the script will upload the specified confdir directory into Zookeeper using the same" + echo " name as the collection (-c) option. Alternatively, if you want to reuse an existing directory" + echo " or create a confdir in Zookeeper that can be shared by multiple collections, use the -n option" + echo "" + echo " -n Name the configuration directory in Zookeeper; by default, the configuration" + echo " will be uploaded to Zookeeper using the collection name (-c), but if you want" + echo " to use an existing directory or override the name of the configuration in" + echo " Zookeeper, then use the -c option." + echo "" + echo " -shards <#> Number of shards to split the collection into; default is 1" + echo "" + echo " -replicationFactor <#> Number of copies of each document in the collection, default is 1 (no replication)" + echo "" + echo " -p Port of a local Solr instance where you want to create the new collection" + echo " If not specified, the script will search the local system for a running" + echo " Solr instance and will use the port of the first server it finds." + echo "" + echo " -V Enable more verbose output." + echo "" + elif [ "$CMD" == "zk" ]; then + print_short_zk_usage "" + echo " Can be run on remote (non-Solr) hosts, as long as valid ZK_HOST information is provided" + echo " Be sure to check the Solr logs in case of errors." + echo "" + echo " -z zkHost Optional Zookeeper connection string for all commands. If specified it" + echo " overrides the 'ZK_HOST=...'' defined in solr.in.sh." + echo "" + echo " -V Enable more verbose output." + echo "" + echo " upconfig uploads a configset from the local machine to Zookeeper. (Backcompat: -upconfig)" + echo "" + echo " downconfig downloads a configset from Zookeeper to the local machine. (Backcompat: -downconfig)" + echo "" + echo " -n configName Name of the configset in Zookeeper that will be the destination of" + echo " 'upconfig' and the source for 'downconfig'." + echo "" + echo " -d confdir The local directory the configuration will be uploaded from for" + echo " 'upconfig' or downloaded to for 'downconfig'. If 'confdir' is a child of" + echo " ...solr/server/solr/configsets' then the configs will be copied from/to" + echo " that directory. Otherwise it is interpreted as a simple local path." + echo "" + echo " cp copies files or folders to/from Zookeeper or Zokeeper -> Zookeeper" + echo " -r Recursively copy to . Command will fail if has children and " + echo " -r is not specified. Optional" + echo "" + echo " , : [file:][/]path/to/local/file or zk:/path/to/zk/node" + echo " NOTE: and may both be Zookeeper resources prefixed by 'zk:'" + echo " When is a zk resource, may be '.'" + echo " If ends with '/', then will be a local folder or parent znode and the last" + echo " element of the path will be appended unless also ends in a slash. " + echo " may be zk:, which may be useful when using the cp -r form to backup/restore " + echo " the entire zk state." + echo " You must enclose local paths that end in a wildcard in quotes or just" + echo " end the local path in a slash. That is," + echo " 'bin/solr zk cp -r /some/dir/ zk:/ -z localhost:2181' is equivalent to" + echo " 'bin/solr zk cp -r \"/some/dir/*\" zk:/ -z localhost:2181'" + echo " but 'bin/solr zk cp -r /some/dir/* zk:/ -z localhost:2181' will throw an error" + echo "" + echo " here's an example of backup/restore for a ZK configuration:" + echo " to copy to local: 'bin/solr zk cp -r zk:/ /some/dir -z localhost:2181'" + echo " to restore to ZK: 'bin/solr zk cp -r /some/dir/ zk:/ -z localhost:2181'" + echo "" + echo " The 'file:' prefix is stripped, thus 'file:/wherever' specifies an absolute local path and" + echo " 'file:somewhere' specifies a relative local path. All paths on Zookeeper are absolute." + echo "" + echo " Zookeeper nodes CAN have data, so moving a single file to a parent znode" + echo " will overlay the data on the parent Znode so specifying the trailing slash" + echo " can be important." + echo "" + echo " Wildcards are supported when copying from local, trailing only and must be quoted." + echo "" + echo " rm deletes files or folders on Zookeeper" + echo " -r Recursively delete if is a directory. Command will fail if " + echo " has children and -r is not specified. Optional" + echo " : [zk:]/path/to/zk/node. may not be the root ('/')" + echo "" + echo " mv moves (renames) znodes on Zookeeper" + echo " , : Zookeeper nodes, the 'zk:' prefix is optional." + echo " If ends with '/', then will be a parent znode" + echo " and the last element of the path will be appended." + echo " Zookeeper nodes CAN have data, so moving a single file to a parent znode" + echo " will overlay the data on the parent Znode so specifying the trailing slash" + echo " is important." + echo "" + echo " ls lists the znodes on Zookeeper" + echo " -r recursively descends the path listing all znodes. Optional" + echo " : The Zookeeper path to use as the root." + echo "" + echo " Only the node names are listed, not data" + echo "" + echo " mkroot makes a znode in Zookeeper with no data. Can be used to make a path of arbitrary" + echo " depth but primarily intended to create a 'chroot'." + echo "" + echo " : The Zookeeper path to create. Leading slash is assumed if not present." + echo " Intermediate nodes are created as needed if not present." + echo "" + elif [ "$CMD" == "auth" ]; then + echo "" + echo "Usage: solr auth enable [-type basicAuth] -credentials user:pass [-blockUnknown ] [-updateIncludeFileOnly ] [-V]" + echo " solr auth enable [-type basicAuth] -prompt [-blockUnknown ] [-updateIncludeFileOnly ] [-V]" + echo " solr auth enable -type kerberos -config \"\" [-updateIncludeFileOnly ] [-V]" + echo " solr auth disable [-updateIncludeFileOnly ] [-V]" + echo "" + echo " Updates or enables/disables authentication. Must be run on the machine hosting Solr." + echo "" + echo " -type The authentication mechanism (basicAuth or kerberos) to enable. Defaults to 'basicAuth'." + echo "" + echo " -credentials The username and password of the initial user. Applicable for basicAuth only." + echo " Note: only one of -prompt or -credentials must be provided" + echo "" + echo " -config \"\" Configuration parameters (Solr startup parameters). Required and applicable only for Kerberos" + echo "" + echo " -prompt Prompts the user to provide the credentials. Applicable for basicAuth only." + echo " Note: only one of -prompt or -credentials must be provided" + echo "" + echo " -blockUnknown When true, this blocks out access to unauthenticated users. When not provided," + echo " this defaults to false (i.e. unauthenticated users can access all endpoints, except the" + echo " operations like collection-edit, security-edit, core-admin-edit etc.). Check the reference" + echo " guide for Basic Authentication for more details. Applicable for basicAuth only." + echo "" + echo " -updateIncludeFileOnly Only update the solr.in.sh or solr.in.cmd file, and skip actual enabling/disabling" + echo " authentication (i.e. don't update security.json)" + echo "" + echo " -z zkHost Zookeeper connection string. Unnecessary if ZK_HOST is defined in solr.in.sh." + echo "" + echo " -d Specify the Solr server directory" + echo "" + echo " -s Specify the Solr home directory. This is where any credentials or authentication" + echo " configuration files (e.g. basicAuth.conf) would be placed." + echo "" + echo " -V Enable more verbose output." + echo "" + fi +} # end print_usage + +function print_short_zk_usage() { + + if [ "$1" != "" ]; then + echo -e "\nERROR: $1\n" + fi + + echo " Usage: solr zk upconfig|downconfig -d -n [-z zkHost]" + echo " solr zk cp [-r] [-z zkHost]" + echo " solr zk rm [-r] [-z zkHost]" + echo " solr zk mv [-z zkHost]" + echo " solr zk ls [-r] [-z zkHost]" + echo " solr zk mkroot [-z zkHost]" + echo "" + + if [ "$1" == "" ]; then + echo "Type bin/solr zk -help for full usage help" + else + exit 1 + fi +} + +# used to show the script is still alive when waiting on work to complete +function spinner() { + local pid=$1 + local delay=0.5 + local spinstr='|/-\' + while [ "$(ps aux | awk '{print $2}' | grep -w $pid)" ]; do + local temp=${spinstr#?} + printf " [%c] " "$spinstr" + local spinstr=$temp${spinstr%"$temp"} + sleep $delay + printf "\b\b\b\b\b\b" + done + printf " \b\b\b\b" +} + +# given a port, find the pid for a Solr process +function solr_pid_by_port() { + THE_PORT="$1" + if [ -e "$SOLR_PID_DIR/solr-$THE_PORT.pid" ]; then + PID=`cat "$SOLR_PID_DIR/solr-$THE_PORT.pid"` + CHECK_PID=`ps auxww | awk '{print $2}' | grep -w $PID | sort -r | tr -d ' '` + if [ "$CHECK_PID" != "" ]; then + local solrPID=$PID + fi + fi + echo "$solrPID" +} + +# extract the value of the -Djetty.port parameter from a running Solr process +function jetty_port() { + SOLR_PID="$1" + SOLR_PROC=`ps auxww | grep -w $SOLR_PID | grep start\.jar | grep jetty\.port` + IFS=' ' read -a proc_args <<< "$SOLR_PROC" + for arg in "${proc_args[@]}" + do + IFS='=' read -a pair <<< "$arg" + if [ "${pair[0]}" == "-Djetty.port" ]; then + local jetty_port="${pair[1]}" + break + fi + done + echo "$jetty_port" +} # end jetty_port func + +# run a Solr command-line tool using the SolrCLI class; +# useful for doing cross-platform work from the command-line using Java +function run_tool() { + + "$JAVA" $SOLR_SSL_OPTS $AUTHC_OPTS $SOLR_ZK_CREDS_AND_ACLS -Dsolr.install.dir="$SOLR_TIP" \ + -Dlog4j.configurationFile="$DEFAULT_SERVER_DIR/resources/log4j2-console.xml" \ + -classpath "$DEFAULT_SERVER_DIR/solr-webapp/webapp/WEB-INF/lib/*:$DEFAULT_SERVER_DIR/lib/ext/*:$DEFAULT_SERVER_DIR/lib/*" \ + org.apache.solr.util.SolrCLI "$@" + + return $? +} # end run_tool function + +# get information about any Solr nodes running on this host +function get_info() { + CODE=4 + # first, see if Solr is running + numSolrs=`find "$SOLR_PID_DIR" -name "solr-*.pid" -type f | wc -l | tr -d ' '` + if [ "$numSolrs" != "0" ]; then + echo -e "\nFound $numSolrs Solr nodes: " + while read PIDF + do + ID=`cat "$PIDF"` + port=`jetty_port "$ID"` + if [ "$port" != "" ]; then + echo -e "\nSolr process $ID running on port $port" + run_tool status -solr "$SOLR_URL_SCHEME://$SOLR_TOOL_HOST:$port/solr" + CODE=$? + echo "" + else + echo -e "\nSolr process $ID from $PIDF not found." + CODE=1 + fi + done < <(find "$SOLR_PID_DIR" -name "solr-*.pid" -type f) + else + # no pid files but check using ps just to be sure + numSolrs=`ps auxww | grep start\.jar | grep solr\.solr\.home | grep -v grep | wc -l | sed -e 's/^[ \t]*//'` + if [ "$numSolrs" != "0" ]; then + echo -e "\nFound $numSolrs Solr nodes: " + PROCESSES=$(ps auxww | grep start\.jar | grep solr\.solr\.home | grep -v grep | awk '{print $2}' | sort -r) + for ID in $PROCESSES + do + port=`jetty_port "$ID"` + if [ "$port" != "" ]; then + echo "" + echo "Solr process $ID running on port $port" + run_tool status -solr "$SOLR_URL_SCHEME://$SOLR_TOOL_HOST:$port/solr" + CODE=$? + echo "" + fi + done + else + echo -e "\nNo Solr nodes are running.\n" + CODE=3 + fi + fi + + return $CODE +} # end get_info + +function run_package() { + runningSolrUrl="" + + numSolrs=`find "$SOLR_PID_DIR" -name "solr-*.pid" -type f | wc -l | tr -d ' '` + if [ "$numSolrs" != "0" ]; then + #echo -e "\nFound $numSolrs Solr nodes: " + while read PIDF + do + ID=`cat "$PIDF"` + port=`jetty_port "$ID"` + if [ "$port" != "" ]; then + #echo -e "\nSolr process $ID running on port $port" + runningSolrUrl="$SOLR_URL_SCHEME://$SOLR_TOOL_HOST:$port/solr" + break + CODE=$? + echo "" + else + echo -e "\nSolr process $ID from $PIDF not found." + CODE=1 + fi + done < <(find "$SOLR_PID_DIR" -name "solr-*.pid" -type f) + else + # no pid files but check using ps just to be sure + numSolrs=`ps auxww | grep start\.jar | grep solr\.solr\.home | grep -v grep | wc -l | sed -e 's/^[ \t]*//'` + if [ "$numSolrs" != "0" ]; then + echo -e "\nFound $numSolrs Solr nodes: " + PROCESSES=$(ps auxww | grep start\.jar | grep solr\.solr\.home | grep -v grep | awk '{print $2}' | sort -r) + for ID in $PROCESSES + do + port=`jetty_port "$ID"` + if [ "$port" != "" ]; then + echo "" + echo "Solr process $ID running on port $port" + runningSolrUrl="$SOLR_URL_SCHEME://$SOLR_TOOL_HOST:$port/solr" + break + CODE=$? + echo "" + fi + done + else + echo -e "\nNo Solr nodes are running.\n" + exit 1 + CODE=3 + fi + fi + + run_tool package -solrUrl "$runningSolrUrl" $@ + #exit $? +} + +# tries to gracefully stop Solr using the Jetty +# stop command and if that fails, then uses kill -9 +# (will attempt to jstack before killing) +function stop_solr() { + + DIR="$1" + SOLR_PORT="$2" + THIS_STOP_PORT="${STOP_PORT:-$(expr $SOLR_PORT - 1000)}" + STOP_KEY="$3" + SOLR_PID="$4" + + if [ "$SOLR_PID" != "" ]; then + echo -e "Sending stop command to Solr running on port $SOLR_PORT ... waiting up to $SOLR_STOP_WAIT seconds to allow Jetty process $SOLR_PID to stop gracefully." + "$JAVA" $SOLR_SSL_OPTS $AUTHC_OPTS -jar "$DIR/start.jar" "STOP.PORT=$THIS_STOP_PORT" "STOP.KEY=$STOP_KEY" --stop || true + (loops=0 + while true + do + CHECK_PID=`ps auxww | awk '{print $2}' | grep -w $SOLR_PID | sort -r | tr -d ' '` + if [ "$CHECK_PID" != "" ]; then + slept=$((loops * 2)) + if [ $slept -lt $SOLR_STOP_WAIT ]; then + sleep 2 + loops=$[$loops+1] + else + exit # subshell! + fi + else + exit # subshell! + fi + done) & + spinner $! + rm -f "$SOLR_PID_DIR/solr-$SOLR_PORT.pid" + else + echo -e "No Solr nodes found to stop." + exit 0 + fi + + CHECK_PID=`ps auxww | awk '{print $2}' | grep -w $SOLR_PID | sort -r | tr -d ' '` + if [ "$CHECK_PID" != "" ]; then + if [ "$JSTACK" != "" ]; then + echo -e "Solr process $SOLR_PID is still running; jstacking it now." + $JSTACK $SOLR_PID + fi + echo -e "Solr process $SOLR_PID is still running; forcefully killing it now." + kill -9 $SOLR_PID + echo "Killed process $SOLR_PID" + rm -f "$SOLR_PID_DIR/solr-$SOLR_PORT.pid" + sleep 10 + fi + + CHECK_PID=`ps auxww | awk '{print $2}' | grep -w $SOLR_PID | sort -r | tr -d ' '` + if [ "$CHECK_PID" != "" ]; then + echo "ERROR: Failed to kill previous Solr Java process $SOLR_PID ... script fails." + exit 1 + fi +} # end stop_solr + +if [ $# -eq 1 ]; then + case $1 in + -help|-usage|-h|--help) + print_usage "" + exit + ;; + -info|-i|status) + get_info + exit $? + ;; + -version|-v|version) + run_tool version + exit + ;; + esac +fi + +if [ $# -gt 0 ]; then + # if first arg starts with a dash (and it's not -help or -info), + # then assume they are starting Solr, such as: solr -f + if [[ $1 == -* ]]; then + SCRIPT_CMD="start" + else + SCRIPT_CMD="$1" + shift + fi +else + # no args - just show usage and exit + print_usage "" + exit +fi + +if [ "$SCRIPT_CMD" == "status" ]; then + # hacky - the script hits this if the user passes additional args with the status command, + # which is not supported but also not worth complaining about either + get_info + exit +fi + +# assert tool +if [ "$SCRIPT_CMD" == "assert" ]; then + run_tool assert $* + exit $? +fi + +# run a healthcheck and exit if requested +if [ "$SCRIPT_CMD" == "healthcheck" ]; then + + VERBOSE="" + + if [ $# -gt 0 ]; then + while true; do + case "$1" in + -c|-collection) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "$SCRIPT_CMD" "Collection name is required when using the $1 option!" + exit 1 + fi + HEALTHCHECK_COLLECTION="$2" + shift 2 + ;; + -z|-zkhost) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "$SCRIPT_CMD" "ZooKeeper connection string is required when using the $1 option!" + exit 1 + fi + ZK_HOST="$2" + shift 2 + ;; + -help|-usage) + print_usage "$SCRIPT_CMD" + exit 0 + ;; + -V|--verbose) + VERBOSE="-verbose" + shift + ;; + --) + shift + break + ;; + *) + if [ "$1" != "" ]; then + print_usage "$SCRIPT_CMD" "Unrecognized or misplaced argument: $1!" + exit 1 + else + break # out-of-args, stop looping + fi + ;; + esac + done + fi + + if [ -z "$ZK_HOST" ]; then + ZK_HOST=localhost:9983 + fi + + if [ -z "$HEALTHCHECK_COLLECTION" ]; then + echo "collection parameter is required!" + print_usage "healthcheck" + exit 1 + fi + + run_tool healthcheck -zkHost "$ZK_HOST" -collection "$HEALTHCHECK_COLLECTION" $VERBOSE + + exit $? +fi + +if [[ "$SCRIPT_CMD" == "config" ]]; then + CONFIG_PARAMS=() + + if [ $# -gt 0 ]; then + while true; do + case "$1" in + -z|-zkhost|-zkHost) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "$SCRIPT_CMD" "ZooKeeper connection string is required when using the $1 option!" + exit 1 + fi + ZK_HOST="$2" + shift 2 + ;; + -s|-scheme) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "$SCRIPT_CMD" "URL scheme is required when using the $1 option!" + exit 1 + fi + SOLR_URL_SCHEME="$2" + shift 2 + ;; + *) # Pass through all other params + if [ "$1" != "" ]; then + CONFIG_PARAMS+=($1) + shift + else + break + fi + ;; + esac + done + fi + if [[ -n "$ZK_HOST" ]]; then + CONFIG_PARAMS+=("-z" "$ZK_HOST") + fi + if [[ -n "$SOLR_URL_SCHEME" ]]; then + CONFIG_PARAMS+=("-scheme" "$SOLR_URL_SCHEME") + fi + run_tool config "${CONFIG_PARAMS[@]}" + exit $? +fi + +# create a core or collection +if [[ "$SCRIPT_CMD" == "create" || "$SCRIPT_CMD" == "create_core" || "$SCRIPT_CMD" == "create_collection" ]]; then + + CREATE_NUM_SHARDS=1 + CREATE_REPFACT=1 + FORCE=false + VERBOSE="" + + if [ $# -gt 0 ]; then + while true; do + case "$1" in + -c|-core|-collection) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "$SCRIPT_CMD" "name is required when using the $1 option!" + exit 1 + fi + CREATE_NAME="$2" + shift 2 + ;; + -n|-confname) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "$SCRIPT_CMD" "Configuration name is required when using the $1 option!" + exit 1 + fi + CREATE_CONFNAME="$2" + shift 2 + ;; + -d|-confdir) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "$SCRIPT_CMD" "Configuration directory is required when using the $1 option!" + exit 1 + fi + CREATE_CONFDIR="$2" + shift 2 + ;; + -s|-shards) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "$SCRIPT_CMD" "Shard count is required when using the $1 option!" + exit 1 + fi + CREATE_NUM_SHARDS="$2" + shift 2 + ;; + -rf|-replicationFactor) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "$SCRIPT_CMD" "Replication factor is required when using the $1 option!" + exit 1 + fi + CREATE_REPFACT="$2" + shift 2 + ;; + -p|-port) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "$SCRIPT_CMD" "Solr port is required when using the $1 option!" + exit 1 + fi + CREATE_PORT="$2" + shift 2 + ;; + -V|--verbose) + VERBOSE="-verbose" + shift + ;; + -force) + FORCE=true + shift + ;; + -help|-usage) + print_usage "$SCRIPT_CMD" + exit 0 + ;; + --) + shift + break + ;; + *) + if [ "$1" != "" ]; then + print_usage "$SCRIPT_CMD" "Unrecognized or misplaced argument: $1!" + exit 1 + else + break # out-of-args, stop looping + fi + ;; + esac + done + fi + + if [ -z "$CREATE_CONFDIR" ]; then + CREATE_CONFDIR='_default' + fi + + # validate the confdir arg (if provided) + if [[ ! -d "$SOLR_TIP/server/solr/configsets/$CREATE_CONFDIR" && ! -d "$CREATE_CONFDIR" ]]; then + echo -e "\nSpecified configuration directory $CREATE_CONFDIR not found!\n" + exit 1 + fi + + if [ -z "$CREATE_NAME" ]; then + echo "Name (-c) argument is required!" + print_usage "$SCRIPT_CMD" + exit 1 + fi + + if [ -z "$CREATE_PORT" ]; then + for ID in `ps auxww | grep java | grep start\.jar | awk '{print $2}' | sort -r` + do + port=`jetty_port "$ID"` + if [ "$port" != "" ]; then + CREATE_PORT=$port + break + fi + done + fi + + if [ -z "$CREATE_PORT" ]; then + echo "Failed to determine the port of a local Solr instance, cannot create $CREATE_NAME!" + exit 1 + fi + + if [[ "$CREATE_CONFDIR" == "_default" ]] && ([[ "$CREATE_CONFNAME" == "" ]] || [[ "$CREATE_CONFNAME" == "_default" ]]); then + echo "WARNING: Using _default configset with data driven schema functionality. NOT RECOMMENDED for production use." + echo " To turn off: bin/solr config -c $CREATE_NAME -p $CREATE_PORT -action set-user-property -property update.autoCreateFields -value false" + fi + + if [[ $EUID -eq 0 ]] && [[ "$FORCE" == "false" ]] ; then + echo "WARNING: Creating cores as the root user can cause Solr to fail and is not advisable. Exiting." + echo " If you started Solr as root (not advisable either), force core creation by adding argument -force" + exit 1 + fi + if [ "$SCRIPT_CMD" == "create_core" ]; then + run_tool create_core -name "$CREATE_NAME" -solrUrl "$SOLR_URL_SCHEME://$SOLR_TOOL_HOST:$CREATE_PORT/solr" \ + -confdir "$CREATE_CONFDIR" -configsetsDir "$SOLR_TIP/server/solr/configsets" \ + $VERBOSE + exit $? + else + run_tool "$SCRIPT_CMD" -name "$CREATE_NAME" -solrUrl "$SOLR_URL_SCHEME://$SOLR_TOOL_HOST:$CREATE_PORT/solr" \ + -shards "$CREATE_NUM_SHARDS" -replicationFactor "$CREATE_REPFACT" \ + -confname "$CREATE_CONFNAME" -confdir "$CREATE_CONFDIR" \ + -configsetsDir "$SOLR_TIP/server/solr/configsets" \ + $VERBOSE + exit $? + fi +fi + +# delete a core or collection +if [[ "$SCRIPT_CMD" == "delete" ]]; then + + VERBOSE="" + + if [ $# -gt 0 ]; then + while true; do + case "$1" in + -c|-core|-collection) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "$SCRIPT_CMD" "name is required when using the $1 option!" + exit 1 + fi + DELETE_NAME="$2" + shift 2 + ;; + -p|-port) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "$SCRIPT_CMD" "Solr port is required when using the $1 option!" + exit 1 + fi + DELETE_PORT="$2" + shift 2 + ;; + -deleteConfig) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "$SCRIPT_CMD" "true|false is required when using the $1 option!" + exit 1 + fi + DELETE_CONFIG="$2" + shift 2 + ;; + -V|--verbose) + VERBOSE="-verbose" + shift + ;; + -help|-usage) + print_usage "$SCRIPT_CMD" + exit 0 + ;; + --) + shift + break + ;; + *) + if [ "$1" != "" ]; then + print_usage "$SCRIPT_CMD" "Unrecognized or misplaced argument: $1!" + exit 1 + else + break # out-of-args, stop looping + fi + ;; + esac + done + fi + + if [ -z "$DELETE_NAME" ]; then + echo "Name (-c) argument is required!" + print_usage "$SCRIPT_CMD" + exit 1 + fi + + # If not defined, use the collection name for the name of the configuration in Zookeeper + if [ -z "$DELETE_CONFIG" ]; then + DELETE_CONFIG=true + fi + + if [ -z "$DELETE_PORT" ]; then + for ID in `ps auxww | grep java | grep start\.jar | awk '{print $2}' | sort -r` + do + port=`jetty_port "$ID"` + if [ "$port" != "" ]; then + DELETE_PORT=$port + break + fi + done + fi + + if [ -z "$DELETE_PORT" ]; then + echo "Failed to determine the port of a local Solr instance, cannot delete $DELETE_NAME!" + exit 1 + fi + + run_tool delete -name "$DELETE_NAME" -deleteConfig "$DELETE_CONFIG" \ + -solrUrl "$SOLR_URL_SCHEME://$SOLR_TOOL_HOST:$DELETE_PORT/solr" \ + $VERBOSE + exit $? +fi + +ZK_RECURSE=false +# Zookeeper file maintenance (upconfig, downconfig, files up/down etc.) +# It's a little clumsy to have the parsing go round and round for upconfig and downconfig, but that's +# necessary for back-compat +if [[ "$SCRIPT_CMD" == "zk" ]]; then + + VERBOSE="" + + if [ $# -gt 0 ]; then + while true; do + case "$1" in + -upconfig|upconfig|-downconfig|downconfig|cp|rm|mv|ls|mkroot) + if [ "${1:0:1}" == "-" ]; then + ZK_OP=${1:1} + else + ZK_OP=$1 + fi + shift 1 + ;; + -z|-zkhost) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_short_zk_usage "$SCRIPT_CMD" "ZooKeeper connection string is required when using the $1 option!" + fi + ZK_HOST="$2" + shift 2 + ;; + -n|-confname) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_short_zk_usage "$SCRIPT_CMD" "Configuration name is required when using the $1 option!" + fi + CONFIGSET_CONFNAME="$2" + shift 2 + ;; + -d|-confdir) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_short_zk_usage "$SCRIPT_CMD" "Configuration directory is required when using the $1 option!" + fi + CONFIGSET_CONFDIR="$2" + shift 2 + ;; + -r) + ZK_RECURSE="true" + shift + ;; + -V|--verbose) + VERBOSE="-verbose" + shift + ;; + -help|-usage|-h) + print_usage "$SCRIPT_CMD" + exit 0 + ;; + --) + shift + break + ;; + *) # Pick up or params for rm, ls, cp, mv, mkroot. + if [ "$1" == "" ]; then + break # out-of-args, stop looping + fi + if [ -z "$ZK_SRC" ]; then + ZK_SRC=$1 + else + if [ -z "$ZK_DST" ]; then + ZK_DST=$1 + else + print_short_zk_usage "Unrecognized or misplaced command $1. 'cp' with trailing asterisk requires quoting, see help text." + fi + fi + shift + ;; + esac + done + fi + + if [ -z "$ZK_OP" ]; then + print_short_zk_usage "Zookeeper operation (one of 'upconfig', 'downconfig', 'rm', 'mv', 'cp', 'ls', 'mkroot') is required!" + fi + + if [ -z "$ZK_HOST" ]; then + print_short_zk_usage "Zookeeper address (-z) argument is required or ZK_HOST must be specified in the solr.in.sh file." + fi + + if [[ "$ZK_OP" == "upconfig" || "$ZK_OP" == "downconfig" ]]; then + if [ -z "$CONFIGSET_CONFDIR" ]; then + print_short_zk_usage "Local directory of the configset (-d) argument is required!" + fi + + if [ -z "$CONFIGSET_CONFNAME" ]; then + print_short_zk_usage "Configset name on Zookeeper (-n) argument is required!" + fi + fi + + if [[ "$ZK_OP" == "cp" || "$ZK_OP" == "mv" ]]; then + if [[ -z "$ZK_SRC" || -z "$ZK_DST" ]]; then + print_short_zk_usage " and must be specified when using either the 'mv' or 'cp' commands." + fi + if [[ "$ZK_OP" == "cp" && "${ZK_SRC:0:3}" != "zk:" && "${ZK_DST:0:3}" != "zk:" ]]; then + print_short_zk_usage "One of the source or desintation paths must be prefixed by 'zk:' for the 'cp' command." + fi + fi + + if [[ "$ZK_OP" == "mkroot" ]]; then + if [[ -z "$ZK_SRC" ]]; then + print_short_zk_usage " must be specified when using the 'mkroot' command." + fi + fi + + + case "$ZK_OP" in + upconfig) + run_tool "$ZK_OP" -confname "$CONFIGSET_CONFNAME" -confdir "$CONFIGSET_CONFDIR" -zkHost "$ZK_HOST" -configsetsDir "$SOLR_TIP/server/solr/configsets" $VERBOSE + ;; + downconfig) + run_tool "$ZK_OP" -confname "$CONFIGSET_CONFNAME" -confdir "$CONFIGSET_CONFDIR" -zkHost "$ZK_HOST" $VERBOSE + ;; + rm) + if [ -z "$ZK_SRC" ]; then + print_short_zk_usage "Zookeeper path to remove must be specified when using the 'rm' command" + fi + run_tool "$ZK_OP" -path "$ZK_SRC" -zkHost "$ZK_HOST" -recurse "$ZK_RECURSE" $VERBOSE + ;; + mv) + run_tool "$ZK_OP" -src "$ZK_SRC" -dst "$ZK_DST" -zkHost "$ZK_HOST" $VERBOSE + ;; + cp) + run_tool "$ZK_OP" -src "$ZK_SRC" -dst "$ZK_DST" -zkHost "$ZK_HOST" -recurse "$ZK_RECURSE" $VERBOSE + ;; + ls) + if [ -z "$ZK_SRC" ]; then + print_short_zk_usage "Zookeeper path to list must be specified when using the 'ls' command" + fi + run_tool "$ZK_OP" -path "$ZK_SRC" -recurse "$ZK_RECURSE" -zkHost "$ZK_HOST" $VERBOSE + ;; + mkroot) + if [ -z "$ZK_SRC" ]; then + print_short_zk_usage "Zookeeper path to list must be specified when using the 'mkroot' command" + fi + run_tool "$ZK_OP" -path "$ZK_SRC" -zkHost "$ZK_HOST" $VERBOSE + ;; + *) + print_short_zk_usage "Unrecognized Zookeeper operation $ZK_OP" + ;; + esac + + exit $? +fi + + +if [[ "$SCRIPT_CMD" == "autoscaling" ]]; then + run_tool autoscaling $@ + exit $? +fi + +if [[ "$SCRIPT_CMD" == "export" ]]; then + run_tool export $@ + exit $? +fi + +if [[ "$SCRIPT_CMD" == "package" ]]; then + run_package $@ + exit $? +fi + +if [[ "$SCRIPT_CMD" == "auth" ]]; then + + VERBOSE="" + + declare -a AUTH_PARAMS + if [ $# -gt 0 ]; then + while true; do + case "$1" in + enable|disable) + AUTH_OP=$1 + AUTH_PARAMS=("${AUTH_PARAMS[@]}" "$AUTH_OP") + shift + ;; + -z|-zkhost|zkHost) + ZK_HOST="$2" + AUTH_PARAMS=("${AUTH_PARAMS[@]}" "-zkHost" "$ZK_HOST") + shift 2 + ;; + -t|-type) + AUTH_TYPE="$2" + AUTH_PARAMS=("${AUTH_PARAMS[@]}" "-type" "$AUTH_TYPE") + shift 2 + ;; + -credentials) + AUTH_CREDENTIALS="$2" + AUTH_PARAMS=("${AUTH_PARAMS[@]}" "-credentials" "$AUTH_CREDENTIALS") + shift 2 + ;; + -config) + AUTH_CONFIG="`echo $2| base64`" + AUTH_PARAMS=("${AUTH_PARAMS[@]}" "-config" "$AUTH_CONFIG") + shift 2 + ;; + -solrIncludeFile) + SOLR_INCLUDE="$2" + shift 2 + ;; + -prompt) + AUTH_PARAMS=("${AUTH_PARAMS[@]}" "-prompt" "$2") + shift + ;; + -blockUnknown) + AUTH_PARAMS=("${AUTH_PARAMS[@]}" "-blockUnknown" "$2") + shift + break + ;; + -updateIncludeFileOnly) + AUTH_PARAMS=("${AUTH_PARAMS[@]}" "-updateIncludeFileOnly" "$2") + shift + break + ;; + -V|--verbose) + VERBOSE="-verbose" + shift + ;; + -d|-dir) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "$SCRIPT_CMD" "Server directory is required when using the $1 option!" + exit 1 + fi + + if [[ "$2" == "." || "$2" == "./" || "$2" == ".." || "$2" == "../" ]]; then + SOLR_SERVER_DIR="$(pwd)/$2" + else + # see if the arg value is relative to the tip vs full path + if [[ "$2" != /* ]] && [[ -d "$SOLR_TIP/$2" ]]; then + SOLR_SERVER_DIR="$SOLR_TIP/$2" + else + SOLR_SERVER_DIR="$2" + fi + fi + # resolve it to an absolute path + SOLR_SERVER_DIR="$(cd "$SOLR_SERVER_DIR"; pwd)" + shift 2 + ;; + -s|-solr.home) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "$SCRIPT_CMD" "Solr home directory is required when using the $1 option!" + exit 1 + fi + + SOLR_HOME="$2" + shift 2 + ;; + -help|-usage|-h) + print_usage "$SCRIPT_CMD" + exit 0 + ;; + --) + shift + break + ;; + *) + shift + break + ;; + esac + done + fi + + if [ -z "$SOLR_SERVER_DIR" ]; then + SOLR_SERVER_DIR="$DEFAULT_SERVER_DIR" + fi + if [ ! -e "$SOLR_SERVER_DIR" ]; then + echo -e "\nSolr server directory $SOLR_SERVER_DIR not found!\n" + exit 1 + fi + + if [ -z "$SOLR_HOME" ]; then + SOLR_HOME="$SOLR_SERVER_DIR/solr" + elif [[ $SOLR_HOME != /* ]]; then + if [[ -d "`pwd`/$SOLR_HOME" ]]; then + SOLR_HOME="$(pwd)/$SOLR_HOME" + elif [[ -d "$SOLR_SERVER_DIR/$SOLR_HOME" ]]; then + SOLR_HOME="$SOLR_SERVER_DIR/$SOLR_HOME" + SOLR_PID_DIR="$SOLR_HOME" + fi + fi + + if [ -z "$AUTH_OP" ]; then + print_usage "$SCRIPT_CMD" + exit 0 + fi + + AUTH_PARAMS=("${AUTH_PARAMS[@]}" "-solrIncludeFile" "$SOLR_INCLUDE") + + if [ -z "$AUTH_PORT" ]; then + for ID in `ps auxww | grep java | grep start\.jar | awk '{print $2}' | sort -r` + do + port=`jetty_port "$ID"` + if [ "$port" != "" ]; then + AUTH_PORT=$port + break + fi + done + fi + run_tool auth ${AUTH_PARAMS[@]} -solrUrl "$SOLR_URL_SCHEME://$SOLR_TOOL_HOST:$AUTH_PORT/solr" -authConfDir "$SOLR_HOME" $VERBOSE + exit $? +fi + + +# verify the command given is supported +if [ "$SCRIPT_CMD" != "stop" ] && [ "$SCRIPT_CMD" != "start" ] && [ "$SCRIPT_CMD" != "restart" ] && [ "$SCRIPT_CMD" != "status" ] && [ "$SCRIPT_CMD" != "assert" ]; then + print_usage "" "$SCRIPT_CMD is not a valid command!" + exit 1 +fi + +#Check current Ulimits for Open Files and Max Processes. Warn if they are below the recommended values. + +if [ -z "$SOLR_RECOMMENDED_MAX_PROCESSES" ]; then + SOLR_RECOMMENDED_MAX_PROCESSES=65000 +fi + +if [ -z "$SOLR_RECOMMENDED_OPEN_FILES" ]; then + SOLR_RECOMMENDED_OPEN_FILES=65000 +fi + +if [ -z "$SOLR_ULIMIT_CHECKS" ] || [ "$SOLR_ULIMIT_CHECKS" != "false" ]; then + if [ "$SCRIPT_CMD" == "start" ] || [ "$SCRIPT_CMD" == "restart" ] || [ "$SCRIPT_CMD" == "status" ]; then + if hash ulimit 2>/dev/null; then + openFiles=$(ulimit -n) + maxProcs=$(ulimit -u) + virtualMemory=$(ulimit -v) + maxMemory=$(ulimit -m) + if [ $openFiles != "unlimited" ] && [ $openFiles -lt "$SOLR_RECOMMENDED_OPEN_FILES" ]; then + echo "*** [WARN] *** Your open file limit is currently $openFiles. " + echo " It should be set to $SOLR_RECOMMENDED_OPEN_FILES to avoid operational disruption. " + echo " If you no longer wish to see this warning, set SOLR_ULIMIT_CHECKS to false in your profile or solr.in.sh" + fi + + if [ $maxProcs != "unlimited" ] && [ $maxProcs -lt "$SOLR_RECOMMENDED_MAX_PROCESSES" ]; then + echo "*** [WARN] *** Your Max Processes Limit is currently $maxProcs. " + echo " It should be set to $SOLR_RECOMMENDED_MAX_PROCESSES to avoid operational disruption. " + echo " If you no longer wish to see this warning, set SOLR_ULIMIT_CHECKS to false in your profile or solr.in.sh" + fi + if [ $virtualMemory != "unlimited" ]; then + echo "*** [WARN] *** Your Virtual Memory limit is $virtualMemory. " + echo " It should be set to 'unlimited' to avoid operational disruption. " + echo " If you no longer wish to see this warning, set SOLR_ULIMIT_CHECKS to false in your profile or solr.in.sh" + fi + if [ $maxMemory != "unlimited" ]; then + echo "*** [WARN] *** Your Max Memory Size limit is $maxMemory. " + echo " It should be set to 'unlimited' to avoid operational disruption. " + echo " If you no longer wish to see this warning, set SOLR_ULIMIT_CHECKS to false in your profile or solr.in.sh" + fi + + else + echo "Could not check ulimits for processes and open files, recommended values are" + echo " max processes: $SOLR_RECOMMENDED_MAX_PROCESSES " + echo " open files: $SOLR_RECOMMENDED_OPEN_FILES" + echo " virtual memory: unlimited" + echo " max memorh size: unlimited" + fi + fi +fi + +# Run in foreground (default is to run in the background) +FG="false" +FORCE=false +noprompt=false +SOLR_OPTS=($SOLR_OPTS) +PASS_TO_RUN_EXAMPLE= + +if [ $# -gt 0 ]; then + while true; do + case "$1" in + -c|-cloud) + SOLR_MODE="solrcloud" + PASS_TO_RUN_EXAMPLE+=" -c" + shift + ;; + -d|-dir) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "$SCRIPT_CMD" "Server directory is required when using the $1 option!" + exit 1 + fi + + if [[ "$2" == "." || "$2" == "./" || "$2" == ".." || "$2" == "../" ]]; then + SOLR_SERVER_DIR="$(pwd)/$2" + else + # see if the arg value is relative to the tip vs full path + if [[ "$2" != /* ]] && [[ -d "$SOLR_TIP/$2" ]]; then + SOLR_SERVER_DIR="$SOLR_TIP/$2" + else + SOLR_SERVER_DIR="$2" + fi + fi + # resolve it to an absolute path + SOLR_SERVER_DIR="$(cd "$SOLR_SERVER_DIR"; pwd)" + shift 2 + ;; + -s|-solr.home) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "$SCRIPT_CMD" "Solr home directory is required when using the $1 option!" + exit 1 + fi + + SOLR_HOME="$2" + shift 2 + ;; + -t|-data.home) + SOLR_DATA_HOME="$2" + shift 2 + ;; + -e|-example) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "$SCRIPT_CMD" "Example name is required when using the $1 option!" + exit 1 + fi + EXAMPLE="$2" + shift 2 + ;; + -f|-foreground) + FG="true" + shift + ;; + -h|-host) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "$SCRIPT_CMD" "Hostname is required when using the $1 option!" + exit 1 + fi + SOLR_HOST="$2" + PASS_TO_RUN_EXAMPLE+=" -h $SOLR_HOST" + shift 2 + ;; + -m|-memory) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "$SCRIPT_CMD" "Memory setting is required when using the $1 option!" + exit 1 + fi + SOLR_HEAP="$2" + PASS_TO_RUN_EXAMPLE+=" -m $SOLR_HEAP" + shift 2 + ;; + -p|-port) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "$SCRIPT_CMD" "Port number is required when using the $1 option!" + exit 1 + fi + SOLR_PORT="$2" + PASS_TO_RUN_EXAMPLE+=" -p $SOLR_PORT" + shift 2 + ;; + -z|-zkhost) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "$SCRIPT_CMD" "Zookeeper connection string is required when using the $1 option!" + exit 1 + fi + ZK_HOST="$2" + SOLR_MODE="solrcloud" + PASS_TO_RUN_EXAMPLE+=" -z $ZK_HOST" + shift 2 + ;; + -a|-addlopts) + ADDITIONAL_CMD_OPTS="$2" + PASS_TO_RUN_EXAMPLE+=" -a \"$ADDITIONAL_CMD_OPTS\"" + shift 2 + ;; + -j|-jettyconfig) + ADDITIONAL_JETTY_CONFIG="$2" + PASS_TO_RUN_EXAMPLE+=" -j \"$ADDITIONAL_JETTY_CONFIG\"" + shift 2 + ;; + -k|-key) + STOP_KEY="$2" + shift 2 + ;; + -help|-usage) + print_usage "$SCRIPT_CMD" + exit 0 + ;; + -noprompt) + noprompt=true + PASS_TO_RUN_EXAMPLE+=" -noprompt" + shift + ;; + -V|-verbose) + verbose=true + PASS_TO_RUN_EXAMPLE+=" --verbose" + shift + ;; + -v) + SOLR_LOG_LEVEL=DEBUG + PASS_TO_RUN_EXAMPLE+=" -Dsolr.log.level=$SOLR_LOG_LEVEL" + shift + ;; + -q) + SOLR_LOG_LEVEL=WARN + PASS_TO_RUN_EXAMPLE+=" -Dsolr.log.level=$SOLR_LOG_LEVEL" + shift + ;; + -all) + stop_all=true + shift + ;; + -force) + FORCE=true + PASS_TO_RUN_EXAMPLE+=" -force" + shift + ;; + --) + shift + break + ;; + *) + if [ "${1:0:2}" == "-D" ]; then + # pass thru any opts that begin with -D (java system props) + SOLR_OPTS+=("$1") + PASS_TO_RUN_EXAMPLE+=" $1" + shift + else + if [ "$1" != "" ]; then + print_usage "$SCRIPT_CMD" "$1 is not supported by this script" + exit 1 + else + break # out-of-args, stop looping + fi + fi + ;; + esac + done +fi + +if [[ $SOLR_LOG_LEVEL ]] ; then + SOLR_LOG_LEVEL_OPT="-Dsolr.log.level=$SOLR_LOG_LEVEL" +fi + +if [ -z "$SOLR_SERVER_DIR" ]; then + SOLR_SERVER_DIR="$DEFAULT_SERVER_DIR" +fi + +if [ ! -e "$SOLR_SERVER_DIR" ]; then + echo -e "\nSolr server directory $SOLR_SERVER_DIR not found!\n" + exit 1 +fi + +if [[ "$FG" == 'true' && "$EXAMPLE" != "" ]]; then + FG='false' + echo -e "\nWARNING: Foreground mode (-f) not supported when running examples.\n" +fi + +# +# If the user specified an example to run, invoke the run_example tool (Java app) and exit +# otherwise let this script proceed to process the user request +# +if [ -n "$EXAMPLE" ] && [ "$SCRIPT_CMD" == "start" ]; then + run_tool run_example -e $EXAMPLE -d "$SOLR_SERVER_DIR" -urlScheme $SOLR_URL_SCHEME $PASS_TO_RUN_EXAMPLE + exit $? +fi + +############# start/stop logic below here ################ + +if $verbose ; then + echo "Using Solr root directory: $SOLR_TIP" + echo "Using Java: $JAVA" + "$JAVA" -version +fi + +if [ "$SOLR_HOST" != "" ]; then + SOLR_HOST_ARG=("-Dhost=$SOLR_HOST") +else + SOLR_HOST_ARG=() +fi + +if [ -z "$STOP_KEY" ]; then + STOP_KEY='solrrocks' +fi + +# stop all if no port specified +if [[ "$SCRIPT_CMD" == "stop" && -z "$SOLR_PORT" ]]; then + if $stop_all; then + none_stopped=true + find "$SOLR_PID_DIR" -name "solr-*.pid" -type f | while read PIDF + do + NEXT_PID=`cat "$PIDF"` + port=`jetty_port "$NEXT_PID"` + if [ "$port" != "" ]; then + stop_solr "$SOLR_SERVER_DIR" "$port" "$STOP_KEY" "$NEXT_PID" + none_stopped=false + fi + rm -f "$PIDF" + done + # TODO: none_stopped doesn't get reflected across the subshell + # This can be uncommented once we find a clean way out of it + # if $none_stopped; then + # echo -e "\nNo Solr nodes found to stop.\n" + # fi + else + # not stopping all and don't have a port, but if we can find the pid file for the default port 8983, then use that + none_stopped=true + numSolrs=`find "$SOLR_PID_DIR" -name "solr-*.pid" -type f | wc -l | tr -d ' '` + if [ $numSolrs -eq 1 ]; then + # only do this if there is only 1 node running, otherwise they must provide the -p or -all + PID="$(cat "$(find "$SOLR_PID_DIR" -name "solr-*.pid" -type f)")" + CHECK_PID=`ps auxww | awk '{print $2}' | grep -w $PID | sort -r | tr -d ' '` + if [ "$CHECK_PID" != "" ]; then + port=`jetty_port "$CHECK_PID"` + if [ "$port" != "" ]; then + stop_solr "$SOLR_SERVER_DIR" "$port" "$STOP_KEY" "$CHECK_PID" + none_stopped=false + fi + fi + fi + + if $none_stopped; then + if [ $numSolrs -gt 0 ]; then + echo -e "\nFound $numSolrs Solr nodes running! Must either specify a port using -p or -all to stop all Solr nodes on this host.\n" + else + echo -e "\nNo Solr nodes found to stop.\n" + fi + exit 1 + fi + fi + exit +fi + +if [ -z "$SOLR_PORT" ]; then + SOLR_PORT=8983 +fi + +if [ -z "$STOP_PORT" ]; then + STOP_PORT=`expr $SOLR_PORT - 1000` +fi + +if [ "$SCRIPT_CMD" == "start" ] || [ "$SCRIPT_CMD" == "restart" ] ; then + if [[ $EUID -eq 0 ]] && [[ "$FORCE" == "false" ]] ; then + echo "WARNING: Starting Solr as the root user is a security risk and not considered best practice. Exiting." + echo " Please consult the Reference Guide. To override this check, start with argument '-force'" + exit 1 + fi +fi + +if [[ "$SCRIPT_CMD" == "start" ]]; then + # see if Solr is already running + SOLR_PID=`solr_pid_by_port "$SOLR_PORT"` + + if [ -z "$SOLR_PID" ]; then + # not found using the pid file ... but use ps to ensure not found + SOLR_PID=`ps auxww | grep start\.jar | grep -w "\-Djetty\.port=$SOLR_PORT" | grep -v grep | awk '{print $2}' | sort -r` + fi + + if [ "$SOLR_PID" != "" ]; then + echo -e "\nPort $SOLR_PORT is already being used by another process (pid: $SOLR_PID)\nPlease choose a different port using the -p option.\n" + exit 1 + fi +else + # either stop or restart + # see if Solr is already running + SOLR_PID=`solr_pid_by_port "$SOLR_PORT"` + if [ -z "$SOLR_PID" ]; then + # not found using the pid file ... but use ps to ensure not found + SOLR_PID=`ps auxww | grep start\.jar | grep -w "\-Djetty\.port=$SOLR_PORT" | grep -v grep | awk '{print $2}' | sort -r` + fi + if [ "$SOLR_PID" != "" ]; then + stop_solr "$SOLR_SERVER_DIR" "$SOLR_PORT" "$STOP_KEY" "$SOLR_PID" + else + if [ "$SCRIPT_CMD" == "stop" ]; then + echo -e "No process found for Solr node running on port $SOLR_PORT" + exit 1 + fi + fi +fi + +if [ -z "$SOLR_HOME" ]; then + SOLR_HOME="$SOLR_SERVER_DIR/solr" +elif [[ $SOLR_HOME != /* ]]; then + if [[ -d "`pwd`/$SOLR_HOME" ]]; then + SOLR_HOME="$(pwd)/$SOLR_HOME" + elif [[ -d "$SOLR_SERVER_DIR/$SOLR_HOME" ]]; then + SOLR_HOME="$SOLR_SERVER_DIR/$SOLR_HOME" + SOLR_PID_DIR="$SOLR_HOME" + fi +fi + +# Set the default configset dir to be bootstrapped as _default +if [ -z "$DEFAULT_CONFDIR" ]; then + DEFAULT_CONFDIR="$SOLR_SERVER_DIR/solr/configsets/_default/conf" +fi + +# This is quite hacky, but examples rely on a different log4j2.xml +# so that we can write logs for examples to $SOLR_HOME/../logs +if [ -z "$SOLR_LOGS_DIR" ]; then + SOLR_LOGS_DIR="$SOLR_SERVER_DIR/logs" +fi +EXAMPLE_DIR="$SOLR_TIP/example" +if [ "${SOLR_HOME:0:${#EXAMPLE_DIR}}" = "$EXAMPLE_DIR" ]; then + LOG4J_PROPS="$DEFAULT_SERVER_DIR/resources/log4j2.xml" + SOLR_LOGS_DIR="$SOLR_HOME/../logs" +fi + +LOG4J_CONFIG=() +if [ -n "$LOG4J_PROPS" ]; then + LOG4J_CONFIG+=("-Dlog4j.configurationFile=$LOG4J_PROPS") +fi + +if [ "$SCRIPT_CMD" == "stop" ]; then + # already stopped, script is done. + exit 0 +fi + +# NOTE: If the script gets to here, then it is starting up a Solr node. + +if [ ! -e "$SOLR_HOME" ]; then + echo -e "\nSolr home directory $SOLR_HOME not found!\n" + exit 1 +fi +if [[ $SOLR_DATA_HOME ]] && [ ! -e "$SOLR_DATA_HOME" ]; then + echo -e "\nSolr data home directory $SOLR_DATA_HOME not found!\n" + exit 1 +fi +if $verbose ; then + q="" +else + q="-q" +fi +# Rotate and clean on startup. Default to false since 7.4 as log4j2 handles startup rotation +if [ "${SOLR_LOG_PRESTART_ROTATION:=false}" == "true" ]; then + # Enable any of these if you require old remove/archive behavior + #run_tool utils -s "$DEFAULT_SERVER_DIR" -l "$SOLR_LOGS_DIR" $q -remove_old_solr_logs 7 || echo "Failed removing old solr logs" + #run_tool utils -s "$DEFAULT_SERVER_DIR" -l "$SOLR_LOGS_DIR" $q -archive_gc_logs $q || echo "Failed archiving old GC logs" + #run_tool utils -s "$DEFAULT_SERVER_DIR" -l "$SOLR_LOGS_DIR" $q -archive_console_logs || echo "Failed archiving old console logs" + run_tool utils -s "$DEFAULT_SERVER_DIR" -l "$SOLR_LOGS_DIR" $q -rotate_solr_logs 10 || echo "Failed rotating old solr logs" +fi + +# Establish default GC logging opts if no env var set (otherwise init to sensible default) +if [ -z ${GC_LOG_OPTS+x} ]; then + if [[ "$JAVA_VER_NUM" -lt "9" ]] ; then + GC_LOG_OPTS=('-verbose:gc' '-XX:+PrintHeapAtGC' '-XX:+PrintGCDetails' \ + '-XX:+PrintGCDateStamps' '-XX:+PrintGCTimeStamps' '-XX:+PrintTenuringDistribution' \ + '-XX:+PrintGCApplicationStoppedTime') + else + GC_LOG_OPTS=('-Xlog:gc*') + fi +else + GC_LOG_OPTS=($GC_LOG_OPTS) +fi + +# if verbose gc logging enabled, setup the location of the log file and rotation +if [ "$GC_LOG_OPTS" != "" ]; then + if [[ "$JAVA_VER_NUM" -lt "9" ]] ; then + gc_log_flag="-Xloggc" + if [ "$JAVA_VENDOR" == "IBM J9" ]; then + gc_log_flag="-Xverbosegclog" + fi + GC_LOG_OPTS+=("$gc_log_flag:$SOLR_LOGS_DIR/solr_gc.log" '-XX:+UseGCLogFileRotation' '-XX:NumberOfGCLogFiles=9' '-XX:GCLogFileSize=20M') + else + # http://openjdk.java.net/jeps/158 + for i in "${!GC_LOG_OPTS[@]}"; + do + # for simplicity, we only look at the prefix '-Xlog:gc' + # (if 'all' or multiple tags are used starting with anything other then 'gc' the user is on their own) + # if a single additional ':' exists in param, then there is already an explicit output specifier + GC_LOG_OPTS[$i]=$(echo ${GC_LOG_OPTS[$i]} | sed "s|^\(-Xlog:gc[^:]*$\)|\1:file=$SOLR_LOGS_DIR/solr_gc.log:time,uptime:filecount=9,filesize=20M|") + done + fi +fi + +# If ZK_HOST is defined, the assume SolrCloud mode +if [[ -n "$ZK_HOST" ]]; then + SOLR_MODE="solrcloud" +fi + +if [ "$SOLR_MODE" == 'solrcloud' ]; then + if [ -z "$ZK_CLIENT_TIMEOUT" ]; then + ZK_CLIENT_TIMEOUT="15000" + fi + + CLOUD_MODE_OPTS=("-DzkClientTimeout=$ZK_CLIENT_TIMEOUT") + + if [ "$ZK_HOST" != "" ]; then + CLOUD_MODE_OPTS+=("-DzkHost=$ZK_HOST") + else + if $verbose ; then + echo "Configuring SolrCloud to launch an embedded Zookeeper using -DzkRun" + fi + + CLOUD_MODE_OPTS+=('-DzkRun') + fi + + # and if collection1 needs to be bootstrapped + if [ -e "$SOLR_HOME/collection1/core.properties" ]; then + CLOUD_MODE_OPTS+=('-Dbootstrap_confdir=./solr/collection1/conf' '-Dcollection.configName=myconf' '-DnumShards=1') + fi + +else + if [ ! -e "$SOLR_HOME/solr.xml" ]; then + echo -e "\nSolr home directory $SOLR_HOME must contain a solr.xml file!\n" + exit 1 + fi +fi + +# IP-based access control +IP_ACL_OPTS=("-Dsolr.jetty.inetaccess.includes=${SOLR_IP_WHITELIST}" \ + "-Dsolr.jetty.inetaccess.excludes=${SOLR_IP_BLACKLIST}") + +# These are useful for attaching remote profilers like VisualVM/JConsole +if [ "$ENABLE_REMOTE_JMX_OPTS" == "true" ]; then + + if [ -z "$RMI_PORT" ]; then + RMI_PORT=`expr $SOLR_PORT + 10000` + if [ $RMI_PORT -gt 65535 ]; then + echo -e "\nRMI_PORT is $RMI_PORT, which is invalid!\n" + exit 1 + fi + fi + + REMOTE_JMX_OPTS=('-Dcom.sun.management.jmxremote' \ + '-Dcom.sun.management.jmxremote.local.only=false' \ + '-Dcom.sun.management.jmxremote.ssl=false' \ + '-Dcom.sun.management.jmxremote.authenticate=false' \ + "-Dcom.sun.management.jmxremote.port=$RMI_PORT" \ + "-Dcom.sun.management.jmxremote.rmi.port=$RMI_PORT") + + # if the host is set, then set that as the rmi server hostname + if [ "$SOLR_HOST" != "" ]; then + REMOTE_JMX_OPTS+=("-Djava.rmi.server.hostname=$SOLR_HOST") + fi +else + REMOTE_JMX_OPTS=() +fi + +# Enable java security manager (limiting filesystem access and other things) +if [ "$SOLR_SECURITY_MANAGER_ENABLED" == "true" ]; then + SECURITY_MANAGER_OPTS=('-Djava.security.manager' \ + "-Djava.security.policy=${SOLR_SERVER_DIR}/etc/security.policy" \ + "-Djava.security.properties=${SOLR_SERVER_DIR}/etc/security.properties" \ + '-Dsolr.internal.network.permission=*') +else + SECURITY_MANAGER_OPTS=() +fi + +JAVA_MEM_OPTS=() +if [ -z "$SOLR_HEAP" ] && [ -n "$SOLR_JAVA_MEM" ]; then + JAVA_MEM_OPTS=($SOLR_JAVA_MEM) +else + SOLR_HEAP="${SOLR_HEAP:-512m}" + JAVA_MEM_OPTS=("-Xms$SOLR_HEAP" "-Xmx$SOLR_HEAP") +fi + +# Pick default for Java thread stack size, and then add to SOLR_OPTS +if [ -z ${SOLR_JAVA_STACK_SIZE+x} ]; then + SOLR_JAVA_STACK_SIZE='-Xss256k' +fi +SOLR_OPTS+=($SOLR_JAVA_STACK_SIZE) + +if [ -z "$SOLR_TIMEZONE" ]; then + SOLR_TIMEZONE='UTC' +fi + +# Launches Solr in foreground/background depending on parameters +function start_solr() { + + run_in_foreground="$1" + stop_port="$STOP_PORT" + + SOLR_ADDL_ARGS="$2" + SOLR_JETTY_ADDL_CONFIG="$3" + + # define default GC_TUNE + if [ -z ${GC_TUNE+x} ]; then + GC_TUNE=('-XX:+UseG1GC' \ + '-XX:+PerfDisableSharedMem' \ + '-XX:+ParallelRefProcEnabled' \ + '-XX:MaxGCPauseMillis=250' \ + '-XX:+UseLargePages' \ + '-XX:+AlwaysPreTouch' \ + '-XX:+ExplicitGCInvokesConcurrent') + else + GC_TUNE=($GC_TUNE) + fi + + if [ -n "$SOLR_WAIT_FOR_ZK" ]; then + WAIT_FOR_ZK_PROP="-DwaitForZk=$SOLR_WAIT_FOR_ZK" + SOLR_OPTS+=($WAIT_FOR_ZK_PROP) + fi + + # If SSL-related system props are set, add them to SOLR_OPTS + if [ "$SOLR_SSL_ENABLED" ]; then + # If using SSL and solr.jetty.https.port not set explicitly, use the jetty.port + SSL_PORT_PROP="-Dsolr.jetty.https.port=$SOLR_PORT" + SOLR_OPTS+=($SOLR_SSL_OPTS "$SSL_PORT_PROP") + fi + + # If authentication system props are set, add them to SOLR_OPTS + if [ -n "$AUTHC_OPTS" ]; then + SOLR_OPTS+=($AUTHC_OPTS) + fi + + if $verbose ; then + echo -e "\nStarting Solr using the following settings:" + echo -e " JAVA = $JAVA" + echo -e " SOLR_SERVER_DIR = $SOLR_SERVER_DIR" + echo -e " SOLR_HOME = $SOLR_HOME" + echo -e " SOLR_HOST = $SOLR_HOST" + echo -e " SOLR_PORT = $SOLR_PORT" + echo -e " STOP_PORT = $STOP_PORT" + echo -e " JAVA_MEM_OPTS = ${JAVA_MEM_OPTS[@]}" + echo -e " GC_TUNE = ${GC_TUNE[@]}" + echo -e " GC_LOG_OPTS = ${GC_LOG_OPTS[@]}" + echo -e " SOLR_TIMEZONE = $SOLR_TIMEZONE" + + if [ "$SOLR_MODE" == "solrcloud" ]; then + echo -e " CLOUD_MODE_OPTS = ${CLOUD_MODE_OPTS[@]}" + fi + + if [ "$SOLR_OPTS" != "" ]; then + echo -e " SOLR_OPTS = ${SOLR_OPTS[@]}" + fi + + if [ "$SOLR_ADDL_ARGS" != "" ]; then + echo -e " SOLR_ADDL_ARGS = $SOLR_ADDL_ARGS" + fi + + if [ "$ENABLE_REMOTE_JMX_OPTS" == "true" ]; then + echo -e " RMI_PORT = $RMI_PORT" + echo -e " REMOTE_JMX_OPTS = ${REMOTE_JMX_OPTS[@]}" + fi + + if [ "$SOLR_LOG_LEVEL" != "" ]; then + echo -e " SOLR_LOG_LEVEL = $SOLR_LOG_LEVEL" + fi + + if [ "$SOLR_DATA_HOME" != "" ]; then + echo -e " SOLR_DATA_HOME = $SOLR_DATA_HOME" + fi + echo -e "\n" + fi + + # need to launch solr from the server dir + cd "$SOLR_SERVER_DIR" + + if [ ! -e "$SOLR_SERVER_DIR/start.jar" ]; then + echo -e "\nERROR: start.jar file not found in $SOLR_SERVER_DIR!\nPlease check your -d parameter to set the correct Solr server directory.\n" + exit 1 + fi + + SOLR_START_OPTS=('-server' "${JAVA_MEM_OPTS[@]}" "${GC_TUNE[@]}" "${GC_LOG_OPTS[@]}" "${IP_ACL_OPTS[@]}" \ + "${REMOTE_JMX_OPTS[@]}" "${CLOUD_MODE_OPTS[@]}" $SOLR_LOG_LEVEL_OPT -Dsolr.log.dir="$SOLR_LOGS_DIR" \ + "-Djetty.port=$SOLR_PORT" "-DSTOP.PORT=$stop_port" "-DSTOP.KEY=$STOP_KEY" \ + # '-OmitStackTraceInFastThrow' ensures stack traces in errors, + # users who don't care about useful error msgs can override in SOLR_OPTS with +OmitStackTraceInFastThrow + "${SOLR_HOST_ARG[@]}" "-Duser.timezone=$SOLR_TIMEZONE" "-XX:-OmitStackTraceInFastThrow" \ + "-Djetty.home=$SOLR_SERVER_DIR" "-Dsolr.solr.home=$SOLR_HOME" "-Dsolr.data.home=$SOLR_DATA_HOME" "-Dsolr.install.dir=$SOLR_TIP" \ + "-Dsolr.default.confdir=$DEFAULT_CONFDIR" "${LOG4J_CONFIG[@]}" "${SOLR_OPTS[@]}" "${SECURITY_MANAGER_OPTS[@]}") + + if [ "$SOLR_MODE" == "solrcloud" ]; then + IN_CLOUD_MODE=" in SolrCloud mode" + fi + + mkdir -p "$SOLR_LOGS_DIR" 2>/dev/null + if [ $? -ne 0 ]; then + echo -e "\nERROR: Logs directory $SOLR_LOGS_DIR could not be created. Exiting" + exit 1 + fi + if [ ! -w "$SOLR_LOGS_DIR" ]; then + echo -e "\nERROR: Logs directory $SOLR_LOGS_DIR is not writable. Exiting" + exit 1 + fi + case "$SOLR_LOGS_DIR" in + contexts|etc|lib|modules|resources|scripts|solr|solr-webapp) + echo -e "\nERROR: Logs directory $SOLR_LOGS_DIR is invalid. Reserved for the system. Exiting" + exit 1 + ;; + esac + + if [ "$run_in_foreground" == "true" ]; then + exec "$JAVA" "${SOLR_START_OPTS[@]}" $SOLR_ADDL_ARGS -jar start.jar "${SOLR_JETTY_CONFIG[@]}" $SOLR_JETTY_ADDL_CONFIG + else + # run Solr in the background + nohup "$JAVA" "${SOLR_START_OPTS[@]}" $SOLR_ADDL_ARGS -Dsolr.log.muteconsole \ + "-XX:OnOutOfMemoryError=$SOLR_TIP/bin/oom_solr.sh $SOLR_PORT $SOLR_LOGS_DIR" \ + -jar start.jar "${SOLR_JETTY_CONFIG[@]}" $SOLR_JETTY_ADDL_CONFIG \ + 1>"$SOLR_LOGS_DIR/solr-$SOLR_PORT-console.log" 2>&1 & echo $! > "$SOLR_PID_DIR/solr-$SOLR_PORT.pid" + + # check if /proc/sys/kernel/random/entropy_avail exists then check output of cat /proc/sys/kernel/random/entropy_avail to see if less than 300 + if [[ -f /proc/sys/kernel/random/entropy_avail ]] && (( `cat /proc/sys/kernel/random/entropy_avail` < 300)); then + echo "Warning: Available entropy is low. As a result, use of the UUIDField, SSL, or any other features that require" + echo "RNG might not work properly. To check for the amount of available entropy, use 'cat /proc/sys/kernel/random/entropy_avail'." + echo "" + fi + # no lsof on cygwin though + if lsof -v 2>&1 | grep -q revision; then + echo -n "Waiting up to $SOLR_STOP_WAIT seconds to see Solr running on port $SOLR_PORT" + # Launch in a subshell to show the spinner + (loops=0 + while true + do + running=$(lsof -t -PniTCP:$SOLR_PORT -sTCP:LISTEN) + if [ -z "$running" ]; then + slept=$((loops * 2)) + if [ $slept -lt $SOLR_STOP_WAIT ]; then + sleep 2 + loops=$[$loops+1] + else + echo -e "Still not seeing Solr listening on $SOLR_PORT after $SOLR_STOP_WAIT seconds!" + tail -30 "$SOLR_LOGS_DIR/solr.log" + exit # subshell! + fi + else + SOLR_PID=`ps auxww | grep start\.jar | grep -w "\-Djetty\.port=$SOLR_PORT" | grep -v grep | awk '{print $2}' | sort -r` + echo -e "\nStarted Solr server on port $SOLR_PORT (pid=$SOLR_PID). Happy searching!\n" + exit # subshell! + fi + done) & + spinner $! + else + echo -e "NOTE: Please install lsof as this script needs it to determine if Solr is listening on port $SOLR_PORT." + sleep 10 + SOLR_PID=`ps auxww | grep start\.jar | grep -w "\-Djetty\.port=$SOLR_PORT" | grep -v grep | awk '{print $2}' | sort -r` + echo -e "\nStarted Solr server on port $SOLR_PORT (pid=$SOLR_PID). Happy searching!\n" + return; + fi + fi +} + +start_solr "$FG" "$ADDITIONAL_CMD_OPTS" "$ADDITIONAL_JETTY_CONFIG" + +exit $? diff --git a/KeywordSearch/solr/bin/solr.cmd b/KeywordSearch/solr/bin/solr.cmd new file mode 100755 index 0000000000..b25a6be44e --- /dev/null +++ b/KeywordSearch/solr/bin/solr.cmd @@ -0,0 +1,2069 @@ +@REM +@REM Licensed to the Apache Software Foundation (ASF) under one or more +@REM contributor license agreements. See the NOTICE file distributed with +@REM this work for additional information regarding copyright ownership. +@REM The ASF licenses this file to You under the Apache License, Version 2.0 +@REM (the "License"); you may not use this file except in compliance with +@REM the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, software +@REM distributed under the License is distributed on an "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@REM See the License for the specific language governing permissions and +@REM limitations under the License. + +@echo off + +@REM Make sure to keep line endings as CRLF for .cmd files + +IF "%OS%"=="Windows_NT" setlocal enabledelayedexpansion enableextensions + +set "PASS_TO_RUN_EXAMPLE=" + +REM Determine top-level Solr directory +set SDIR=%~dp0 +IF "%SDIR:~-1%"=="\" set SDIR=%SDIR:~0,-1% +set SOLR_TIP=%SDIR%\.. +pushd %SOLR_TIP% +set SOLR_TIP=%CD% +popd + +REM Used to report errors before exiting the script +set SCRIPT_ERROR= +set NO_USER_PROMPT=0 + +REM Allow user to import vars from an include file +REM vars set in the include file can be overridden with +REM command line args +IF "%SOLR_INCLUDE%"=="" set "SOLR_INCLUDE=%SOLR_TIP%\bin\solr.in.cmd" +IF EXIST "%SOLR_INCLUDE%" CALL "%SOLR_INCLUDE%" + +set "DEFAULT_SERVER_DIR=%SOLR_TIP%\server" + +REM Select HTTP OR HTTPS related configurations +set SOLR_URL_SCHEME=http +set "SOLR_JETTY_CONFIG=--module=http" +set "SOLR_SSL_OPTS= " + +IF DEFINED SOLR_HADOOP_CREDENTIAL_PROVIDER_PATH ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dhadoop.security.credential.provider.path=%SOLR_HADOOP_CREDENTIAL_PROVIDER_PATH%" +) + +IF NOT DEFINED SOLR_SSL_ENABLED ( + IF DEFINED SOLR_SSL_KEY_STORE ( + set "SOLR_SSL_ENABLED=true" + ) ELSE ( + set "SOLR_SSL_ENABLED=false" + ) +) + +IF "%SOLR_SSL_ENABLED%"=="true" ( + set "SOLR_JETTY_CONFIG=--lib="%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*"" + if !JAVA_MAJOR_VERSION! GEQ 9 ( + set "SOLR_JETTY_CONFIG=!SOLR_JETTY_CONFIG! --module=https" + ) else ( + set "SOLR_JETTY_CONFIG=!SOLR_JETTY_CONFIG! --module=https8" + ) + set SOLR_URL_SCHEME=https + IF DEFINED SOLR_SSL_KEY_STORE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dsolr.jetty.keystore=%SOLR_SSL_KEY_STORE%" + ) + + IF DEFINED SOLR_SSL_KEY_STORE_TYPE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dsolr.jetty.keystore.type=%SOLR_SSL_KEY_STORE_TYPE%" + ) + + IF DEFINED SOLR_SSL_TRUST_STORE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dsolr.jetty.truststore=%SOLR_SSL_TRUST_STORE%" + ) + IF DEFINED SOLR_SSL_TRUST_STORE_TYPE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dsolr.jetty.truststore.type=%SOLR_SSL_TRUST_STORE_TYPE%" + ) + + IF NOT DEFINED SOLR_SSL_CLIENT_HOSTNAME_VERIFICATION ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dsolr.jetty.ssl.verifyClientHostName=HTTPS" + ) + + IF DEFINED SOLR_SSL_NEED_CLIENT_AUTH ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dsolr.jetty.ssl.needClientAuth=%SOLR_SSL_NEED_CLIENT_AUTH%" + ) + IF DEFINED SOLR_SSL_WANT_CLIENT_AUTH ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dsolr.jetty.ssl.wantClientAuth=%SOLR_SSL_WANT_CLIENT_AUTH%" + ) + + IF DEFINED SOLR_SSL_CLIENT_KEY_STORE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.keyStore=%SOLR_SSL_CLIENT_KEY_STORE%" + + IF DEFINED SOLR_SSL_CLIENT_KEY_STORE_TYPE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.keyStoreType=%SOLR_SSL_CLIENT_KEY_STORE_TYPE%" + ) + ) ELSE ( + IF DEFINED SOLR_SSL_KEY_STORE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.keyStore=%SOLR_SSL_KEY_STORE%" + ) + IF DEFINED SOLR_SSL_KEY_STORE_TYPE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.keyStoreType=%SOLR_SSL_KEY_STORE_TYPE%" + ) + ) + + IF DEFINED SOLR_SSL_CLIENT_TRUST_STORE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.trustStore=%SOLR_SSL_CLIENT_TRUST_STORE%" + + IF DEFINED SOLR_SSL_CLIENT_TRUST_STORE_TYPE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.trustStoreType=%SOLR_SSL_CLIENT_TRUST_STORE_TYPE%" + ) + ) ELSE ( + IF DEFINED SOLR_SSL_TRUST_STORE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.trustStore=%SOLR_SSL_TRUST_STORE%" + ) + IF DEFINED SOLR_SSL_TRUST_STORE_TYPE ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Djavax.net.ssl.trustStoreType=%SOLR_SSL_TRUST_STORE_TYPE%" + ) + ) + IF DEFINED SOLR_SSL_CHECK_PEER_NAME ( + set "SOLR_SSL_OPTS=!SOLR_SSL_OPTS! -Dsolr.ssl.checkPeerName=%SOLR_SSL_CHECK_PEER_NAME%" + ) +) ELSE ( + set SOLR_SSL_OPTS= +) + +REM Requestlog options +IF "%SOLR_REQUESTLOG_ENABLED%"=="true" ( + set "SOLR_JETTY_CONFIG=!SOLR_JETTY_CONFIG! --module=requestlog" +) + +REM Authentication options + +IF NOT DEFINED SOLR_AUTH_TYPE ( + IF DEFINED SOLR_AUTHENTICATION_OPTS ( + echo WARNING: SOLR_AUTHENTICATION_OPTS variable configured without associated SOLR_AUTH_TYPE variable + echo Please configure SOLR_AUTH_TYPE variable with the authentication type to be used. + echo Currently supported authentication types are [kerberos, basic] + ) +) + +IF DEFINED SOLR_AUTH_TYPE ( + IF DEFINED SOLR_AUTHENTICATION_CLIENT_BUILDER ( + echo WARNING: SOLR_AUTHENTICATION_CLIENT_BUILDER and SOLR_AUTH_TYPE variables are configured together + echo Use SOLR_AUTH_TYPE variable to configure authentication type to be used + echo Currently supported authentication types are [kerberos, basic] + echo The value of SOLR_AUTHENTICATION_CLIENT_BUILDER configuration variable will be ignored + ) +) + +IF DEFINED SOLR_AUTH_TYPE ( + IF /I "%SOLR_AUTH_TYPE%" == "basic" ( + set SOLR_AUTHENTICATION_CLIENT_BUILDER="org.apache.solr.client.solrj.impl.PreemptiveBasicAuthClientBuilderFactory" + ) ELSE ( + IF /I "%SOLR_AUTH_TYPE%" == "kerberos" ( + set SOLR_AUTHENTICATION_CLIENT_BUILDER="org.apache.solr.client.solrj.impl.PreemptiveBasicAuthClientBuilderFactory" + ) ELSE ( + echo ERROR: Value specified for SOLR_AUTH_TYPE configuration variable is invalid. + goto err + ) + ) +) + +IF DEFINED SOLR_AUTHENTICATION_CLIENT_CONFIGURER ( + echo WARNING: Found unsupported configuration variable SOLR_AUTHENTICATION_CLIENT_CONFIGURER + echo Please start using SOLR_AUTH_TYPE instead +) +IF DEFINED SOLR_AUTHENTICATION_CLIENT_BUILDER ( + set AUTHC_CLIENT_BUILDER_ARG="-Dsolr.httpclient.builder.factory=%SOLR_AUTHENTICATION_CLIENT_BUILDER%" +) +set "AUTHC_OPTS=%AUTHC_CLIENT_BUILDER_ARG% %SOLR_AUTHENTICATION_OPTS%" + +REM Set the SOLR_TOOL_HOST variable for use when connecting to a running Solr instance +IF NOT "%SOLR_HOST%"=="" ( + set "SOLR_TOOL_HOST=%SOLR_HOST%" +) ELSE ( + set "SOLR_TOOL_HOST=localhost" +) +IF "%SOLR_JETTY_HOST%"=="" ( + set SOLR_JETTY_HOST=0.0.0.0 +) + +REM Verify Java is available +IF DEFINED SOLR_JAVA_HOME set "JAVA_HOME=%SOLR_JAVA_HOME%" +REM Try to detect JAVA_HOME from the registry +IF NOT DEFINED JAVA_HOME ( + FOR /F "skip=2 tokens=2*" %%A IN ('REG QUERY "HKLM\Software\JavaSoft\Java Runtime Environment" /v CurrentVersion') DO set CurVer=%%B + FOR /F "skip=2 tokens=2*" %%A IN ('REG QUERY "HKLM\Software\JavaSoft\Java Runtime Environment\!CurVer!" /v JavaHome') DO ( + set "JAVA_HOME=%%B" + ) +) +IF NOT DEFINED JAVA_HOME goto need_java_home +set JAVA_HOME=%JAVA_HOME:"=% +IF %JAVA_HOME:~-1%==\ SET JAVA_HOME=%JAVA_HOME:~0,-1% +IF NOT EXIST "%JAVA_HOME%\bin\java.exe" ( + set "SCRIPT_ERROR=java.exe not found in %JAVA_HOME%\bin. Please set JAVA_HOME to a valid JRE / JDK directory." + goto err +) +set "JAVA=%JAVA_HOME%\bin\java" +CALL :resolve_java_info +IF !JAVA_MAJOR_VERSION! LSS 8 ( + set "SCRIPT_ERROR=Java 1.8 or later is required to run Solr. Current Java version is: !JAVA_VERSION_INFO! (detected major: !JAVA_MAJOR_VERSION!)" + goto err +) + +set FIRST_ARG=%1 + +IF [%1]==[] goto usage + +IF "%1"=="-help" goto usage +IF "%1"=="-usage" goto usage +IF "%1"=="-h" goto usage +IF "%1"=="--help" goto usage +IF "%1"=="/?" goto usage +IF "%1"=="-i" goto get_info +IF "%1"=="-info" goto get_info +IF "%1"=="status" goto get_info +IF "%1"=="version" goto get_version +IF "%1"=="-v" goto get_version +IF "%1"=="-version" goto get_version +IF "%1"=="assert" goto run_assert +IF "%1"=="autoscaling" goto run_autoscaling +IF "%1"=="export" goto run_export +IF "%1"=="package" goto run_package + +REM Only allow the command to be the first argument, assume start if not supplied +IF "%1"=="start" goto set_script_cmd +IF "%1"=="stop" goto set_script_cmd +IF "%1"=="restart" goto set_script_cmd +IF "%1"=="healthcheck" ( + REM healthcheck uses different arg parsing strategy + set SCRIPT_CMD=healthcheck + SHIFT + goto parse_healthcheck_args +) +IF "%1"=="create" ( + set SCRIPT_CMD=create + SHIFT + goto parse_create_args +) +IF "%1"=="create_core" ( + set SCRIPT_CMD=create_core + SHIFT + goto parse_create_args +) +IF "%1"=="create_collection" ( + set SCRIPT_CMD=create_collection + SHIFT + goto parse_create_args +) +IF "%1"=="delete" ( + set SCRIPT_CMD=delete + SHIFT + goto parse_delete_args +) +IF "%1"=="zk" ( + set SCRIPT_CMD=zk + SHIFT + set ZK_RECURSE=false + goto parse_zk_args +) +IF "%1"=="auth" ( + set SCRIPT_CMD=auth + SHIFT + goto run_auth +) +IF "%1"=="config" ( + REM config uses different arg parsing strategy + set SCRIPT_CMD=config + SHIFT + set CONFIG_ARGS= + goto parse_config_args +) + +goto parse_args + +:usage +IF NOT "%SCRIPT_ERROR%"=="" ECHO %SCRIPT_ERROR% +IF [%FIRST_ARG%]==[] goto script_usage +IF "%FIRST_ARG%"=="-help" goto script_usage +IF "%FIRST_ARG%"=="-usage" goto script_usage +IF "%FIRST_ARG%"=="-h" goto script_usage +IF "%FIRST_ARG%"=="--help" goto script_usage +IF "%FIRST_ARG%"=="/?" goto script_usage +IF "%SCRIPT_CMD%"=="start" goto start_usage +IF "%SCRIPT_CMD%"=="restart" goto start_usage +IF "%SCRIPT_CMD%"=="stop" goto stop_usage +IF "%SCRIPT_CMD%"=="healthcheck" goto healthcheck_usage +IF "%SCRIPT_CMD%"=="create" goto create_usage +IF "%SCRIPT_CMD%"=="create_core" goto create_core_usage +IF "%SCRIPT_CMD%"=="create_collection" goto create_collection_usage +IF "%SCRIPT_CMD%"=="delete" goto delete_usage +IF "%SCRIPT_CMD%"=="zk" goto zk_usage +IF "%SCRIPT_CMD%"=="auth" goto auth_usage +IF "%SCRIPT_CMD%"=="status" goto status_usage +goto done + +:script_usage +@echo. +@echo Usage: solr COMMAND OPTIONS +@echo where COMMAND is one of: start, stop, restart, healthcheck, create, create_core, create_collection, delete, version, zk, auth, assert, config, autoscaling, export +@echo. +@echo Standalone server example (start Solr running in the background on port 8984): +@echo. +@echo solr start -p 8984 +@echo. +@echo SolrCloud example (start Solr running in SolrCloud mode using localhost:2181 to connect to Zookeeper, with 1g max heap size and remote Java debug options enabled): +@echo. +@echo solr start -c -m 1g -z localhost:2181 -a "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=1044" +@echo. +@echo Omit '-z localhost:2181' from the above command if you have defined ZK_HOST in solr.in.cmd. +@echo. +@echo Pass -help after any COMMAND to see command-specific usage information, +@echo such as: solr start -help or solr stop -help +@echo. +goto done + +:start_usage +@echo. +@echo Usage: solr %SCRIPT_CMD% [-f] [-c] [-h hostname] [-p port] [-d directory] [-z zkHost] [-m memory] [-e example] [-s solr.solr.home] [-t solr.data.home] [-a "additional-options"] [-V] +@echo. +@echo -f Start Solr in foreground; default starts Solr in the background +@echo and sends stdout / stderr to solr-PORT-console.log +@echo. +@echo -c or -cloud Start Solr in SolrCloud mode; if -z not supplied and ZK_HOST not defined in +@echo solr.in.cmd, an embedded ZooKeeper instance is started on Solr port+1000, +@echo such as 9983 if Solr is bound to 8983 +@echo. +@echo -h host Specify the hostname for this Solr instance +@echo. +@echo -p port Specify the port to start the Solr HTTP listener on; default is 8983 +@echo " The specified port (SOLR_PORT) will also be used to determine the stop port" +@echo " STOP_PORT=(\$SOLR_PORT-1000) and JMX RMI listen port RMI_PORT=(\$SOLR_PORT+10000). " +@echo " For instance, if you set -p 8985, then the STOP_PORT=7985 and RMI_PORT=18985" +@echo. +@echo -d dir Specify the Solr server directory; defaults to server +@echo. +@echo -z zkHost Zookeeper connection string; only used when running in SolrCloud mode using -c +@echo If neither ZK_HOST is defined in solr.in.cmd nor the -z parameter is specified, +@echo an embedded ZooKeeper instance will be launched. +@echo. +@echo -m memory Sets the min (-Xms) and max (-Xmx) heap size for the JVM, such as: -m 4g +@echo results in: -Xms4g -Xmx4g; by default, this script sets the heap size to 512m +@echo. +@echo -s dir Sets the solr.solr.home system property; Solr will create core directories under +@echo this directory. This allows you to run multiple Solr instances on the same host +@echo while reusing the same server directory set using the -d parameter. If set, the +@echo specified directory should contain a solr.xml file, unless solr.xml exists in Zookeeper. +@echo This parameter is ignored when running examples (-e), as the solr.solr.home depends +@echo on which example is run. The default value is server/solr. If passed a relative dir +@echo validation with the current dir will be done before trying the default server/^ +@echo. +@echo -t dir Sets the solr.data.home system property, where Solr will store index data in ^/data subdirectories. +@echo If not set, Solr uses solr.solr.home for both config and data. +@echo. +@echo -e example Name of the example to run; available examples: +@echo cloud: SolrCloud example +@echo techproducts: Comprehensive example illustrating many of Solr's core capabilities +@echo dih: Data Import Handler +@echo schemaless: Schema-less example +@echo. +@echo -a opts Additional parameters to pass to the JVM when starting Solr, such as to setup +@echo Java debug options. For example, to enable a Java debugger to attach to the Solr JVM +@echo you could pass: -a "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=18983" +@echo In most cases, you should wrap the additional parameters in double quotes. +@echo. +@echo -j opts Additional parameters to pass to Jetty when starting Solr. +@echo For example, to add configuration folder that jetty should read +@echo you could pass: -j "--include-jetty-dir=/etc/jetty/custom/server/" +@echo In most cases, you should wrap the additional parameters in double quotes. +@echo. +@echo -noprompt Don't prompt for input; accept all defaults when running examples that accept user input +@echo. +@echo -v and -q Verbose (-v) or quiet (-q) logging. Sets default log level to DEBUG or WARN instead of INFO +@echo. +@echo -V/-verbose Verbose messages from this script +@echo. +goto done + +:status_usage +@echo. +@echo Usage: solr status +@echo. +@echo NOTE: This command will show the status of all running Solr servers +@echo. +goto done + +:stop_usage +@echo. +@echo Usage: solr stop [-k key] [-p port] [-V] +@echo. +@echo -k key Stop key; default is solrrocks +@echo. +@echo -p port Specify the port the Solr HTTP listener is bound to +@echo. +@echo -all Find and stop all running Solr servers on this host +@echo. +@echo -V/-verbose Verbose messages from this script +@echo. +@echo NOTE: To see if any Solr servers are running, do: solr status +@echo. +goto done + +:healthcheck_usage +@echo. +@echo Usage: solr healthcheck [-c collection] [-z zkHost] [-V] +@echo. +@echo Can be run from remote (non-Solr^) hosts, as long as a proper ZooKeeper connection is provided +@echo. +@echo -c collection Collection to run healthcheck against. +@echo. +@echo -z zkHost Zookeeper connection string; unnecessary if ZK_HOST is defined in solr.in.cmd; +@echo otherwise, default is localhost:9983 +@echo. +@echo -V Enable more verbose output +@echo. +goto done + +:create_usage +echo. +echo Usage: solr create [-c name] [-d confdir] [-n confname] [-shards #] [-replicationFactor #] [-p port] [-V] +echo. +echo Create a core or collection depending on whether Solr is running in standalone (core) or SolrCloud +echo mode (collection). In other words, this action detects which mode Solr is running in, and then takes +echo the appropriate action (either create_core or create_collection). For detailed usage instructions, do: +echo. +echo bin\solr create_core -help +echo. +echo or +echo. +echo bin\solr create_collection -help +echo. +goto done + +:delete_usage +echo. +echo Usage: solr delete [-c name] [-deleteConfig true^|false] [-p port] [-V] +echo. +echo Deletes a core or collection depending on whether Solr is running in standalone (core) or SolrCloud +echo mode (collection). If you're deleting a collection in SolrCloud mode, the default behavior is to also +echo delete the configuration directory from Zookeeper so long as it is not being used by another collection. +echo You can override this behavior by passing -deleteConfig false when running this command. +echo. +echo Can be run on remote (non-Solr^) hosts, as long as a valid SOLR_HOST is provided in solr.in.cmd +echo. +echo -c name Name of core to delete +echo. +echo -deleteConfig boolean Delete the configuration directory from Zookeeper; default is true +echo. +echo -p port Port of a local Solr instance where you want to delete the core/collection +echo If not specified, the script will search the local system for a running +echo Solr instance and will use the port of the first server it finds. +echo. +echo -V Enables more verbose output. +echo. +goto done + +:create_core_usage +echo. +echo Usage: solr create_core [-c ^] [-d confdir] [-p port] [-V] +echo. +echo When a configSet is used, this can be run from any host. If pointing at a non-configSet directory, this +echo must be run from the host that you wish to create the core on. +echo. +echo -c ^ Name of core to create +echo. +echo -d confdir Configuration directory to copy when creating the new core, built-in options are: +echo. +echo _default: Minimal configuration, which supports enabling/disabling field-guessing support +echo sample_techproducts_configs: Example configuration with many optional features enabled to +echo demonstrate the full power of Solr +echo. +echo If not specified, default is: _default +echo. +echo Alternatively, you can pass the path to your own configuration directory instead of using +echo one of the built-in configurations, such as: bin\solr create_core -c mycore -d c:/tmp/myconfig +echo. +echo -p port Port of a local Solr instance where you want to create the new core +echo If not specified, the script will search the local system for a running +echo Solr instance and will use the port of the first server it finds. +echo. +echo -V Enable more verbose output. +echo. +goto done + +:create_collection_usage +echo. +echo Usage: solr create_collection [-c collection] [-d confdir] [-n confname] [-shards #] [-replicationFactor #] [-p port] [-V] +echo. +echo Can be run from remote (non-Solr^) hosts, as long as a valid SOLR_HOST is provided in solr.in.cmd. +echo. +echo -c ^ Name of collection to create +echo. +echo -d ^ Configuration directory to copy when creating the new collection, built-in options are: +echo. +echo _default: Minimal configuration, which supports enabling/disabling field-guessing support +echo sample_techproducts_configs: Example configuration with many optional features enabled to +echo demonstrate the full power of Solr +echo. +echo If not specified, default is: _default +echo. +echo Alternatively, you can pass the path to your own configuration directory instead of using +echo one of the built-in configurations, such as: bin\solr create_collection -c mycoll -d c:/tmp/myconfig +echo. +echo By default the script will upload the specified confdir directory into Zookeeper using the same +echo name as the collection (-c) option. Alternatively, if you want to reuse an existing directory +echo or create a confdir in Zookeeper that can be shared by multiple collections, use the -n option +echo. +echo -n configName Name the configuration directory in Zookeeper; by default, the configuration +echo will be uploaded to Zookeeper using the collection name (-c), but if you want +echo to use an existing directory or override the name of the configuration in +echo Zookeeper, then use the -c option. +echo. +echo -shards # Number of shards to split the collection into; default is 1 +echo. +echo -replicationFactor # Number of copies of each document in the collection, default is 1 (no replication) +echo. +echo -p port Port of a local Solr instance where you want to create the new collection +echo If not specified, the script will search the local system for a running +echo Solr instance and will use the port of the first server it finds. +echo. +echo -V Enable more verbose output. +echo. +goto done + +:zk_usage +set ZK_FULL=true +goto zk_short_usage +:zk_full_usage +echo Can be run on remote (non-Solr^) hosts, as long as valid ZK_HOST information is provided. +echo Be sure to check the Solr logs in case of errors. +echo. +echo -z zkHost Optional Zookeeper connection string for all commands. If specified it +echo overrides the 'ZK_HOST=...'' defined in solr.in.cmd. +echo. +echo -V Enable more verbose output. +echo. +echo upconfig uploads a configset from the local machine to Zookeeper. (Backcompat: -upconfig) +echo. +echo downconfig downloads a configset from Zookeeper to the local machine. (Backcompat: -downconfig) +echo. +echo -n configName Name of the configset in Zookeeper that will be the destination of +echo 'upconfig' and the source for 'downconfig'. +echo. +echo -d confdir The local directory the configuration will be uploaded from for +echo 'upconfig' or downloaded to for 'downconfig'. If 'confdir' is a child of +echo ...solr/server/solr/configsets' then the configs will be copied from/to +echo that directory. Otherwise it is interpreted as a simple local path. +echo. +echo cp copies files or folders to/from Zookeeper or Zokeeper -^> Zookeeper +echo -r Recursively copy ^ to ^. Command will fail if ^ has children and +echo -r is not specified. Optional +echo. +echo. ^, ^ : [file:][/]path/to/local/file or zk:/path/to/zk/node +echo NOTE: ^ and ^ may both be Zookeeper resources prefixed by 'zk:' +echo When ^ is a zk resource, ^ may be '.' +echo If ^ ends with '/', then ^ will be a local folder or parent znode and the last +echo element of the ^ path will be appended unless ^ also ends in a slash. +echo ^ may be zk:, which may be useful when using the cp -r form to backup/restore +echo the entire zk state. +echo You must enclose local paths that end in a wildcard in quotes or just +echo end the local path in a slash. That is, +echo 'bin/solr zk cp -r /some/dir/ zk:/ -z localhost:2181' is equivalent to +echo 'bin/solr zk cp -r ^"/some/dir/*^" zk:/ -z localhost:2181' +echo but 'bin/solr zk cp -r /some/dir/* zk:/ -z localhost:2181' will throw an error. +echo. +echo Here's an example of backup/restore for a ZK configuration: +echo to copy to local: 'bin/solr zk cp -r zk:/ /some/dir -z localhost:2181' +echo to restore to ZK: 'bin/solr zk cp -r /some/dir/ zk:/ -z localhost:2181' +echo. +echo The 'file:' prefix is stripped, thus 'file:/wherever' specifies an absolute local path and +echo 'file:somewhere' specifies a relative local path. All paths on Zookeeper are absolute. +echo. +echo Zookeeper nodes CAN have data, so moving a single file to a parent znode +echo will overlay the data on the parent Znode so specifying the trailing slash +echo can be important. +echo. +echo Wildcards are supported when copying from local, trailing only and must be quoted. +echo. +echo rm deletes files or folders on Zookeeper +echo -r Recursively delete if ^ is a directory. Command will fail if ^ +echo has children and -r is not specified. Optional +echo ^ : [zk:]/path/to/zk/node. ^ may not be the root ('/') +echo. +echo mv moves (renames) znodes on Zookeeper +echo ^, ^ : Zookeeper nodes, the 'zk:' prefix is optional. +echo If ^ ends with '/', then ^ will be a parent znode +echo and the last element of the ^ path will be appended. +echo Zookeeper nodes CAN have data, so moving a single file to a parent znode +echo will overlay the data on the parent Znode so specifying the trailing slash +echo is important. +echo. +echo ls lists the znodes on Zookeeper +echo -r recursively descends the path listing all znodes. Optional +echo ^: The Zookeeper path to use as the root. +echo. +echo Only the node names are listed, not data +echo. +echo mkroot makes a znode in Zookeeper with no data. Can be used to make a path of arbitrary +echo depth but primarily intended to create a 'chroot'. +echo. +echo ^: The Zookeeper path to create. Leading slash is assumed if not present. +echo Intermediate nodes are created as needed if not present. +echo. + +goto done + +:zk_short_usage +IF NOT "!ERROR_MSG!"=="" ( + echo ERROR: !ERROR_MSG! + echo. +) +echo Usage: solr zk upconfig^|downconfig -d ^ -n ^ [-z zkHost] +echo solr zk cp [-r] ^ ^ [-z zkHost] +echo solr zk rm [-r] ^ [-z zkHost] +echo solr zk mv ^ ^ [-z zkHost] +echo solr zk ls [-r] ^ [-z zkHost] +echo solr zk mkroot ^ [-z zkHost] +echo. +IF "%ZK_FULL%"=="true" ( + goto zk_full_usage +) ELSE ( + echo Type bin/solr zk -help for full usage help +) +goto done + +:auth_usage +echo Usage: solr auth enable [-type basicAuth] -credentials user:pass [-blockUnknown ^] [-updateIncludeFileOnly ^] [-V] +echo solr auth enable [-type basicAuth] -prompt ^ [-blockUnknown ^] [-updateIncludeFileOnly ^] [-V] +echo solr auth disable [-updateIncludeFileOnly ^] [-V] +echo. +echo Updates or enables/disables authentication. Must be run on the machine hosting Solr. +echo. +echo -type ^ The authentication mechanism to enable. Defaults to 'basicAuth'. +echo. +echo -credentials ^ The username and password of the initial user +echo Note: only one of -prompt or -credentials must be provided +echo. +echo -prompt ^ Prompts the user to provide the credentials +echo Note: only one of -prompt or -credentials must be provided +echo. +echo -blockUnknown ^ When true, this blocks out access to unauthenticated users. When not provided, +echo this defaults to false (i.e. unauthenticated users can access all endpoints, except the +echo operations like collection-edit, security-edit, core-admin-edit etc.^). Check the reference +echo guide for Basic Authentication for more details. +echo. +echo -updateIncludeFileOnly ^ Only update the solr.in.sh or solr.in.cmd file, and skip actual enabling/disabling" +echo authentication (i.e. don't update security.json^)" +echo. +echo -z zkHost Zookeeper connection string. Unnecessary if ZK_HOST is defined in solr.in.cmd. +echo. +echo -d ^ Specify the Solr server directory" +echo. +echo -s ^ Specify the Solr home directory. This is where any credentials or authentication" +echo configuration files (e.g. basicAuth.conf^) would be placed." +echo. +echo -V Enable more verbose output +echo. +goto done + +REM Really basic command-line arg parsing +:parse_args + +set "arg=%~1" +set "firstTwo=%arg:~0,2%" +IF "%SCRIPT_CMD%"=="" set SCRIPT_CMD=start +IF [%1]==[] goto process_script_cmd +IF "%1"=="-help" goto usage +IF "%1"=="-usage" goto usage +IF "%1"=="/?" goto usage +IF "%1"=="-f" goto set_foreground_mode +IF "%1"=="-foreground" goto set_foreground_mode +IF "%1"=="-V" goto set_verbose +IF "%1"=="-verbose" goto set_verbose +IF "%1"=="-v" goto set_debug +IF "%1"=="-q" goto set_warn +IF "%1"=="-c" goto set_cloud_mode +IF "%1"=="-cloud" goto set_cloud_mode +IF "%1"=="-d" goto set_server_dir +IF "%1"=="-dir" goto set_server_dir +IF "%1"=="-s" goto set_solr_home_dir +IF "%1"=="-t" goto set_solr_data_dir +IF "%1"=="-solr.home" goto set_solr_home_dir +IF "%1"=="-e" goto set_example +IF "%1"=="-example" goto set_example +IF "%1"=="-h" goto set_host +IF "%1"=="-host" goto set_host +IF "%1"=="-m" goto set_memory +IF "%1"=="-memory" goto set_memory +IF "%1"=="-p" goto set_port +IF "%1"=="-port" goto set_port +IF "%1"=="-z" goto set_zookeeper +IF "%1"=="-zkhost" goto set_zookeeper +IF "%1"=="-zkHost" goto set_zookeeper +IF "%1"=="-a" goto set_addl_opts +IF "%1"=="-addlopts" goto set_addl_opts +IF "%1"=="-j" goto set_addl_jetty_config +IF "%1"=="-jettyconfig" goto set_addl_jetty_config +IF "%1"=="-noprompt" goto set_noprompt +IF "%1"=="-k" goto set_stop_key +IF "%1"=="-key" goto set_stop_key +IF "%1"=="-all" goto set_stop_all +IF "%firstTwo%"=="-D" goto set_passthru +IF NOT "%1"=="" goto invalid_cmd_line +goto invalid_cmd_line + +:set_script_cmd +set SCRIPT_CMD=%1 +SHIFT +goto parse_args + +:set_foreground_mode +set FG=1 +SHIFT +goto parse_args + +:set_verbose +set verbose=1 +set "PASS_TO_RUN_EXAMPLE=--verbose !PASS_TO_RUN_EXAMPLE!" +SHIFT +goto parse_args + +:set_debug +set SOLR_LOG_LEVEL=DEBUG +set "PASS_TO_RUN_EXAMPLE=!PASS_TO_RUN_EXAMPLE! -Dsolr.log.level=%SOLR_LOG_LEVEL%" +SHIFT +goto parse_args + +:set_warn +set SOLR_LOG_LEVEL=WARN +set "PASS_TO_RUN_EXAMPLE=!PASS_TO_RUN_EXAMPLE! -Dsolr.log.level=%SOLR_LOG_LEVEL%" +SHIFT +goto parse_args + +:set_cloud_mode +set SOLR_MODE=solrcloud +SHIFT +goto parse_args + +:set_server_dir + +set "arg=%~2" +IF "%arg%"=="" ( + set SCRIPT_ERROR=Directory name is required! + goto invalid_cmd_line +) +set firstChar=%arg:~0,1% +IF "%firstChar%"=="-" ( + set SCRIPT_ERROR=Expected directory but found %2 instead! + goto invalid_cmd_line +) + +REM See if they are using a short-hand name relative from the Solr tip directory +IF EXIST "%SOLR_TIP%\%~2" ( + set "SOLR_SERVER_DIR=%SOLR_TIP%\%~2" +) ELSE ( + set "SOLR_SERVER_DIR=%~2" +) +SHIFT +SHIFT +goto parse_args + +:set_solr_home_dir + +set "arg=%~2" +IF "%arg%"=="" ( + set SCRIPT_ERROR=Directory name is required! + goto invalid_cmd_line +) + +set firstChar=%arg:~0,1% +IF "%firstChar%"=="-" ( + set SCRIPT_ERROR=Expected directory but found %2 instead! + goto invalid_cmd_line +) +set "SOLR_HOME=%~2" +SHIFT +SHIFT +goto parse_args + +:set_solr_data_dir + +set "arg=%~2" +IF "%arg%"=="" ( + set SCRIPT_ERROR=Directory name is required! + goto invalid_cmd_line +) + +set firstChar=%arg:~0,1% +IF "%firstChar%"=="-" ( + set SCRIPT_ERROR=Expected directory but found %2 instead! + goto invalid_cmd_line +) +set "SOLR_DATA_HOME=%~2" +SHIFT +SHIFT +goto parse_args + +:set_example + +set "arg=%~2" +IF "%arg%"=="" ( + set SCRIPT_ERROR=Example name is required! + goto invalid_cmd_line +) + +set firstChar=%arg:~0,1% +IF "%firstChar%"=="-" ( + set SCRIPT_ERROR=Expected example name but found %2 instead! + goto invalid_cmd_line +) + +set EXAMPLE=%~2 +SHIFT +SHIFT +goto parse_args + +:set_memory + +set "arg=%~2" +IF "%arg%"=="" ( + set SCRIPT_ERROR=Memory setting is required! + goto invalid_cmd_line +) + +set firstChar=%arg:~0,1% +IF "%firstChar%"=="-" ( + set SCRIPT_ERROR=Expected memory setting but found %2 instead! + goto invalid_cmd_line +) + +set SOLR_HEAP=%~2 +set "PASS_TO_RUN_EXAMPLE=-m %~2 !PASS_TO_RUN_EXAMPLE!" +SHIFT +SHIFT +goto parse_args + +:set_host +set "arg=%~2" +IF "%arg%"=="" ( + set SCRIPT_ERROR=Hostname is required! + goto invalid_cmd_line +) + +set firstChar=%arg:~0,1% +IF "%firstChar%"=="-" ( + set SCRIPT_ERROR=Expected hostname but found %2 instead! + goto invalid_cmd_line +) + +set SOLR_HOST=%~2 +set "PASS_TO_RUN_EXAMPLE=-h %~2 !PASS_TO_RUN_EXAMPLE!" +SHIFT +SHIFT +goto parse_args + +:set_port +set "arg=%~2" +IF "%arg%"=="" ( + set SCRIPT_ERROR=Port is required! + goto invalid_cmd_line +) + +set firstChar=%arg:~0,1% +IF "%firstChar%"=="-" ( + set SCRIPT_ERROR=Expected port but found %2 instead! + goto invalid_cmd_line +) + +set SOLR_PORT=%~2 +set "PASS_TO_RUN_EXAMPLE=-p %~2 !PASS_TO_RUN_EXAMPLE!" +SHIFT +SHIFT +goto parse_args + +:set_stop_key +set "arg=%~2" +IF "%arg%"=="" ( + set SCRIPT_ERROR=Stop key is required! + goto invalid_cmd_line +) + +set firstChar=%arg:~0,1% +IF "%firstChar%"=="-" ( + set SCRIPT_ERROR=Expected stop key but found %2 instead! + goto invalid_cmd_line +) +set STOP_KEY=%~2 +SHIFT +SHIFT +goto parse_args + +:set_stop_all +set STOP_ALL=1 +SHIFT +goto parse_args + +:set_zookeeper + +set "arg=%~2" +IF "%arg%"=="" ( + set SCRIPT_ERROR=Zookeeper connection string is required! + goto invalid_cmd_line +) + +set firstChar=%arg:~0,1% +IF "%firstChar%"=="-" ( + set SCRIPT_ERROR=Expected Zookeeper connection string but found %2 instead! + goto invalid_cmd_line +) + +set "ZK_HOST=%~2" +set "PASS_TO_RUN_EXAMPLE=-z %~2 !PASS_TO_RUN_EXAMPLE!" +SHIFT +SHIFT +goto parse_args + +:set_addl_opts +set "arg=%~2" +set "SOLR_ADDL_ARGS=%~2" +SHIFT +SHIFT +goto parse_args + +:set_addl_jetty_config +set "arg=%~2" +set "SOLR_JETTY_ADDL_CONFIG=%~2" +SHIFT +SHIFT +goto parse_args + +:set_passthru +set "PASSTHRU=%~1=%~2" +IF NOT "%SOLR_OPTS%"=="" ( + set "SOLR_OPTS=%SOLR_OPTS% %PASSTHRU%" +) ELSE ( + set "SOLR_OPTS=%PASSTHRU%" +) +set "PASS_TO_RUN_EXAMPLE=%PASSTHRU% !PASS_TO_RUN_EXAMPLE!" +SHIFT +SHIFT +goto parse_args + +:set_noprompt +set NO_USER_PROMPT=1 +set "PASS_TO_RUN_EXAMPLE=-noprompt !PASS_TO_RUN_EXAMPLE!" + +SHIFT +goto parse_args + +REM Perform the requested command after processing args +:process_script_cmd + +IF "%verbose%"=="1" ( + CALL :safe_echo "Using Solr root directory: %SOLR_TIP%" + CALL :safe_echo "Using Java: %JAVA%" + "%JAVA%" -version + @echo. +) + +IF NOT "%SOLR_HOST%"=="" ( + set SOLR_HOST_ARG=-Dhost=%SOLR_HOST% +) ELSE ( + set SOLR_HOST_ARG= +) + +IF "%SOLR_SERVER_DIR%"=="" set "SOLR_SERVER_DIR=%DEFAULT_SERVER_DIR%" + +IF NOT EXIST "%SOLR_SERVER_DIR%" ( + set "SCRIPT_ERROR=Solr server directory %SOLR_SERVER_DIR% not found!" + goto err +) + +IF NOT "%EXAMPLE%"=="" goto run_example + +:start_solr +IF "%SOLR_HOME%"=="" set "SOLR_HOME=%SOLR_SERVER_DIR%\solr" +IF EXIST "%cd%\%SOLR_HOME%" set "SOLR_HOME=%cd%\%SOLR_HOME%" + +IF NOT EXIST "%SOLR_HOME%\" ( + IF EXIST "%SOLR_SERVER_DIR%\%SOLR_HOME%" ( + set "SOLR_HOME=%SOLR_SERVER_DIR%\%SOLR_HOME%" + ) ELSE ( + set "SCRIPT_ERROR=Solr home directory %SOLR_HOME% not found!" + goto err + ) +) + +IF "%STOP_KEY%"=="" set STOP_KEY=solrrocks + +@REM This is quite hacky, but examples rely on a different log4j2.xml +@REM so that we can write logs for examples to %SOLR_HOME%\..\logs +IF [%SOLR_LOGS_DIR%] == [] ( + set "SOLR_LOGS_DIR=%SOLR_SERVER_DIR%\logs" +) ELSE ( + set SOLR_LOGS_DIR=%SOLR_LOGS_DIR:"=% +) + +set "EXAMPLE_DIR=%SOLR_TIP%\example" +set TMP_SOLR_HOME=!SOLR_HOME:%EXAMPLE_DIR%=! +IF NOT "%TMP_SOLR_HOME%"=="%SOLR_HOME%" ( + set "SOLR_LOGS_DIR=%SOLR_HOME%\..\logs" + set "LOG4J_CONFIG=%SOLR_SERVER_DIR%\resources\log4j2.xml" +) + +set IS_RESTART=0 +IF "%SCRIPT_CMD%"=="restart" ( + IF "%SOLR_PORT%"=="" ( + set "SCRIPT_ERROR=Must specify the port when trying to restart Solr." + goto err + ) + set SCRIPT_CMD=stop + set IS_RESTART=1 +) + +@REM stop logic here +IF "%SCRIPT_CMD%"=="stop" ( + IF "%SOLR_PORT%"=="" ( + IF "%STOP_ALL%"=="1" ( + set found_it=0 + for /f "usebackq" %%i in (`dir /b "%SOLR_TIP%\bin" ^| findstr /i "^solr-.*\.port$"`) do ( + set SOME_SOLR_PORT= + For /F "delims=" %%J In ('type "%SOLR_TIP%\bin\%%i"') do set SOME_SOLR_PORT=%%~J + if NOT "!SOME_SOLR_PORT!"=="" ( + for /f "tokens=2,5" %%j in ('netstat -aon ^| find "TCP " ^| find ":0 " ^| find ":!SOME_SOLR_PORT! "') do ( + @REM j is the ip:port and k is the pid + IF NOT "%%k"=="0" ( + IF "%%j"=="%SOLR_JETTY_HOST%:!SOME_SOLR_PORT!" ( + set found_it=1 + @echo Stopping Solr process %%k running on port !SOME_SOLR_PORT! + IF "%STOP_PORT%"=="" set /A STOP_PORT=!SOME_SOLR_PORT! - 1000 + "%JAVA%" %SOLR_SSL_OPTS% -Djetty.home="%SOLR_SERVER_DIR%" -jar "%SOLR_SERVER_DIR%\start.jar" STOP.PORT=!STOP_PORT! STOP.KEY=%STOP_KEY% --stop + del "%SOLR_TIP%"\bin\solr-!SOME_SOLR_PORT!.port + timeout /T 5 + REM Kill it if it is still running after the graceful shutdown + IF EXIST "%JAVA_HOME%\bin\jstack.exe" ( + qprocess "%%k" >nul 2>nul && "%JAVA_HOME%\bin\jstack.exe" %%k && taskkill /f /PID %%k + ) else ( + qprocess "%%k" >nul 2>nul && taskkill /f /PID %%k + ) + ) + ) + ) + ) + ) + if "!found_it!"=="0" echo No Solr nodes found to stop. + ) ELSE ( + set "SCRIPT_ERROR=Must specify the port when trying to stop Solr, or use -all to stop all running nodes on this host." + goto err + ) + ) ELSE ( + set found_it=0 + For /f "tokens=2,5" %%M in ('netstat -nao ^| find "TCP " ^| find ":0 " ^| find ":%SOLR_PORT% "') do ( + IF NOT "%%N"=="0" ( + IF "%%M"=="%SOLR_JETTY_HOST%:%SOLR_PORT%" ( + set found_it=1 + @echo Stopping Solr process %%N running on port %SOLR_PORT% + IF "%STOP_PORT%"=="" set /A STOP_PORT=%SOLR_PORT% - 1000 + "%JAVA%" %SOLR_SSL_OPTS% -Djetty.home="%SOLR_SERVER_DIR%" -jar "%SOLR_SERVER_DIR%\start.jar" %SOLR_JETTY_CONFIG% STOP.PORT=!STOP_PORT! STOP.KEY=%STOP_KEY% --stop + del "%SOLR_TIP%"\bin\solr-%SOLR_PORT%.port + timeout /T 5 + REM Kill it if it is still running after the graceful shutdown + IF EXIST "%JAVA_HOME%\bin\jstack.exe" ( + qprocess "%%N" >nul 2>nul && "%JAVA_HOME%\bin\jstack.exe" %%N && taskkill /f /PID %%N + ) else ( + qprocess "%%N" >nul 2>nul && taskkill /f /PID %%N + ) + ) + ) + ) + if "!found_it!"=="0" echo No Solr found running on port %SOLR_PORT% + ) + + IF "!IS_RESTART!"=="0" goto done +) + +IF "!IS_RESTART!"=="1" set SCRIPT_CMD=start + +IF "%SOLR_PORT%"=="" set SOLR_PORT=8983 +IF "%STOP_PORT%"=="" set /A STOP_PORT=%SOLR_PORT% - 1000 + +IF "%SCRIPT_CMD%"=="start" ( + REM see if Solr is already running using netstat + For /f "tokens=2,5" %%j in ('netstat -aon ^| find "TCP " ^| find ":0 " ^| find ":%SOLR_PORT% "') do ( + IF NOT "%%k"=="0" ( + IF "%%j"=="%SOLR_JETTY_HOST%:%SOLR_PORT%" ( + set "SCRIPT_ERROR=Process %%k is already listening on port %SOLR_PORT%. If this is Solr, please stop it first before starting (or use restart). If this is not Solr, then please choose a different port using -p PORT" + goto err + ) + ) + ) +) + +@REM determine if -server flag is supported by current JVM +"%JAVA%" -server -version > nul 2>&1 +IF ERRORLEVEL 1 ( + set IS_JDK=false + set "SERVEROPT=" + @echo WARNING: You are using a JRE without support for -server option. Please upgrade to latest JDK for best performance + @echo. +) ELSE ( + set IS_JDK=true + set "SERVEROPT=-server" +) +if !JAVA_MAJOR_VERSION! LSS 9 ( + "%JAVA%" -d64 -version > nul 2>&1 + IF ERRORLEVEL 1 ( + set "IS_64BIT=false" + @echo WARNING: 32-bit Java detected. Not recommended for production. Point your JAVA_HOME to a 64-bit JDK + @echo. + ) ELSE ( + set IS_64bit=true + ) +) ELSE ( + set IS_64bit=true +) + +REM Clean up and rotate logs. Default to false since 7.4 as log4j2 handles startup rotation +IF [%SOLR_LOG_PRESTART_ROTATION%] == [] ( + set SOLR_LOG_PRESTART_ROTATION=false +) +IF [%SOLR_LOG_PRESTART_ROTATION%] == [true] ( + REM Enable any of these if you require old remove/archive behavior + REM call :run_utils "-remove_old_solr_logs 7" || echo "Failed removing old solr logs" + REM call :run_utils "-archive_gc_logs" || echo "Failed archiving old GC logs" + REM call :run_utils "-archive_console_logs" || echo "Failed archiving old console logs" + call :run_utils "-rotate_solr_logs 9" || echo "Failed rotating old solr logs" +) + +IF NOT "%ZK_HOST%"=="" set SOLR_MODE=solrcloud + +IF "%SOLR_MODE%"=="solrcloud" ( + IF "%ZK_CLIENT_TIMEOUT%"=="" set "ZK_CLIENT_TIMEOUT=15000" + + set "CLOUD_MODE_OPTS=-DzkClientTimeout=!ZK_CLIENT_TIMEOUT!" + + IF NOT "%ZK_HOST%"=="" ( + set "CLOUD_MODE_OPTS=!CLOUD_MODE_OPTS! -DzkHost=%ZK_HOST%" + ) ELSE ( + IF "%verbose%"=="1" echo Configuring SolrCloud to launch an embedded Zookeeper using -DzkRun + set "CLOUD_MODE_OPTS=!CLOUD_MODE_OPTS! -DzkRun" + ) + IF EXIST "%SOLR_HOME%\collection1\core.properties" set "CLOUD_MODE_OPTS=!CLOUD_MODE_OPTS! -Dbootstrap_confdir=./solr/collection1/conf -Dcollection.configName=myconf -DnumShards=1" +) ELSE ( + set CLOUD_MODE_OPTS= + IF NOT EXIST "%SOLR_HOME%\solr.xml" ( + set "SCRIPT_ERROR=Solr home directory %SOLR_HOME% must contain solr.xml!" + goto err + ) +) + +REM IP-based access control +set IP_ACL_OPTS=-Dsolr.jetty.inetaccess.includes="%SOLR_IP_WHITELIST%" ^ +-Dsolr.jetty.inetaccess.excludes="%SOLR_IP_BLACKLIST%" + +REM These are useful for attaching remove profilers like VisualVM/JConsole +IF "%ENABLE_REMOTE_JMX_OPTS%"=="true" ( + IF "!RMI_PORT!"=="" set RMI_PORT=1%SOLR_PORT% + set REMOTE_JMX_OPTS=-Dcom.sun.management.jmxremote ^ +-Dcom.sun.management.jmxremote.local.only=false ^ +-Dcom.sun.management.jmxremote.ssl=false ^ +-Dcom.sun.management.jmxremote.authenticate=false ^ +-Dcom.sun.management.jmxremote.port=!RMI_PORT! ^ +-Dcom.sun.management.jmxremote.rmi.port=!RMI_PORT! + + IF NOT "%SOLR_HOST%"=="" set REMOTE_JMX_OPTS=%REMOTE_JMX_OPTS% -Djava.rmi.server.hostname=%SOLR_HOST% +) ELSE ( + set REMOTE_JMX_OPTS= +) + +REM Enable java security manager (limiting filesystem access and other things) +IF "%SOLR_SECURITY_MANAGER_ENABLED%"=="true" ( + set SECURITY_MANAGER_OPTS=-Djava.security.manager ^ +-Djava.security.policy="%SOLR_SERVER_DIR%\etc\security.policy" ^ +-Djava.security.properties="%SOLR_SERVER_DIR%\etc\security.properties" ^ +-Dsolr.internal.network.permission=* +) + +IF NOT "%SOLR_HEAP%"=="" set SOLR_JAVA_MEM=-Xms%SOLR_HEAP% -Xmx%SOLR_HEAP% +IF "%SOLR_JAVA_MEM%"=="" set SOLR_JAVA_MEM=-Xms512m -Xmx512m +IF "%SOLR_JAVA_STACK_SIZE%"=="" set SOLR_JAVA_STACK_SIZE=-Xss256k +set SOLR_OPTS=%SOLR_JAVA_STACK_SIZE% %SOLR_OPTS% +IF "%SOLR_TIMEZONE%"=="" set SOLR_TIMEZONE=UTC + +IF "%GC_TUNE%"=="" ( + set GC_TUNE=-XX:+UseG1GC ^ + -XX:+PerfDisableSharedMem ^ + -XX:+ParallelRefProcEnabled ^ + -XX:MaxGCPauseMillis=250 ^ + -XX:+UseLargePages ^ + -XX:+AlwaysPreTouch ^ + -XX:+ExplicitGCInvokesConcurrent +) + +if !JAVA_MAJOR_VERSION! GEQ 9 ( + IF NOT "%GC_LOG_OPTS%"=="" ( + echo ERROR: On Java 9 you cannot set GC_LOG_OPTS, only default GC logging is available. Exiting + GOTO :eof + ) + set GC_LOG_OPTS="-Xlog:gc*:file=\"!SOLR_LOGS_DIR!\solr_gc.log\":time,uptime:filecount=9,filesize=20M" +) else ( + IF "%GC_LOG_OPTS%"=="" ( + rem Set defaults for Java 8 + set GC_LOG_OPTS=-verbose:gc ^ + -XX:+PrintHeapAtGC ^ + -XX:+PrintGCDetails ^ + -XX:+PrintGCDateStamps ^ + -XX:+PrintGCTimeStamps ^ + -XX:+PrintTenuringDistribution ^ + -XX:+PrintGCApplicationStoppedTime + ) + if "%JAVA_VENDOR%" == "IBM J9" ( + set GC_LOG_OPTS=!GC_LOG_OPTS! "-Xverbosegclog:!SOLR_LOGS_DIR!\solr_gc.log" -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=9 -XX:GCLogFileSize=20M + ) else ( + set GC_LOG_OPTS=!GC_LOG_OPTS! "-Xloggc:!SOLR_LOGS_DIR!\solr_gc.log" -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=9 -XX:GCLogFileSize=20M + ) +) + +IF "%verbose%"=="1" ( + @echo Starting Solr using the following settings: + CALL :safe_echo " JAVA = %JAVA%" + CALL :safe_echo " SOLR_SERVER_DIR = %SOLR_SERVER_DIR%" + CALL :safe_echo " SOLR_HOME = %SOLR_HOME%" + @echo SOLR_HOST = %SOLR_HOST% + @echo SOLR_PORT = %SOLR_PORT% + @echo STOP_PORT = %STOP_PORT% + @echo SOLR_JAVA_MEM = %SOLR_JAVA_MEM% + @echo GC_TUNE = !GC_TUNE! + @echo GC_LOG_OPTS = %GC_LOG_OPTS% + @echo SOLR_TIMEZONE = %SOLR_TIMEZONE% + + IF "%SOLR_MODE%"=="solrcloud" ( + @echo CLOUD_MODE_OPTS = %CLOUD_MODE_OPTS% + ) + + IF NOT "%SOLR_OPTS%"=="" ( + @echo SOLR_OPTS = %SOLR_OPTS% + ) + + IF NOT "%SOLR_ADDL_ARGS%"=="" ( + CALL :safe_echo " SOLR_ADDL_ARGS = %SOLR_ADDL_ARGS%" + ) + + IF NOT "%SOLR_JETTY_ADDL_CONFIG%"=="" ( + CALL :safe_echo " SOLR_JETTY_ADDL_CONFIG = %SOLR_JETTY_ADDL_CONFIG%" + ) + + IF "%ENABLE_REMOTE_JMX_OPTS%"=="true" ( + @echo RMI_PORT = !RMI_PORT! + @echo REMOTE_JMX_OPTS = %REMOTE_JMX_OPTS% + ) + + IF NOT "%SOLR_LOG_LEVEL%"=="" ( + @echo SOLR_LOG_LEVEL = !SOLR_LOG_LEVEL! + ) + + IF NOT "%SOLR_DATA_HOME%"=="" ( + @echo SOLR_DATA_HOME = !SOLR_DATA_HOME! + ) + + @echo. +) + +set START_OPTS=-Duser.timezone=%SOLR_TIMEZONE% +REM '-OmitStackTraceInFastThrow' ensures stack traces in errors, +REM users who don't care about useful error msgs can override in SOLR_OPTS with +OmitStackTraceInFastThrow +set "START_OPTS=%START_OPTS% -XX:-OmitStackTraceInFastThrow" +set START_OPTS=%START_OPTS% !GC_TUNE! %GC_LOG_OPTS% +IF NOT "!CLOUD_MODE_OPTS!"=="" set "START_OPTS=%START_OPTS% !CLOUD_MODE_OPTS!" +IF NOT "!IP_ACL_OPTS!"=="" set "START_OPTS=%START_OPTS% !IP_ACL_OPTS!" +IF NOT "%REMOTE_JMX_OPTS%"=="" set "START_OPTS=%START_OPTS% %REMOTE_JMX_OPTS%" +IF NOT "%SOLR_ADDL_ARGS%"=="" set "START_OPTS=%START_OPTS% %SOLR_ADDL_ARGS%" +IF NOT "%SOLR_HOST_ARG%"=="" set "START_OPTS=%START_OPTS% %SOLR_HOST_ARG%" +IF NOT "%SOLR_OPTS%"=="" set "START_OPTS=%START_OPTS% %SOLR_OPTS%" +IF NOT "!SECURITY_MANAGER_OPTS!"=="" set "START_OPTS=%START_OPTS% !SECURITY_MANAGER_OPTS!" +IF "%SOLR_SSL_ENABLED%"=="true" ( + set "SSL_PORT_PROP=-Dsolr.jetty.https.port=%SOLR_PORT%" + set "START_OPTS=%START_OPTS% %SOLR_SSL_OPTS% !SSL_PORT_PROP!" +) +IF NOT "%SOLR_LOG_LEVEL%"=="" set "START_OPTS=%START_OPTS% -Dsolr.log.level=%SOLR_LOG_LEVEL%" + +set SOLR_LOGS_DIR_QUOTED="%SOLR_LOGS_DIR%" +set SOLR_DATA_HOME_QUOTED="%SOLR_DATA_HOME%" + +set "START_OPTS=%START_OPTS% -Dsolr.log.dir=%SOLR_LOGS_DIR_QUOTED%" +IF NOT "%SOLR_DATA_HOME%"=="" set "START_OPTS=%START_OPTS% -Dsolr.data.home=%SOLR_DATA_HOME_QUOTED%" +IF NOT DEFINED LOG4J_CONFIG set "LOG4J_CONFIG=%SOLR_SERVER_DIR%\resources\log4j2.xml" + +cd /d "%SOLR_SERVER_DIR%" + +IF NOT EXIST "%SOLR_LOGS_DIR%" ( + mkdir "%SOLR_LOGS_DIR%" +) +copy /Y NUL "%SOLR_LOGS_DIR%\.writable" > NUL 2>&1 && set WRITEOK=1 +IF DEFINED WRITEOK ( + del "%SOLR_LOGS_DIR%\.writable" +) else ( + echo "ERROR: Logs directory %SOLR_LOGS_DIR% is not writable or could not be created. Exiting" + GOTO :eof +) +echo " contexts etc lib modules resources scripts solr solr-webapp " > "%TEMP%\solr-pattern.txt" +findstr /i /C:" %SOLR_LOGS_DIR% " "%TEMP%\solr-pattern.txt" 1>nul +if %ERRORLEVEL% == 0 ( + echo "ERROR: Logs directory %SOLR_LOGS_DIR% is invalid. Reserved for the system. Exiting" + GOTO :eof +) + +IF NOT EXIST "%SOLR_SERVER_DIR%\tmp" ( + mkdir "%SOLR_SERVER_DIR%\tmp" +) + +IF "%DEFAULT_CONFDIR%"=="" set "DEFAULT_CONFDIR=%SOLR_SERVER_DIR%\solr\configsets\_default\conf" + +IF "%FG%"=="1" ( + REM run solr in the foreground + title "Solr-%SOLR_PORT%" + echo %SOLR_PORT%>"%SOLR_TIP%"\bin\solr-%SOLR_PORT%.port + "%JAVA%" %SERVEROPT% %SOLR_JAVA_MEM% %START_OPTS% ^ + -Dlog4j.configurationFile="%LOG4J_CONFIG%" -DSTOP.PORT=!STOP_PORT! -DSTOP.KEY=%STOP_KEY% ^ + -Dsolr.solr.home="%SOLR_HOME%" -Dsolr.install.dir="%SOLR_TIP%" -Dsolr.default.confdir="%DEFAULT_CONFDIR%" ^ + -Djetty.host=%SOLR_JETTY_HOST% -Djetty.port=%SOLR_PORT% -Djetty.home="%SOLR_SERVER_DIR%" ^ + -Djava.io.tmpdir="%SOLR_SERVER_DIR%\tmp" -jar start.jar %SOLR_JETTY_CONFIG% "%SOLR_JETTY_ADDL_CONFIG%" +) ELSE ( + START /B "Solr-%SOLR_PORT%" /D "%SOLR_SERVER_DIR%" ^ + "%JAVA%" %SERVEROPT% %SOLR_JAVA_MEM% %START_OPTS% ^ + -Dlog4j.configurationFile="%LOG4J_CONFIG%" -DSTOP.PORT=!STOP_PORT! -DSTOP.KEY=%STOP_KEY% ^ + -Dsolr.log.muteconsole ^ + -Dsolr.solr.home="%SOLR_HOME%" -Dsolr.install.dir="%SOLR_TIP%" -Dsolr.default.confdir="%DEFAULT_CONFDIR%" ^ + -Djetty.host=%SOLR_JETTY_HOST% -Djetty.port=%SOLR_PORT% -Djetty.home="%SOLR_SERVER_DIR%" ^ + -Djava.io.tmpdir="%SOLR_SERVER_DIR%\tmp" -jar start.jar %SOLR_JETTY_CONFIG% "%SOLR_JETTY_ADDL_CONFIG%" > "!SOLR_LOGS_DIR!\solr-%SOLR_PORT%-console.log" + echo %SOLR_PORT%>"%SOLR_TIP%"\bin\solr-%SOLR_PORT%.port + + REM now wait to see Solr come online ... + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" -Dsolr.default.confdir="%DEFAULT_CONFDIR%"^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI status -maxWaitSecs 30 -solr !SOLR_URL_SCHEME!://%SOLR_TOOL_HOST%:%SOLR_PORT%/solr +) + +goto done + +:run_example +REM Run the requested example + +"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI run_example -script "%SDIR%\solr.cmd" -e %EXAMPLE% -d "%SOLR_SERVER_DIR%" ^ + -urlScheme !SOLR_URL_SCHEME! !PASS_TO_RUN_EXAMPLE! + +REM End of run_example +goto done + +:get_info +REM Find all Java processes, correlate with those listening on a port +REM and then try to contact via that port using the status tool +for /f "usebackq" %%i in (`dir /b "%SOLR_TIP%\bin" ^| findstr /i "^solr-.*\.port$"`) do ( + set SOME_SOLR_PORT= + For /F "Delims=" %%J In ('type "%SOLR_TIP%\bin\%%i"') do set SOME_SOLR_PORT=%%~J + if NOT "!SOME_SOLR_PORT!"=="" ( + for /f "tokens=2,5" %%j in ('netstat -aon ^| find "TCP " ^| find ":0 " ^| find ":!SOME_SOLR_PORT! "') do ( + IF NOT "%%k"=="0" ( + if "%%j"=="%SOLR_JETTY_HOST%:!SOME_SOLR_PORT!" ( + @echo. + set has_info=1 + echo Found Solr process %%k running on port !SOME_SOLR_PORT! + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI status -solr !SOLR_URL_SCHEME!://%SOLR_TOOL_HOST%:!SOME_SOLR_PORT!/solr + @echo. + ) + ) + ) + ) +) +if NOT "!has_info!"=="1" echo No running Solr nodes found. +set has_info= +goto done + +:parse_healthcheck_args +IF [%1]==[] goto run_healthcheck +IF "%1"=="-V" goto set_healthcheck_verbose +IF "%1"=="-c" goto set_healthcheck_collection +IF "%1"=="-collection" goto set_healthcheck_collection +IF "%1"=="-z" goto set_healthcheck_zk +IF "%1"=="-zkhost" goto set_healthcheck_zk +IF "%1"=="-zkHost" goto set_healthcheck_zk +IF "%1"=="-help" goto usage +IF "%1"=="-usage" goto usage +IF "%1"=="/?" goto usage +goto run_healthcheck + +:set_healthcheck_verbose +set HEALTHCHECK_VERBOSE="-verbose" +SHIFT +goto parse_healthcheck_args + +:set_healthcheck_collection +set HEALTHCHECK_COLLECTION=%~2 +SHIFT +SHIFT +goto parse_healthcheck_args + +:set_healthcheck_zk +set ZK_HOST=%~2 +SHIFT +SHIFT +goto parse_healthcheck_args + +:run_healthcheck +IF NOT DEFINED HEALTHCHECK_COLLECTION goto healthcheck_usage +IF NOT DEFINED HEALTHCHECK_VERBOSE set "HEALTHCHECK_VERBOSE=" +IF NOT DEFINED HEALTHCHECK_ZK_HOST set "HEALTHCHECK_ZK_HOST=localhost:9983" +echo ZK_HOST: !ZK_HOST! +"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI healthcheck -collection !HEALTHCHECK_COLLECTION! -zkHost !ZK_HOST! %HEALTHCHECK_VERBOSE% +goto done + +:run_assert +"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI %* +if errorlevel 1 ( + exit /b 1 +) +goto done + +:run_autoscaling +"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI %* +goto done: + +:run_export +"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI %* +goto done: + +:run_package +REM TODO: Compute the running Solr URL and populate it as a parameter (as has been done for the shell script) +REM Without that, users will have to supply -solrUrl parameter in every request. Life can be so hard for Windows users! +"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI %* +goto done: + +:parse_config_args +IF [%1]==[] goto run_config +IF "%1"=="-z" goto set_config_zk +IF "%1"=="-zkhost" goto set_config_zk +IF "%1"=="-zkHost" goto set_config_zk +IF "%1"=="-s" goto set_config_url_scheme +IF "%1"=="-scheme" goto set_config_url_scheme +set "CONFIG_ARGS=!CONFIG_ARGS! %1" +SHIFT +goto parse_config_args + +:set_config_zk +set ZK_HOST=%~2 +SHIFT +SHIFT +goto parse_config_args + +:set_config_url_scheme +set SOLR_URL_SCHEME=%~2 +SHIFT +SHIFT +goto parse_config_args + +:run_config +IF NOT "!ZK_HOST!"=="" SET "CONFIG_ARGS=!CONFIG_ARGS! -z !ZK_HOST!" +IF NOT "!SOLR_URL_SCHEME!"=="" SET "CONFIG_ARGS=!CONFIG_ARGS! -scheme !SOLR_URL_SCHEME!" + +"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI config !CONFIG_ARGS! +if errorlevel 1 ( + exit /b 1 +) +goto done + +:get_version +"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI version +goto done + +:run_utils +set "TOOL_CMD=%~1" +set q="-q" +IF "%verbose%"=="1" set q="" +"%JAVA%" %SOLR_SSL_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI utils -s "%DEFAULT_SERVER_DIR%" -l "%SOLR_LOGS_DIR%" %q:"=% %TOOL_CMD% +if errorlevel 1 ( + exit /b 1 +) +goto done + +:parse_create_args +IF [%1]==[] goto run_create +IF "%1"=="-V" goto set_create_verbose +IF "%1"=="-c" goto set_create_name +IF "%1"=="-core" goto set_create_name +IF "%1"=="-collection" goto set_create_name +IF "%1"=="-d" goto set_create_confdir +IF "%1"=="-confdir" goto set_create_confdir +IF "%1"=="-n" goto set_create_confname +IF "%1"=="-confname" goto set_create_confname +IF "%1"=="-s" goto set_create_shards +IF "%1"=="-shards" goto set_create_shards +IF "%1"=="-rf" goto set_create_rf +IF "%1"=="-replicationFactor" goto set_create_rf +IF "%1"=="-p" goto set_create_port +IF "%1"=="-port" goto set_create_port +IF "%1"=="-help" goto usage +IF "%1"=="-usage" goto usage +IF "%1"=="/?" goto usage +goto run_create + + +:set_create_verbose +set CREATE_VERBOSE="-verbose" +SHIFT +goto parse_create_args + +:set_create_name +set CREATE_NAME=%~2 +SHIFT +SHIFT +goto parse_create_args + +:set_create_confdir +set CREATE_CONFDIR=%~2 +SHIFT +SHIFT +goto parse_create_args + +:set_create_confname +set CREATE_CONFNAME=%~2 +SHIFT +SHIFT +goto parse_create_args + +:set_create_port +set CREATE_PORT=%~2 +SHIFT +SHIFT +goto parse_create_args + +:set_create_shards +set CREATE_NUM_SHARDS=%~2 +SHIFT +SHIFT +goto parse_create_args + +:set_create_rf +set CREATE_REPFACT=%~2 +SHIFT +SHIFT +goto parse_create_args + +:run_create +IF "!CREATE_NAME!"=="" ( + set "SCRIPT_ERROR=Name (-c) is a required parameter for %SCRIPT_CMD%" + goto invalid_cmd_line +) +IF NOT DEFINED CREATE_VERBOSE set "CREATE_VERBOSE=" +IF "!CREATE_CONFDIR!"=="" set CREATE_CONFDIR=_default +IF "!CREATE_NUM_SHARDS!"=="" set CREATE_NUM_SHARDS=1 +IF "!CREATE_REPFACT!"=="" set CREATE_REPFACT=1 +IF "!CREATE_CONFNAME!"=="" set CREATE_CONFNAME=!CREATE_NAME! + +REM Find a port that Solr is running on +if "!CREATE_PORT!"=="" ( + for /f "usebackq" %%i in (`dir /b "%SOLR_TIP%\bin" ^| findstr /i "^solr-.*\.port$"`) do ( + set SOME_SOLR_PORT= + For /F "Delims=" %%J In ('type "%SOLR_TIP%\bin\%%i"') do set SOME_SOLR_PORT=%%~J + if NOT "!SOME_SOLR_PORT!"=="" ( + for /f "tokens=2,5" %%j in ('netstat -aon ^| find "TCP " ^| find ":0 " ^| find ":!SOME_SOLR_PORT! "') do ( + IF NOT "%%k"=="0" set CREATE_PORT=!SOME_SOLR_PORT! + ) + ) + ) +) +if "!CREATE_PORT!"=="" ( + set "SCRIPT_ERROR=Could not find a running Solr instance on this host! Please use the -p option to specify the port." + goto err +) + +if "!CREATE_CONFDIR!"=="_default" ( + echo WARNING: Using _default configset with data driven schema functionality. NOT RECOMMENDED for production use. + echo To turn off: bin\solr config -c !CREATE_NAME! -p !CREATE_PORT! -action set-user-property -property update.autoCreateFields -value false +) + +if "%SCRIPT_CMD%"=="create_core" ( + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI create_core -name !CREATE_NAME! -solrUrl !SOLR_URL_SCHEME!://%SOLR_TOOL_HOST%:!CREATE_PORT!/solr ^ + -confdir !CREATE_CONFDIR! -configsetsDir "%SOLR_TIP%\server\solr\configsets" %CREATE_VERBOSE% +) else ( + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" -Dsolr.default.confdir="%DEFAULT_CONFDIR%"^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI create -name !CREATE_NAME! -shards !CREATE_NUM_SHARDS! -replicationFactor !CREATE_REPFACT! ^ + -confname !CREATE_CONFNAME! -confdir !CREATE_CONFDIR! -configsetsDir "%SOLR_TIP%\server\solr\configsets" ^ + -solrUrl !SOLR_URL_SCHEME!://%SOLR_TOOL_HOST%:!CREATE_PORT!/solr %CREATE_VERBOSE% +) + +goto done + +:parse_delete_args +IF [%1]==[] goto run_delete +IF "%1"=="-V" goto set_delete_verbose +IF "%1"=="-c" goto set_delete_name +IF "%1"=="-core" goto set_delete_name +IF "%1"=="-collection" goto set_delete_name +IF "%1"=="-p" goto set_delete_port +IF "%1"=="-port" goto set_delete_port +IF "%1"=="-deleteConfig" goto set_delete_config +IF "%1"=="-help" goto usage +IF "%1"=="-usage" goto usage +IF "%1"=="/?" goto usage +goto run_delete + +:set_delete_verbose +set DELETE_VERBOSE="-verbose" +SHIFT +goto parse_delete_args + +:set_delete_name +set DELETE_NAME=%~2 +SHIFT +SHIFT +goto parse_delete_args + +:set_delete_port +set DELETE_PORT=%~2 +SHIFT +SHIFT +goto parse_delete_args + +:set_delete_config +set DELETE_CONFIG=%~2 +SHIFT +SHIFT +goto parse_delete_args + +:run_delete +IF NOT DEFINED DELETE_VERBOSE set "DELETE_VERBOSE=" +IF "!DELETE_NAME!"=="" ( + set "SCRIPT_ERROR=Name (-c) is a required parameter for %SCRIPT_CMD%" + goto invalid_cmd_line +) + +REM Find a port that Solr is running on +if "!DELETE_PORT!"=="" ( + for /f "usebackq" %%i in (`dir /b "%SOLR_TIP%\bin" ^| findstr /i "^solr-.*\.port$"`) do ( + set SOME_SOLR_PORT= + For /F "Delims=" %%J In ('type "%SOLR_TIP%\bin\%%i"') do set SOME_SOLR_PORT=%%~J + if NOT "!SOME_SOLR_PORT!"=="" ( + for /f "tokens=2,5" %%j in ('netstat -aon ^| find "TCP " ^| find ":0 " ^| find ":!SOME_SOLR_PORT! "') do ( + IF NOT "%%k"=="0" set DELETE_PORT=!SOME_SOLR_PORT! + ) + ) + ) +) +if "!DELETE_PORT!"=="" ( + set "SCRIPT_ERROR=Could not find a running Solr instance on this host! Please use the -p option to specify the port." + goto err +) + +if "!DELETE_CONFIG!"=="" ( + set DELETE_CONFIG=true +) + +"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ +-Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ +-classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ +org.apache.solr.util.SolrCLI delete -name !DELETE_NAME! -deleteConfig !DELETE_CONFIG! ^ +-solrUrl !SOLR_URL_SCHEME!://%SOLR_TOOL_HOST%:!DELETE_PORT!/solr %DELETE_VERBOSE% + +goto done + +REM Clumsy to do the state machine thing for -d and -n, but that's required for back-compat +:parse_zk_args +IF "%1"=="-upconfig" ( + goto set_zk_op +) ELSE IF "%1"=="-V" ( + goto set_zk_verbose +) ELSE IF "%1"=="upconfig" ( + goto set_zk_op +) ELSE IF "%1"=="-downconfig" ( + goto set_zk_op +) ELSE IF "%1"=="downconfig" ( + goto set_zk_op +) ELSE IF "%1"=="cp" ( + goto set_zk_op +) ELSE IF "%1"=="mv" ( + goto set_zk_op +) ELSE IF "%1"=="rm" ( + goto set_zk_op +) ELSE IF "%1"=="ls" ( + goto set_zk_op +) ELSE IF "%1"=="mkroot" ( + goto set_zk_op +) ELSE IF "%1"=="-n" ( + goto set_config_name +) ELSE IF "%1"=="-r" ( + goto set_zk_recurse +) ELSE IF "%1"=="-configname" ( + goto set_config_name +) ELSE IF "%1"=="-d" ( + goto set_configdir +) ELSE IF "%1"=="-confdir" ( + goto set_configdir +) ELSE IF "%1"=="-z" ( + goto set_config_zk +) ELSE IF "%1"=="/?" ( + goto zk_usage +) ELSE IF "%1"=="-h" ( + goto zk_usage +) ELSE IF "%1"=="-help" ( + goto zk_usage +) ELSE IF "!ZK_SRC!"=="" ( + if not "%~1"=="" ( + goto set_zk_src + ) +) ELSE IF "!ZK_DST!"=="" ( + IF "%ZK_OP%"=="cp" ( + goto set_zk_dst + ) + IF "%ZK_OP%"=="mv" ( + goto set_zk_dst + ) + set ZK_DST="_" +) ELSE IF NOT "%1"=="" ( + set ERROR_MSG="Unrecognized or misplaced zk argument %1%" + goto zk_short_usage +) +goto run_zk + +:set_zk_op +set ZK_OP=%~1 +SHIFT +goto parse_zk_args + +:set_zk_verbose +set ZK_VERBOSE="-verbose" +SHIFT +goto parse_zk_args + +:set_config_name +set CONFIGSET_NAME=%~2 +SHIFT +SHIFT +goto parse_zk_args + +:set_configdir +set CONFIGSET_DIR=%~2 +SHIFT +SHIFT +goto parse_zk_args + +:set_config_zk +set ZK_HOST=%~2 +SHIFT +SHIFT +goto parse_zk_args + +:set_zk_src +set ZK_SRC=%~1 +SHIFT +goto parse_zk_args + +:set_zk_dst +set ZK_DST=%~1 +SHIFT +goto parse_zk_args + +:set_zk_recurse +set ZK_RECURSE="true" +SHIFT +goto parse_zk_args + +:run_zk +IF "!ZK_OP!"=="" ( + set "ERROR_MSG=Invalid command specified for zk sub-command" + goto zk_short_usage +) + +IF "!ZK_HOST!"=="" ( + set "ERROR_MSG=Must specify -z zkHost" + goto zk_short_usage +) + +IF "!ZK_OP!"=="-upconfig" ( + set ZK_OP="upconfig" +) +IF "!ZK_OP!"=="-downconfig" ( + set ZK_OP="downconfig" +) + +IF "!ZK_OP!"=="upconfig" ( + IF "!CONFIGSET_NAME!"=="" ( + set ERROR_MSG="-n option must be set for upconfig" + goto zk_short_usage + ) + IF "!CONFIGSET_DIR!"=="" ( + set ERROR_MSG="The -d option must be set for upconfig." + goto zk_short_usage + ) + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI !ZK_OP! -confname !CONFIGSET_NAME! -confdir !CONFIGSET_DIR! -zkHost !ZK_HOST! %ZK_VERBOSE%^ + -configsetsDir "%SOLR_TIP%/server/solr/configsets" +) ELSE IF "!ZK_OP!"=="downconfig" ( + IF "!CONFIGSET_NAME!"=="" ( + set ERROR_MSG="-n option must be set for downconfig" + goto zk_short_usage + ) + IF "!CONFIGSET_DIR!"=="" ( + set ERROR_MSG="The -d option must be set for downconfig." + goto zk_short_usage + ) + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI !ZK_OP! -confname !CONFIGSET_NAME! -confdir !CONFIGSET_DIR! -zkHost !ZK_HOST! %ZK_VERBOSE% +) ELSE IF "!ZK_OP!"=="cp" ( + IF "%ZK_SRC%"=="" ( + set ERROR_MSG=" must be specified for 'cp' command" + goto zk_short_usage + ) + IF "%ZK_DST%"=="" ( + set ERROR_MSG= must be specified for 'cp' command" + goto zk_short_usage + ) + IF NOT "!ZK_SRC:~0,3!"=="zk:" ( + IF NOT "!%ZK_DST:~0,3!"=="zk:" ( + set ERROR_MSG="At least one of src or dst must be prefixed by 'zk:'" + goto zk_short_usage + ) + ) + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI !ZK_OP! -zkHost !ZK_HOST! -src !ZK_SRC! -dst !ZK_DST! -recurse !ZK_RECURSE! %ZK_VERBOSE% +) ELSE IF "!ZK_OP!"=="mv" ( + IF "%ZK_SRC%"=="" ( + set ERROR_MSG=" must be specified for 'mv' command" + goto zk_short_usage + ) + IF "%ZK_DST%"=="" ( + set ERROR_MSG=" must be specified for 'mv' command" + goto zk_short_usage + ) + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI !ZK_OP! -zkHost !ZK_HOST! -src !ZK_SRC! -dst !ZK_DST! %ZK_VERBOSE% +) ELSE IF "!ZK_OP!"=="rm" ( + IF "%ZK_SRC"=="" ( + set ERROR_MSG="Zookeeper path to remove must be specified when using the 'rm' command" + goto zk_short_usage + ) + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI !ZK_OP! -zkHost !ZK_HOST! -path !ZK_SRC! -recurse !ZK_RECURSE! %ZK_VERBOSE% +) ELSE IF "!ZK_OP!"=="ls" ( + IF "%ZK_SRC"=="" ( + set ERROR_MSG="Zookeeper path to remove must be specified when using the 'ls' command" + goto zk_short_usage + ) + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI !ZK_OP! -zkHost !ZK_HOST! -path !ZK_SRC! -recurse !ZK_RECURSE! %ZK_VERBOSE% +) ELSE IF "!ZK_OP!"=="mkroot" ( + IF "%ZK_SRC"=="" ( + set ERROR_MSG="Zookeeper path to create must be specified when using the 'mkroot' command" + goto zk_short_usage + ) + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%SOLR_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI !ZK_OP! -zkHost !ZK_HOST! -path !ZK_SRC! %ZK_VERBOSE% +) ELSE ( + set ERROR_MSG="Unknown zk option !ZK_OP!" + goto zk_short_usage +) +goto done + + +:run_auth +IF "%1"=="-help" goto usage +IF "%1"=="-usage" goto usage + +REM Options parsing. +REM Note: With the following technique of parsing, it is not possible +REM to have an option without a value. +set "AUTH_PARAMS=%1" +set "option=" +for %%a in (%*) do ( + if not defined option ( + set arg=%%a + if "!arg:~0,1!" equ "-" set "option=!arg!" + ) else ( + set "option!option!=%%a" + if "!option!" equ "-d" set "SOLR_SERVER_DIR=%%a" + if "!option!" equ "-s" set "SOLR_HOME=%%a" + if not "!option!" equ "-s" if not "!option!" equ "-d" ( + set "AUTH_PARAMS=!AUTH_PARAMS! !option! %%a" + ) + set "option=" + ) +) +IF "%SOLR_SERVER_DIR%"=="" set "SOLR_SERVER_DIR=%DEFAULT_SERVER_DIR%" +IF NOT EXIST "%SOLR_SERVER_DIR%" ( + set "SCRIPT_ERROR=Solr server directory %SOLR_SERVER_DIR% not found!" + goto err +) +IF "%SOLR_HOME%"=="" set "SOLR_HOME=%SOLR_SERVER_DIR%\solr" +IF EXIST "%cd%\%SOLR_HOME%" set "SOLR_HOME=%cd%\%SOLR_HOME%" +IF NOT EXIST "%SOLR_HOME%\" ( + IF EXIST "%SOLR_SERVER_DIR%\%SOLR_HOME%" ( + set "SOLR_HOME=%SOLR_SERVER_DIR%\%SOLR_HOME%" + ) ELSE ( + set "SCRIPT_ERROR=Solr home directory %SOLR_HOME% not found!" + goto err + ) +) + +if "!AUTH_PORT!"=="" ( + for /f "usebackq" %%i in (`dir /b "%SOLR_TIP%\bin" ^| findstr /i "^solr-.*\.port$"`) do ( + set SOME_SOLR_PORT= + For /F "Delims=" %%J In ('type "%SOLR_TIP%\bin\%%i"') do set SOME_SOLR_PORT=%%~J + if NOT "!SOME_SOLR_PORT!"=="" ( + for /f "tokens=2,5" %%j in ('netstat -aon ^| find "TCP " ^| find ":0 " ^| find ":!SOME_SOLR_PORT! "') do ( + IF NOT "%%k"=="0" set AUTH_PORT=!SOME_SOLR_PORT! + ) + ) + ) +) +"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.util.SolrCLI auth %AUTH_PARAMS% -solrIncludeFile "%SOLR_INCLUDE%" -authConfDir "%SOLR_HOME%" ^ + -solrUrl !SOLR_URL_SCHEME!://%SOLR_TOOL_HOST%:!AUTH_PORT!/solr +goto done + + +:invalid_cmd_line +@echo. +IF "!SCRIPT_ERROR!"=="" ( + @echo Invalid command-line option: %1 +) ELSE ( + @echo ERROR: !SCRIPT_ERROR! +) +@echo. +IF "%FIRST_ARG%"=="start" ( + goto start_usage +) ELSE IF "%FIRST_ARG:~0,1%" == "-" ( + goto start_usage +) ELSE IF "%FIRST_ARG%"=="restart" ( + goto start_usage +) ELSE IF "%FIRST_ARG%"=="stop" ( + goto stop_usage +) ELSE IF "%FIRST_ARG%"=="healthcheck" ( + goto healthcheck_usage +) ELSE IF "%FIRST_ARG%"=="create" ( + goto create_usage +) ELSE IF "%FIRST_ARG%"=="create_core" ( + goto create_core_usage +) ELSE IF "%FIRST_ARG%"=="create_collection" ( + goto create_collection_usage +) ELSE IF "%FIRST_ARG%"=="zk" ( + goto zk_short_usage +) ELSE IF "%FIRST_ARG%"=="auth" ( + goto auth_usage +) ELSE IF "%FIRST_ARG%"=="status" ( + goto status_usage +) ELSE ( + goto script_usage +) + +:need_java_home +@echo Please set the JAVA_HOME environment variable to the path where you installed Java 1.8+ +goto done + +:need_java_vers +@echo Java 1.8 or later is required to run Solr. +goto done + +:err +@echo. +@echo ERROR: !SCRIPT_ERROR! +@echo. +exit /b 1 + +:done +ENDLOCAL +exit /b 0 + +REM Tests what Java we have and sets some global variables +:resolve_java_info + +CALL :resolve_java_vendor + +set JAVA_MAJOR_VERSION=0 +set JAVA_VERSION_INFO= +set JAVA_BUILD=0 + +FOR /f "usebackq tokens=3" %%a IN (`^""%JAVA%" -version 2^>^&1 ^| findstr "version"^"`) do ( + set JAVA_VERSION_INFO=%%a + REM Remove surrounding quotes + set JAVA_VERSION_INFO=!JAVA_VERSION_INFO:"=! + + REM Extract the major Java version, e.g. 7, 8, 9, 10 ... + for /f "tokens=1,2 delims=._-" %%a in ("!JAVA_VERSION_INFO!") do ( + if %%a GEQ 9 ( + set JAVA_MAJOR_VERSION=%%a + ) else ( + set JAVA_MAJOR_VERSION=%%b + ) + ) + + REM Don't look for "_{build}" if we're on IBM J9. + if NOT "%JAVA_VENDOR%" == "IBM J9" ( + for /f "delims=_ tokens=2" %%a in ("!JAVA_VERSION_INFO!") do ( + set /a JAVA_BUILD=%%a + ) + ) +) +GOTO :eof + +REM Set which JVM vendor we have +:resolve_java_vendor +"%JAVA%" -version 2>&1 | findstr /i "IBM J9" > nul +if %ERRORLEVEL% == 1 ( set "JAVA_VENDOR=Oracle" ) else ( set "JAVA_VENDOR=IBM J9" ) + +set JAVA_VENDOR_OUT= +GOTO :eof + +REM Safe echo which does not mess with () in strings +:safe_echo +set "eout=%1" +set eout=%eout:"=% +echo !eout! +GOTO :eof diff --git a/KeywordSearch/solr/bin/solr.in.cmd b/KeywordSearch/solr/bin/solr.in.cmd new file mode 100755 index 0000000000..7bbd9a587a --- /dev/null +++ b/KeywordSearch/solr/bin/solr.in.cmd @@ -0,0 +1,206 @@ +@REM +@REM Licensed to the Apache Software Foundation (ASF) under one or more +@REM contributor license agreements. See the NOTICE file distributed with +@REM this work for additional information regarding copyright ownership. +@REM The ASF licenses this file to You under the Apache License, Version 2.0 +@REM (the "License"); you may not use this file except in compliance with +@REM the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, software +@REM distributed under the License is distributed on an "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@REM See the License for the specific language governing permissions and +@REM limitations under the License. + +@echo off + +REM Settings here will override settings in existing env vars or in bin/solr. The default shipped state +REM of this file is completely commented. + +REM By default the script will use JAVA_HOME to determine which java +REM to use, but you can set a specific path for Solr to use without +REM affecting other Java applications on your server/workstation. +REM set SOLR_JAVA_HOME= + +REM Increase Java Min/Max Heap as needed to support your indexing / query needs +REM set SOLR_JAVA_MEM=-Xms512m -Xmx512m + +REM Configure verbose GC logging: +REM For Java 8: if this is set, additional params will be added to specify the log file & rotation +REM For Java 9 or higher: GC_LOG_OPTS is currently not supported. If you set it, the startup script will exit with failure. +REM set GC_LOG_OPTS=-verbose:gc -XX:+PrintHeapAtGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+PrintTenuringDistribution -XX:+PrintGCApplicationStoppedTime + +REM Various GC settings have shown to work well for a number of common Solr workloads. +REM See solr.cmd GC_TUNE for the default list. +REM set GC_TUNE=-XX:+ExplicitGCInvokesConcurrent +REM set GC_TUNE=-XX:SurvivorRatio=4 +REM set GC_TUNE=%GC_TUNE% -XX:TargetSurvivorRatio=90 +REM set GC_TUNE=%GC_TUNE% -XX:MaxTenuringThreshold=8 +REM set GC_TUNE=%GC_TUNE% -XX:+UseConcMarkSweepGC +REM set GC_TUNE=%GC_TUNE% -XX:ConcGCThreads=4 +REM set GC_TUNE=%GC_TUNE% -XX:ParallelGCThreads=4 +REM set GC_TUNE=%GC_TUNE% -XX:+CMSScavengeBeforeRemark +REM set GC_TUNE=%GC_TUNE% -XX:PretenureSizeThreshold=64m +REM set GC_TUNE=%GC_TUNE% -XX:+UseCMSInitiatingOccupancyOnly +REM set GC_TUNE=%GC_TUNE% -XX:CMSInitiatingOccupancyFraction=50 +REM set GC_TUNE=%GC_TUNE% -XX:CMSMaxAbortablePrecleanTime=6000 +REM set GC_TUNE=%GC_TUNE% -XX:+CMSParallelRemarkEnabled +REM set GC_TUNE=%GC_TUNE% -XX:+ParallelRefProcEnabled etc. + +REM Set the ZooKeeper connection string if using an external ZooKeeper ensemble +REM e.g. host1:2181,host2:2181/chroot +REM Leave empty if not using SolrCloud +REM set ZK_HOST= + +REM Set the ZooKeeper client timeout (for SolrCloud mode) +REM set ZK_CLIENT_TIMEOUT=15000 + +REM By default the start script uses "localhost"; override the hostname here +REM for production SolrCloud environments to control the hostname exposed to cluster state +REM set SOLR_HOST=192.168.1.1 + +REM By default Solr will try to connect to Zookeeper with 30 seconds in timeout; override the timeout if needed +REM set SOLR_WAIT_FOR_ZK=30 + +REM By default the start script uses UTC; override the timezone if needed +REM set SOLR_TIMEZONE=UTC + +REM Set to true to activate the JMX RMI connector to allow remote JMX client applications +REM to monitor the JVM hosting Solr; set to "false" to disable that behavior +REM (false is recommended in production environments) +REM set ENABLE_REMOTE_JMX_OPTS=false + +REM The script will use SOLR_PORT+10000 for the RMI_PORT or you can set it here +REM set RMI_PORT=18983 + +REM Anything you add to the SOLR_OPTS variable will be included in the java +REM start command line as-is, in ADDITION to other options. If you specify the +REM -a option on start script, those options will be appended as well. Examples: +REM set SOLR_OPTS=%SOLR_OPTS% -Dsolr.autoSoftCommit.maxTime=3000 +REM set SOLR_OPTS=%SOLR_OPTS% -Dsolr.autoCommit.maxTime=60000 +REM set SOLR_OPTS=%SOLR_OPTS% -Dsolr.clustering.enabled=true + +REM Path to a directory for Solr to store cores and their data. By default, Solr will use server\solr +REM If solr.xml is not stored in ZooKeeper, this directory needs to contain solr.xml +REM set SOLR_HOME= + +REM Path to a directory that Solr will use as root for data folders for each core. +REM If not set, defaults to /data. Overridable per core through 'dataDir' core property +REM set SOLR_DATA_HOME= + +REM Changes the logging level. Valid values: ALL, TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF. Default is INFO +REM This is an alternative to changing the rootLogger in log4j2.xml +REM set SOLR_LOG_LEVEL=INFO + +REM Location where Solr should write logs to. Absolute or relative to solr start dir +REM set SOLR_LOGS_DIR=logs + +REM Enables log rotation before starting Solr. Setting SOLR_LOG_PRESTART_ROTATION=true will let Solr take care of pre +REM start rotation of logs. This is false by default as log4j2 handles this for us. If you choose to use another log +REM framework that cannot do startup rotation, you may want to enable this to let Solr rotate logs on startup. +REM set SOLR_LOG_PRESTART_ROTATION=false + +REM Enables jetty request log for all requests +REM set SOLR_REQUESTLOG_ENABLED=false + +REM Set the host interface to listen on. Jetty will listen on all interfaces (0.0.0.0) by default. +REM This must be an IPv4 ("a.b.c.d") or bracketed IPv6 ("[x::y]") address, not a hostname! +REM set SOLR_JETTY_HOST=0.0.0.0 + +REM Sets the port Solr binds to, default is 8983 +REM set SOLR_PORT=8983 + +REM Restrict access to solr by IP address. +REM Specify a comma-separated list of addresses or networks, for example: +REM 127.0.0.1, 192.168.0.0/24, [::1], [2000:123:4:5::]/64 +REM set SOLR_IP_WHITELIST= + +REM Block access to solr from specific IP addresses. +REM Specify a comma-separated list of addresses or networks, for example: +REM 127.0.0.1, 192.168.0.0/24, [::1], [2000:123:4:5::]/64 +REM set SOLR_IP_BLACKLIST= + +REM Enables HTTPS. It is implictly true if you set SOLR_SSL_KEY_STORE. Use this config +REM to enable https module with custom jetty configuration. +REM set SOLR_SSL_ENABLED=true +REM Uncomment to set SSL-related system properties +REM Be sure to update the paths to the correct keystore for your environment +REM set SOLR_SSL_KEY_STORE=etc/solr-ssl.keystore.p12 +REM set SOLR_SSL_KEY_STORE_PASSWORD=secret +REM set SOLR_SSL_TRUST_STORE=etc/solr-ssl.keystore.p12 +REM set SOLR_SSL_TRUST_STORE_PASSWORD=secret +REM Require clients to authenticate +REM set SOLR_SSL_NEED_CLIENT_AUTH=false +REM Enable clients to authenticate (but not require) +REM set SOLR_SSL_WANT_CLIENT_AUTH=false +REM Verify client hostname during SSL handshake +REM set SOLR_SSL_CLIENT_HOSTNAME_VERIFICATION=false +REM SSL Certificates contain host/ip "peer name" information that is validated by default. Setting +REM this to false can be useful to disable these checks when re-using a certificate on many hosts +REM set SOLR_SSL_CHECK_PEER_NAME=true +REM Override Key/Trust Store types if necessary +REM set SOLR_SSL_KEY_STORE_TYPE=PKCS12 +REM set SOLR_SSL_TRUST_STORE_TYPE=PKCS12 + +REM Uncomment if you want to override previously defined SSL values for HTTP client +REM otherwise keep them commented and the above values will automatically be set for HTTP clients +REM set SOLR_SSL_CLIENT_KEY_STORE= +REM set SOLR_SSL_CLIENT_KEY_STORE_PASSWORD= +REM set SOLR_SSL_CLIENT_TRUST_STORE= +REM set SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD= +REM set SOLR_SSL_CLIENT_KEY_STORE_TYPE= +REM set SOLR_SSL_CLIENT_TRUST_STORE_TYPE= + +REM Sets path of Hadoop credential provider (hadoop.security.credential.provider.path property) and +REM enables usage of credential store. +REM Credential provider should store the following keys: +REM * solr.jetty.keystore.password +REM * solr.jetty.truststore.password +REM Set the two below if you want to set specific store passwords for HTTP client +REM * javax.net.ssl.keyStorePassword +REM * javax.net.ssl.trustStorePassword +REM More info: https://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-common/CredentialProviderAPI.html +REM set SOLR_HADOOP_CREDENTIAL_PROVIDER_PATH=localjceks://file/home/solr/hadoop-credential-provider.jceks +REM set SOLR_OPTS=%SOLR_OPTS% -Dsolr.ssl.credential.provider.chain=hadoop + +REM Settings for authentication +REM Please configure only one of SOLR_AUTHENTICATION_CLIENT_BUILDER or SOLR_AUTH_TYPE parameters +REM set SOLR_AUTHENTICATION_CLIENT_BUILDER=org.apache.solr.client.solrj.impl.PreemptiveBasicAuthClientBuilderFactory +REM set SOLR_AUTH_TYPE=basic +REM set SOLR_AUTHENTICATION_OPTS=-Dbasicauth=solr:SolrRocks + +REM Settings for ZK ACL +REM set SOLR_ZK_CREDS_AND_ACLS=-DzkACLProvider=org.apache.solr.common.cloud.VMParamsAllAndReadonlyDigestZkACLProvider ^ +REM -DzkCredentialsProvider=org.apache.solr.common.cloud.VMParamsSingleSetCredentialsDigestZkCredentialsProvider ^ +REM -DzkDigestUsername=admin-user -DzkDigestPassword=CHANGEME-ADMIN-PASSWORD ^ +REM -DzkDigestReadonlyUsername=readonly-user -DzkDigestReadonlyPassword=CHANGEME-READONLY-PASSWORD +REM set SOLR_OPTS=%SOLR_OPTS% %SOLR_ZK_CREDS_AND_ACLS% + +REM When running Solr in non-cloud mode and if planning to do distributed search (using the "shards" parameter), the +REM list of hosts needs to be whitelisted or Solr will forbid the request. The whitelist can be configured in solr.xml, +REM or if you are using the OOTB solr.xml, can be specified using the system property "solr.shardsWhitelist". Alternatively +REM host checking can be disabled by using the system property "solr.disable.shardsWhitelist" +REM set SOLR_OPTS=%SOLR_OPTS% -Dsolr.shardsWhitelist=http://localhost:8983,http://localhost:8984 + +REM For a visual indication in the Admin UI of what type of environment this cluster is, configure +REM a -Dsolr.environment property below. Valid values are prod, stage, test, dev, with an optional +REM label or color, e.g. -Dsolr.environment=test,label=Functional+test,color=brown +REM set SOLR_OPTS=%SOLR_OPTS% -Dsolr.environment=prod + +REM Specifies the path to a common library directory that will be shared across all cores. +REM Any JAR files in this directory will be added to the search path for Solr plugins. +REM If the specified path is not absolute, it will be relative to `%SOLR_HOME%`. +REM set SOLR_OPTS=%SOLR_OPTS% -Dsolr.sharedLib=/path/to/lib + +REM Runs solr in a java security manager sandbox. This can protect against some attacks. +REM Runtime properties are passed to the security policy file (server\etc\security.policy) +REM You can also tweak via standard JDK files such as ~\.java.policy, see https://s.apache.org/java8policy +REM This is experimental! It may not work at all with Hadoop/HDFS features. +REM set SOLR_SECURITY_MANAGER_ENABLED=false + +REM Solr is by default allowed to read and write data from/to SOLR_HOME and a few other well defined locations +REM Sometimes it may be necessary to place a core or a backup on a different location or a different disk +REM This parameter lets you specify file system path(s) to explicitly allow. The special value of '*' will allow any path +REM SOLR_OPTS="%SOLR_OPTS% -Dsolr.allowPaths=D:\,E:\other\path" diff --git a/KeywordSearch/solr/bin/solr.in.sh b/KeywordSearch/solr/bin/solr.in.sh new file mode 100755 index 0000000000..29261ce6e1 --- /dev/null +++ b/KeywordSearch/solr/bin/solr.in.sh @@ -0,0 +1,234 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Settings here will override settings in existing env vars or in bin/solr. The default shipped state +# of this file is completely commented. + +# By default the script will use JAVA_HOME to determine which java +# to use, but you can set a specific path for Solr to use without +# affecting other Java applications on your server/workstation. +#SOLR_JAVA_HOME="" + +# This controls the number of seconds that the solr script will wait for +# Solr to stop gracefully or Solr to start. If the graceful stop fails, +# the script will forcibly stop Solr. If the start fails, the script will +# give up waiting and display the last few lines of the logfile. +#SOLR_STOP_WAIT="180" + +# Increase Java Heap as needed to support your indexing / query needs +#SOLR_HEAP="512m" + +# Expert: If you want finer control over memory options, specify them directly +# Comment out SOLR_HEAP if you are using this though, that takes precedence +#SOLR_JAVA_MEM="-Xms512m -Xmx512m" + +# Enable verbose GC logging... +# * If this is unset, various default options will be selected depending on which JVM version is in use +# * For Java 8: if this is set, additional params will be added to specify the log file & rotation +# * For Java 9 or higher: each included opt param that starts with '-Xlog:gc', but does not include an +# output specifier, will have a 'file' output specifier (as well as formatting & rollover options) +# appended, using the effective value of the SOLR_LOGS_DIR. +# +#GC_LOG_OPTS='-Xlog:gc*' # (Java 9+) +#GC_LOG_OPTS="-verbose:gc -XX:+PrintHeapAtGC -XX:+PrintGCDetails \ +# -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+PrintTenuringDistribution -XX:+PrintGCApplicationStoppedTime" + +# These GC settings have shown to work well for a number of common Solr workloads +#GC_TUNE=" \ +#-XX:+ExplicitGCInvokesConcurrent \ +#-XX:SurvivorRatio=4 \ +#-XX:TargetSurvivorRatio=90 \ +#-XX:MaxTenuringThreshold=8 \ +#-XX:+UseConcMarkSweepGC \ +#-XX:ConcGCThreads=4 -XX:ParallelGCThreads=4 \ +#-XX:+CMSScavengeBeforeRemark \ +#-XX:PretenureSizeThreshold=64m \ +#-XX:+UseCMSInitiatingOccupancyOnly \ +#-XX:CMSInitiatingOccupancyFraction=50 \ +#-XX:CMSMaxAbortablePrecleanTime=6000 \ +#-XX:+CMSParallelRemarkEnabled \ +#-XX:+ParallelRefProcEnabled etc. + +# Set the ZooKeeper connection string if using an external ZooKeeper ensemble +# e.g. host1:2181,host2:2181/chroot +# Leave empty if not using SolrCloud +#ZK_HOST="" + +# Set the ZooKeeper client timeout (for SolrCloud mode) +#ZK_CLIENT_TIMEOUT="15000" + +# By default the start script uses "localhost"; override the hostname here +# for production SolrCloud environments to control the hostname exposed to cluster state +#SOLR_HOST="192.168.1.1" + +# By default Solr will try to connect to Zookeeper with 30 seconds in timeout; override the timeout if needed +#SOLR_WAIT_FOR_ZK="30" + +# By default the start script uses UTC; override the timezone if needed +#SOLR_TIMEZONE="UTC" + +# Set to true to activate the JMX RMI connector to allow remote JMX client applications +# to monitor the JVM hosting Solr; set to "false" to disable that behavior +# (false is recommended in production environments) +#ENABLE_REMOTE_JMX_OPTS="false" + +# The script will use SOLR_PORT+10000 for the RMI_PORT or you can set it here +# RMI_PORT=18983 + +# Anything you add to the SOLR_OPTS variable will be included in the java +# start command line as-is, in ADDITION to other options. If you specify the +# -a option on start script, those options will be appended as well. Examples: +#SOLR_OPTS="$SOLR_OPTS -Dsolr.autoSoftCommit.maxTime=3000" +#SOLR_OPTS="$SOLR_OPTS -Dsolr.autoCommit.maxTime=60000" +#SOLR_OPTS="$SOLR_OPTS -Dsolr.clustering.enabled=true" + +# Location where the bin/solr script will save PID files for running instances +# If not set, the script will create PID files in $SOLR_TIP/bin +#SOLR_PID_DIR= + +# Path to a directory for Solr to store cores and their data. By default, Solr will use server/solr +# If solr.xml is not stored in ZooKeeper, this directory needs to contain solr.xml +#SOLR_HOME= + +# Path to a directory that Solr will use as root for data folders for each core. +# If not set, defaults to /data. Overridable per core through 'dataDir' core property +#SOLR_DATA_HOME= + +# Solr provides a default Log4J configuration xml file in server/resources +# however, you may want to customize the log settings and file appender location +# so you can point the script to use a different log4j2.xml file +#LOG4J_PROPS=/var/solr/log4j2.xml + +# Changes the logging level. Valid values: ALL, TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF. Default is INFO +# This is an alternative to changing the rootLogger in log4j2.xml +#SOLR_LOG_LEVEL=INFO + +# Location where Solr should write logs to. Absolute or relative to solr start dir +#SOLR_LOGS_DIR=logs + +# Enables log rotation before starting Solr. Setting SOLR_LOG_PRESTART_ROTATION=true will let Solr take care of pre +# start rotation of logs. This is false by default as log4j2 handles this for us. If you choose to use another log +# framework that cannot do startup rotation, you may want to enable this to let Solr rotate logs on startup. +#SOLR_LOG_PRESTART_ROTATION=false + +# Enables jetty request log for all requests +#SOLR_REQUESTLOG_ENABLED=false + +# Sets the port Solr binds to, default is 8983 +#SOLR_PORT=8983 + +# Restrict access to solr by IP address. +# Specify a comma-separated list of addresses or networks, for example: +# 127.0.0.1, 192.168.0.0/24, [::1], [2000:123:4:5::]/64 +#SOLR_IP_WHITELIST= + +# Block access to solr from specific IP addresses. +# Specify a comma-separated list of addresses or networks, for example: +# 127.0.0.1, 192.168.0.0/24, [::1], [2000:123:4:5::]/64 +#SOLR_IP_BLACKLIST= + +# Enables HTTPS. It is implictly true if you set SOLR_SSL_KEY_STORE. Use this config +# to enable https module with custom jetty configuration. +#SOLR_SSL_ENABLED=true +# Uncomment to set SSL-related system properties +# Be sure to update the paths to the correct keystore for your environment +#SOLR_SSL_KEY_STORE=etc/solr-ssl.keystore.p12 +#SOLR_SSL_KEY_STORE_PASSWORD=secret +#SOLR_SSL_TRUST_STORE=etc/solr-ssl.keystore.p12 +#SOLR_SSL_TRUST_STORE_PASSWORD=secret +# Require clients to authenticate +#SOLR_SSL_NEED_CLIENT_AUTH=false +# Enable clients to authenticate (but not require) +#SOLR_SSL_WANT_CLIENT_AUTH=false +# Verify client's hostname during SSL handshake +#SOLR_SSL_CLIENT_HOSTNAME_VERIFICATION=false +# SSL Certificates contain host/ip "peer name" information that is validated by default. Setting +# this to false can be useful to disable these checks when re-using a certificate on many hosts +#SOLR_SSL_CHECK_PEER_NAME=true +# Override Key/Trust Store types if necessary +#SOLR_SSL_KEY_STORE_TYPE=PKCS12 +#SOLR_SSL_TRUST_STORE_TYPE=PKCS12 + +# Uncomment if you want to override previously defined SSL values for HTTP client +# otherwise keep them commented and the above values will automatically be set for HTTP clients +#SOLR_SSL_CLIENT_KEY_STORE= +#SOLR_SSL_CLIENT_KEY_STORE_PASSWORD= +#SOLR_SSL_CLIENT_TRUST_STORE= +#SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD= +#SOLR_SSL_CLIENT_KEY_STORE_TYPE= +#SOLR_SSL_CLIENT_TRUST_STORE_TYPE= + +# Sets path of Hadoop credential provider (hadoop.security.credential.provider.path property) and +# enables usage of credential store. +# Credential provider should store the following keys: +# * solr.jetty.keystore.password +# * solr.jetty.truststore.password +# Set the two below if you want to set specific store passwords for HTTP client +# * javax.net.ssl.keyStorePassword +# * javax.net.ssl.trustStorePassword +# More info: https://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-common/CredentialProviderAPI.html +#SOLR_HADOOP_CREDENTIAL_PROVIDER_PATH=localjceks://file/home/solr/hadoop-credential-provider.jceks +#SOLR_OPTS=" -Dsolr.ssl.credential.provider.chain=hadoop" + +# Settings for authentication +# Please configure only one of SOLR_AUTHENTICATION_CLIENT_BUILDER or SOLR_AUTH_TYPE parameters +#SOLR_AUTHENTICATION_CLIENT_BUILDER="org.apache.solr.client.solrj.impl.PreemptiveBasicAuthClientBuilderFactory" +#SOLR_AUTH_TYPE="basic" +#SOLR_AUTHENTICATION_OPTS="-Dbasicauth=solr:SolrRocks" + +# Settings for ZK ACL +#SOLR_ZK_CREDS_AND_ACLS="-DzkACLProvider=org.apache.solr.common.cloud.VMParamsAllAndReadonlyDigestZkACLProvider \ +# -DzkCredentialsProvider=org.apache.solr.common.cloud.VMParamsSingleSetCredentialsDigestZkCredentialsProvider \ +# -DzkDigestUsername=admin-user -DzkDigestPassword=CHANGEME-ADMIN-PASSWORD \ +# -DzkDigestReadonlyUsername=readonly-user -DzkDigestReadonlyPassword=CHANGEME-READONLY-PASSWORD" +#SOLR_OPTS="$SOLR_OPTS $SOLR_ZK_CREDS_AND_ACLS" + + +# Settings for common system values that may cause operational imparement when system defaults are used. +# Solr can use many processes and many file handles. On modern operating systems the savings by leaving +# these settings low is minuscule, while the consequence can be Solr instability. To turn these checks off, set +# SOLR_ULIMIT_CHECKS=false either here or as part of your profile. + +# Different limits can be set in solr.in.sh or your profile if you prefer as well. +#SOLR_RECOMMENDED_OPEN_FILES= +#SOLR_RECOMMENDED_MAX_PROCESSES= +#SOLR_ULIMIT_CHECKS= + +# When running Solr in non-cloud mode and if planning to do distributed search (using the "shards" parameter), the +# list of hosts needs to be whitelisted or Solr will forbid the request. The whitelist can be configured in solr.xml, +# or if you are using the OOTB solr.xml, can be specified using the system property "solr.shardsWhitelist". Alternatively +# host checking can be disabled by using the system property "solr.disable.shardsWhitelist" +#SOLR_OPTS="$SOLR_OPTS -Dsolr.shardsWhitelist=http://localhost:8983,http://localhost:8984" + +# For a visual indication in the Admin UI of what type of environment this cluster is, configure +# a -Dsolr.environment property below. Valid values are prod, stage, test, dev, with an optional +# label or color, e.g. -Dsolr.environment=test,label=Functional+test,color=brown +#SOLR_OPTS="$SOLR_OPTS -Dsolr.environment=prod" + +# Specifies the path to a common library directory that will be shared across all cores. +# Any JAR files in this directory will be added to the search path for Solr plugins. +# If the specified path is not absolute, it will be relative to `$SOLR_HOME`. +#SOLR_OPTS="$SOLR_OPTS -Dsolr.sharedLib=/path/to/lib" + +# Runs solr in java security manager sandbox. This can protect against some attacks. +# Runtime properties are passed to the security policy file (server/etc/security.policy) +# You can also tweak via standard JDK files such as ~/.java.policy, see https://s.apache.org/java8policy +# This is experimental! It may not work at all with Hadoop/HDFS features. +#SOLR_SECURITY_MANAGER_ENABLED=false + +# Solr is by default allowed to read and write data from/to SOLR_HOME and a few other well defined locations +# Sometimes it may be necessary to place a core or a backup on a different location or a different disk +# This parameter lets you specify file system path(s) to explicitly allow. The special value of '*' will allow any path +#SOLR_OPTS="$SOLR_OPTS -Dsolr.allowPaths=/mnt/bigdisk,/other/path" diff --git a/KeywordSearch/solr/server/README.txt b/KeywordSearch/solr/server/README.txt new file mode 100755 index 0000000000..d4b421cac3 --- /dev/null +++ b/KeywordSearch/solr/server/README.txt @@ -0,0 +1,109 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +Solr server +------------ + +This directory contains an instance of the Jetty Servlet container setup to +run Solr. + +To run Solr: + + cd $SOLR_INSTALL + bin/solr start + +where $SOLR_INSTALL is the location where you extracted the Solr installation bundle. + +Server directory layout +----------------------- + +server/contexts + + This directory contains the Jetty Web application deployment descriptor for the Solr Web app. + +server/etc + + Jetty configuration and example SSL keystore + +server/lib + + Jetty and other 3rd party libraries + +server/logs + + Solr log files + +server/resources + + Contains configuration files, such as the Log4j configuration (log4j2.xml) for configuring Solr loggers. + +server/scripts/cloud-scripts + + Command-line utility for working with ZooKeeper when running in SolrCloud mode, see zkcli.sh / .cmd for + usage information. + +server/solr + + Default solr.solr.home directory where Solr will create core directories; must contain solr.xml + +server/solr/configsets + + Directories containing different configuration options for running Solr. + + _default : Bare minimum configurations with field-guessing and managed schema turned + on by default, so as to start indexing data in Solr without having to design + a schema upfront. You can use the REST API to manage your schema as you refine your index + requirements. You can turn off the field (for a collection, say mycollection) guessing by: + curl http://host:8983/solr/mycollection/config -d '{"set-user-property": {"update.autoCreateFields":"false"}}' + + sample_techproducts_configs : Comprehensive example configuration that demonstrates many of the powerful + features of Solr, based on the use case of building a search solution for + tech products. + +server/solr-webapp + + Contains files used by the Solr server; do not edit files in this directory (Solr is not a Java Web application). + + +Notes About Solr Examples +-------------------------- + +* SolrHome * + +By default, start.jar starts Solr in Jetty using the default Solr Home +directory of "./solr/" (relative to the working directory of the servlet +container). + +* References to Jar Files Outside This Directory * + +Various example SolrHome dirs contained in this directory may use "" +statements in the solrconfig.xml file to reference plugin jars outside of +this directory for loading "contrib" plugins via relative paths. + +If you make a copy of this example server and wish to use the +ExtractingRequestHandler (SolrCell), DataImportHandler (DIH), the +clustering component, or any other modules in "contrib", you will need to +copy the required jars or update the paths to those jars in your +solrconfig.xml. + +* Logging * + +By default, Jetty & Solr will log to the console and logs/solr.log. This can +be convenient when first getting started, but eventually you will want to +log just to a file. To configure logging, edit the log4j2.xml file in +"resources". + +It is also possible to setup log4j or other popular logging frameworks. + diff --git a/KeywordSearch/solr/server/contexts/solr-jetty-context.xml b/KeywordSearch/solr/server/contexts/solr-jetty-context.xml new file mode 100755 index 0000000000..6392cd11b7 --- /dev/null +++ b/KeywordSearch/solr/server/contexts/solr-jetty-context.xml @@ -0,0 +1,8 @@ + + + + + /solr-webapp/webapp + /etc/webdefault.xml + false + diff --git a/KeywordSearch/solr/server/etc/jetty-http.xml b/KeywordSearch/solr/server/etc/jetty-http.xml new file mode 100755 index 0000000000..42e99be82d --- /dev/null +++ b/KeywordSearch/solr/server/etc/jetty-http.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/KeywordSearch/solr/server/etc/jetty-https.xml b/KeywordSearch/solr/server/etc/jetty-https.xml new file mode 100755 index 0000000000..03a384ec3e --- /dev/null +++ b/KeywordSearch/solr/server/etc/jetty-https.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + alpn + + + + + + + + h2 + http/1.1 + + + http/1.1 + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/KeywordSearch/solr/server/etc/jetty-https8.xml b/KeywordSearch/solr/server/etc/jetty-https8.xml new file mode 100755 index 0000000000..9c090ab3ef --- /dev/null +++ b/KeywordSearch/solr/server/etc/jetty-https8.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + http/1.1 + + + + + + + + + + + + + + + + + + + diff --git a/KeywordSearch/solr/server/etc/jetty-requestlog.xml b/KeywordSearch/solr/server/etc/jetty-requestlog.xml new file mode 100755 index 0000000000..34a1e90200 --- /dev/null +++ b/KeywordSearch/solr/server/etc/jetty-requestlog.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + /yyyy_mm_dd.request.log + yyyy_MM_dd + 90 + true + UTC + + + + + + + + diff --git a/KeywordSearch/solr/server/etc/jetty-ssl.xml b/KeywordSearch/solr/server/etc/jetty-ssl.xml new file mode 100755 index 0000000000..53e0ec1109 --- /dev/null +++ b/KeywordSearch/solr/server/etc/jetty-ssl.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/KeywordSearch/solr/server/etc/jetty.xml b/KeywordSearch/solr/server/etc/jetty.xml new file mode 100755 index 0000000000..ecd4f220fe --- /dev/null +++ b/KeywordSearch/solr/server/etc/jetty.xml @@ -0,0 +1,248 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + solr.jetty + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + https + + + + + + + + + + + + + + + + + true + false + requestedPath + + + + + + * + Content-Security-Policy + default-src 'none'; base-uri 'none'; connect-src 'self'; form-action 'self'; font-src 'self'; frame-ancestors 'none'; img-src 'self'; media-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self'; worker-src 'self'; + + + + + + + * + X-Content-Type-Options + nosniff + + + + + + + * + X-Frame-Options + SAMEORIGIN + + + + + + + * + X-XSS-Protection + 1; mode=block + + + + + + + + + ^/$ + /solr/ + + + + + + + /v2/* + /solr/____v2 + + + + + + + /api/* + /solr/____v2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + false + false + + + + + + + + + org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern + .*/servlet-api-[^/]*\.jar$ + + + + + + /contexts + 0 + + + + + + + + + + + + diff --git a/KeywordSearch/solr/server/etc/security.policy b/KeywordSearch/solr/server/etc/security.policy new file mode 100755 index 0000000000..bcf82b9eb2 --- /dev/null +++ b/KeywordSearch/solr/server/etc/security.policy @@ -0,0 +1,203 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Policy file for solr. Please keep minimal and avoid wildcards. + +// permissions needed for tests to pass, based on properties set by the build system +// NOTE: if the property is not set, the permission entry is ignored. +grant { + // contain read access to only what we need: + // 3rd party jar resources (where symlinks are not supported), test-files/ resources + permission java.io.FilePermission "${common.dir}${/}-", "read"; + permission java.io.FilePermission "${common.dir}${/}..${/}solr${/}-", "read"; + // 3rd party jar resources (where symlinks are supported) + permission java.io.FilePermission "${user.home}${/}.ivy2${/}cache${/}-", "read"; + // system jar resources + permission java.io.FilePermission "${java.home}${/}-", "read"; + permission java.io.FilePermission "${junit4.childvm.cwd}", "read"; + permission java.io.FilePermission "${junit4.childvm.cwd}${/}temp", "read,write,delete"; + permission java.io.FilePermission "${junit4.childvm.cwd}${/}temp${/}-", "read,write,delete"; + permission java.io.FilePermission "${junit4.childvm.cwd}${/}jacoco.db", "write"; + permission java.io.FilePermission "${junit4.tempDir}${/}*", "read,write,delete"; + permission java.io.FilePermission "${clover.db.dir}${/}-", "read,write,delete"; + permission java.io.FilePermission "${tests.linedocsfile}", "read"; + // DirectoryFactoryTest messes with these (wtf?) + permission java.io.FilePermission "/tmp/inst1/conf/solrcore.properties", "read"; + permission java.io.FilePermission "/path/to/myinst/conf/solrcore.properties", "read"; + // TestConfigSets messes with these (wtf?) + permission java.io.FilePermission "/path/to/solr/home/lib", "read"; + + permission java.nio.file.LinkPermission "hard"; + + // all possibilities of accepting/binding/connections on localhost with ports >=1024: + permission java.net.SocketPermission "localhost:1024-", "accept,listen,connect,resolve"; + permission java.net.SocketPermission "127.0.0.1:1024-", "accept,listen,connect,resolve"; + permission java.net.SocketPermission "[::1]:1024-", "accept,listen,connect,resolve"; + // "dead hosts", we try to keep it fast + permission java.net.SocketPermission "[::1]:4", "connect,resolve"; + permission java.net.SocketPermission "[::1]:6", "connect,resolve"; + permission java.net.SocketPermission "[::1]:8", "connect,resolve"; + + // Basic permissions needed for Lucene to work: + permission java.util.PropertyPermission "*", "read,write"; + + // needed by gson serialization of junit4 runner: TODO clean that up + permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; + permission java.lang.RuntimePermission "accessDeclaredMembers"; + // needed by junit4 runner to capture sysout/syserr: + permission java.lang.RuntimePermission "setIO"; + // needed by randomized runner to catch failures from other threads: + permission java.lang.RuntimePermission "setDefaultUncaughtExceptionHandler"; + // needed by randomized runner getTopThreadGroup: + permission java.lang.RuntimePermission "modifyThreadGroup"; + // needed by tests e.g. shutting down executors: + permission java.lang.RuntimePermission "modifyThread"; + // needed for tons of test hacks etc + permission java.lang.RuntimePermission "getStackTrace"; + // needed for mock filesystems in tests + permission java.lang.RuntimePermission "fileSystemProvider"; + // needed for test of IOUtils.spins (maybe it can be avoided) + permission java.lang.RuntimePermission "getFileStoreAttributes"; + // analyzers/uima: needed by lucene expressions' JavascriptCompiler + permission java.lang.RuntimePermission "createClassLoader"; + // needed to test unmap hack on platforms that support it + permission java.lang.RuntimePermission "accessClassInPackage.sun.misc"; + // needed by jacoco to dump coverage + permission java.lang.RuntimePermission "shutdownHooks"; + // needed by org.apache.logging.log4j + permission java.lang.RuntimePermission "getenv.*"; + permission java.lang.RuntimePermission "getClassLoader"; + permission java.lang.RuntimePermission "setContextClassLoader"; + permission java.lang.RuntimePermission "getStackWalkerWithClassReference"; + // needed by bytebuddy + permission java.lang.RuntimePermission "defineClass"; + // needed by mockito + permission java.lang.RuntimePermission "accessClassInPackage.sun.reflect"; + permission java.lang.RuntimePermission "reflectionFactoryAccess"; + // needed by SolrResourceLoader + permission java.lang.RuntimePermission "closeClassLoader"; + // needed by HttpSolrClient + permission java.lang.RuntimePermission "getFileSystemAttributes"; + // needed by hadoop auth (TODO: there is a cleaner way to handle this) + permission java.lang.RuntimePermission "loadLibrary.jaas"; + permission java.lang.RuntimePermission "loadLibrary.jaas_unix"; + permission java.lang.RuntimePermission "loadLibrary.jaas_nt"; + // needed by hadoop common RawLocalFileSystem for java nio getOwner + permission java.lang.RuntimePermission "accessUserInformation"; + // needed by hadoop hdfs + permission java.lang.RuntimePermission "readFileDescriptor"; + permission java.lang.RuntimePermission "writeFileDescriptor"; + // needed by hadoop http + permission java.lang.RuntimePermission "getProtectionDomain"; + + // These two *have* to be spelled out a separate + permission java.lang.management.ManagementPermission "control"; + permission java.lang.management.ManagementPermission "monitor"; + + // needed by hadoop htrace + permission java.net.NetPermission "getNetworkInformation"; + + // needed by DIH + permission java.sql.SQLPermission "deregisterDriver"; + + permission java.util.logging.LoggingPermission "control"; + + // needed by solr mbeans feature/tests + // TODO: can we remove wildcard for class names/members? + permission javax.management.MBeanPermission "*", "getAttribute"; + permission javax.management.MBeanPermission "*", "getMBeanInfo"; + permission javax.management.MBeanPermission "*", "queryMBeans"; + permission javax.management.MBeanPermission "*", "queryNames"; + permission javax.management.MBeanPermission "*", "registerMBean"; + permission javax.management.MBeanPermission "*", "unregisterMBean"; + permission javax.management.MBeanServerPermission "createMBeanServer"; + permission javax.management.MBeanServerPermission "findMBeanServer"; + permission javax.management.MBeanServerPermission "releaseMBeanServer"; + permission javax.management.MBeanTrustPermission "register"; + + // needed by hadoop auth + permission javax.security.auth.AuthPermission "getSubject"; + permission javax.security.auth.AuthPermission "modifyPrincipals"; + permission javax.security.auth.AuthPermission "doAs"; + permission javax.security.auth.AuthPermission "getLoginConfiguration"; + permission javax.security.auth.AuthPermission "setLoginConfiguration"; + permission javax.security.auth.AuthPermission "modifyPrivateCredentials"; + permission javax.security.auth.AuthPermission "modifyPublicCredentials"; + permission javax.security.auth.PrivateCredentialPermission "org.apache.hadoop.security.Credentials * \"*\"", "read"; + + // needed by hadoop security + permission java.security.SecurityPermission "putProviderProperty.SaslPlainServer"; + permission java.security.SecurityPermission "insertProvider"; + + permission javax.xml.bind.JAXBPermission "setDatatypeConverter"; + + // SSL related properties for Solr tests + permission javax.net.ssl.SSLPermission "setDefaultSSLContext"; + + // SASL/Kerberos related properties for Solr tests + permission javax.security.auth.PrivateCredentialPermission "javax.security.auth.kerberos.KerberosTicket * \"*\"", "read"; + + // may only be necessary with Java 7? + permission javax.security.auth.PrivateCredentialPermission "javax.security.auth.kerberos.KeyTab * \"*\"", "read"; + permission javax.security.auth.PrivateCredentialPermission "sun.security.jgss.krb5.Krb5Util$KeysFromKeyTab * \"*\"", "read"; + + permission javax.security.auth.kerberos.ServicePermission "*", "initiate"; + permission javax.security.auth.kerberos.ServicePermission "*", "accept"; + permission javax.security.auth.kerberos.DelegationPermission "\"*\" \"krbtgt/EXAMPLE.COM@EXAMPLE.COM\""; + + // java 8 accessibility requires this perm - should not after 8 I believe (rrd4j is the root reason we hit an accessibility code path) + permission java.awt.AWTPermission "*"; + + // used by solr to create sandboxes (e.g. script execution) + permission java.security.SecurityPermission "createAccessControlContext"; +}; + +// additional permissions based on system properties set by /bin/solr +// NOTE: if the property is not set, the permission entry is ignored. +grant { + permission java.io.FilePermission "${hadoop.security.credential.provider.path}", "read,write,delete,readlink"; + permission java.io.FilePermission "${hadoop.security.credential.provider.path}${/}-", "read,write,delete,readlink"; + + permission java.io.FilePermission "${solr.jetty.keystore}", "read,write,delete,readlink"; + permission java.io.FilePermission "${solr.jetty.keystore}${/}-", "read,write,delete,readlink"; + + permission java.io.FilePermission "${solr.jetty.truststore}", "read,write,delete,readlink"; + permission java.io.FilePermission "${solr.jetty.truststore}${/}-", "read,write,delete,readlink"; + + permission java.io.FilePermission "${solr.install.dir}", "read,write,delete,readlink"; + permission java.io.FilePermission "${solr.install.dir}${/}-", "read,write,delete,readlink"; + + permission java.io.FilePermission "${jetty.home}", "read,write,delete,readlink"; + permission java.io.FilePermission "${jetty.home}${/}-", "read,write,delete,readlink"; + + permission java.io.FilePermission "${solr.solr.home}", "read,write,delete,readlink"; + permission java.io.FilePermission "${solr.solr.home}${/}-", "read,write,delete,readlink"; + + permission java.io.FilePermission "${solr.data.home}", "read,write,delete,readlink"; + permission java.io.FilePermission "${solr.data.home}${/}-", "read,write,delete,readlink"; + + permission java.io.FilePermission "${solr.default.confdir}", "read,write,delete,readlink"; + permission java.io.FilePermission "${solr.default.confdir}${/}-", "read,write,delete,readlink"; + + permission java.io.FilePermission "${solr.log.dir}", "read,write,delete,readlink"; + permission java.io.FilePermission "${solr.log.dir}${/}-", "read,write,delete,readlink"; + + permission java.io.FilePermission "${log4j.configurationFile}", "read,write,delete,readlink"; + + // expanded to a wildcard if set, allows all networking everywhere + permission java.net.SocketPermission "${solr.internal.network.permission}", "accept,listen,connect,resolve"; +}; diff --git a/KeywordSearch/solr/server/etc/security.properties b/KeywordSearch/solr/server/etc/security.properties new file mode 100755 index 0000000000..7f196a8fbb --- /dev/null +++ b/KeywordSearch/solr/server/etc/security.properties @@ -0,0 +1,24 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# command-line security properties file +# +# By default, when enabling security manager, DNS lookups are cached indefinitely, +# as protection against DNS spoofing. We set this back to the default (non-security-manager) +# value of 30 seconds, to prevent surprising behavior (e.g. nodes in cloud environments without +# static IP addresses). Users concerned about DNS spoofing should instead follow best practices: +# populating solr.shardsWhitelist, enabling TLS, etc. +networkaddress.cache.ttl=30 diff --git a/KeywordSearch/solr/server/etc/webdefault.xml b/KeywordSearch/solr/server/etc/webdefault.xml new file mode 100755 index 0000000000..f0882926a9 --- /dev/null +++ b/KeywordSearch/solr/server/etc/webdefault.xml @@ -0,0 +1,527 @@ + + + + + + + + + + + + + + + + + + + + + + + Default web.xml file. + This file is applied to a Web application before its own WEB_INF/web.xml file + + + + + + + + org.eclipse.jetty.servlet.listener.ELContextCleaner + + + + + + + + org.eclipse.jetty.servlet.listener.IntrospectorCleaner + + + + + + + + + + + + + + + + + + + default + org.eclipse.jetty.servlet.DefaultServlet + + aliases + false + + + acceptRanges + true + + + dirAllowed + false + + + welcomeServlets + false + + + redirectWelcome + false + + + maxCacheSize + 256000000 + + + maxCachedFileSize + 200000000 + + + maxCachedFiles + 2048 + + + gzip + true + + + useFileMappedBuffer + true + + + + 0 + + + + default + / + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + jsp + org.apache.jasper.servlet.JspServlet + + logVerbosityLevel + DEBUG + + + fork + false + + + xpoweredBy + false + + + 0 + + + + jsp + *.jsp + *.jspf + *.jspx + *.xsp + *.JSP + *.JSPF + *.JSPX + *.XSP + + + + + + + + + + + + + + + + + + + + + + + + + + + + 30 + + + + + + + + + + + + + index.html + index.htm + index.jsp + + + + + + ar + ISO-8859-6 + + + be + ISO-8859-5 + + + bg + ISO-8859-5 + + + ca + ISO-8859-1 + + + cs + ISO-8859-2 + + + da + ISO-8859-1 + + + de + ISO-8859-1 + + + el + ISO-8859-7 + + + en + ISO-8859-1 + + + es + ISO-8859-1 + + + et + ISO-8859-1 + + + fi + ISO-8859-1 + + + fr + ISO-8859-1 + + + hr + ISO-8859-2 + + + hu + ISO-8859-2 + + + is + ISO-8859-1 + + + it + ISO-8859-1 + + + iw + ISO-8859-8 + + + ja + Shift_JIS + + + ko + EUC-KR + + + lt + ISO-8859-2 + + + lv + ISO-8859-2 + + + mk + ISO-8859-5 + + + nl + ISO-8859-1 + + + no + ISO-8859-1 + + + pl + ISO-8859-2 + + + pt + ISO-8859-1 + + + ro + ISO-8859-2 + + + ru + ISO-8859-5 + + + sh + ISO-8859-5 + + + sk + ISO-8859-2 + + + sl + ISO-8859-2 + + + sq + ISO-8859-2 + + + sr + ISO-8859-5 + + + sv + ISO-8859-1 + + + tr + ISO-8859-9 + + + uk + ISO-8859-5 + + + zh + GB2312 + + + zh_TW + Big5 + + + + + + Disable TRACE + / + TRACE + + + + + + diff --git a/KeywordSearch/solr/server/lib/ext/disruptor-3.4.2.jar b/KeywordSearch/solr/server/lib/ext/disruptor-3.4.2.jar new file mode 100755 index 0000000000..b366bbebc5 Binary files /dev/null and b/KeywordSearch/solr/server/lib/ext/disruptor-3.4.2.jar differ diff --git a/KeywordSearch/solr/server/lib/ext/jcl-over-slf4j-1.7.24.jar b/KeywordSearch/solr/server/lib/ext/jcl-over-slf4j-1.7.24.jar new file mode 100755 index 0000000000..2ea9e37487 Binary files /dev/null and b/KeywordSearch/solr/server/lib/ext/jcl-over-slf4j-1.7.24.jar differ diff --git a/KeywordSearch/solr/server/lib/ext/jul-to-slf4j-1.7.24.jar b/KeywordSearch/solr/server/lib/ext/jul-to-slf4j-1.7.24.jar new file mode 100755 index 0000000000..82f8d17c02 Binary files /dev/null and b/KeywordSearch/solr/server/lib/ext/jul-to-slf4j-1.7.24.jar differ diff --git a/KeywordSearch/solr/server/lib/ext/log4j-1.2-api-2.13.2.jar b/KeywordSearch/solr/server/lib/ext/log4j-1.2-api-2.13.2.jar new file mode 100755 index 0000000000..d0e6b7fffe Binary files /dev/null and b/KeywordSearch/solr/server/lib/ext/log4j-1.2-api-2.13.2.jar differ diff --git a/KeywordSearch/solr/server/lib/ext/log4j-api-2.13.2.jar b/KeywordSearch/solr/server/lib/ext/log4j-api-2.13.2.jar new file mode 100755 index 0000000000..afc89ff0d5 Binary files /dev/null and b/KeywordSearch/solr/server/lib/ext/log4j-api-2.13.2.jar differ diff --git a/KeywordSearch/solr/server/lib/ext/log4j-core-2.13.2.jar b/KeywordSearch/solr/server/lib/ext/log4j-core-2.13.2.jar new file mode 100755 index 0000000000..9b6bdff8e2 Binary files /dev/null and b/KeywordSearch/solr/server/lib/ext/log4j-core-2.13.2.jar differ diff --git a/KeywordSearch/solr/server/lib/ext/log4j-slf4j-impl-2.13.2.jar b/KeywordSearch/solr/server/lib/ext/log4j-slf4j-impl-2.13.2.jar new file mode 100755 index 0000000000..19e257cae8 Binary files /dev/null and b/KeywordSearch/solr/server/lib/ext/log4j-slf4j-impl-2.13.2.jar differ diff --git a/KeywordSearch/solr/server/lib/ext/log4j-web-2.13.2.jar b/KeywordSearch/solr/server/lib/ext/log4j-web-2.13.2.jar new file mode 100755 index 0000000000..c96dc2e238 Binary files /dev/null and b/KeywordSearch/solr/server/lib/ext/log4j-web-2.13.2.jar differ diff --git a/KeywordSearch/solr/server/lib/ext/slf4j-api-1.7.24.jar b/KeywordSearch/solr/server/lib/ext/slf4j-api-1.7.24.jar new file mode 100755 index 0000000000..05941a12f0 Binary files /dev/null and b/KeywordSearch/solr/server/lib/ext/slf4j-api-1.7.24.jar differ diff --git a/KeywordSearch/solr/server/lib/http2-common-9.4.27.v20200227.jar b/KeywordSearch/solr/server/lib/http2-common-9.4.27.v20200227.jar new file mode 100755 index 0000000000..d42399fdef Binary files /dev/null and b/KeywordSearch/solr/server/lib/http2-common-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/lib/http2-hpack-9.4.27.v20200227.jar b/KeywordSearch/solr/server/lib/http2-hpack-9.4.27.v20200227.jar new file mode 100755 index 0000000000..ef55bbe988 Binary files /dev/null and b/KeywordSearch/solr/server/lib/http2-hpack-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/lib/http2-server-9.4.27.v20200227.jar b/KeywordSearch/solr/server/lib/http2-server-9.4.27.v20200227.jar new file mode 100755 index 0000000000..fa355943cd Binary files /dev/null and b/KeywordSearch/solr/server/lib/http2-server-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/lib/javax.servlet-api-3.1.0.jar b/KeywordSearch/solr/server/lib/javax.servlet-api-3.1.0.jar new file mode 100755 index 0000000000..6b14c3d267 Binary files /dev/null and b/KeywordSearch/solr/server/lib/javax.servlet-api-3.1.0.jar differ diff --git a/KeywordSearch/solr/server/lib/jetty-alpn-java-server-9.4.27.v20200227.jar b/KeywordSearch/solr/server/lib/jetty-alpn-java-server-9.4.27.v20200227.jar new file mode 100755 index 0000000000..5f743e760a Binary files /dev/null and b/KeywordSearch/solr/server/lib/jetty-alpn-java-server-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/lib/jetty-alpn-server-9.4.27.v20200227.jar b/KeywordSearch/solr/server/lib/jetty-alpn-server-9.4.27.v20200227.jar new file mode 100755 index 0000000000..0adfdc73ba Binary files /dev/null and b/KeywordSearch/solr/server/lib/jetty-alpn-server-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/lib/jetty-continuation-9.4.27.v20200227.jar b/KeywordSearch/solr/server/lib/jetty-continuation-9.4.27.v20200227.jar new file mode 100755 index 0000000000..dea8a52d3c Binary files /dev/null and b/KeywordSearch/solr/server/lib/jetty-continuation-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/lib/jetty-deploy-9.4.27.v20200227.jar b/KeywordSearch/solr/server/lib/jetty-deploy-9.4.27.v20200227.jar new file mode 100755 index 0000000000..ab33050a82 Binary files /dev/null and b/KeywordSearch/solr/server/lib/jetty-deploy-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/lib/jetty-http-9.4.27.v20200227.jar b/KeywordSearch/solr/server/lib/jetty-http-9.4.27.v20200227.jar new file mode 100755 index 0000000000..556a76be5a Binary files /dev/null and b/KeywordSearch/solr/server/lib/jetty-http-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/lib/jetty-io-9.4.27.v20200227.jar b/KeywordSearch/solr/server/lib/jetty-io-9.4.27.v20200227.jar new file mode 100755 index 0000000000..375f825188 Binary files /dev/null and b/KeywordSearch/solr/server/lib/jetty-io-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/lib/jetty-jmx-9.4.27.v20200227.jar b/KeywordSearch/solr/server/lib/jetty-jmx-9.4.27.v20200227.jar new file mode 100755 index 0000000000..522c13ef3a Binary files /dev/null and b/KeywordSearch/solr/server/lib/jetty-jmx-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/lib/jetty-rewrite-9.4.27.v20200227.jar b/KeywordSearch/solr/server/lib/jetty-rewrite-9.4.27.v20200227.jar new file mode 100755 index 0000000000..b9c20ff800 Binary files /dev/null and b/KeywordSearch/solr/server/lib/jetty-rewrite-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/lib/jetty-security-9.4.27.v20200227.jar b/KeywordSearch/solr/server/lib/jetty-security-9.4.27.v20200227.jar new file mode 100755 index 0000000000..4ee129b4e0 Binary files /dev/null and b/KeywordSearch/solr/server/lib/jetty-security-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/lib/jetty-server-9.4.27.v20200227.jar b/KeywordSearch/solr/server/lib/jetty-server-9.4.27.v20200227.jar new file mode 100755 index 0000000000..5185014cbc Binary files /dev/null and b/KeywordSearch/solr/server/lib/jetty-server-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/lib/jetty-servlet-9.4.27.v20200227.jar b/KeywordSearch/solr/server/lib/jetty-servlet-9.4.27.v20200227.jar new file mode 100755 index 0000000000..4ea397d55d Binary files /dev/null and b/KeywordSearch/solr/server/lib/jetty-servlet-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/lib/jetty-servlets-9.4.27.v20200227.jar b/KeywordSearch/solr/server/lib/jetty-servlets-9.4.27.v20200227.jar new file mode 100755 index 0000000000..5a8d07c4f4 Binary files /dev/null and b/KeywordSearch/solr/server/lib/jetty-servlets-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/lib/jetty-util-9.4.27.v20200227.jar b/KeywordSearch/solr/server/lib/jetty-util-9.4.27.v20200227.jar new file mode 100755 index 0000000000..6b53df4c07 Binary files /dev/null and b/KeywordSearch/solr/server/lib/jetty-util-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/lib/jetty-webapp-9.4.27.v20200227.jar b/KeywordSearch/solr/server/lib/jetty-webapp-9.4.27.v20200227.jar new file mode 100755 index 0000000000..234bf2f64b Binary files /dev/null and b/KeywordSearch/solr/server/lib/jetty-webapp-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/lib/jetty-xml-9.4.27.v20200227.jar b/KeywordSearch/solr/server/lib/jetty-xml-9.4.27.v20200227.jar new file mode 100755 index 0000000000..859888805d Binary files /dev/null and b/KeywordSearch/solr/server/lib/jetty-xml-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/lib/metrics-core-4.1.5.jar b/KeywordSearch/solr/server/lib/metrics-core-4.1.5.jar new file mode 100755 index 0000000000..a383ed6f45 Binary files /dev/null and b/KeywordSearch/solr/server/lib/metrics-core-4.1.5.jar differ diff --git a/KeywordSearch/solr/server/lib/metrics-graphite-4.1.5.jar b/KeywordSearch/solr/server/lib/metrics-graphite-4.1.5.jar new file mode 100755 index 0000000000..0eca3738e8 Binary files /dev/null and b/KeywordSearch/solr/server/lib/metrics-graphite-4.1.5.jar differ diff --git a/KeywordSearch/solr/server/lib/metrics-jetty9-4.1.5.jar b/KeywordSearch/solr/server/lib/metrics-jetty9-4.1.5.jar new file mode 100755 index 0000000000..f3ad6856e9 Binary files /dev/null and b/KeywordSearch/solr/server/lib/metrics-jetty9-4.1.5.jar differ diff --git a/KeywordSearch/solr/server/lib/metrics-jmx-4.1.5.jar b/KeywordSearch/solr/server/lib/metrics-jmx-4.1.5.jar new file mode 100755 index 0000000000..6aaaf33721 Binary files /dev/null and b/KeywordSearch/solr/server/lib/metrics-jmx-4.1.5.jar differ diff --git a/KeywordSearch/solr/server/lib/metrics-jvm-4.1.5.jar b/KeywordSearch/solr/server/lib/metrics-jvm-4.1.5.jar new file mode 100755 index 0000000000..ba1c3b8323 Binary files /dev/null and b/KeywordSearch/solr/server/lib/metrics-jvm-4.1.5.jar differ diff --git a/KeywordSearch/solr/server/modules/http.mod b/KeywordSearch/solr/server/modules/http.mod new file mode 100755 index 0000000000..d4ceec5120 --- /dev/null +++ b/KeywordSearch/solr/server/modules/http.mod @@ -0,0 +1,9 @@ +# +# Jetty HTTP Connector +# + +[depend] +server + +[xml] +etc/jetty-http.xml \ No newline at end of file diff --git a/KeywordSearch/solr/server/modules/https.mod b/KeywordSearch/solr/server/modules/https.mod new file mode 100755 index 0000000000..8affbcf60f --- /dev/null +++ b/KeywordSearch/solr/server/modules/https.mod @@ -0,0 +1,9 @@ +# +# Jetty HTTPS Connector +# + +[depend] +ssl + +[xml] +etc/jetty-https.xml \ No newline at end of file diff --git a/KeywordSearch/solr/server/modules/https8.mod b/KeywordSearch/solr/server/modules/https8.mod new file mode 100755 index 0000000000..f799f6bd0c --- /dev/null +++ b/KeywordSearch/solr/server/modules/https8.mod @@ -0,0 +1,9 @@ +# +# Jetty HTTPS Connector +# + +[depend] +ssl + +[xml] +etc/jetty-https8.xml \ No newline at end of file diff --git a/KeywordSearch/solr/server/modules/requestlog.mod b/KeywordSearch/solr/server/modules/requestlog.mod new file mode 100755 index 0000000000..2b048dbc76 --- /dev/null +++ b/KeywordSearch/solr/server/modules/requestlog.mod @@ -0,0 +1,9 @@ +# +# Request Log module +# + +[depend] +server + +[xml] +etc/jetty-requestlog.xml diff --git a/KeywordSearch/solr/server/modules/server.mod b/KeywordSearch/solr/server/modules/server.mod new file mode 100755 index 0000000000..0d60a9e3f4 --- /dev/null +++ b/KeywordSearch/solr/server/modules/server.mod @@ -0,0 +1,11 @@ +# +# Base Server Module +# + +[lib] +lib/*.jar +lib/ext/*.jar +resources/ + +[xml] +etc/jetty.xml \ No newline at end of file diff --git a/KeywordSearch/solr/server/modules/ssl.mod b/KeywordSearch/solr/server/modules/ssl.mod new file mode 100755 index 0000000000..091e3dea0d --- /dev/null +++ b/KeywordSearch/solr/server/modules/ssl.mod @@ -0,0 +1,9 @@ +# +# SSL Keystore module +# + +[depend] +server + +[xml] +etc/jetty-ssl.xml \ No newline at end of file diff --git a/KeywordSearch/solr/server/resources/jetty-logging.properties b/KeywordSearch/solr/server/resources/jetty-logging.properties new file mode 100755 index 0000000000..e7a31b0d58 --- /dev/null +++ b/KeywordSearch/solr/server/resources/jetty-logging.properties @@ -0,0 +1 @@ +org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.Slf4jLog diff --git a/KeywordSearch/solr/server/resources/log4j2-console.xml b/KeywordSearch/solr/server/resources/log4j2-console.xml new file mode 100755 index 0000000000..923b018f04 --- /dev/null +++ b/KeywordSearch/solr/server/resources/log4j2-console.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + %maxLen{%-5p - %d{yyyy-MM-dd HH:mm:ss.SSS}; %c; %m%notEmpty{ =>%ex{short}}}{10240}%n + + + + + + + + + + + + + + + + diff --git a/KeywordSearch/solr/server/resources/log4j2.xml b/KeywordSearch/solr/server/resources/log4j2.xml new file mode 100755 index 0000000000..0a545b2a68 --- /dev/null +++ b/KeywordSearch/solr/server/resources/log4j2.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + %maxLen{%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p (%t) [%X{collection} %X{shard} %X{replica} %X{core}] %c{1.} %m%notEmpty{ =>%ex{short}}}{10240}%n + + + + + + + + %maxLen{%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p (%t) [%X{collection} %X{shard} %X{replica} %X{core}] %c{1.} %m%notEmpty{ =>%ex{short}}}{10240}%n + + + + + + + + + + + + + %maxLen{%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p (%t) [%X{collection} %X{shard} %X{replica} %X{core}] %c{1.} %m%notEmpty{ =>%ex{short}}}{10240}%n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/KeywordSearch/solr/server/scripts/cloud-scripts/snapshotscli.sh b/KeywordSearch/solr/server/scripts/cloud-scripts/snapshotscli.sh new file mode 100755 index 0000000000..e5a26d6457 --- /dev/null +++ b/KeywordSearch/solr/server/scripts/cloud-scripts/snapshotscli.sh @@ -0,0 +1,176 @@ +#!/usr/bin/env bash + +set -e + +run_solr_snapshot_tool() { + JVM="java" + scriptDir=$(dirname "$0") + if [ -n "$LOG4J_PROPS" ]; then + log4j_config="file:${LOG4J_PROPS}" + else + log4j_config="file:${scriptDir}/../../resources/log4j2-console.xml" + fi + PATH=${JAVA_HOME}/bin:${PATH} ${JVM} ${ZKCLI_JVM_FLAGS} -Dlog4j.configurationFile=${log4j_config} \ + -classpath "${solrLibPath}" org.apache.solr.core.snapshots.SolrSnapshotsTool "$@" 2> /dev/null +} + +usage() { + run_solr_snapshot_tool --help +} + +distcp_warning() { + echo "SOLR_USE_DISTCP environment variable is not set. \ + Do you want to use hadoop distcp tool for exporting Solr collection snapshot ?" +} + +parse_options() { + OPTIND=3 + while getopts ":c:d:s:z:p:r:i:" o ; do + case "${o}" in + d) + destPath=${OPTARG} + ;; + s) + sourcePath=${OPTARG} + ;; + c) + collectionName=${OPTARG} + ;; + z) + solrZkEnsemble=${OPTARG} + ;; + p) + pathPrefix=${OPTARG} + ;; + r) + backupRepoName=${OPTARG} + ;; + i) + aysncReqId=${OPTARG} + ;; + *) + echo "Unknown option ${OPTARG}" + usage 1>&2 + exit 1 + ;; + esac + done +} + +prepare_snapshot_export() { + #Make sure to cleanup the temporary files. + scratch=$(mktemp -d -t solrsnaps.XXXXXXXXXX) + function finish { + rm -rf "${scratch}" + } + trap finish EXIT + + if hdfs dfs -test -d "${destPath}" ; then + run_solr_snapshot_tool --prepare-snapshot-export "$@" -t "${scratch}" + + hdfs dfs -mkdir -p "${copyListingDirPath}" > /dev/null + find "${scratch}" -type f -printf "%f\n" | while read shardId; do + echo "Copying the copy-listing for $shardId" + hdfs dfs -copyFromLocal "${scratch}/${shardId}" "${copyListingDirPath}" > /dev/null + done + else + echo "Directory ${destPath} does not exist." + exit 1 + fi +} + +copy_snapshot_files() { + copylisting_dir_path="$1" + + if hdfs dfs -test -d "${copylisting_dir_path}" ; then + for shardId in $(hdfs dfs -stat "%n" "${copylisting_dir_path}/*"); do + oPath="${destPath}/${snapshotName}/snapshot.${shardId}" + echo "Copying the index files for ${shardId} to ${oPath}" + ${distCpCmd} -f "${copylisting_dir_path}/${shardId}" "${oPath}" > /dev/null + done + else + echo "Directory ${copylisting_dir_path} does not exist." + exit 1 + fi +} + +collectionName="" +solrZkEnsemble="" +pathPrefix="" +destPath="" +sourcePath="" +cmd="$1" +snapshotName="$2" +copyListingDirPath="" +distCpCmd="${SOLR_DISTCP_CMD:-hadoop distcp}" +scriptDir=$(dirname "$0") +solrLibPath="${SOLR_LIB_PATH:-${scriptDir}/../../solr-webapp/webapp/WEB-INF/lib/*:${scriptDir}/../../lib/ext/*}" + +case "${cmd}" in + --create) + run_solr_snapshot_tool "$@" + ;; + --delete) + run_solr_snapshot_tool "$@" + ;; + --list) + run_solr_snapshot_tool "$@" + ;; + --describe) + run_solr_snapshot_tool "$@" + ;; + --prepare-snapshot-export) + : "${SOLR_USE_DISTCP:? $(distcp_warning)}" + + parse_options "$@" + + : "${destPath:? Please specify destination directory using -d option}" + + copyListingDirPath="${destPath}/copylistings" + prepare_snapshot_export "${@:2}" + echo "Done. GoodBye!" + ;; + --export) + if [ -z "${SOLR_USE_DISTCP}" ]; then + run_solr_snapshot_tool "$@" + echo "Done. GoodBye!" + exit 0 + fi + + parse_options "$@" + + : "${snapshotName:? Please specify the name of the snapshot}" + : "${destPath:? Please specify destination directory using -d option}" + + if [ -n "${collectionName}" ] && [ -n "${sourcePath}" ]; then + echo "The -c and -s options can not be specified together" + exit 1 + fi + + if [ -z "${collectionName}" ] && [ -z "${sourcePath}" ]; then + echo "At least one of options (-c or -s) must be specified" + exit 1 + fi + + if [ -n "${collectionName}" ]; then + copyListingDirPath="${destPath}/${snapshotName}/copylistings" + prepare_snapshot_export "${@:2}" + copy_snapshot_files "${destPath}/${snapshotName}/copylistings" + hdfs dfs -rm -r -f -skipTrash "${destPath}/${snapshotName}/copylistings" > /dev/null + else + copy_snapshot_files "${sourcePath}/copylistings" + echo "Copying the collection meta-data to ${destPath}/${snapshotName}" + ${distCpCmd} "${sourcePath}/${snapshotName}/*" "${destPath}/${snapshotName}/" > /dev/null + fi + + echo "Done. GoodBye!" + ;; + --help) + usage 1>&2 + ;; + *) + echo "Unknown command ${cmd}" + usage 1>&2 + exit 1 +esac + diff --git a/KeywordSearch/solr/server/scripts/cloud-scripts/zkcli.bat b/KeywordSearch/solr/server/scripts/cloud-scripts/zkcli.bat new file mode 100755 index 0000000000..8b10b1927a --- /dev/null +++ b/KeywordSearch/solr/server/scripts/cloud-scripts/zkcli.bat @@ -0,0 +1,21 @@ +@echo off +REM You can override pass the following parameters to this script: +REM + +set JVM=java + +REM Find location of this script + +set SDIR=%~dp0 +if "%SDIR:~-1%"=="\" set SDIR=%SDIR:~0,-1% + +set "LOG4J_CONFIG=file:///%SDIR%\..\..\resources\log4j2-console.xml" + +REM Settings for ZK ACL +REM set SOLR_ZK_CREDS_AND_ACLS=-DzkACLProvider=org.apache.solr.common.cloud.VMParamsAllAndReadonlyDigestZkACLProvider ^ +REM -DzkCredentialsProvider=org.apache.solr.common.cloud.VMParamsSingleSetCredentialsDigestZkCredentialsProvider ^ +REM -DzkDigestUsername=admin-user -DzkDigestPassword=CHANGEME-ADMIN-PASSWORD ^ +REM -DzkDigestReadonlyUsername=readonly-user -DzkDigestReadonlyPassword=CHANGEME-READONLY-PASSWORD + +"%JVM%" %SOLR_ZK_CREDS_AND_ACLS% %ZKCLI_JVM_FLAGS% -Dlog4j.configurationFile="%LOG4J_CONFIG%" ^ +-classpath "%SDIR%\..\..\solr-webapp\webapp\WEB-INF\lib\*;%SDIR%\..\..\lib\ext\*;%SDIR%\..\..\lib\*" org.apache.solr.cloud.ZkCLI %* diff --git a/KeywordSearch/solr/server/scripts/cloud-scripts/zkcli.sh b/KeywordSearch/solr/server/scripts/cloud-scripts/zkcli.sh new file mode 100755 index 0000000000..844548a75e --- /dev/null +++ b/KeywordSearch/solr/server/scripts/cloud-scripts/zkcli.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +# You can override pass the following parameters to this script: +# + +JVM="java" + +# Find location of this script + +sdir="`dirname \"$0\"`" + +log4j_config="file:$sdir/../../resources/log4j2-console.xml" + +# Settings for ZK ACL +#SOLR_ZK_CREDS_AND_ACLS="-DzkACLProvider=org.apache.solr.common.cloud.VMParamsAllAndReadonlyDigestZkACLProvider \ +# -DzkCredentialsProvider=org.apache.solr.common.cloud.VMParamsSingleSetCredentialsDigestZkCredentialsProvider \ +# -DzkDigestUsername=admin-user -DzkDigestPassword=CHANGEME-ADMIN-PASSWORD \ +# -DzkDigestReadonlyUsername=readonly-user -DzkDigestReadonlyPassword=CHANGEME-READONLY-PASSWORD" + +PATH=$JAVA_HOME/bin:$PATH $JVM $SOLR_ZK_CREDS_AND_ACLS $ZKCLI_JVM_FLAGS -Dlog4j.configurationFile=$log4j_config \ +-classpath "$sdir/../../solr-webapp/webapp/WEB-INF/lib/*:$sdir/../../lib/ext/*:$sdir/../../lib/*" org.apache.solr.cloud.ZkCLI ${1+"$@"} + diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/antlr4-runtime-4.5.1-1.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/antlr4-runtime-4.5.1-1.jar new file mode 100755 index 0000000000..387129d648 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/antlr4-runtime-4.5.1-1.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/asm-7.2.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/asm-7.2.jar new file mode 100755 index 0000000000..5058db4fa5 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/asm-7.2.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/asm-commons-7.2.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/asm-commons-7.2.jar new file mode 100755 index 0000000000..bb84f3a9d5 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/asm-commons-7.2.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/avatica-core-1.13.0.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/avatica-core-1.13.0.jar new file mode 100755 index 0000000000..a508768422 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/avatica-core-1.13.0.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/caffeine-2.8.4.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/caffeine-2.8.4.jar new file mode 100755 index 0000000000..96cac37c51 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/caffeine-2.8.4.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/calcite-core-1.18.0.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/calcite-core-1.18.0.jar new file mode 100755 index 0000000000..a814080a28 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/calcite-core-1.18.0.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/calcite-linq4j-1.18.0.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/calcite-linq4j-1.18.0.jar new file mode 100755 index 0000000000..dc5002d5bd Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/calcite-linq4j-1.18.0.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-cli-1.4.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-cli-1.4.jar new file mode 100755 index 0000000000..22deb3089e Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-cli-1.4.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-codec-1.13.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-codec-1.13.jar new file mode 100755 index 0000000000..bf6ccb385d Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-codec-1.13.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-collections-3.2.2.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-collections-3.2.2.jar new file mode 100755 index 0000000000..fa5df82a63 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-collections-3.2.2.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-compiler-3.0.9.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-compiler-3.0.9.jar new file mode 100755 index 0000000000..2866a66625 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-compiler-3.0.9.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-configuration2-2.1.1.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-configuration2-2.1.1.jar new file mode 100755 index 0000000000..666baa09d2 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-configuration2-2.1.1.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-exec-1.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-exec-1.3.jar new file mode 100755 index 0000000000..9a64351981 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-exec-1.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-io-2.6.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-io-2.6.jar new file mode 100755 index 0000000000..00556b119d Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-io-2.6.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-lang3-3.9.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-lang3-3.9.jar new file mode 100755 index 0000000000..0d89693926 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-lang3-3.9.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-math3-3.6.1.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-math3-3.6.1.jar new file mode 100755 index 0000000000..0ff582cfcb Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-math3-3.6.1.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-text-1.6.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-text-1.6.jar new file mode 100755 index 0000000000..63e47300c6 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/commons-text-1.6.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/curator-client-2.13.0.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/curator-client-2.13.0.jar new file mode 100755 index 0000000000..7c01fbe81e Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/curator-client-2.13.0.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/curator-framework-2.13.0.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/curator-framework-2.13.0.jar new file mode 100755 index 0000000000..46cada0777 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/curator-framework-2.13.0.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/curator-recipes-2.13.0.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/curator-recipes-2.13.0.jar new file mode 100755 index 0000000000..caf7b87491 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/curator-recipes-2.13.0.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/disruptor-3.4.2.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/disruptor-3.4.2.jar new file mode 100755 index 0000000000..b366bbebc5 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/disruptor-3.4.2.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/eigenbase-properties-1.1.5.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/eigenbase-properties-1.1.5.jar new file mode 100755 index 0000000000..786c6c6a2b Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/eigenbase-properties-1.1.5.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/guava-25.1-jre.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/guava-25.1-jre.jar new file mode 100755 index 0000000000..babc175535 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/guava-25.1-jre.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/hadoop-annotations-3.2.0.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/hadoop-annotations-3.2.0.jar new file mode 100755 index 0000000000..0a52d1b6d4 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/hadoop-annotations-3.2.0.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/hadoop-auth-3.2.0.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/hadoop-auth-3.2.0.jar new file mode 100755 index 0000000000..683f3f7d1a Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/hadoop-auth-3.2.0.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/hadoop-common-3.2.0.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/hadoop-common-3.2.0.jar new file mode 100755 index 0000000000..77a00c750c Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/hadoop-common-3.2.0.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/hadoop-hdfs-client-3.2.0.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/hadoop-hdfs-client-3.2.0.jar new file mode 100755 index 0000000000..59afc3eaf6 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/hadoop-hdfs-client-3.2.0.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/hppc-0.8.1.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/hppc-0.8.1.jar new file mode 100755 index 0000000000..39a7c24db6 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/hppc-0.8.1.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/htrace-core4-4.1.0-incubating.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/htrace-core4-4.1.0-incubating.jar new file mode 100755 index 0000000000..12349a2066 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/htrace-core4-4.1.0-incubating.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/http2-client-9.4.27.v20200227.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/http2-client-9.4.27.v20200227.jar new file mode 100755 index 0000000000..058e9033fa Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/http2-client-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/http2-common-9.4.27.v20200227.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/http2-common-9.4.27.v20200227.jar new file mode 100755 index 0000000000..d42399fdef Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/http2-common-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/http2-hpack-9.4.27.v20200227.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/http2-hpack-9.4.27.v20200227.jar new file mode 100755 index 0000000000..ef55bbe988 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/http2-hpack-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/http2-http-client-transport-9.4.27.v20200227.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/http2-http-client-transport-9.4.27.v20200227.jar new file mode 100755 index 0000000000..aedb3e38a0 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/http2-http-client-transport-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/httpclient-4.5.10.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/httpclient-4.5.10.jar new file mode 100755 index 0000000000..d0c7821c82 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/httpclient-4.5.10.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/httpcore-4.4.12.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/httpcore-4.4.12.jar new file mode 100755 index 0000000000..1838672ac3 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/httpcore-4.4.12.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/httpmime-4.5.10.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/httpmime-4.5.10.jar new file mode 100755 index 0000000000..0fae6d0542 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/httpmime-4.5.10.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jackson-annotations-2.10.1.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jackson-annotations-2.10.1.jar new file mode 100755 index 0000000000..a10399ce3e Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jackson-annotations-2.10.1.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jackson-core-2.10.1.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jackson-core-2.10.1.jar new file mode 100755 index 0000000000..1640a4e08f Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jackson-core-2.10.1.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jackson-databind-2.10.1.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jackson-databind-2.10.1.jar new file mode 100755 index 0000000000..abe3748dbd Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jackson-databind-2.10.1.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jackson-dataformat-smile-2.10.1.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jackson-dataformat-smile-2.10.1.jar new file mode 100755 index 0000000000..6526f94433 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jackson-dataformat-smile-2.10.1.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/janino-3.0.9.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/janino-3.0.9.jar new file mode 100755 index 0000000000..761e0c2a0a Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/janino-3.0.9.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/java-semver-0.9.0.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/java-semver-0.9.0.jar new file mode 100755 index 0000000000..842d290ca4 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/java-semver-0.9.0.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jetty-alpn-client-9.4.27.v20200227.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jetty-alpn-client-9.4.27.v20200227.jar new file mode 100755 index 0000000000..0db577f8c5 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jetty-alpn-client-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jetty-alpn-java-client-9.4.27.v20200227.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jetty-alpn-java-client-9.4.27.v20200227.jar new file mode 100755 index 0000000000..d09841c8b7 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jetty-alpn-java-client-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jetty-client-9.4.27.v20200227.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jetty-client-9.4.27.v20200227.jar new file mode 100755 index 0000000000..b89cf7fe75 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jetty-client-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jetty-http-9.4.27.v20200227.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jetty-http-9.4.27.v20200227.jar new file mode 100755 index 0000000000..556a76be5a Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jetty-http-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jetty-io-9.4.27.v20200227.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jetty-io-9.4.27.v20200227.jar new file mode 100755 index 0000000000..375f825188 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jetty-io-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jetty-util-9.4.27.v20200227.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jetty-util-9.4.27.v20200227.jar new file mode 100755 index 0000000000..6b53df4c07 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jetty-util-9.4.27.v20200227.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jose4j-0.6.5.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jose4j-0.6.5.jar new file mode 100755 index 0000000000..02c0a5a66c Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/jose4j-0.6.5.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/json-path-2.4.0.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/json-path-2.4.0.jar new file mode 100755 index 0000000000..6229306b85 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/json-path-2.4.0.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/kerb-core-1.0.1.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/kerb-core-1.0.1.jar new file mode 100755 index 0000000000..655c87a627 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/kerb-core-1.0.1.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/kerb-util-1.0.1.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/kerb-util-1.0.1.jar new file mode 100755 index 0000000000..8b9b244505 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/kerb-util-1.0.1.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/kerby-asn1-1.0.1.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/kerby-asn1-1.0.1.jar new file mode 100755 index 0000000000..6488b7462b Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/kerby-asn1-1.0.1.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/kerby-pkix-1.0.1.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/kerby-pkix-1.0.1.jar new file mode 100755 index 0000000000..443d981891 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/kerby-pkix-1.0.1.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-analyzers-common-8.6.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-analyzers-common-8.6.3.jar new file mode 100755 index 0000000000..09479e7bfa Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-analyzers-common-8.6.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-analyzers-kuromoji-8.6.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-analyzers-kuromoji-8.6.3.jar new file mode 100755 index 0000000000..b77bc376d8 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-analyzers-kuromoji-8.6.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-analyzers-nori-8.6.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-analyzers-nori-8.6.3.jar new file mode 100755 index 0000000000..876475ed18 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-analyzers-nori-8.6.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-analyzers-phonetic-8.6.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-analyzers-phonetic-8.6.3.jar new file mode 100755 index 0000000000..731e48d596 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-analyzers-phonetic-8.6.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-backward-codecs-8.6.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-backward-codecs-8.6.3.jar new file mode 100755 index 0000000000..882ef6dc16 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-backward-codecs-8.6.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-classification-8.6.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-classification-8.6.3.jar new file mode 100755 index 0000000000..26a5597cf9 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-classification-8.6.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-codecs-8.6.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-codecs-8.6.3.jar new file mode 100755 index 0000000000..bed07de222 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-codecs-8.6.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-core-8.6.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-core-8.6.3.jar new file mode 100755 index 0000000000..8cd3f6bdc0 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-core-8.6.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-expressions-8.6.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-expressions-8.6.3.jar new file mode 100755 index 0000000000..566bfa1a2c Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-expressions-8.6.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-grouping-8.6.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-grouping-8.6.3.jar new file mode 100755 index 0000000000..014ec65a0e Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-grouping-8.6.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-highlighter-8.6.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-highlighter-8.6.3.jar new file mode 100755 index 0000000000..7844c16de9 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-highlighter-8.6.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-join-8.6.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-join-8.6.3.jar new file mode 100755 index 0000000000..13ae61da9e Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-join-8.6.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-memory-8.6.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-memory-8.6.3.jar new file mode 100755 index 0000000000..5b649100cb Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-memory-8.6.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-misc-8.6.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-misc-8.6.3.jar new file mode 100755 index 0000000000..6782e84753 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-misc-8.6.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-queries-8.6.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-queries-8.6.3.jar new file mode 100755 index 0000000000..3eba9e9034 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-queries-8.6.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-queryparser-8.6.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-queryparser-8.6.3.jar new file mode 100755 index 0000000000..ac56bbda82 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-queryparser-8.6.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-sandbox-8.6.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-sandbox-8.6.3.jar new file mode 100755 index 0000000000..a718570646 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-sandbox-8.6.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-spatial-extras-8.6.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-spatial-extras-8.6.3.jar new file mode 100755 index 0000000000..bf60088d1f Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-spatial-extras-8.6.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-spatial3d-8.6.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-spatial3d-8.6.3.jar new file mode 100755 index 0000000000..60a3779b67 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-spatial3d-8.6.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-suggest-8.6.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-suggest-8.6.3.jar new file mode 100755 index 0000000000..b347e54921 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/lucene-suggest-8.6.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-buffer-4.1.47.Final.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-buffer-4.1.47.Final.jar new file mode 100755 index 0000000000..e80f769613 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-buffer-4.1.47.Final.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-codec-4.1.47.Final.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-codec-4.1.47.Final.jar new file mode 100755 index 0000000000..9deb6efd6f Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-codec-4.1.47.Final.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-common-4.1.47.Final.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-common-4.1.47.Final.jar new file mode 100755 index 0000000000..7efa59345a Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-common-4.1.47.Final.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-handler-4.1.47.Final.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-handler-4.1.47.Final.jar new file mode 100755 index 0000000000..fb3889ffa8 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-handler-4.1.47.Final.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-resolver-4.1.47.Final.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-resolver-4.1.47.Final.jar new file mode 100755 index 0000000000..b15d287062 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-resolver-4.1.47.Final.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-transport-4.1.47.Final.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-transport-4.1.47.Final.jar new file mode 100755 index 0000000000..1aab3d9808 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-transport-4.1.47.Final.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-transport-native-epoll-4.1.47.Final.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-transport-native-epoll-4.1.47.Final.jar new file mode 100755 index 0000000000..4e3e83d798 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-transport-native-epoll-4.1.47.Final.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-transport-native-unix-common-4.1.47.Final.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-transport-native-unix-common-4.1.47.Final.jar new file mode 100755 index 0000000000..54f63ae2d8 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/netty-transport-native-unix-common-4.1.47.Final.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/opentracing-api-0.33.0.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/opentracing-api-0.33.0.jar new file mode 100755 index 0000000000..e3d65567d7 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/opentracing-api-0.33.0.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/opentracing-noop-0.33.0.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/opentracing-noop-0.33.0.jar new file mode 100755 index 0000000000..f5101f8596 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/opentracing-noop-0.33.0.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/opentracing-util-0.33.0.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/opentracing-util-0.33.0.jar new file mode 100755 index 0000000000..5e5e2e1fa8 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/opentracing-util-0.33.0.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/org.restlet-2.4.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/org.restlet-2.4.3.jar new file mode 100755 index 0000000000..52df9a9f58 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/org.restlet-2.4.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/org.restlet.ext.servlet-2.4.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/org.restlet.ext.servlet-2.4.3.jar new file mode 100755 index 0000000000..63c749db29 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/org.restlet.ext.servlet-2.4.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/protobuf-java-3.11.0.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/protobuf-java-3.11.0.jar new file mode 100755 index 0000000000..8d63e97eeb Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/protobuf-java-3.11.0.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/re2j-1.2.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/re2j-1.2.jar new file mode 100755 index 0000000000..945db1ca03 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/re2j-1.2.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/rrd4j-3.5.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/rrd4j-3.5.jar new file mode 100755 index 0000000000..535ea8fbea Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/rrd4j-3.5.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/s2-geometry-library-java-1.0.0.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/s2-geometry-library-java-1.0.0.jar new file mode 100755 index 0000000000..87638c0757 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/s2-geometry-library-java-1.0.0.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/solr-core-8.6.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/solr-core-8.6.3.jar new file mode 100755 index 0000000000..ca1feae0ab Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/solr-core-8.6.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/solr-solrj-8.6.3.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/solr-solrj-8.6.3.jar new file mode 100755 index 0000000000..759a36bd82 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/solr-solrj-8.6.3.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/spatial4j-0.7.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/spatial4j-0.7.jar new file mode 100755 index 0000000000..feb2e02aa1 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/spatial4j-0.7.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/stax2-api-3.1.4.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/stax2-api-3.1.4.jar new file mode 100755 index 0000000000..dded036928 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/stax2-api-3.1.4.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/t-digest-3.1.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/t-digest-3.1.jar new file mode 100755 index 0000000000..a638007a87 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/t-digest-3.1.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/woodstox-core-asl-4.4.1.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/woodstox-core-asl-4.4.1.jar new file mode 100755 index 0000000000..d8b4e8cf87 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/woodstox-core-asl-4.4.1.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/zookeeper-3.5.7.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/zookeeper-3.5.7.jar new file mode 100755 index 0000000000..78b2ff9495 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/zookeeper-3.5.7.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/zookeeper-jute-3.5.7.jar b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/zookeeper-jute-3.5.7.jar new file mode 100755 index 0000000000..408bbd1973 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/lib/zookeeper-jute-3.5.7.jar differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/web.xml b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/web.xml new file mode 100755 index 0000000000..53ab57abbb --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/WEB-INF/web.xml @@ -0,0 +1,114 @@ + + + + + + + SolrRequestFilter + org.apache.solr.servlet.SolrDispatchFilter + + + excludePatterns + /partials/.+,/libs/.+,/css/.+,/js/.+,/img/.+,/templates/.+ + + + + + SolrRequestFilter + /* + + + + LoadAdminUI + org.apache.solr.servlet.LoadAdminUiServlet + + + + SolrRestApi + org.restlet.ext.servlet.ServerServlet + + org.restlet.application + org.apache.solr.rest.SolrSchemaRestApi + + + + + LoadAdminUI + /index.html + + + + SolrRestApi + /schema/* + + + + .xsl + + application/xslt+xml + + + + index.html + + + + + + Disable TRACE + / + TRACE + + + + + + Enable everything but TRACE + / + TRACE + + + + + + diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/analysis.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/analysis.css new file mode 100755 index 0000000000..d3c1852e8c --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/analysis.css @@ -0,0 +1,303 @@ +/* + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#content #analysis-holder +{ + background-image: url( ../../img/div.gif ); + background-position: 50% 0; + background-repeat: repeat-y; +} + +#content #analysis #field-analysis +{ + margin-bottom: 0; +} + +#content #analysis #field-analysis .content +{ + padding-bottom: 0; +} + +#content #analysis .settings-holder +{ + clear: both; + padding-top: 15px; +} + +#content #analysis .settings +{ + background-color: #fff; + border-top: 1px solid #fafafa; + border-bottom: 1px solid #fafafa; + padding-top: 10px; + padding-bottom: 10px; +} + +#content #analysis .settings select.loader +{ + background-position: 3px 50%; + padding-left: 21px; +} + +#content #analysis .settings select optgroup +{ + font-style: normal; + padding: 5px; +} + +#content #analysis .settings select option +{ + padding-left: 10px; +} + +#content #analysis .settings #tor_schema +{ + background-image: url( ../../img/ico/question-white.png ); + background-position: 0 50%; + color: #4D4D4D; + margin-left: 5px; + padding-left: 21px; +} + +#content #analysis .settings #tor_schema:hover +{ + background-image: url( ../../img/ico/question.png ); +} + +#content #analysis .settings #tor_schema span +{ +/* display: none; */ +} + +#content #analysis .settings #tor_schema:hover span +{ + display: inline; +} + +#content #analysis .settings .buttons +{ + float: right; + width: 47%; +} + +#content #analysis .settings button +{ + float: right; +} + +#content #analysis .settings button span +{ + background-image: url( ../../img/ico/funnel.png ); +} + +#content #analysis .settings .verbose_output +{ + float: left; + width: auto; +} + +#content #analysis .settings .verbose_output a +{ + background-image: url( ../../img/ico/ui-check-box-uncheck.png ); + background-position: 0 50%; + color: #4D4D4D; + display: block; + padding-left: 21px; +} + +#content #analysis .settings .verbose_output.active a +{ + background-image: url( ../../img/ico/ui-check-box.png ); +} + +#content #analysis .index label, +#content #analysis .query label +{ + display: block; +} + +#content #analysis .index textarea, +#content #analysis .query textarea +{ + display: block; + width: 100%; +} + +#content #analysis .index +{ + float: left; + margin-right: 0.5%; + min-width: 47%; + max-width: 99%; +} + +#content #analysis .query +{ + float: right; + margin-left: 0.5%; + min-width: 47%; + max-width: 99%; +} + +#content #analysis .analysis-error +{ + background-color: #f00; + background-image: url( ../../img/ico/construction.png ); + background-position: 10px 50%; + color: #fff; + font-weight: bold; + margin-bottom: 20px; + padding: 10px; + padding-left: 35px; +} + +#content #analysis .analysis-error .head a +{ + color: #fff; + cursor: auto; +} + +#content #analysis #analysis-result +{ + overflow: auto; +} + +#content #analysis #analysis-result .index, +#content #analysis #analysis-result .query +{ + background-color: #fff; + padding-top: 20px; +} + +#content #analysis #analysis-result table +{ + border-collapse: collapse; +} + +#content #analysis #analysis-result td +{ + vertical-align: top; + white-space: nowrap; +} + +#content #analysis #analysis-result td.part.analyzer div, +#content #analysis #analysis-result td.part.spacer .holder, +#content #analysis #analysis-result td td td +{ + padding-top: 1px; + padding-bottom: 1px; +} + +#content #analysis #analysis-result.verbose_output td.legend +{ + display: table-cell; +} + +#content #analysis #analysis-result.verbose_output td.data tr.verbose_output +{ + display: table-row; +} + +#content #analysis #analysis-result .match +{ + background-color: #F0D9C3; +} + +#content #analysis #analysis-result td.part +{ + padding-bottom: 10px; +} + +#content #analysis #analysis-result td.part.analyzer div +{ + border-right: 1px solid #f0f0f0; + padding-right: 10px; +} + +#content #analysis #analysis-result td.part.analyzer abbr +{ + color: #4D4D4D; +} + +#content #analysis #analysis-result td.part.legend .holder, +#content #analysis #analysis-result td.part.data .holder +{ + padding-left: 10px; + padding-right: 10px; + border-right: 1px solid #c0c0c0; +} + +#content #analysis #analysis-result td.part.legend td +{ + color: #4D4D4D; +} + +#content #analysis #analysis-result td.part.legend .holder +{ + border-right-color: #f0f0f0; +} + +#content #analysis #analysis-result td.part.data:last-child .holder +{ + padding-right: 0; + border-right: 0; +} + +#content #analysis #analysis-result td.details +{ + padding-left: 10px; + padding-right: 10px; + border-left: 1px solid #f0f0f0; + border-right: 1px solid #f0f0f0; +} + +#content #analysis #analysis-result td.details:first-child +{ + padding-left: 0; + border-left: 0; +} + +#content #analysis #analysis-result td.details:last-child +{ + padding-right: 0; + border-right: 0; +} + +#content #analysis #analysis-result td.details tr.empty td +{ + color: #f0f0f0; +} + +#content #analysis #analysis-result td.details tr.raw_bytes td +{ + letter-spacing: -1px; +} + +#content #analysis #analysis-result .part table table td +{ + border-top: 1px solid #f0f0f0; +} + +#content #analysis #analysis-result .part table table tr:first-child td +{ + border-top: 0; +} + +#content #analysis #field-analysis h2 { background-image: url( ../../img/ico/receipt.png ); } +#content #analysis .analysis-result h2 { background-image: url( ../../img/ico/receipt-invoice.png ); } diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/angular-csp.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/angular-csp.css new file mode 100755 index 0000000000..4442d0cb5b --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/angular-csp.css @@ -0,0 +1,49 @@ +/* +The MIT License +Copyright (c) 2010-2015 Google, Inc. http://angularjs.org +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +/* + AngularJS v1.7.9 + (c) 2010-2018 Google, Inc. http://angularjs.org + License: MIT +*/ +/* Include this file in your html if you are using the CSP mode. */ + +@charset "UTF-8"; + +[ng\:cloak], +[ng-cloak], +[data-ng-cloak], +[x-ng-cloak], +.ng-cloak, +.x-ng-cloak, +.ng-hide:not(.ng-hide-animate) { + display: none !important; +} + +ng\:form { + display: block; +} + +.ng-animate-shim { + visibility:hidden; +} + +.ng-anchor { + position:absolute; +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/chosen.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/chosen.css new file mode 100755 index 0000000000..c7eddbcd9f --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/chosen.css @@ -0,0 +1,518 @@ +/* +Chosen +- by Patrick Filler for Harvest http://getharvest.com +- Copyright (c) 2011-2018 by Harvest +Available for use under the MIT License +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +/*! +Chosen, a Select Box Enhancer for jQuery and Prototype +by Patrick Filler for Harvest, http://getharvest.com + +Version 1.8.7 +Full source at https://github.com/harvesthq/chosen +Copyright (c) 2011-2018 Harvest http://getharvest.com + +MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md +This file is generated by `grunt build`, do not edit it by hand. +*/ + +/* @group Base */ +.chosen-container { + position: relative; + display: inline-block; + vertical-align: middle; + font-size: 13px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.chosen-container * { + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.chosen-container .chosen-drop { + position: absolute; + top: 100%; + z-index: 1010; + width: 100%; + border: 1px solid #aaa; + border-top: 0; + background: #fff; + -webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15); + box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15); + clip: rect(0, 0, 0, 0); + -webkit-clip-path: inset(100% 100%); + clip-path: inset(100% 100%); +} + +.chosen-container.chosen-with-drop .chosen-drop { + clip: auto; + -webkit-clip-path: none; + clip-path: none; +} + +.chosen-container a { + cursor: pointer; +} + +.chosen-container .search-choice .group-name, .chosen-container .chosen-single .group-name { + margin-right: 4px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + font-weight: normal; + color: #999999; +} + +.chosen-container .search-choice .group-name:after, .chosen-container .chosen-single .group-name:after { + content: ":"; + padding-left: 2px; + vertical-align: top; +} + +/* @end */ +/* @group Single Chosen */ +.chosen-container-single .chosen-single { + position: relative; + display: block; + overflow: hidden; + padding: 0 0 0 8px; + height: 25px; + border: 1px solid #aaa; + border-radius: 5px; + background-color: #fff; + background: -webkit-gradient(linear, left top, left bottom, color-stop(20%, #fff), color-stop(50%, #f6f6f6), color-stop(52%, #eee), to(#f4f4f4)); + background: linear-gradient(#fff 20%, #f6f6f6 50%, #eee 52%, #f4f4f4 100%); + background-clip: padding-box; + -webkit-box-shadow: 0 0 3px #fff inset, 0 1px 1px rgba(0, 0, 0, 0.1); + box-shadow: 0 0 3px #fff inset, 0 1px 1px rgba(0, 0, 0, 0.1); + color: #444; + text-decoration: none; + white-space: nowrap; + line-height: 24px; +} + +.chosen-container-single .chosen-default { + color: #999; +} + +.chosen-container-single .chosen-single span { + display: block; + overflow: hidden; + margin-right: 26px; + text-overflow: ellipsis; + white-space: nowrap; +} + +.chosen-container-single .chosen-single-with-deselect span { + margin-right: 38px; +} + +.chosen-container-single .chosen-single abbr { + position: absolute; + top: 6px; + right: 26px; + display: block; + width: 12px; + height: 12px; + background: url("../../img/chosen-sprite.png") -42px 1px no-repeat; + font-size: 1px; +} + +.chosen-container-single .chosen-single abbr:hover { + background-position: -42px -10px; +} + +.chosen-container-single.chosen-disabled .chosen-single abbr:hover { + background-position: -42px -10px; +} + +.chosen-container-single .chosen-single div { + position: absolute; + top: 0; + right: 0; + display: block; + width: 18px; + height: 100%; +} + +.chosen-container-single .chosen-single div b { + display: block; + width: 100%; + height: 100%; + background: url("../../img/chosen-sprite.png") no-repeat 0px 2px; +} + +.chosen-container-single .chosen-search { + position: relative; + z-index: 1010; + margin: 0; + padding: 3px 4px; + white-space: nowrap; +} + +.chosen-container-single .chosen-search input[type="text"] { + margin: 1px 0; + padding: 4px 20px 4px 5px; + width: 100%; + height: auto; + outline: 0; + border: 1px solid #aaa; + background: url("../../img/chosen-sprite.png") no-repeat 100% -20px; + font-size: 1em; + font-family: sans-serif; + line-height: normal; + border-radius: 0; +} + +.chosen-container-single .chosen-drop { + margin-top: -1px; + border-radius: 0 0 4px 4px; + background-clip: padding-box; +} + +.chosen-container-single.chosen-container-single-nosearch .chosen-search { + position: absolute; + clip: rect(0, 0, 0, 0); + -webkit-clip-path: inset(100% 100%); + clip-path: inset(100% 100%); +} + +/* @end */ +/* @group Results */ +.chosen-container .chosen-results { + color: #444; + position: relative; + overflow-x: hidden; + overflow-y: auto; + margin: 0 4px 4px 0; + padding: 0 0 0 4px; + max-height: 240px; + -webkit-overflow-scrolling: touch; +} + +.chosen-container .chosen-results li { + display: none; + margin: 0; + padding: 5px 6px; + list-style: none; + line-height: 15px; + word-wrap: break-word; + -webkit-touch-callout: none; +} + +.chosen-container .chosen-results li.active-result { + display: list-item; + cursor: pointer; +} + +.chosen-container .chosen-results li.disabled-result { + display: list-item; + color: #ccc; + cursor: default; +} + +.chosen-container .chosen-results li.highlighted { + background-color: #3875d7; + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(20%, #3875d7), color-stop(90%, #2a62bc)); + background-image: linear-gradient(#3875d7 20%, #2a62bc 90%); + color: #fff; +} + +.chosen-container .chosen-results li.no-results { + color: #777; + display: list-item; + background: #f4f4f4; +} + +.chosen-container .chosen-results li.group-result { + display: list-item; + font-weight: bold; + cursor: default; +} + +.chosen-container .chosen-results li.group-option { + padding-left: 15px; +} + +.chosen-container .chosen-results li em { + font-style: normal; + text-decoration: underline; +} + +/* @end */ +/* @group Multi Chosen */ +.chosen-container-multi .chosen-choices { + position: relative; + overflow: hidden; + margin: 0; + padding: 0 5px; + width: 100%; + height: auto; + border: 1px solid #aaa; + background-color: #fff; + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(1%, #eee), color-stop(15%, #fff)); + background-image: linear-gradient(#eee 1%, #fff 15%); + cursor: text; +} + +.chosen-container-multi .chosen-choices li { + float: left; + list-style: none; +} + +.chosen-container-multi .chosen-choices li.search-field { + margin: 0; + padding: 0; + white-space: nowrap; +} + +.chosen-container-multi .chosen-choices li.search-field input[type="text"] { + margin: 1px 0; + padding: 0; + height: 25px; + outline: 0; + border: 0 !important; + background: transparent !important; + -webkit-box-shadow: none; + box-shadow: none; + color: #999; + font-size: 100%; + font-family: sans-serif; + line-height: normal; + border-radius: 0; + width: 25px; +} + +.chosen-container-multi .chosen-choices li.search-choice { + position: relative; + margin: 3px 5px 3px 0; + padding: 3px 20px 3px 5px; + border: 1px solid #aaa; + max-width: 100%; + border-radius: 3px; + background-color: #eeeeee; + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), to(#eee)); + background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%); + background-size: 100% 19px; + background-repeat: repeat-x; + background-clip: padding-box; + -webkit-box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05); + box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05); + color: #333; + line-height: 13px; + cursor: default; +} + +.chosen-container-multi .chosen-choices li.search-choice span { + word-wrap: break-word; +} + +.chosen-container-multi .chosen-choices li.search-choice .search-choice-close { + position: absolute; + top: 4px; + right: 3px; + display: block; + width: 12px; + height: 12px; + background: url("../../img/chosen-sprite.png") -42px 1px no-repeat; + font-size: 1px; +} + +.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover { + background-position: -42px -10px; +} + +.chosen-container-multi .chosen-choices li.search-choice-disabled { + padding-right: 5px; + border: 1px solid #ccc; + background-color: #e4e4e4; + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), to(#eee)); + background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%); + color: #666; +} + +.chosen-container-multi .chosen-choices li.search-choice-focus { + background: #d4d4d4; +} + +.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close { + background-position: -42px -10px; +} + +.chosen-container-multi .chosen-results { + margin: 0; + padding: 0; +} + +.chosen-container-multi .chosen-drop .result-selected { + display: list-item; + color: #ccc; + cursor: default; +} + +/* @end */ +/* @group Active */ +.chosen-container-active .chosen-single { + border: 1px solid #5897fb; + -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); + box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); +} + +.chosen-container-active.chosen-with-drop .chosen-single { + border: 1px solid #aaa; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(20%, #eee), color-stop(80%, #fff)); + background-image: linear-gradient(#eee 20%, #fff 80%); + -webkit-box-shadow: 0 1px 0 #fff inset; + box-shadow: 0 1px 0 #fff inset; +} + +.chosen-container-active.chosen-with-drop .chosen-single div { + border-left: none; + background: transparent; +} + +.chosen-container-active.chosen-with-drop .chosen-single div b { + background-position: -18px 2px; +} + +.chosen-container-active .chosen-choices { + border: 1px solid #5897fb; + -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); + box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); +} + +.chosen-container-active .chosen-choices li.search-field input[type="text"] { + color: #222 !important; +} + +/* @end */ +/* @group Disabled Support */ +.chosen-disabled { + opacity: 0.5 !important; + cursor: default; +} + +.chosen-disabled .chosen-single { + cursor: default; +} + +.chosen-disabled .chosen-choices .search-choice .search-choice-close { + cursor: default; +} + +/* @end */ +/* @group Right to Left */ +.chosen-rtl { + text-align: right; +} + +.chosen-rtl .chosen-single { + overflow: visible; + padding: 0 8px 0 0; +} + +.chosen-rtl .chosen-single span { + margin-right: 0; + margin-left: 26px; + direction: rtl; +} + +.chosen-rtl .chosen-single-with-deselect span { + margin-left: 38px; +} + +.chosen-rtl .chosen-single div { + right: auto; + left: 3px; +} + +.chosen-rtl .chosen-single abbr { + right: auto; + left: 26px; +} + +.chosen-rtl .chosen-choices li { + float: right; +} + +.chosen-rtl .chosen-choices li.search-field input[type="text"] { + direction: rtl; +} + +.chosen-rtl .chosen-choices li.search-choice { + margin: 3px 5px 3px 0; + padding: 3px 5px 3px 19px; +} + +.chosen-rtl .chosen-choices li.search-choice .search-choice-close { + right: auto; + left: 4px; +} + +.chosen-rtl.chosen-container-single .chosen-results { + margin: 0 0 4px 4px; + padding: 0 4px 0 0; +} + +.chosen-rtl .chosen-results li.group-option { + padding-right: 15px; + padding-left: 0; +} + +.chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div { + border-right: none; +} + +.chosen-rtl .chosen-search input[type="text"] { + padding: 4px 5px 4px 20px; + background: url("../../img/chosen-sprite.png") no-repeat -30px -20px; + direction: rtl; +} + +.chosen-rtl.chosen-container-single .chosen-single div b { + background-position: 6px 2px; +} + +.chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b { + background-position: -12px 2px; +} + +/* @end */ +/* @group Retina compatibility */ +@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi), only screen and (min-resolution: 1.5dppx) { + .chosen-rtl .chosen-search input[type="text"], + .chosen-container-single .chosen-single abbr, + .chosen-container-single .chosen-single div b, + .chosen-container-single .chosen-search input[type="text"], + .chosen-container-multi .chosen-choices .search-choice .search-choice-close, + .chosen-container .chosen-results-scroll-down span, + .chosen-container .chosen-results-scroll-up span { + background-image: url("../../img/chosen-sprite@2x.png") !important; + background-size: 52px 37px !important; + background-repeat: no-repeat !important; + } +} + +/* @end */ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/cloud.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/cloud.css new file mode 100755 index 0000000000..16730c38e4 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/cloud.css @@ -0,0 +1,723 @@ +/* + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#content #cloud +{ + position: relative; +} + +#content #cloud .loader +{ + background-position: 0 50%; + padding-left: 21px; +} + +#content #cloud #error +{ + background-color: #f00; + background-image: url( ../../img/ico/construction.png ); + background-position: 10px 12px; + color: #fff; + font-weight: bold; + margin-bottom: 20px; + padding: 10px; + padding-left: 35px; +} + +#content #cloud #error .msg +{ + font-style: italic; + font-weight: normal; + margin-top: 10px; +} + +#content #cloud #debug +{ + background-color: #fff; + box-shadow: 0px 0px 10px #c0c0c0; + -moz-box-shadow: 0px 0px 10px #c0c0c0; + -webkit-box-shadow: 0px 0px 10px #c0c0c0; + padding: 20px; + position: absolute; + left: 50px; + top: 10px; +} + +#content #cloud #debug ul +{ + margin-bottom: 5px; +} + +#content #cloud #debug ul a +{ + background-position: 4px 50%; + border-right: 0; + display: block; + padding: 2px 4px; + padding-left: 25px; +} + +#content #cloud #debug ul a:hover, +#content #cloud #debug ul a.hover +{ + background-color: #f0f0f0; +} + +#content #cloud #debug .clipboard +{ + float: left; + position: relative; +} + +#content #cloud #debug .clipboard a +{ + background-image: url( ../../img/ico/clipboard-paste.png ); + z-index: 98; +} + +#content #cloud #debug .clipboard a:hover, +#content #cloud #debug .clipboard a.hover, +#content #cloud #debug .clipboard.copied a +{ + background-image: url( ../../img/ico/clipboard-paste-document-text.png ); +} + +#content #cloud #debug .close +{ + float: right; +} + +#content #cloud #debug .close a +{ + background-image: url( ../../img/ico/cross-0.png ); + padding-left: 21px; +} + +#content #cloud #debug .close a:hover +{ + background-image: url( ../../img/ico/cross-1.png ); +} + +#content #cloud #debug .debug +{ + border: 1px solid #f0f0f0; + max-height: 350px; + overflow: auto; + padding: 5px; + width: 500px; +} + +#content #cloud #debug .debug .loader +{ + background-position: 5px 50%; + display: block; + padding: 10px 26px; +} + +#content #cloud .content +{ + padding-left: 0; + padding-right: 0; +} + +#content #cloud .content.show +{ + background-image: url( ../../img/div.gif ); + background-repeat: repeat-y; + background-position: 31% 0; +} + +#content #cloud #tree +{ + float: left; + width: 30%; + overflow-x: overlay; + overflow-y: hidden; +} + +#content #cloud .show #tree +{ + overflow: hidden; +} + +#content #cloud #file-content +{ + float: right; + width: 68%; +} + +#content #cloud .show #file-content +{ + display: block; +} + +#content #cloud #file-content .close +{ + background-image: url( ../../img/ico/cross-0.png ); + background-position: 50% 50%; + display: block; + height: 20px; + position: absolute; + right: 0; + top: 0; + width: 20px; +} + +#content #cloud #file-content .close:hover +{ + background-image: url( ../../img/ico/cross-1.png ); +} + +#content #cloud #file-content #toggle.plus +{ + font-style: italic; + padding-left: 17px; + background-image: url( ../../img/ico/toggle-small-expand.png ); +} + +#content #cloud #file-content #toggle.minus +{ + font-style: italic; + padding-left: 17px; + background-image: url( ../../img/ico/toggle-small.png ); +} + +#content #cloud #file-content #data +{ + border-top: 1px solid #c0c0c0; + margin-top: 10px; + padding-top: 10px; +} + +#content #cloud #file-content #data pre +{ + display: block; + max-height: 600px; + overflow: auto; +} + +#content #cloud #file-content #data em +{ + color: #4d4d4d; +} + +#content #cloud #file-content #prop +{ +} + +#content #cloud #file-content li +{ + padding-top: 3px; + padding-bottom: 3px; +} + +#content #cloud #file-content li.odd +{ + background-color: #F8F8F8; +} + +#content #cloud #file-content li dt +{ + float: left; + width: 19%; +} + +#content #cloud #file-content li dd +{ + float: right; + width: 80%; +} + +/* tree */ + +#content #cloud #legend +{ + border: 1px solid #f0f0f0; + padding: 10px; + position: absolute; + right: 0; + bottom: 0; +} + +#content #cloud #legend li +{ + padding-left: 15px; + position: relative; +} + +#content #cloud #legend li svg +{ + position: absolute; + left: 0; + top: 2px; +} + +#content #graph-content +{ + min-height: 400px; +} + +#content #graph-content .node +{ + fill: #333; +} + +#content #cloud #legend circle, +#content #graph-content .node circle +{ + fill: #fff; + stroke: #c0c0c0; + stroke-width: 1.5px; +} + +#content #graph-content .node.lvl-3 text +{ + cursor: pointer; +} + +#content #graph-content .node.lvl-3:hover circle +{ + stroke: #000 !important; +} + +#content #graph-content .node.lvl-3:hover text +{ + fill: #000 !important; +} + +#content #graph-content .link +{ + fill: none; + stroke: #e0e0e0; + stroke-width: 1.5px; +} + +#content #cloud #legend .gone circle, +#content #graph-content .node.gone circle, +#content #graph-content .link.gone +{ + stroke: #f0f0f0; +} + +#content #graph-content .node.gone text +{ + fill: #f0f0f0; +} + +#content #cloud #legend ul .gone +{ + color: #e0e0e0; +} + +#content #cloud #legend .recovery_failed, +#content #cloud #legend .recovery_failed circle, +#content #graph-content .node.recovery_failed circle +{ + color: #C43C35; + stroke: #C43C35; + font-style: italic; +} + +#content #graph-content .node.recovery_failed text +{ + fill: #C43C35; + font-style: italic; +} + +#content #cloud #legend .down, +#content #cloud #legend .down circle, +#content #graph-content .node.down circle +{ + color: #c48f00; + stroke: #c48f00; +} + +#content #graph-content .node.down text +{ + fill: #c48f00; +} + +#content #cloud #legend .recovering, +#content #cloud #legend .recovering circle, +#content #graph-content .node.recovering circle +{ + color: #d5dd00; + stroke: #d5dd00; + font-style: italic; +} + +#content #graph-content .node.recovering text +{ + fill: #d5dd00; + font-style: italic; +} + +#content #cloud #legend .active, +#content #cloud #legend .active circle, +#content #graph-content .node.active circle +{ + color: #57A957; + stroke: #57A957; +} + +#content #graph-content .node.active text +{ + fill: #57A957; +} + +#content #cloud #legend .leader circle, +#content #graph-content .node.leader circle +{ + fill: #000; +} + +#content #cloud #legend .leader circle +{ + stroke: #fff; +} + +#content #graph-content .link.lvl-2, +#content #graph-content .link.leader +{ + stroke: #c0c0c0; +} + +#content #cloud #legend .leader, +#content #graph-content .leader text +{ + font-weight: bold; +} + +#content #graph-content .node.lvl-0 circle +{ + stroke: #fff; +} + +#content #graph-content .link.lvl-1 +{ + stroke: #fff; +} + +#cloudGraphPaging +{ + display: inline-block; + padding-top: 15px; + padding-bottom: 15px; +} + +#nodesPaging +{ + padding-top: 5px; + padding-bottom: 5px; +} + +#content #cloud #legend .shard-inactive, +#content #cloud #legend .shard-inactive li, +#content #cloud #legend .shard-inactive li text, +#content #graph-content .shard-inactive text +{ + text-decoration: line-through; +} +#content #cloud #legend .shard-inactive circle, +#content #graph-content .shard-inactive circle, +#content #graph-content .link.shard-inactive +{ + stroke: #e9e9e9; +} + +#content #cloud #legend .replicatype, +#content #cloud #legend .replicatype rect, +#content #graph-content .node.replicatype rect +{ + color: #007BA7; + stroke: #007BA7; + fill:rgb(0,123,167); + +} + +#content #graph-content .node.replicatype text +{ + fill: #007BA7; +} + +/* Nodes tab */ +#nodes-table { + border-collapse: collapse; +} + +#nodes-table td, #nodes-table th { + border: 1px solid #ddd; + padding: 8px; + vertical-align: top; +} +#nodes-table th { + font-weight: bolder; + font-stretch: extra-expanded; + background: #F8F8F8; +} +#content #cloud #nodes-content #nodes-table +{ + border-top: 1px solid #c0c0c0; + margin-top: 10px; + padding-top: 10px; +} + +#content #cloud #nodes-content .host-name, +#content #cloud #nodes-content .node-name a +{ + font-weight: bold; + font-size: larger; +} + +#content #cloud #nodes-content a, +#content #cloud #nodes-content a:hover, +#content #cloud #nodes-content a.hover +{ + text-decoration: underline; + text-decoration-style: dotted; + text-decoration-color: #beebff; +} + +#content #cloud #nodes-content a:hover, +#content #cloud #nodes-content a.hover +{ + background-color: #beebff; +} + +#content #cloud #nodes-content .host-spec, +#content #cloud #nodes-content .node-spec, +#content #cloud #nodes-content .node-spec a +{ + font-style: italic; +} +#content #cloud #nodes-content .node-uptime +{ + font-weight: bolder; + font-size: 20px; +} +#content #cloud #nodes-content .node-load, +#content #cloud #nodes-content .node-cpu, +#content #cloud #nodes-content .node-heap, +#content #cloud #nodes-content .node-disk +{ + font-weight: bolder; + font-size: 20px; +} + +#content #cloud #nodes-content .pct-normal +{ + color: darkgreen; +} + +#content #cloud #nodes-content .pct-warn +{ + color: orange; +} + +#content #cloud #nodes-content .pct-critical +{ + color: red; +} + +#content #cloud #nodes-content .node-down +{ + font-weight: bold; + font-size: 12px; +} + +#content #cloud #nodes-content .dead-node +{ + background-color: salmon; +} + +/* Styling of reload and details buttons */ +#content #cloud #controls, +#content #cloud #frame #zk-status-content #zk-controls +{ + display: block; + height: 30px; +} + +#content #cloud .reload +{ + background-image: url( ../../img/ico/arrow-circle.png ); + padding-left: 21px; + float: left; +} + +#content #cloud .reload.loader +{ + padding-left: 0; +} + +#content #cloud .details-button +{ + background-image: url(../../img/ico/ui-check-box-uncheck.png); + background-position: 0 50%; + color: #8D8D8D; + margin-top: 7px; + margin-left: 10px; + padding-left: 21px; + width: 30px; +} + +#content #cloud .details-button.on +{ + background-image: url( ../../img/ico/ui-check-box.png ); + color: #333; +} + +#content #cloud #nodes-content .more +{ + font-style: italic; + text-underline: #0000fa; +} + +/* Disk usage details d3 chart bars style */ +.chart { + background: #eee; + padding: 1px; +} +.chart div { + width:90%; +} +.chart div div { + display:inline-block; +} +.chart div div.rect { + transition: all 0.5s ease-out; + -moz-transition: all 0.5s ease-out; + -webkit-transition: all 0.5s ease-out; + width:0; + font: 10px sans-serif; + background-color: #4CAF50; + text-align: left; + padding: 3px; + margin: 2px; + color: #000000; + box-shadow: 1px 1px 1px #666; +} + +#content #nodes-content .leader +{ + font-weight: bold; +} + +#content #nodes-content .scroll-height-250 +{ + max-height: 250px; + overflow-scrolling: auto; + overflow: auto; + /*overflow-y: auto;*/ +} + +#content #nodes-content .min-width-150 +{ + min-width: 150px; +} + +#content #cloud #nodes-content .node-cores +{ + min-width: 150px; +} + +#content #nodes-content .core-details +{ + padding-left: 21px; +} + + + +::-webkit-scrollbar { + -webkit-appearance: none; + width: 7px; + height: 7px; +} + +::-webkit-scrollbar-thumb { + border-radius: 4px; + background-color: rgba(0,0,0,.5); + -webkit-box-shadow: 0 0 1px rgba(255,255,255,.5); +} +#content #cloud #zk-table td, +#content #cloud #zk-table th +{ + border: 0px solid #ddd; + border-bottom: 0.50px solid #eee; + padding-right: 5px; + padding-left: 5px; +} + +#content #cloud #zk-table th +{ + border-bottom: 1px solid #ddd; + border-top: 1px solid #ddd; + font-weight: bolder; + font-stretch: extra-expanded; + background: #F8F8F8; +} + +#content #cloud #zk-table +{ + border-top: 1px solid #c0c0c0; + margin-top: 10px; + border-collapse: collapse; + + font-weight: bold; +} + +#content #cloud #zk-table #detail-divider +{ + background-color: #f8f8f8; + height: 10px; +} + +.zookeeper-status +{ + font-size: large; +} + +.zookeeper-errors +{ + background-color: lightpink; + padding: 10px; + border: 1px; + margin-top: 10px; + margin-bottom: 10px; +} + +.zookeeper-errors li::before +{ + content: "- "; +} + +.zkstatus-green +{ + color: darkgreen; +} + +.zkstatus-yellow +{ + color: orange; +} + +.zkstatus-red +{ + color: red; +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/collections.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/collections.css new file mode 100755 index 0000000000..41f152b7b7 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/collections.css @@ -0,0 +1,377 @@ +/* + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#content #collections +{ + position: relative; +} + +#content #collections #ui-block +{ + background-color: #fff; + height: 200px; + position: absolute; + left: -5px; + top: 35px; + width: 500px; +} + +#content #collections #frame +{ + float: right; + width: 86%; +} + +#content #collections #navigation +{ + width: 12%; +} + +#content #collections #navigation a +{ + padding-left: 5px; +} + +#content #collections #navigation ul +{ + padding-top: 20px; +} + +#content #collections #navigation hr +{ + margin-top: 20px; + margin-bottom: 20px; +} + +#content #collections #frame .actions +{ + margin-bottom: 20px; + min-height: 30px; +} + +#content #collections .actions div.action +{ + width: 320px; +} + +#content #collections .actions div.action .cloud +{ +} + +#content #collections .actions form .directory-note +{ + background-image: url( ../../img/ico/information-white.png ); + background-position: 22% 1px; + color: #4D4D4D; +} + +#content #collections .actions form .error +{ + background-image: url( ../../img/ico/cross-button.png ); + background-position: 22% 1px; + color: #c00; + font-weight: bold; +} + +#content #collections .actions form p +{ + padding-bottom: 8px; +} + +#content #collections .actions form label +{ + float: left; + padding-top: 3px; + padding-bottom: 3px; + text-align: right; + width: 25%; +} + +#content #collections .actions form input, +#content #collections .actions form select, +#content #collections .actions form .buttons, +#content #collections .actions form .note span +{ + float: right; + width: 71%; +} + +#content #collections .actions form .chosen-container +{ + width: 71% !important; +} + +#content #collections .actions form .note span +{ + padding-left: 3px; + padding-right: 3px; +} + +#content #collections .actions form .buttons +{ + padding-top: 10px; +} + +#content #collections .actions form button.submit +{ + margin-right: 20px; +} + +#content #collections .actions form button.submit span +{ + background-image: url( ../../img/ico/tick.png ); +} + +#content #collections .actions form button.reset span +{ + background-image: url( ../../img/ico/cross.png ); +} + +#content #collections #navigation #add span +{ + background-image: url( ../../img/ico/plus-button.png ); +} + +#content #collections #navigation #create-alias span +{ + background-image: url( ../../img/ico/arrow-switch.png ); +} + + +#content #collections .actions #delete-collection, +#content #collections .actions #delete-alias +{ + margin-right: 20px; +} + +#content #collections .actions #delete-collection span +{ + background-image: url( ../../img/ico/cross.png ); +} + +#content #collections .actions #reload span +{ + background-image: url( ../../img/ico/arrow-circle.png ); +} + +#content #collections .actions #rename span +{ + background-image: url( ../../img/ico/ui-text-field-select.png ); +} + +#content #collections .actions #delete-alias span +{ + background-image: url( ../../img/ico/cross-button.png ); +} + + +#content #collections .actions div.action +{ + background-color: #fff; + border: 1px solid #f0f0f0; + box-shadow: 5px 5px 10px #c0c0c0; + -moz-box-shadow: 5px 5px 10px #c0c0c0; + -webkit-box-shadow: 5px 5px 10px #c0c0c0; + position: absolute; + left: 50px; + top: 40px; + padding: 10px; +} + +#content #collections .actions #add-replica span +{ + background-image: url( ../../img/ico/plus-button.png ); +} + +#content #collections div.action.add-replica { + border: 1px solid #f0f0f0; + width: 400px; + margin-right: 0px; + padding: 10px; + float: right; +} + +#content #collections div.action.add-replica p { + padding-bottom: 8px; +} + +#content #collections div.action.add-replica .buttons { + float: right; +} + +#content #collections div.action.add-replica .buttons .submit span { + background-image: url( ../../img/ico/tick.png ); + background-position: 0% 50%; +} + +#content #collections div.action.add-replica .buttons .reset span { + background-image: url( ../../img/ico/cross.png ); + background-position: 0% 50%; +} + +#content #collections #data #alias-data h2 { background-image: url( ../../img/ico/box.png ); } +#content #collections #data #collection-data h2 { background-image: url( ../../img/ico/box.png ); } +#content #collections #data #shard-data h2 { background-image: url( ../../img/ico/sitemap.png ); } +#content #collections #data #shard-data .replica h2 { background-image: url( ../../img/ico/node-slave.png ); } + +#content #collections #data #index-data +{ + margin-top: 10px; +} + +#content #collections #data li +{ + padding-bottom: 3px; + padding-top: 3px; +} + +#content #collections #data li.odd +{ + background-color: #f8f8f8; +} + +#content #collections #data li dt +{ + float: left; + width: 50%; +} + +#content #collections #data li dd +{ + float: right; + width: 50%; +} + +#content #collections #data li dd.ico +{ + background-image: url( ../../img/ico/slash.png ); + height: 20px; +} + +#content #collections #data li dd.ico.ico-1 +{ + background-image: url( ../../img/ico/tick.png ); +} + +#content #collections #data li dd.ico span +{ +} + +#content #collections #add_advanced { + background-image: url( ../../img/ico/chevron-small-expand.png ); + background-position: 100% 50%; + cursor: pointer; + padding-right: 21px; +} + +#content #collections #add_advanced.open { + background-image: url( ../../img/ico/chevron-small.png ); +} + +#content #collections .shard { + margin-left: 40px; +} + +#content #collections .replica { + margin-left: 40px; +} + +#content #collections .shard h2 span.openReplica { + background-image: url( ../../img/ico/chevron-small-expand.png ); + background-position: 100% 50%; + cursor: pointer; + padding-right: 21px; +} + +#content #collections .shard h2 span.openReplica .open { + background-image: url( ../../img/ico/chevron-small.png ); +} + +#content #collections .replica h2 span { + background-image: url( ../../img/ico/chevron-small-expand.png ); + background-position: 100% 50%; + cursor: pointer; + padding-right: 21px; +} + +#content #collections .replica h2 span.rem { + background-image: url( ../../img/ico/cross.png ); + background-position: 100% 50%; + cursor: pointer; + padding-right: 21px; + right:10px; +} + +#content #collections .shard h2 span.rem { + background-image: url( ../../img/ico/cross.png ); + background-position: 100% 50%; + cursor: pointer; + padding-right: 21px; + right:10px; +} + +#content #collections .replica h2 span .open { + background-image: url( ../../img/ico/chevron-small.png ); +} + +#content #collections #add-replica { + float: right; +} + +#content #collections .add select { + width: 100%; +} + +#content #collections .chosen-container ul { + width: 100%; + padding: 5px; +} + +#content #collections .delete-replica span +{ + background-image: url( ../../img/ico/cross.png ); +} +#content #collections .delete-replica button.submit span +{ + background-image: url( ../../img/ico/tick.png ); +} + +#content #collections .delete-shard span +{ + background-image: url( ../../img/ico/cross.png ); +} +#content #collections .delete-shard button.submit span +{ + background-image: url( ../../img/ico/tick.png ); +} + +#content #collections #alias-data { + float: left; + width: 35%; +} + +#content #collections #collection-data { + float: left; + width: 35%; +} + +#content #collections #shard-data { + float: left; + width: 65%; +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/common.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/common.css new file mode 100755 index 0000000000..a881681291 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/common.css @@ -0,0 +1,748 @@ +/* + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +* +{ + background-repeat: no-repeat; + margin: 0; + padding: 0; +} + +body, h1, h2, h3, h4, h5, h6, a, button, input, select, option, textarea, th, td, div.ui-tooltip-content +{ + color: #333; + font: 12px/1.6em "Lucida Grande", "DejaVu Sans", "Bitstream Vera Sans", Verdana, Arial, sans-serif; +} + +body +{ + padding: 30px; + text-align: center; +} + +a, button +{ + cursor: pointer; +} + +input, select, textarea +{ + border: 1px solid #c0c0c0; + padding: 2px; +} + +input[readonly=readonly] +{ + border-color: #f0f0f0; +} + +button +{ + background-color: #e6e6e6; + background-repeat: no-repeat; + background-image: -webkit-gradient( linear, 0 0, 0 100%, from( #ffffff ), color-stop( 25%, #ffffff ), to( #e6e6e6 ) ); + background-image: -webkit-linear-gradient( #ffffff, #ffffff 25%, #e6e6e6 ); + background-image: -moz-linear-gradient( top, #ffffff, #ffffff 25%, #e6e6e6 ); + background-image: -ms-linear-gradient( #ffffff, #ffffff 25%, #e6e6e6 ); + background-image: -o-linear-gradient( #ffffff, #ffffff 25%, #e6e6e6 ); + background-image: linear-gradient( #ffffff, #ffffff 25%, #e6e6e6 ); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0 ); + border: 1px solid #ccc; + border-bottom-color: #bbb; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + -khtml-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 0 rgba( 255, 255, 255, 0.2 ), 0 1px 2px rgba( 0, 0, 0, 0.05 ); + -moz-box-shadow: inset 0 1px 0 rgba( 255, 255, 255, 0.2 ), 0 1px 2px rgba( 0, 0, 0, 0.05 ); + box-shadow: inset 0 1px 0 rgba( 255, 255, 255, 0.2 ), 0 1px 2px rgba( 0, 0, 0, 0.05 ); + color: #333; + cursor: pointer; + display: inline-block; + padding: 4px 7px 5px; + overflow: visible; + text-shadow: 0 1px 1px rgba( 255, 255, 255, 0.75 ); + -webkit-transition: 0.1s linear background-image; + -moz-transition: 0.1s linear background-image; + -ms-transition: 0.1s linear background-image; + -o-transition: 0.1s linear background-image; + transition: 0.1s linear background-image; +} + +button span +{ + background-position: 0 50%; + display: block; + padding-left: 21px; +} + +button[type=submit], button.primary +{ + background-color: #0064cd; + background-repeat: repeat-x; + background-image: -khtml-gradient( linear, left top, left bottom, from( #049cdb ), to( #0064cd ) ); + background-image: -moz-linear-gradient( top, #049cdb, #0064cd ); + background-image: -ms-linear-gradient( top, #049cdb, #0064cd ); + background-image: -webkit-gradient( linear, left top, left bottom, color-stop( 0%, #049cdb ), color-stop( 100%, #0064cd ) ); + background-image: -webkit-linear-gradient( top, #049cdb, #0064cd ); + background-image: -o-linear-gradient( top, #049cdb, #0064cd ); + background-image: linear-gradient( top, #049cdb, #0064cd ); + border-color: #0064cd #0064cd #003f81; + border-color: rgba( 0, 0, 0, 0.1 ) rgba( 0, 0, 0, 0.1 ) rgba( 0, 0, 0, 0.25 ); + color: #ffffff; + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0 ); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} + +button.success +{ + background-color: #57a957; + background-repeat: repeat-x; + background-image: -khtml-gradient( linear, left top, left bottom, from( #62c462 ), to( #57a957 ) ); + background-image: -moz-linear-gradient( top, #62c462, #57a957 ); + background-image: -ms-linear-gradient( top, #62c462, #57a957 ); + background-image: -webkit-gradient( linear, left top, left bottom, color-stop( 0%, #62c462 ), color-stop( 100%, #57a957 ) ); + background-image: -webkit-linear-gradient( top, #62c462, #57a957 ); + background-image: -o-linear-gradient( top, #62c462, #57a957 ); + background-image: linear-gradient( top, #62c462, #57a957 ); + border-color: #57a957 #57a957 #3d773d; + border-color: rgba( 0, 0, 0, 0.1 ) rgba( 0, 0, 0, 0.1 ) rgba( 0, 0, 0, 0.25 ); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#62c462', endColorstr='#57a957', GradientType=0 ); + color: #ffffff; + text-shadow: 0 -1px 0 rgba( 0, 0, 0, 0.25 ); +} + +button.warn +{ + background-color: #c43c35; + background-repeat: repeat-x; + background-image: -khtml-gradient( linear, left top, left bottom, from( #ee5f5b ), to( #c43c35 ) ); + background-image: -moz-linear-gradient( top, #ee5f5b, #c43c35 ); + background-image: -ms-linear-gradient( top, #ee5f5b, #c43c35 ); + background-image: -webkit-gradient( linear, left top, left bottom, color-stop( 0%, #ee5f5b ), color-stop( 100%, #c43c35 ) ); + background-image: -webkit-linear-gradient( top, #ee5f5b, #c43c35 ); + background-image: -o-linear-gradient( top, #ee5f5b, #c43c35 ); + background-image: linear-gradient( top, #ee5f5b, #c43c35 ); + border-color: #c43c35 #c43c35 #882a25; + border-color: rgba( 0, 0, 0, 0.1 ) rgba( 0, 0, 0, 0.1 ) rgba( 0, 0, 0, 0.25 ); + color: #ffffff; + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0 ); + text-shadow: 0 -1px 0 rgba( 0, 0, 0, 0.25 ); +} + +a +{ + text-decoration: none; +} + +pre +{ + color: #333; + text-align: left; +} + +abbr +{ + cursor: help; +} + +ul +{ + list-style: none; +} + +.clearfix:after { clear: both; content: "."; display: block; font-size: 0; height: 0; visibility: hidden; } +.clearfix { display: block; } + +.loader +{ + background-image: url( ../../img/loader.gif ) !important; +} + +.loader-light +{ + background-image: url( ../../img/loader-light.gif ) !important; +} + +.universal-loader { + position: absolute; + left: -16px; + top: 0px; + width: 16px; + height: 16px; +} + +#wrapper +{ + position: relative; + margin: 0 auto; + margin-bottom: 30px; + text-align: left; +} + +#header +{ + padding-bottom: 10px; + position: fixed; + z-index: 42; +} + +.scroll #header +{ + position: absolute; +} + +#header #solr +{ + background-image: url( ../../img/solr.svg ); + background-size: 128px; + display: block; + height: 78px; + width: 150px; +} + +#header #solr span +{ + display: none; +} + +#main +{ + min-width: 750px; + position: relative; +} + +#main.error +{ + border: 0; + min-height: 0; + padding-top: 20px; +} + +#main.error .message +{ + background-color: #f00; + background-image: url( ../../img/ico/construction.png ); + background-position: 10px 50%; + color: #fff; + font-weight: bold; + margin-left: 150px; + margin-bottom: 20px; + padding: 10px; + padding-left: 35px; +} + +#main.error .code +{ + border: 1px solid #c0c0c0; + padding: 5px; +} + +#meta +{ + position: absolute; + bottom: -26px; + right: 0; +} + +#meta li +{ + float: left; +} + +#meta li a +{ + background-position: 10px 50%; + display: block; + height: 25px; + line-height: 25px; + padding-left: 31px; + padding-right: 10px; +} + +#meta li a:hover +{ + background-color: #f0f0f0; +} + +#meta .documentation a { background-image: url( ../../img/ico/document-text.png ); } +#meta .issues a { background-image: url( ../../img/ico/bug.png ); } +#meta .irc a { background-image: url( ../../img/ico/users.png ); } +#meta .mailinglist a { background-image: url( ../../img/ico/mail.png ); } +#meta .wiki-query-syntax a { background-image: url( ../../img/ico/script-code.png ); } + +#environment +{ + background-image: url( ../../img/ico/box.png ); + background-position: 5px 50%; + font-weight: bold; + padding: 5px 10px; + padding-left: 26px; +} + +.has-environment #environment +{ + display: block; +} + +#environment.prod +{ + background-color: #c37f7f; + color: #fff; +} + +#environment.stage +{ + background-color: orange; + color: #fff; +} + +#environment.test +{ + background-color: #f5f5b2; +} + +#environment.dev +{ + background-color: #cce7cc; +} + +.header-message +{ + border: 1px solid #f00; + margin-left: 150px; + margin-bottom: 20px; +} + +.header-message h2, +.header-message ul, +.header-message p +{ + padding: 10px; +} + +.header-message h2 +{ + background-color: #f00; + color: #fff; + font-weight: bold; +} + +.header-message p +{ + color: #4D4D4D; + padding-top: 0; +} + +#loading +#http-exception +{ + display: none; +} + +.exception +{ + background-color: #f00; + background-image: url( ../../img/ico/construction.png ); + background-position: 10px 50%; + color: #fff; + font-weight: bold; + margin-bottom: 20px; + padding: 10px; + padding-left: 35px; +} + +#content-wrapper +{ + margin-left: 150px; + border: 1px solid #c0c0c0; + min-height: 500px; +} + +#content +{ + padding: 10px; +} + +#content > .loader +{ + background-position: 0 50%; + padding-left: 21px; +} + +#content iframe +{ + border: 0; + display: block; + min-height: 400px; + width: 100%; +} + +#content .block +{ + margin-bottom: 10px; +} + +#content .block h2 +{ + background-color: #fafafa; + background-position: 5px 50%; + border-bottom: 1px solid #f0f0f0; + font-weight: bold; + padding: 5px; + padding-left: 26px; +} + +#content .block.disabled, +#content .block.disabled h2 +{ + color: #c0c0c0; +} + +#content .block .message, +#content .block .content +{ + padding: 5px; +} + +/* syntax */ + +pre.syntax +{ + overflow: auto; +} + +pre.syntax code +{ + display: block; + color: #000; +} + +pre.syntax .comment, +pre.syntax .template_comment, +pre.syntax .diff .header, +pre.syntax .javadoc +{ + color: #998; + font-style: italic; +} + +pre.syntax .keyword, +pre.syntax .css .rule .keyword, +pre.syntax .winutils, +pre.syntax .javascript .title, +pre.syntax .lisp .title, +pre.syntax .subst +{ + color: #000; + font-weight: bold; +} + +pre.syntax .number, +pre.syntax .hexcolor +{ + color: #40a070; +} + +pre.syntax.language-json .number +{ + color: blue; +} + +pre.syntax.language-json .literal +{ + color: firebrick; +} + +pre.syntax .string, +pre.syntax .tag .value, +pre.syntax .phpdoc, +pre.syntax .tex .formula +{ + color: #d14; +} + +pre.syntax.language-json .string +{ + color: green; +} + +pre.syntax .title, +pre.syntax .id +{ + color: #900; + font-weight: bold; +} + +pre.syntax .javascript .title, +pre.syntax .lisp .title, +pre.syntax .subst +{ + font-weight: normal; +} + +pre.syntax .class .title, +pre.syntax .tex .command +{ + color: #458; + font-weight: bold; +} + +pre.syntax .tag, +pre.syntax .css .keyword, +pre.syntax .html .keyword, +pre.syntax .tag .title, +pre.syntax .django .tag .keyword +{ + color: #000080; + font-weight: normal; +} + +pre.syntax .attribute, +pre.syntax .variable, +pre.syntax .instancevar, +pre.syntax .lisp .body +{ + color: #008080; +} + +pre.syntax.language-json .attribute +{ + color: black; + font-weight: bold; +} + +pre.syntax .regexp +{ + color: #009926; +} + +pre.syntax .class +{ + color: #458; + font-weight: bold; +} + +pre.syntax .symbol, +pre.syntax .ruby .symbol .string, +pre.syntax .ruby .symbol .keyword, +pre.syntax .ruby .symbol .keymethods, +pre.syntax .lisp .keyword, +pre.syntax .tex .special +{ + color: #990073; +} + +pre.syntax .builtin, +pre.syntax .built_in, +pre.syntax .lisp .title +{ + color: #0086b3; +} + +pre.syntax .preprocessor, +pre.syntax .pi, +pre.syntax .doctype, +pre.syntax .shebang, +pre.syntax .cdata +{ + color: #999; + font-weight: bold; +} + +pre.syntax .deletion +{ + background: #fdd; +} + +pre.syntax .addition +{ + background: #dfd; +} + +pre.syntax .diff .change +{ + background: #0086b3; +} + +pre.syntax .chunk +{ + color: #aaa; +} + +pre.syntax .tex .formula +{ + opacity: 0.5; +} + +#content .tree li.jstree-last +{ + background:transparent; +} + +#content .tree .jstree-open > ins +{ + background-position: -36px 0; +} + +#content .tree .jstree-closed > ins +{ + background-position: -18px 0; +} + +#content .tree .jstree-leaf > ins +{ + background-position: 0 0; +} + +#content .tree a.active +{ + background-color: #f0f0f0; + color: #00f; +} + +#content .tree a .jstree-icon +{ + background-image: url( ../../img/ico/folder.png ); + background-position: unset; +} + +#content .tree .jstree-leaf a .jstree-icon +{ + background-image: url( ../../img/ico/document-text.png ); + background-position: unset; +} + +#content .tree .jstree-search +{ + font-style:italic; +} + +#content .tree a.jstree-search +{ + color:aqua; +} + +#connection-box +{ + display: none; +} + +#connection-status-modal +{ + position: absolute; + top: 0px; + left: 0px; + width: 100%; + height: 100%; + background-color: #e6e6e6; + opacity: 0.5; + z-index: 100; +} + +#connection-status-recovered +{ + z-index:102; +} + +.connection-status +{ + position: absolute; + left: 200px; + right: 200px; + top: 40%; + height: 75px; + border: 1px solid #f00; + padding: 30px; + background-color: #fff; + opacity: 1; + z-index: 101; +} + +.connection-status p +{ + background-image: url( ../../img/ico/network-status-busy.png ); + background-position: 0 50%; + color: #800; + padding-left: 26px; +} + +#connection-status-recovered p +{ + color: #080; + background-image: url( ../../img/ico/network-status.png ); +} + +#content .address-bar +{ + margin-bottom: 10px; + background-image: url( ../../img/ico/ui-address-bar.png ); + background-position: 5px 50%; + border: 1px solid #f0f0f0; + box-shadow: 1px 1px 0 #f0f0f0; + -moz-box-shadow: 1px 1px 0 #f0f0f0; + -webkit-box-shadow: 1px 1px 0 #f0f0f0; + color: #4D4D4D; + display: block; + overflow: hidden; + padding: 5px; + padding-left: 26px; + white-space: nowrap; +} + +#content .address-bar:focus, +#content .address-bar:hover +{ + border-color: #c0c0c0; + box-shadow: 1px 1px 0 #d8d8d8; + -moz-box-shadow: 1px 1px 0 #d8d8d8; + -webkit-box-shadow: 1px 1px 0 #d8d8d8; + color: #333; +} + +.exception .show-exception { + margin-top: 4px; + display: block; + position: absolute; + right: 10px; + top: 7px; + color: #fff; +} + +#exception .show-exception a:hover { + color: #333; +} + +.other-ui-link { + margin: 0px; + position: absolute; + right: 0px; + top: -20px; +} + +.other-ui-link span, +.new-ui-warning span.help { + background-image: url( ../../img/ico/information-white.png ); + right: 0px; + padding-left: 16px; +} + +.other-ui-link a.ul { + text-decoration: underline; +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/cores.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/cores.css new file mode 100755 index 0000000000..dfeed9cce7 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/cores.css @@ -0,0 +1,225 @@ +/* + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#content #cores +{ + position: relative; +} + +#content #cores #ui-block +{ + background-color: #fff; + height: 200px; + position: absolute; + left: -5px; + top: 35px; + width: 500px; +} + +#content #cores #frame +{ + float: right; + width: 86%; +} + +#content #cores #navigation +{ + padding-top: 50px; + width: 12%; +} + +#content #cores #navigation a +{ + padding-left: 5px; +} + +#content #cores #frame .actions +{ + margin-bottom: 20px; + min-height: 30px; +} + +#content #cores .actions div.action +{ + width: 320px; +} + +#content #cores .actions div.action .cloud +{ +} + +#content #cores .actions form .directory-note +{ + background-image: url( ../../img/ico/information-white.png ); + background-position: 22% 1px; + color: #4D4D4D; +} + +#content #cores .actions form .error +{ + background-image: url( ../../img/ico/cross-button.png ); + background-position: 22% 1px; + color: #c00; + font-weight: bold; +} + +#content #cores .actions form p +{ + padding-bottom: 8px; +} + +#content #cores .actions form label +{ + float: left; + padding-top: 3px; + padding-bottom: 3px; + text-align: right; + width: 25%; +} + +#content #cores .actions form input, +#content #cores .actions form select, +#content #cores .actions form .buttons, +#content #cores .actions form .note span +{ + float: right; + width: 71%; +} + +#content #cores .actions form .note span +{ + padding-left: 3px; + padding-right: 3px; +} + +#content #cores .actions form .buttons +{ + padding-top: 10px; +} + +#content #cores .actions form button.submit +{ + margin-right: 20px; +} + +#content #cores .actions form button.submit span +{ + background-image: url( ../../img/ico/tick.png ); +} + +#content #cores .actions form button.reset span +{ + background-image: url( ../../img/ico/cross.png ); +} + +#content #cores .actions #add +{ + left: 0; + position: absolute; +} + +#content #cores .actions #add span +{ + background-image: url( ../../img/ico/plus-button.png ); +} + +#content #cores .actions #unload +{ + margin-right: 20px; +} + +#content #cores .actions #unload span +{ + background-image: url( ../../img/ico/cross.png ); +} + +#content #cores .actions #reload span +{ + background-image: url( ../../img/ico/arrow-circle.png ); +} + +#content #cores .actions #rename span +{ + background-image: url( ../../img/ico/ui-text-field-select.png ); +} + +#content #cores .actions #swap span +{ + background-image: url( ../../img/ico/arrow-switch.png ); +} + + +#content #cores .actions div.action +{ + background-color: #fff; + border: 1px solid #f0f0f0; + box-shadow: 5px 5px 10px #c0c0c0; + -moz-box-shadow: 5px 5px 10px #c0c0c0; + -webkit-box-shadow: 5px 5px 10px #c0c0c0; + position: absolute; + left: -50px; + top: 40px; + padding: 10px; +} + +#content #cores #data #core-data h2 { background-image: url( ../../img/ico/box.png ); } +#content #cores #data #index-data h2 { background-image: url( ../../img/ico/chart.png ); } + +#content #cores #data #index-data +{ + margin-top: 10px; +} + +#content #cores #data li +{ + padding-bottom: 3px; + padding-top: 3px; +} + +#content #cores #data li.odd +{ + background-color: #f8f8f8; +} + +#content #cores #data li dt +{ + float: left; + width: 17%; +} + +#content #cores #data li dd +{ + float: right; + width: 82%; +} + +#content #cores #data li dd.ico +{ + background-image: url( ../../img/ico/slash.png ); + height: 20px; +} + +#content #cores #data li dd.ico.ico-1 +{ + background-image: url( ../../img/ico/tick.png ); +} + +#content #cores #data li dd.ico span +{ +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/dashboard.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/dashboard.css new file mode 100755 index 0000000000..edfd55657a --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/dashboard.css @@ -0,0 +1,179 @@ +/* + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#content #dashboard .block +{ + background-image: none; + width: 49%; +} + +#content #dashboard .fieldlist +{ + float: left; +} + +#content #dashboard .fieldlist dt, +#content #dashboard .fieldlist dd +{ + display: block; + float: left; +} + +#content #dashboard .fieldlist dt +{ + clear: left; + margin-right: 2%; + text-align: right; + width: 23%; +} + +#content #dashboard .fieldlist dd +{ + width: 74%; +} + +#content #dashboard .fieldlist .index_optimized +{ + margin-top: 10px; +} + +#content #dashboard .fieldlist .ico +{ + background-image: url( ../../img/ico/slash.png ); + height: 20px; +} + +#content #dashboard .fieldlist .ico.ico-1 +{ + background-image: url( ../../img/ico/tick.png ); +} + +#content #dashboard .fieldlist .ico span +{ + display: none; +} + +#content #dashboard #statistics .index_optimized.value a +{ + display: none; +} + +#content #dashboard #statistics .index_optimized.value.ico-0 a +{ + background-color: #f0f0f0; + background-image: url( ../../img/ico/hammer-screwdriver.png ); + background-position: 5px 50%; + border: 1px solid #c0c0c0; + display: block; + float: left; + margin-left: 50px; + padding: 1px 5px; + padding-left: 26px; +} + +#content #dashboard #statistics .index_has-deletions +{ + display: none; +} + +#content #dashboard #statistics .index_has-deletions.value.ico-0 +{ + background-image: url( ../../img/ico/tick-red.png ); +} + +#content #dashboard #replication +{ + float: left; +} + +#content #dashboard #replication .is-replicating +{ + background-position: 99% 50%; + display: block; +} + +#content #dashboard #replication #details table thead td span +{ + display: none; +} + +#content #dashboard #instance +{ + float: right; +} + +#content #dashboard #instance .dir_impl +{ + margin-top: 10px; +} + +#content #dashboard #healthcheck +{ + float: right; +} + +#content #dashboard #healthcheck .ico +{ + background-image: url( ../../img/ico/slash.png ); + height: 20px; + padding-left: 20px; + width: 60%; +} + +#content #dashboard #healthcheck .ico.ico-1 +{ + background-image: url( ../../img/ico/tick.png ); +} + +#content #dashboard #system h2 { background-image: url( ../../img/ico/server.png ); } +#content #dashboard #statistics h2 { background-image: url( ../../img/ico/chart.png ); } +#content #dashboard #replication h2 { background-image: url( ../../img/ico/node.png ); } +#content #dashboard #replication.master h2 { background-image: url( ../../img/ico/node-master.png ); } +#content #dashboard #replication.slave h2 { background-image: url( ../../img/ico/node-slave.png ); } +#content #dashboard #instance h2 { background-image: url( ../../img/ico/server.png ); } +#content #dashboard #collection h2 { background-image: url( ../../img/ico/book-open-text.png ); } +#content #dashboard #shards h2 { background-image: url( ../../img/ico/documents-stack.png ); } + +#content #dashboard #shards { margin-left: 20px;} + +#dashboard #shards .shard h3.shard-title { + display: block; + background-color: #c8c8c8; + font-weight: bold; + padding: 3px; + padding-left: 30px; + margin-left: 20px; + margin-top: 20px; + background-image: url( ../../img/ico/document-text.png ); + background-position-x: 10px; + background-position-y: 3px; +} + +#dashboard #shards .shard .shard-detail { + margin-bottom: 25px; + margin-top: 7px; +} + +#dashboard #shards .shard .replica { + background-color: #e4e4e4; +} + +#dashboard #shards .shard .replica.odd { + background-color: #fff; +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/dataimport.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/dataimport.css new file mode 100755 index 0000000000..d4ff81b02d --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/dataimport.css @@ -0,0 +1,371 @@ +/* + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#content #dataimport +{ + background-image: url( ../../img/div.gif ); + background-position: 21% 0; + background-repeat: repeat-y; +} + +#content #dataimport #frame +{ + float: right; + width: 78%; +} + +#content #dataimport #form +{ + float: left; + width: 20%; +} + +#content #dataimport #form #navigation +{ + border-right: 0; +} + +#content #dataimport #form #navigation a +{ + background-image: url( ../../img/ico/status-offline.png ); +} + +#content #dataimport #form #navigation .current a +{ + background-image: url( ../../img/ico/status.png ); +} + +#content #dataimport #form form +{ + border-top: 1px solid #f0f0f0; + margin-top: 10px; + padding-top: 5px; +} + +#content #dataimport #form label +{ + cursor: pointer; + display: block; + margin-top: 5px; +} + +#content #dataimport #form input, +#content #dataimport #form select, +#content #dataimport #form textarea +{ + margin-bottom: 2px; + width: 100%; +} + +#content #dataimport #form input +{ + width: 98%; +} + +#content #dataimport #form button +{ + margin-top: 10px; +} + +#content #dataimport #form .execute span +{ + background-image: url( ../../img/ico/document-import.png ); +} + +#content #dataimport #form .refresh-status span +{ + background-image: url( ../../img/ico/arrow-circle.png ); +} + +#content #dataimport #form .refresh-status span.success +{ + background-image: url( ../../img/ico/tick.png ); +} + +#content #dataimport #form #start +{ + float: left; + width: 47%; +} + +#content #dataimport #form #rows +{ + float: right; + width: 47%; +} + +#content #dataimport #form .checkbox input +{ + margin-bottom: 0; + width: auto; +} + +#content #dataimport #form #auto-refresh-status +{ + margin-top: 20px; +} + +#content #dataimport #form #auto-refresh-status a +{ + background-image: url( ../../img/ico/ui-check-box-uncheck.png ); + background-position: 0 50%; + color: #4D4D4D; + display: block; + padding-left: 21px; +} + +#content #dataimport #form #auto-refresh-status a.on, +#content #dataimport #form #auto-refresh-status a:hover +{ + color: #333; +} + +#content #dataimport #form #auto-refresh-status a.on +{ + background-image: url( ../../img/ico/ui-check-box.png ); +} + +#content #dataimport #current_state +{ + padding: 10px; + margin-bottom: 20px; +} + +#content #dataimport #current_state .last_update, +#content #dataimport #current_state .info +{ + display: block; + padding-left: 21px; +} + +#content #dataimport #current_state .last_update +{ + color: #4D4D4D; + font-size: 11px; +} + +#content #dataimport #current_state .info +{ + background-position: 0 1px; + position: relative; +} + +#content #dataimport #current_state .info .details span +{ + color: #c0c0c0; +} + +#content #dataimport #current_state .info .abort-import +{ + position: absolute; + right: 0px; + top: 0px; +} + +#content #dataimport #current_state .info .abort-import span +{ + background-image: url( ../../img/ico/cross.png ); +} + +#content #dataimport #current_state .info .abort-import.success span +{ + background-image: url( ../../img/ico/tick.png ); +} + +#content #dataimport #current_state.indexing +{ + background-color: #f9f9f9; +} + +#content #dataimport #current_state.indexing .info +{ + background-image: url( ../../img/ico/hourglass.png ); +} + +#content #dataimport #current_state.indexing .info .abort-import +{ + display: block; +} + +#content #dataimport #current_state.success +{ + background-color: #e6f3e6; +} + +#content #dataimport #current_state.success .info +{ + background-image: url( ../../img/ico/tick-circle.png ); +} + +#content #dataimport #current_state.success .info strong +{ + color: #080; +} + +#content #dataimport #current_state.aborted +{ + background-color: #f3e6e6; +} + +#content #dataimport #current_state.aborted .info +{ + background-image: url( ../../img/ico/slash.png ); +} + +#content #dataimport #current_state.aborted .info strong +{ + color: #800; +} + +#content #dataimport #current_state.failure +{ + background-color: #f3e6e6; +} + +#content #dataimport #current_state.failure .info +{ + background-image: url( ../../img/ico/cross-button.png ); +} + +#content #dataimport #current_state.failure .info strong +{ + color: #800; +} + +#content #dataimport #current_state.idle +{ + background-color: #e6e6ff; +} + +#content #dataimport #current_state.idle .info +{ + background-image: url( ../../img/ico/information.png ); +} + +#content #dataimport #error, +#content #dataimport #deprecation_message +{ + background-color: #f00; + background-image: url( ../../img/ico/construction.png ); + background-position: 10px 50%; + color: #fff; + font-weight: bold; + margin-bottom: 20px; + padding: 10px; + padding-left: 35px; +} + +#content #dataimport .block h2 +{ + border-color: #c0c0c0; + padding-left: 5px; + position: relative; +} + +#content #dataimport .block.hidden h2 +{ + border-color: #fafafa; +} + +#content #dataimport .block h2 a.toggle +{ + background-image: url( ../../img/ico/toggle-small.png ); + background-position: 0 50%; + padding-left: 21px; +} + +#content #dataimport .block.hidden h2 a.toggle +{ + background-image: url( ../../img/ico/toggle-small-expand.png ); +} + +#content #dataimport #config h2 a.r +{ + background-position: 3px 50%; + display: block; + float: right; + margin-left: 10px; + padding-left: 24px; + padding-right: 3px; +} + +#content #dataimport #config h2 a.reload_config +{ + background-image: url( ../../img/ico/arrow-circle.png ); +} + +#content #dataimport #config h2 a.reload_config.success +{ + background-image: url( ../../img/ico/tick.png ); +} + +#content #dataimport #config h2 a.reload_config.error +{ + background-image: url( ../../img/ico/slash.png ); +} + +#content #dataimport #config h2 a.debug_mode +{ + background-image: url( ../../img/ico/hammer.png ); + color: #4D4D4D; +} + +#content #dataimport #config.debug_mode h2 a.debug_mode +{ + background-color: #ff0; + background-image: url( ../../img/ico/hammer-screwdriver.png ); + color: #333; +} + +#content #dataimport #config .content +{ + padding: 5px 2px; +} + +#content #dataimport #dataimport_config .loader +{ + background-position: 0 50%; + padding-left: 21px; +} + +#content #dataimport #dataimport_config .formatted +{ + border: 1px solid #fff; + display: block; + padding: 2px; +} + +#content #dataimport .debug_mode #dataimport_config .editable +{ + display: block; +} + +#content #dataimport #dataimport_config .editable textarea +{ + font-family: monospace; + height: 120px; + min-height: 60px; + width: 100%; +} + +#content #dataimport #debug_response em +{ + color: #4D4D4D; + font-style: normal; +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/documents.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/documents.css new file mode 100755 index 0000000000..b40fde4c27 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/documents.css @@ -0,0 +1,179 @@ +/* + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#content #documents +{ + background-image: url( ../../img/div.gif ); + background-position: 45% 0; + background-repeat: repeat-y; +} + +#content #documents #form +{ + float: left; + /*width: 21%;*/ +} + +#content #documents #form label +{ + cursor: pointer; + display: block; + margin-top: 5px; +} + +#content #documents #form input, +#content #documents #form select, +#content #documents #form textarea +{ + margin-bottom: 2px; + /*width: 100%;*/ +} + +#content #documents #form input, +#content #documents #form textarea +{ + margin-bottom: 2px; + /*width: 98%;*/ +} + +#content #documents #form #start +{ + float: left; + /*width: 45%;*/ +} + +#content #documents #form #rows +{ + float: right; + /* width: 45%;*/ +} + +#content #documents #form .checkbox input +{ + margin-bottom: 0; + width: auto; +} + +#content #documents #form fieldset, +#content #documents #form .optional.expanded +{ + border: 1px solid #fff; + border-top: 1px solid #c0c0c0; + margin-bottom: 5px; +} + +#content #documents #form fieldset.common +{ + margin-top: 10px; +} + +#content #documents #form fieldset legend, +#content #documents #form .optional.expanded legend +{ + display: block; + margin-left: 10px; + padding: 0px 5px; +} + +#content #documents #form fieldset legend label +{ + margin-top: 0; +} + +#content #documents #form fieldset .fieldset +{ + border-bottom: 1px solid #f0f0f0; + margin-bottom: 5px; + padding-bottom: 10px; +} + +#content #documents #form .optional +{ + border: 0; +} + +#content #documents #form .optional legend +{ + margin-left: 0; + padding-left: 0; +} + +#content #documents #form .optional.expanded .fieldset +{ + display: block; +} + +#content #documents #result +{ + float: right; + width: 54%; +} + +#content #documents #result #url +{ + margin-bottom: 10px; + background-image: url( ../../img/ico/ui-address-bar.png ); + background-position: 5px 50%; + border: 1px solid #f0f0f0; + box-shadow: 1px 1px 0 #f0f0f0; + -moz-box-shadow: 1px 1px 0 #f0f0f0; + -webkit-box-shadow: 1px 1px 0 #f0f0f0; + color: #c0c0c0; + display: block; + overflow: hidden; + padding: 5px; + padding-left: 26px; + white-space: nowrap; +} + +#content #documents #result #url:focus, +#content #documents #result #url:hover +{ + border-color: #c0c0c0; + box-shadow: 1px 1px 0 #d8d8d8; + -moz-box-shadow: 1px 1px 0 #d8d8d8; + -webkit-box-shadow: 1px 1px 0 #d8d8d8; + color: #333; +} + +#content #documents #result #response +{ +} + +#content #documents #result #response pre +{ + padding-left: 20px; +} + +.description{ + font-weight: bold; +} + +#document-type{ + padding-bottom: 5px; +} + +#wizard-fields div{ + padding-top: 5px; + padding-bottom: 5px; +} + +#wiz-field-data, #wiz-field-data span{ + vertical-align: top; +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/files.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/files.css new file mode 100755 index 0000000000..917655c37b --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/files.css @@ -0,0 +1,53 @@ +/* + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#content #files #tree-holder +{ + float: left; + width: 20%; +} + +#content #files #tree-holder li +{ + overflow: hidden; +} + +#content #files form .buttons button +{ + float: right; +} + +#content #files #file-content +{ + float: right; + width: 78%; +} + +#content #files .show #file-content +{ + display: block; +} + +#content #files #file-content .response +{ + border: 1px solid transparent; + padding: 2px; + overflow: auto; + max-height: 600px; +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/index.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/index.css new file mode 100755 index 0000000000..4ccccf14e9 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/index.css @@ -0,0 +1,221 @@ +/* + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#content #index .bar-desc +{ + color: #4D4D4D; + font-weight: normal; + margin-left: 10px; + white-space: pre; +} + +#content #index .bar-holder +{ + box-shadow: 5px 5px 10px #c0c0c0; + -moz-box-shadow: 5px 5px 10px #c0c0c0; + -webkit-box-shadow: 5px 5px 10px #c0c0c0; + height: 35px; +} + +#content #index .bar-holder .bar +{ + height: 100%; + position: relative; +} + +#content #index .bar-holder div .val +{ + border-right: 1px solid #f00; + display: block; + padding-right: 5px; + position: absolute; + right: 0; + top: 35px; + white-space: nowrap; +} + +#content #index .bar-holder .bar-max.bar +{ + background-color: #f0f0f0; +} + +#content #index .bar-holder .bar-max.val +{ + border-color: #f0f0f0; + color: #8D8D8D; +} + +#content #index .bar-holder .bar-total.bar +{ + background-color: #c0c0c0; +} + +#content #index .bar-holder .bar-total.val +{ + border-color: #c0c0c0; + color: #4D4D4D; +} + +#content #index .bar-holder .bar-used.bar +{ + background-color: #969696; +} + +#content #index .bar-holder .bar-used.val +{ + border-color: #969696; + color: #969696; +} + +#content #index .bar-holder.bar-lvl-2 .bar-max.val { padding-top: 25px; } +#content #index .bar-holder.bar-lvl-2 .bar-total.val { padding-top: 5px; } +#content #index .bar-holder.bar-lvl-2 { margin-bottom: 45px; } + +#content #index .bar-holder.bar-lvl-3 .bar-max.val { padding-top: 45px; } +#content #index .bar-holder.bar-lvl-3 .bar-total.val { padding-top: 25px; } +#content #index .bar-holder.bar-lvl-3 .bar-used.val { padding-top: 5px; } +#content #index .bar-holder.bar-lvl-3 { margin-bottom: 65px; } + +#content #index .loader +{ + background-position: 0 50%; + padding-left: 21px; +} + +#content #index .index-left +{ + float: left; + width: 55%; +} + +#content #index .index-right +{ + float: right; + width: 40%; +} + +#content #index .data +{ + padding-bottom: 12px; + overflow: hidden; +} + +#content #index .data:hover +{ + overflow-x: auto; +} + +#content #index .data li +{ + padding-top: 3px; + padding-bottom: 3px; +} + +#content #index .data li dt +{ + float: left; + white-space: nowrap; + width: 20%; +} + +#content #index .data li dd +{ + float: right; + text-overflow: ellipsis; + white-space: nowrap; + width: 80% +} + +#content #index .data li dd.odd +{ + background-color: #f0f0f0; +} + +#content #index .data dt span +{ + background-position: 1px 50%; + display: block; + padding-left: 22px; + font-weight: bold; + text-align: left; +} + +#content #index #instance h2 { background-image: url( ../../img/ico/server.png ); } +#content #index #instance .start_time dt span { background-image: url( ../../img/ico/clock-select.png ); } + +#content #index #versions h2 { background-image: url( ../../img/ico/property.png ); } +#content #index #versions .solr span { background-image: url( ../../img/solr-ico.png ); } +#content #index #versions .lucene span { background-image: url( ../../img/lucene-ico.png ); } + +#content #index #jvm h2 { background-image: url( ../../img/ico/jar.png ); } +#content #index #jvm .jvm_version dt span { background-image: url( ../../img/ico/jar.png ); } +#content #index #jvm .processors dt span { background-image: url( ../../img/ico/processor.png ); } +#content #index #jvm .command_line_args dt span { background-image: url( ../../img/ico/terminal.png ); } + +#content #index #system h2 { background-image: url( ../../img/ico/system-monitor.png ); } + +#content #index #system +{ + position: relative; +} + +#content #index #system .reload +{ + background-image: url( ../../img/ico/arrow-circle.png ); + background-position: 50% 50%; + display: block; + height: 30px; + position: absolute; + right: 0; + top: 0; + width: 30px; +} + +#content #index #system .reload.loader +{ + padding-left: 0; +} + +#content #index #system .reload span +{ + display: none; +} + +#content #index #system .content p +{ + margin-top: 10px; + margin-bottom: 5px; +} + +#content #index #system .content .no-info +{ + color: #4D4D4D; + display: none; + font-style: italic; +} + +#content #index #jvm-memory h2 { background-image: url( ../../img/ico/memory.png ); } + +#content #index #jvm-memory-bar +{ + margin-top: 20px; +} + +#content #index #security h2 { background-image: url( ../../img/ico/prohibition.png ); } +#content #index #security div { text-align: right; } diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/java-properties.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/java-properties.css new file mode 100755 index 0000000000..2521359a2e --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/java-properties.css @@ -0,0 +1,47 @@ +/* + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#content #java-properties .loader +{ + background-position: 0 50%; + padding-left: 21px; +} + +#content #java-properties li +{ + padding-top: 3px; + padding-bottom: 3px; +} + +#content #java-properties li.odd +{ + background-color: #f8f8f8; +} + +#content #java-properties li dt +{ + float: left; + width: 29%; +} + +#content #java-properties li dd +{ + float: right; + width: 70% +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/jquery-ui.min.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/jquery-ui.min.css new file mode 100755 index 0000000000..506867f9c8 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/jquery-ui.min.css @@ -0,0 +1,28 @@ +/*! jQuery UI - v1.12.1 - 2017-10-31 +* http://jqueryui.com + +Available for use under the MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +* Includes: core.css, tooltip.css, theme.css +* To view and modify this theme, visit http://jqueryui.com/themeroller/?scope=&folderName=base&cornerRadiusShadow=8px&offsetLeftShadow=0px&offsetTopShadow=0px&thicknessShadow=5px&opacityShadow=30&bgImgOpacityShadow=0&bgTextureShadow=flat&bgColorShadow=666666&opacityOverlay=30&bgImgOpacityOverlay=0&bgTextureOverlay=flat&bgColorOverlay=aaaaaa&iconColorError=cc0000&fcError=5f3f3f&borderColorError=f1a899&bgTextureError=flat&bgColorError=fddfdf&iconColorHighlight=777620&fcHighlight=777620&borderColorHighlight=dad55e&bgTextureHighlight=flat&bgColorHighlight=fffa90&iconColorActive=ffffff&fcActive=ffffff&borderColorActive=003eff&bgTextureActive=flat&bgColorActive=007fff&iconColorHover=555555&fcHover=2b2b2b&borderColorHover=cccccc&bgTextureHover=flat&bgColorHover=ededed&iconColorDefault=777777&fcDefault=454545&borderColorDefault=c5c5c5&bgTextureDefault=flat&bgColorDefault=f6f6f6&iconColorContent=444444&fcContent=333333&borderColorContent=dddddd&bgTextureContent=flat&bgColorContent=ffffff&iconColorHeader=444444&fcHeader=333333&borderColorHeader=dddddd&bgTextureHeader=flat&bgColorHeader=e9e9e9&cornerRadius=3px&fwDefault=normal&fsDefault=1em&ffDefault=Arial%2CHelvetica%2Csans-serif +* Copyright jQuery Foundation and other contributors; Licensed MIT */ + +.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px}body .ui-tooltip{text-align:left;border-width:2px}.ui-widget{font-size:1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget.ui-widget-content{border:1px solid #c5c5c5}.ui-widget-content{border:1px solid #ddd;background:#fff;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #ddd;background:#e9e9e9;color:#333;font-weight:bold}.ui-widget-header a{color:#333}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default,.ui-button,html .ui-button.ui-state-disabled:hover,html .ui-button.ui-state-disabled:active{border:1px solid #c5c5c5;background:#f6f6f6;font-weight:normal;color:#454545}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited,a.ui-button,a:link.ui-button,a:visited.ui-button,.ui-button{color:#454545;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus,.ui-button:hover,.ui-button:focus{border:1px solid #ccc;background:#ededed;font-weight:normal;color:#2b2b2b}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited,a.ui-button:hover,a.ui-button:focus{color:#2b2b2b;text-decoration:none}.ui-visual-focus{box-shadow:0 0 3px 1px rgb(94,158,214)}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active,a.ui-button:active,.ui-button:active,.ui-button.ui-state-active:hover{border:1px solid #003eff;background:#007fff;font-weight:normal;color:#fff}.ui-icon-background,.ui-state-active .ui-icon-background{border:#003eff;background-color:#fff}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#fff;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #dad55e;background:#fffa90;color:#777620}.ui-state-checked{border:1px solid #dad55e;background:#fffa90}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#777620}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #f1a899;background:#fddfdf;color:#5f3f3f}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#5f3f3f}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#5f3f3f}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon,.ui-button:hover .ui-icon,.ui-button:focus .ui-icon{background-image:url("images/ui-icons_555555_256x240.png")}.ui-state-active .ui-icon,.ui-button:active .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-highlight .ui-icon,.ui-button .ui-state-highlight.ui-icon{background-image:url("images/ui-icons_777620_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cc0000_256x240.png")}.ui-button .ui-icon{background-image:url("images/ui-icons_777777_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-caret-1-n{background-position:0 0}.ui-icon-caret-1-ne{background-position:-16px 0}.ui-icon-caret-1-e{background-position:-32px 0}.ui-icon-caret-1-se{background-position:-48px 0}.ui-icon-caret-1-s{background-position:-65px 0}.ui-icon-caret-1-sw{background-position:-80px 0}.ui-icon-caret-1-w{background-position:-96px 0}.ui-icon-caret-1-nw{background-position:-112px 0}.ui-icon-caret-2-n-s{background-position:-128px 0}.ui-icon-caret-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-65px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-65px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:1px -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:3px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:3px}.ui-widget-overlay{background:#aaa;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{-webkit-box-shadow:0 0 5px #666;box-shadow:0 0 5px #666} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/jquery-ui.structure.min.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/jquery-ui.structure.min.css new file mode 100755 index 0000000000..6386db0904 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/jquery-ui.structure.min.css @@ -0,0 +1,24 @@ +/*! jQuery UI - v1.12.1 - 2017-10-31 +* http://jqueryui.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +* Copyright jQuery Foundation and other contributors; Licensed MIT */ + +.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px}body .ui-tooltip{border-width:2px} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/jstree.style.min.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/jstree.style.min.css new file mode 100755 index 0000000000..4f60797458 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/jstree.style.min.css @@ -0,0 +1,24 @@ +/* + +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ +.jstree-node,.jstree-children,.jstree-container-ul{display:block;margin:0;padding:0;list-style-type:none;list-style-image:none}.jstree-node{white-space:nowrap}.jstree-anchor{display:inline-block;color:black;white-space:nowrap;padding:0 4px 0 1px;margin:0;vertical-align:top}.jstree-anchor:focus{outline:0}.jstree-anchor,.jstree-anchor:link,.jstree-anchor:visited,.jstree-anchor:hover,.jstree-anchor:active{text-decoration:none;color:inherit}.jstree-icon{display:inline-block;text-decoration:none;margin:0;padding:0;vertical-align:top;text-align:center}.jstree-icon:empty{display:inline-block;text-decoration:none;margin:0;padding:0;vertical-align:top;text-align:center}.jstree-ocl{cursor:pointer}.jstree-leaf>.jstree-ocl{cursor:default}.jstree .jstree-open>.jstree-children{display:block}.jstree .jstree-closed>.jstree-children,.jstree .jstree-leaf>.jstree-children{display:none}.jstree-anchor>.jstree-themeicon{margin-right:2px}.jstree-no-icons .jstree-themeicon,.jstree-anchor>.jstree-themeicon-hidden{display:none}.jstree-hidden,.jstree-node.jstree-hidden{display:none}.jstree-rtl .jstree-anchor{padding:0 1px 0 4px}.jstree-rtl .jstree-anchor>.jstree-themeicon{margin-left:2px;margin-right:0}.jstree-rtl .jstree-node{margin-left:0}.jstree-rtl .jstree-container-ul>.jstree-node{margin-right:0}.jstree-wholerow-ul{position:relative;display:inline-block;min-width:100%}.jstree-wholerow-ul .jstree-leaf>.jstree-ocl{cursor:pointer}.jstree-wholerow-ul .jstree-anchor,.jstree-wholerow-ul .jstree-icon{position:relative}.jstree-wholerow-ul .jstree-wholerow{width:100%;cursor:pointer;position:absolute;left:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jstree-contextmenu .jstree-anchor{-webkit-user-select:none;-webkit-touch-callout:none}.vakata-context{display:none}.vakata-context,.vakata-context ul{margin:0;padding:2px;position:absolute;background:#f5f5f5;border:1px solid #979797;box-shadow:2px 2px 2px #999999}.vakata-context ul{list-style:none;left:100%;margin-top:-2.7em;margin-left:-4px}.vakata-context .vakata-context-right ul{left:auto;right:100%;margin-left:auto;margin-right:-4px}.vakata-context li{list-style:none}.vakata-context li>a{display:block;padding:0 2em 0 2em;text-decoration:none;width:auto;color:black;white-space:nowrap;line-height:2.4em;text-shadow:1px 1px 0 white;border-radius:1px}.vakata-context li>a:hover{position:relative;background-color:#e8eff7;box-shadow:0 0 2px #0a6aa1}.vakata-context li>a.vakata-context-parent{background-image:url("data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAIORI4JlrqN1oMSnmmZDQUAOw==");background-position:right center;background-repeat:no-repeat}.vakata-context li>a:focus{outline:0}.vakata-context .vakata-context-hover>a{position:relative;background-color:#e8eff7;box-shadow:0 0 2px #0a6aa1}.vakata-context .vakata-context-separator>a,.vakata-context .vakata-context-separator>a:hover{background:white;border:0;border-top:1px solid #e2e3e3;height:1px;min-height:1px;max-height:1px;padding:0;margin:0 0 0 2.4em;border-left:1px solid #e0e0e0;text-shadow:0 0 0 transparent;box-shadow:0 0 0 transparent;border-radius:0}.vakata-context .vakata-contextmenu-disabled a,.vakata-context .vakata-contextmenu-disabled a:hover{color:silver;background-color:transparent;border:0;box-shadow:0 0 0}.vakata-context .vakata-contextmenu-disabled>a>i{filter:grayscale(100%)}.vakata-context li>a>i{text-decoration:none;display:inline-block;width:2.4em;height:2.4em;background:transparent;margin:0 0 0 -2em;vertical-align:top;text-align:center;line-height:2.4em}.vakata-context li>a>i:empty{width:2.4em;line-height:2.4em}.vakata-context li>a .vakata-contextmenu-sep{display:inline-block;width:1px;height:2.4em;background:white;margin:0 .5em 0 0;border-left:1px solid #e2e3e3}.vakata-context .vakata-contextmenu-shortcut{font-size:.8em;color:silver;opacity:.5;display:none}.vakata-context-rtl ul{left:auto;right:100%;margin-left:auto;margin-right:-4px}.vakata-context-rtl li>a.vakata-context-parent{background-image:url("data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAINjI+AC7rWHIsPtmoxLAA7");background-position:left center;background-repeat:no-repeat}.vakata-context-rtl .vakata-context-separator>a{margin:0 2.4em 0 0;border-left:0;border-right:1px solid #e2e3e3}.vakata-context-rtl .vakata-context-left ul{right:auto;left:100%;margin-left:-4px;margin-right:auto}.vakata-context-rtl li>a>i{margin:0 -2em 0 0}.vakata-context-rtl li>a .vakata-contextmenu-sep{margin:0 0 0 .5em;border-left-color:white;background:#e2e3e3}#jstree-marker{position:absolute;top:0;left:0;margin:-5px 0 0 0;padding:0;border-right:0;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid;width:0;height:0;font-size:0;line-height:0}#jstree-dnd{line-height:16px;margin:0;padding:4px}#jstree-dnd .jstree-icon,#jstree-dnd .jstree-copy{display:inline-block;text-decoration:none;margin:0 2px 0 0;padding:0;width:16px;height:16px}#jstree-dnd .jstree-ok{background:green}#jstree-dnd .jstree-er{background:red}#jstree-dnd .jstree-copy{margin:0 2px 0 2px}.jstree-default .jstree-node,.jstree-default .jstree-icon{background-repeat:no-repeat;background-color:transparent}.jstree-default .jstree-anchor,.jstree-default .jstree-animated,.jstree-default .jstree-wholerow{transition:background-color .15s,box-shadow .15s}.jstree-default .jstree-hovered{background:#e7f4f9;border-radius:2px;box-shadow:inset 0 0 1px #cccccc}.jstree-default .jstree-context{background:#e7f4f9;border-radius:2px;box-shadow:inset 0 0 1px #cccccc}.jstree-default .jstree-clicked{background:#beebff;border-radius:2px;box-shadow:inset 0 0 1px #999999}.jstree-default .jstree-no-icons .jstree-anchor>.jstree-themeicon{display:none}.jstree-default .jstree-disabled{background:transparent;color:#666666}.jstree-default .jstree-disabled.jstree-hovered{background:transparent;box-shadow:none}.jstree-default .jstree-disabled.jstree-clicked{background:#efefef}.jstree-default .jstree-disabled>.jstree-icon{opacity:.8;filter:url("data:image/svg+xml;utf8,#jstree-grayscale");filter:gray;-webkit-filter:grayscale(100%)}.jstree-default .jstree-search{font-style:italic;color:#8b0000;font-weight:bold}.jstree-default .jstree-no-checkboxes .jstree-checkbox{display:none !important}.jstree-default.jstree-checkbox-no-clicked .jstree-clicked{background:transparent;box-shadow:none}.jstree-default.jstree-checkbox-no-clicked .jstree-clicked.jstree-hovered{background:#e7f4f9}.jstree-default.jstree-checkbox-no-clicked>.jstree-wholerow-ul .jstree-wholerow-clicked{background:transparent}.jstree-default.jstree-checkbox-no-clicked>.jstree-wholerow-ul .jstree-wholerow-clicked.jstree-wholerow-hovered{background:#e7f4f9}.jstree-default>.jstree-striped{min-width:100%;display:inline-block;background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAkCAMAAAB/qqA+AAAABlBMVEUAAAAAAAClZ7nPAAAAAnRSTlMNAMM9s3UAAAAXSURBVHjajcEBAQAAAIKg/H/aCQZ70AUBjAATb6YPDgAAAABJRU5ErkJggg==") left top repeat}.jstree-default>.jstree-wholerow-ul .jstree-hovered,.jstree-default>.jstree-wholerow-ul .jstree-clicked{background:transparent;box-shadow:none;border-radius:0}.jstree-default .jstree-wholerow{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.jstree-default .jstree-wholerow-hovered{background:#e7f4f9}.jstree-default .jstree-wholerow-clicked{background:#beebff;background:-webkit-linear-gradient(top, #beebff 0, #a8e4ff 100%);background:linear-gradient(to bottom, #beebff 0, #a8e4ff 100%)}.jstree-default .jstree-node{min-height:24px;line-height:24px;margin-left:24px;min-width:24px}.jstree-default .jstree-anchor{line-height:24px;height:24px}.jstree-default .jstree-icon{width:24px;height:24px;line-height:24px}.jstree-default .jstree-icon:empty{width:24px;height:24px;line-height:24px}.jstree-default.jstree-rtl .jstree-node{margin-right:24px}.jstree-default .jstree-wholerow{height:24px}.jstree-default .jstree-node,.jstree-default .jstree-icon{background-image:url("../../img/jstree/32px.png")} .jstree-default .jstree-node{background-position:-292px -4px;background-repeat:repeat-y} .jstree-default .jstree-last{background:transparent} .jstree-default .jstree-open>.jstree-ocl{background-position:-132px -4px} .jstree-default .jstree-closed>.jstree-ocl{background-position:-100px -4px} .jstree-default .jstree-leaf>.jstree-ocl{background-position:-68px -4px} .jstree-default .jstree-themeicon{background-position:-260px -4px} .jstree-default>.jstree-no-dots .jstree-node,.jstree-default>.jstree-no-dots .jstree-leaf>.jstree-ocl{background:transparent} .jstree-default>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-36px -4px} .jstree-default>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-4px -4px} .jstree-default .jstree-disabled{background:transparent} .jstree-default .jstree-disabled.jstree-hovered{background:transparent} .jstree-default .jstree-disabled.jstree-clicked{background:#efefef} .jstree-default .jstree-checkbox{background-position:-164px -4px} .jstree-default .jstree-checkbox:hover{background-position:-164px -36px} .jstree-default.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox,.jstree-default .jstree-checked>.jstree-checkbox{background-position:-228px -4px} .jstree-default.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover,.jstree-default .jstree-checked>.jstree-checkbox:hover{background-position:-228px -36px} .jstree-default .jstree-anchor>.jstree-undetermined{background-position:-196px -4px} .jstree-default .jstree-anchor>.jstree-undetermined:hover{background-position:-196px -36px} .jstree-default .jstree-checkbox-disabled{opacity:.8;filter:url("data:image/svg+xml;utf8,#jstree-grayscale");filter:gray;-webkit-filter:grayscale(100%)} .jstree-default>.jstree-striped{background-size:auto 48px} .jstree-default.jstree-rtl .jstree-node{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg==");background-position:100% 1px;background-repeat:repeat-y} .jstree-default.jstree-rtl .jstree-last{background:transparent} .jstree-default.jstree-rtl .jstree-open>.jstree-ocl{background-position:-132px -36px} .jstree-default.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-100px -36px} .jstree-default.jstree-rtl .jstree-leaf>.jstree-ocl{background-position:-68px -36px} .jstree-default.jstree-rtl>.jstree-no-dots .jstree-node,.jstree-default.jstree-rtl>.jstree-no-dots .jstree-leaf>.jstree-ocl{background:transparent} .jstree-default.jstree-rtl>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-36px -36px} .jstree-default.jstree-rtl>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-4px -36px} .jstree-default .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0} .jstree-default>.jstree-container-ul .jstree-loading>.jstree-ocl{background:url("../../img/jstree/throbber.gif") center center no-repeat} .jstree-default .jstree-file{background:url("../../img/jstree/32px.png") -100px -68px no-repeat} .jstree-default .jstree-folder{background:url("../../img/jstree/32px.png") -260px -4px no-repeat} .jstree-default>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0} #jstree-dnd.jstree-default{line-height:24px;padding:0 4px} #jstree-dnd.jstree-default .jstree-ok,#jstree-dnd.jstree-default .jstree-er{background-image:url("../../img/jstree/32px.png");background-repeat:no-repeat;background-color:transparent} #jstree-dnd.jstree-default i{background:transparent;width:24px;height:24px;line-height:24px} #jstree-dnd.jstree-default .jstree-ok{background-position:-4px -68px} #jstree-dnd.jstree-default .jstree-er{background-position:-36px -68px} .jstree-default .jstree-ellipsis{overflow:hidden} .jstree-default .jstree-ellipsis .jstree-anchor{width:calc(100% - 29px);text-overflow:ellipsis;overflow:hidden} .jstree-default.jstree-rtl .jstree-node{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg==")} .jstree-default.jstree-rtl .jstree-last{background:transparent} .jstree-default-small .jstree-node{min-height:18px;line-height:18px;margin-left:18px;min-width:18px} .jstree-default-small .jstree-anchor{line-height:18px;height:18px} .jstree-default-small .jstree-icon{width:18px;height:18px;line-height:18px} .jstree-default-small .jstree-icon:empty{width:18px;height:18px;line-height:18px} .jstree-default-small.jstree-rtl .jstree-node{margin-right:18px} .jstree-default-small .jstree-wholerow{height:18px} .jstree-default-small .jstree-node,.jstree-default-small .jstree-icon{background-image:url("../../img/jstree/32px.png")} .jstree-default-small .jstree-node{background-position:-295px -7px;background-repeat:repeat-y} .jstree-default-small .jstree-last{background:transparent} .jstree-default-small .jstree-open>.jstree-ocl{background-position:-135px -7px} .jstree-default-small .jstree-closed>.jstree-ocl{background-position:-103px -7px} .jstree-default-small .jstree-leaf>.jstree-ocl{background-position:-71px -7px} .jstree-default-small .jstree-themeicon{background-position:-263px -7px} .jstree-default-small>.jstree-no-dots .jstree-node,.jstree-default-small>.jstree-no-dots .jstree-leaf>.jstree-ocl{background:transparent} .jstree-default-small>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-39px -7px} .jstree-default-small>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-7px -7px} .jstree-default-small .jstree-disabled{background:transparent} .jstree-default-small .jstree-disabled.jstree-hovered{background:transparent} .jstree-default-small .jstree-disabled.jstree-clicked{background:#efefef} .jstree-default-small .jstree-checkbox{background-position:-167px -7px} .jstree-default-small .jstree-checkbox:hover{background-position:-167px -39px} .jstree-default-small.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox,.jstree-default-small .jstree-checked>.jstree-checkbox{background-position:-231px -7px} .jstree-default-small.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover,.jstree-default-small .jstree-checked>.jstree-checkbox:hover{background-position:-231px -39px} .jstree-default-small .jstree-anchor>.jstree-undetermined{background-position:-199px -7px} .jstree-default-small .jstree-anchor>.jstree-undetermined:hover{background-position:-199px -39px} .jstree-default-small .jstree-checkbox-disabled{opacity:.8;filter:url("data:image/svg+xml;utf8,#jstree-grayscale");filter:gray;-webkit-filter:grayscale(100%)} .jstree-default-small>.jstree-striped{background-size:auto 36px} .jstree-default-small.jstree-rtl .jstree-node{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg==");background-position:100% 1px;background-repeat:repeat-y} .jstree-default-small.jstree-rtl .jstree-last{background:transparent} .jstree-default-small.jstree-rtl .jstree-open>.jstree-ocl{background-position:-135px -39px} .jstree-default-small.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-103px -39px} .jstree-default-small.jstree-rtl .jstree-leaf>.jstree-ocl{background-position:-71px -39px} .jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-node,.jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-leaf>.jstree-ocl{background:transparent} .jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-39px -39px} .jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-7px -39px} .jstree-default-small .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0} .jstree-default-small>.jstree-container-ul .jstree-loading>.jstree-ocl{background:url("../../img/jstree/throbber.gif") center center no-repeat} .jstree-default-small .jstree-file{background:url("../../img/jstree/32px.png") -103px -71px no-repeat} .jstree-default-small .jstree-folder{background:url("../../img/jstree/32px.png") -263px -7px no-repeat} .jstree-default-small>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0} #jstree-dnd.jstree-default-small{line-height:18px;padding:0 4px} #jstree-dnd.jstree-default-small .jstree-ok,#jstree-dnd.jstree-default-small .jstree-er{background-image:url("../../img/jstree/32px.png");background-repeat:no-repeat;background-color:transparent} #jstree-dnd.jstree-default-small i{background:transparent;width:18px;height:18px;line-height:18px} #jstree-dnd.jstree-default-small .jstree-ok{background-position:-7px -71px} #jstree-dnd.jstree-default-small .jstree-er{background-position:-39px -71px} .jstree-default-small .jstree-ellipsis{overflow:hidden} .jstree-default-small .jstree-ellipsis .jstree-anchor{width:calc(100% - 23px);text-overflow:ellipsis;overflow:hidden} .jstree-default-small.jstree-rtl .jstree-node{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAACAQMAAABv1h6PAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMHBgAAiABBI4gz9AAAAABJRU5ErkJggg==")} .jstree-default-small.jstree-rtl .jstree-last{background:transparent} .jstree-default-large .jstree-node{min-height:32px;line-height:32px;margin-left:32px;min-width:32px} .jstree-default-large .jstree-anchor{line-height:32px;height:32px} .jstree-default-large .jstree-icon{width:32px;height:32px;line-height:32px} .jstree-default-large .jstree-icon:empty{width:32px;height:32px;line-height:32px} .jstree-default-large.jstree-rtl .jstree-node{margin-right:32px} .jstree-default-large .jstree-wholerow{height:32px} .jstree-default-large .jstree-node,.jstree-default-large .jstree-icon{background-image:url("../../img/jstree/32px.png")} .jstree-default-large .jstree-node{background-position:-288px 0;background-repeat:repeat-y} .jstree-default-large .jstree-last{background:transparent} .jstree-default-large .jstree-open>.jstree-ocl{background-position:-128px 0} .jstree-default-large .jstree-closed>.jstree-ocl{background-position:-96px 0} .jstree-default-large .jstree-leaf>.jstree-ocl{background-position:-64px 0} .jstree-default-large .jstree-themeicon{background-position:-256px 0} .jstree-default-large>.jstree-no-dots .jstree-node,.jstree-default-large>.jstree-no-dots .jstree-leaf>.jstree-ocl{background:transparent} .jstree-default-large>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-32px 0} .jstree-default-large>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:0 0} .jstree-default-large .jstree-disabled{background:transparent} .jstree-default-large .jstree-disabled.jstree-hovered{background:transparent} .jstree-default-large .jstree-disabled.jstree-clicked{background:#efefef} .jstree-default-large .jstree-checkbox{background-position:-160px 0} .jstree-default-large .jstree-checkbox:hover{background-position:-160px -32px} .jstree-default-large.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox,.jstree-default-large .jstree-checked>.jstree-checkbox{background-position:-224px 0} .jstree-default-large.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover,.jstree-default-large .jstree-checked>.jstree-checkbox:hover{background-position:-224px -32px} .jstree-default-large .jstree-anchor>.jstree-undetermined{background-position:-192px 0} .jstree-default-large .jstree-anchor>.jstree-undetermined:hover{background-position:-192px -32px} .jstree-default-large .jstree-checkbox-disabled{opacity:.8;filter:url("data:image/svg+xml;utf8,#jstree-grayscale");filter:gray;-webkit-filter:grayscale(100%)} .jstree-default-large>.jstree-striped{background-size:auto 64px} .jstree-default-large.jstree-rtl .jstree-node{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg==");background-position:100% 1px;background-repeat:repeat-y} .jstree-default-large.jstree-rtl .jstree-last{background:transparent} .jstree-default-large.jstree-rtl .jstree-open>.jstree-ocl{background-position:-128px -32px} .jstree-default-large.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-96px -32px} .jstree-default-large.jstree-rtl .jstree-leaf>.jstree-ocl{background-position:-64px -32px} .jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-node,.jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-leaf>.jstree-ocl{background:transparent} .jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-32px -32px} .jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:0 -32px} .jstree-default-large .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0} .jstree-default-large>.jstree-container-ul .jstree-loading>.jstree-ocl{background:url("../../img/jstree/throbber.gif") center center no-repeat} .jstree-default-large .jstree-file{background:url("../../img/jstree/32px.png") -96px -64px no-repeat} .jstree-default-large .jstree-folder{background:url("../../img/jstree/32px.png") -256px 0 no-repeat} .jstree-default-large>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0} #jstree-dnd.jstree-default-large{line-height:32px;padding:0 4px} #jstree-dnd.jstree-default-large .jstree-ok,#jstree-dnd.jstree-default-large .jstree-er{background-image:url("../../img/jstree/32px.png");background-repeat:no-repeat;background-color:transparent} #jstree-dnd.jstree-default-large i{background:transparent;width:32px;height:32px;line-height:32px} #jstree-dnd.jstree-default-large .jstree-ok{background-position:0 -64px} #jstree-dnd.jstree-default-large .jstree-er{background-position:-32px -64px} .jstree-default-large .jstree-ellipsis{overflow:hidden} .jstree-default-large .jstree-ellipsis .jstree-anchor{width:calc(100% - 37px);text-overflow:ellipsis;overflow:hidden} .jstree-default-large.jstree-rtl .jstree-node{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAACAQMAAAAD0EyKAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjgIIGBgABCgCBvVLXcAAAAABJRU5ErkJggg==")} .jstree-default-large.jstree-rtl .jstree-last{background:transparent}@media (max-width:768px){#jstree-dnd.jstree-dnd-responsive{line-height:40px;font-weight:bold;font-size:1.1em;text-shadow:1px 1px white} #jstree-dnd.jstree-dnd-responsive>i{background:transparent;width:40px;height:40px} #jstree-dnd.jstree-dnd-responsive>.jstree-ok{background-image:url("../../img/jstree/40px.png");background-position:0 -200px;background-size:120px 240px} #jstree-dnd.jstree-dnd-responsive>.jstree-er{background-image:url("../../img/jstree/40px.png");background-position:-40px -200px;background-size:120px 240px} #jstree-marker.jstree-dnd-responsive{border-left-width:10px;border-top-width:10px;border-bottom-width:10px;margin-top:-10px}}@media (max-width:768px){.jstree-default-responsive .jstree-icon{background-image:url("../../img/jstree/40px.png")} .jstree-default-responsive .jstree-node,.jstree-default-responsive .jstree-leaf>.jstree-ocl{background:transparent} .jstree-default-responsive .jstree-node{min-height:40px;line-height:40px;margin-left:40px;min-width:40px;white-space:nowrap} .jstree-default-responsive .jstree-anchor{line-height:40px;height:40px} .jstree-default-responsive .jstree-icon,.jstree-default-responsive .jstree-icon:empty{width:40px;height:40px;line-height:40px} .jstree-default-responsive>.jstree-container-ul>.jstree-node{margin-left:0} .jstree-default-responsive.jstree-rtl .jstree-node{margin-left:0;margin-right:40px;background:transparent} .jstree-default-responsive.jstree-rtl .jstree-container-ul>.jstree-node{margin-right:0} .jstree-default-responsive .jstree-ocl,.jstree-default-responsive .jstree-themeicon,.jstree-default-responsive .jstree-checkbox{background-size:120px 240px} .jstree-default-responsive .jstree-leaf>.jstree-ocl,.jstree-default-responsive.jstree-rtl .jstree-leaf>.jstree-ocl{background:transparent} .jstree-default-responsive .jstree-open>.jstree-ocl{background-position:0 0 !important} .jstree-default-responsive .jstree-closed>.jstree-ocl{background-position:0 -40px !important} .jstree-default-responsive.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-40px 0 !important} .jstree-default-responsive .jstree-themeicon{background-position:-40px -40px} .jstree-default-responsive .jstree-checkbox,.jstree-default-responsive .jstree-checkbox:hover{background-position:-40px -80px} .jstree-default-responsive.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox,.jstree-default-responsive.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover,.jstree-default-responsive .jstree-checked>.jstree-checkbox,.jstree-default-responsive .jstree-checked>.jstree-checkbox:hover{background-position:0 -80px} .jstree-default-responsive .jstree-anchor>.jstree-undetermined,.jstree-default-responsive .jstree-anchor>.jstree-undetermined:hover{background-position:0 -120px} .jstree-default-responsive .jstree-anchor{font-weight:bold;font-size:1.1em;text-shadow:1px 1px white} .jstree-default-responsive>.jstree-striped{background:transparent} .jstree-default-responsive .jstree-wholerow{border-top:1px solid rgba(255,255,255,0.7);border-bottom:1px solid rgba(64,64,64,0.2);background:#ebebeb;height:40px} .jstree-default-responsive .jstree-wholerow-hovered{background:#e7f4f9} .jstree-default-responsive .jstree-wholerow-clicked{background:#beebff} .jstree-default-responsive .jstree-children .jstree-last>.jstree-wholerow{box-shadow:inset 0 -6px 3px -5px #666666} .jstree-default-responsive .jstree-children .jstree-open>.jstree-wholerow{box-shadow:inset 0 6px 3px -5px #666666;border-top:0} .jstree-default-responsive .jstree-children .jstree-open+.jstree-open{box-shadow:none} .jstree-default-responsive .jstree-node,.jstree-default-responsive .jstree-icon,.jstree-default-responsive .jstree-node>.jstree-ocl,.jstree-default-responsive .jstree-themeicon,.jstree-default-responsive .jstree-checkbox{background-image:url("../../img/jstree/40px.png");background-size:120px 240px} .jstree-default-responsive .jstree-node{background-position:-80px 0;background-repeat:repeat-y} .jstree-default-responsive .jstree-last{background:transparent} .jstree-default-responsive .jstree-leaf>.jstree-ocl{background-position:-40px -120px} .jstree-default-responsive .jstree-last>.jstree-ocl{background-position:-40px -160px} .jstree-default-responsive .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0} .jstree-default-responsive .jstree-file{background:url("../../img/jstree/40px.png") 0 -160px no-repeat;background-size:120px 240px} .jstree-default-responsive .jstree-folder{background:url("../../img/jstree/40px.png") -40px -40px no-repeat;background-size:120px 240px} .jstree-default-responsive>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/logging.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/logging.css new file mode 100755 index 0000000000..6b5a45744a --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/logging.css @@ -0,0 +1,385 @@ +/* + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#content #logging .loader +{ + background-position: 0 50%; + padding-left: 21px; +} + +#content #logging .block h2 +{ + background-image: url( ../../img/ico/document-text.png ); + margin-bottom: 10px; +} + +#content #logging .block h2 span span +{ + color: #c0c0c0; + font-weight: normal; + margin-left: 10px; +} + +#content #logging #viewer +{ + position: relative; +} + +#content #logging #viewer time +{ + white-space: pre; +} + +#content #logging #viewer #footer +{ + margin-top: 20px; +} + +#content #logging #viewer #state +{ + background-position: 0 50%; + float: left; + color: #4D4D4D; + width: 45%; +} + +#content #logging #viewer #date-format +{ + float: right; +} + +#content #logging #viewer #date-format a +{ + background-image: url( ../../img/ico/ui-check-box-uncheck.png ); + background-position: 0 50%; + color: #4D4D4D; + display: block; + padding-left: 21px; +} + +#content #logging #viewer #date-format a:hover +{ + color: #008; +} + +#content #logging #viewer #date-format a.on +{ + background-image: url( ../../img/ico/ui-check-box.png ); + color: #333; +} + +#content #logging #viewer #refresh-toggle { + background-position: 0 50%; + padding-left: 21px; + width:45%; +} + +#content #logging #viewer #refresh-toggle.active { + background-image: url( ../../img/ico/cross-button.png ); +} + +#content #logging #viewer #refresh-toggle.stopped { + background-image: url( ../../img/ico/arrow-circle.png ) ; +} + +#content #logging #viewer table +{ + border-collapse: collapse; + width: 100%; +} + +#content #logging #viewer th, +#content #logging #viewer td a, +#content #logging #viewer tbody .trace td +{ + padding: 3px 10px; +} + +#content #logging #viewer td +{ + vertical-align: top; +} + +#content #logging #viewer td a +{ + display: block; +} + +#content #logging #viewer thead th +{ + font-weight: bold; + text-align: left; +} + +#content #logging #viewer tbody td, +#content #logging #viewer tfoot td +{ + border-top: 1px solid #f0f0f0; +} + +#content #logging #viewer thead th.message +{ + width:100%; +} + +#content #logging #viewer tbody td.span a +{ + padding-left: 0; + padding-right: 0; +} + +#content #logging #viewer tbody span +{ + display: block; + padding-left: 10px; + padding-right: 10px; +} + +#content #logging #viewer tbody .level-info .level span { background-color: #ebf5eb; } +#content #logging #viewer tbody .level-warning span { background-color: #FFD930; } +#content #logging #viewer tbody .level-severe span { background-color: #c43c35; color: #fff; } + +#content #logging #viewer tbody .level-debug span { background-color: #ebf5eb; } +#content #logging #viewer tbody .level-warn span { background-color: #FFD930; } +#content #logging #viewer tbody .level-error span { background-color: #FF6130; } +#content #logging #viewer tbody .level-fatal span { background-color: #c43c35; } + +#content #logging #viewer tbody .has-trace a +{ + cursor: pointer; +} + +#content #logging #viewer tbody .has-trace a:hover +{ + color: #008; +} + +#content #logging #viewer tbody .has-trace .message a +{ + background-image: url( ../../img/ico/information.png ); + background-position: 100% 50%; + display: block; + padding-right: 21px; +} + +#content #logging #viewer tbody .has-trace.open .message a +{ + background-image: url( ../../img/ico/information-white.png ); +} + +#content #logging #viewer tbody .trace td +{ + border-top: 0; + color: #c0c0c0; +} + +#content #logging #viewer tfoot td +{ + color: #4D4D4D; +} + +#content #logging .jstree > li +{ + margin-left: 0; +} + +#content #logging .jstree li +{ + position: relative; +} + +#content #logging .jstree .level-finest { background-color: #d5e5fc; } +#content #logging .jstree .level-fine { background-color: #d5fafc; } +#content #logging .jstree .level-config { background-color: #e6fded; } +#content #logging .jstree .level-info { background-color: #fafcd7; } +#content #logging .jstree .level-warning { background-color: #fcecd5; } +#content #logging .jstree .level-severe { background-color: #fcdcda; } +#content #logging .jstree .level-off { background-color: #ffffff; } + +/* Log4j */ +#content #logging .jstree .level-all { background-color: #9EDAFF; } +#content #logging .jstree .level-trace { background-color: #d5e5fc; } +#content #logging .jstree .level-debug { background-color: #d5fafc; } +#content #logging .jstree .level-warn { background-color: #e6fded; } +#content #logging .jstree .level-error { background-color: #fcecd5; } +#content #logging .jstree .level-fatal { background-color: #fcdcda; } + + +#content #logging .jstree a +{ + height: 17px; + line-height: 17px; + padding: 0; + width: 90%; + vertical-align: middle; +} + +#content #logging .jstree a:hover +{ + color: #008; +} + +#content #logging .jstree a span.ns +{ + display: none; +} + +#content #logging.ns .jstree a span.ns +{ + display: inline; +} + +#content #logging .jstree a span.name +{ + background-position: 100% 50%; + cursor: pointer; + padding-right: 21px; +} + +#content #logging .jstree a span.name em +{ + color: #f00; + font-style: normal; + text-transform: uppercase; +} + +#content #logging .jstree a.trigger.set +{ + font-weight: bold; +} + +#content #logging .jstree a:hover span.name +{ + background-image: url( ../../img/ico/pencil-small.png ); +} + +#content #logging .jstree .selector-holder +{ + position: absolute; + top: -2px; + z-index: 700; +} + +#content #logging .jstree .selector-holder.open +{ + background-color: #fff; + margin-left: -19px; + z-index: 800; +} + +#content #logging .jstree li .selector-holder { left: 475px; } +#content #logging .jstree li li .selector-holder { left: 450px; } +#content #logging .jstree li li li .selector-holder { left: 425px; } +#content #logging .jstree li li li li .selector-holder { left: 400px; } +#content #logging .jstree li li li li li .selector-holder { left: 375px; } +#content #logging .jstree li li li li li li .selector-holder { left: 350px; } +#content #logging .jstree li li li li li li li .selector-holder { left: 325px; } +#content #logging .jstree li li li li li li li li .selector-holder { left: 300px; } + +#content #logging .jstree .selector +{ + border: 1px solid transparent; + position: relative; +} + +#content #logging .jstree .open .selector +{ + border-color: #f0f0f0; + box-shadow: 5px 5px 10px #c0c0c0; + -moz-box-shadow: 5px 5px 10px #c0c0c0; + -webkit-box-shadow: 5px 5px 10px #c0c0c0; +} + +#content #logging .jstree .selector a +{ + display: block; + padding: 2px; + width: auto; +} + +#content #logging .jstree .open .selector .close +{ + background-image: url( ../../img/ico/cross-0.png ); + background-position: 50% 50%; + display: block; + position: absolute; + right: -25px; + top: 0; + width: 20px; +} + +#content #logging .jstree .open .selector .close:hover +{ + background-image: url( ../../img/ico/cross-1.png ); +} + +#content #logging .jstree .open .selector .close span +{ + display: none; +} + +#content #logging .jstree .open .selector a.trigger +{ + display: none; +} + +#content #logging .jstree .open .selector ul +{ + display: block; +} + +#content #logging .jstree .selector ul li +{ + background: none; + margin-left: 0; +} + +#content #logging .jstree .selector ul li a +{ + background-image: url( ../../img/ico/ui-radio-button-uncheck.png ); + background-position: 2px 50%; + padding-left: 21px; +} + +#content #logging .jstree .selector ul li a.level +{ + background-color: #f0f0f0; +} + +#content #logging .jstree .selector ul li a:hover +{ + background-image: url( ../../img/ico/ui-radio-button.png ); +} + +#content #logging .jstree .selector li.unset +{ + border-top: 1px solid #f0f0f0; +} + +#content #logging .jstree .selector li.unset a +{ + background-image: url( ../../img/ico/cross-0.png ); + background-position: 4px 50%; +} + +#content #logging .jstree .selector li.unset a:hover +{ + background-image: url( ../../img/ico/cross-1.png ); + color: #800; +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/login.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/login.css new file mode 100755 index 0000000000..4c91385ba5 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/login.css @@ -0,0 +1,109 @@ +/* + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#content #login +{ + background-position: 0 50%; + padding-left: 21px; + vertical-align: center; + horiz-align: center; +} + +#content #login h1, +#content #login .h1 { + font-size: 2.5rem; +} + +#content #login h2, +#content #login .h2 { + font-size: 2rem; +} + +#content #login p +{ + margin-top: 0; + margin-bottom: 1rem; +} + +#content #login a +{ + color: #0000bf; + cursor: pointer; +} + +#content #login .login-error +{ + font-size: 1rem; + color: red; + margin-top: 10px; + margin-bottom: 10px; +} + +#content #login button { + border-radius: 0; +} + +#content #login button:focus { + outline: 1px dotted; + outline: 5px auto -webkit-focus-ring-color; +} + +#content #login .btn { + display: inline-block; + font-weight: 400; + text-align: center; + white-space: nowrap; + vertical-align: middle; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + border: 1px solid transparent; + padding: 0.375rem 0.75rem; + font-size: 1rem; + line-height: 1.5; + border-radius: 0.25rem; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +#content #login .form-inline .form-group { + display: -ms-flexbox; + display: flex; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + -ms-flex-flow: row wrap; + flex-flow: row wrap; + -ms-flex-align: center; + align-items: center; + margin-bottom: 0; +} + +#content #login .form-control { + display: block; + width: 80%; + padding: 0.375rem 0.75rem; + font-size: 1rem; + line-height: 1.5; + color: #495057; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #ced4da; + border-radius: 0.25rem; + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/menu.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/menu.css new file mode 100755 index 0000000000..b180eaa02a --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/menu.css @@ -0,0 +1,336 @@ +/* + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#menu-wrapper +{ + position: fixed; + top: 120px; + width: 150px; +} + +.scroll #menu-wrapper +{ + position: absolute; + top: 90px; +} + +.has-environment #menu-wrapper +{ + top: 160px; +} + +#menu-wrapper a +{ + display: block; + padding: 4px 2px; + overflow: hidden; + text-overflow: ellipsis; +} + +#core-selector,#collection-selector +{ + margin-top: 20px; + padding-right: 10px; +} + +#core-selector .chosen-container, +#collection-selector .chosen-container +{ + width: 100% !important; +} + +#core-selector a, +#collection-selector a +{ + padding: 0; + padding-left: 8px; +} + +#core-selector select, +#collection-selector select +{ + width: 100%; +} + +#core-selector #has-no-cores a, +#collection-selector #has-no-collections a +{ + background-image: url( ../../img/ico/database--plus.png ); +} + +#core-selector #has-no-cores span, +#collection-selector #has-no-collections span +{ + color: #8D8D8D; + display: block; +} + +#menu-wrapper .active p +{ + background-color: #fafafa; + border-color: #c0c0c0; +} + +#menu-wrapper p a, +#menu a +{ + background-position: 5px 50%; + padding-left: 26px; + padding-top: 5px; + padding-bottom: 5px; +} + +#menu-wrapper p a:hover +{ + background-color: #f0f0f0; +} + +#menu-wrapper .active p a +{ + background-color: #c0c0c0; + font-weight: bold; +} + +#menu p.loader +{ + background-position: 5px 50%; + color: #c0c0c0; + margin-top: 5px; + padding-left: 26px; +} + +#menu p a small +{ + color: #b5b5b5; + font-weight: normal; +} + +#menu p a small span.txt +{ +} + +#menu p a small:hover span.txt +{ + display: inline; +} + +#menu .busy +{ + border-right-color: #f6f5d9; +} + +#menu .busy p a +{ + background-color: #f6f5d9; + background-image: url( ../../img/ico/status-away.png ); +} + +#menu .offline +{ + border-right-color: #eccfcf; +} + +#menu .offline p a +{ + background-color: #eccfcf; + background-image: url( ../../img/ico/status-busy.png ); +} + +#menu .online +{ + border-right-color: #cfecd3; +} + +#menu .online p a +{ + background-color: #cfecd3; + background-image: url( ../../img/ico/status.png ); +} + +#menu .ping small +{ + color: #000 +} + +#menu li +{ + border-bottom: 1px solid #f0f0f0; +} + +#menu li:last-child +{ + border-bottom: 0; +} + +#menu li.optional +{ +} + +.sub-menu p +{ + border-top: 1px solid #f0f0f0; +} + +.sub-menu li:first-child p +{ + border-top: 0; +} + +.sub-menu p a +{ + background-image: url( ../../img/ico/status-offline.png ); +} + +.sub-menu .active p a +{ + background-image: url( ../../img/ico/box.png ); +} + +.sub-menu ul, +#menu ul +{ + padding-top: 5px; + padding-bottom: 10px; +} + +.sub-menu .active ul, +#menu .active ul +{ + display: block; +} + +#menu ul li +{ + border-bottom: 0; +} + +#core-menu ul li a, +#collection-menu ul li a, +#menu ul li a +{ + background-position: 7px 50%; + border-bottom: 1px solid #f0f0f0; + margin-left: 15px; + padding-left: 26px; +} + +.sub-menu ul li:last-child a, +#menu ul li:last-child a +{ + border-bottom: 0; +} + +.sub-menu ul li a:hover, +#menu ul li a:hover +{ + background-color: #f0f0f0; + color: #333; +} + +.sub-menu ul li.active a, +#menu ul li.active a +{ + background-color: #d0d0d0; + border-color: #d0d0d0; + color: #FFF; +} + +#menu #index.global p a { background-image: url( ../../img/ico/dashboard.png ); } + +#menu #login.global p a { background-image: url( ../../img/ico/users.png ); } + +#menu #logging.global p a { background-image: url( ../../img/ico/inbox-document-text.png ); } +#menu #logging.global .level a { background-image: url( ../../img/ico/gear.png ); } + +#menu #java-properties.global p a { background-image: url( ../../img/ico/jar.png ); } + +#menu #threads.global p a { background-image: url( ../../img/ico/ui-accordion.png ); } + +#menu #collections.global p a { background-image: url( ../../img/ico/documents-stack.png ); } +#menu #cores.global p a { background-image: url( ../../img/ico/databases.png ); } +#menu #cluster-suggestions.global p a { background-image: url( ../../img/ico/idea.png ); } + +#menu #cloud.global p a { background-image: url( ../../img/ico/network-cloud.png ); } +#menu #cloud.global .tree a { background-image: url( ../../img/ico/folder-tree.png ); } +#menu #cloud.global .nodes a { background-image: url( ../../img/solr-ico.png ); } +#menu #cloud.global .zkstatus a { background-image: url( ../../img/ico/node-master.png ); } +#menu #cloud.global .graph a { background-image: url( ../../img/ico/molecule.png ); } + +.sub-menu .ping.error a +{ + + background-color: #ffcccc; + background-image: url( ../../img/ico/system-monitor--exclamation.png ); + border-color: #ffcccc; + cursor: help; +} + +.sub-menu .overview a { background-image: url( ../../img/ico/home.png ); } +.sub-menu .query a { background-image: url( ../../img/ico/magnifier.png ); } +.sub-menu .stream a { background-image: url( ../../img/ico/node.png ); } +.sub-menu .analysis a { background-image: url( ../../img/ico/funnel.png ); } +.sub-menu .documents a { background-image: url( ../../img/ico/documents-stack.png ); } +.sub-menu .files a { background-image: url( ../../img/ico/folder.png ); } +.sub-menu .schema a { background-image: url( ../../img/ico/book-open-text.png ); } +.sub-menu .replication a { background-image: url( ../../img/ico/node.png ); } +.sub-menu .distribution a { background-image: url( ../../img/ico/node-select.png ); } +.sub-menu .ping a { background-image: url( ../../img/ico/system-monitor.png ); } +.sub-menu .logging a { background-image: url( ../../img/ico/inbox-document-text.png ); } +.sub-menu .plugins a { background-image: url( ../../img/ico/block.png ); } +.sub-menu .dataimport a { background-image: url( ../../img/ico/document-import.png ); } +.sub-menu .segments a { background-image: url( ../../img/ico/construction.png ); } + + +#content #navigation +{ + border-right: 1px solid #e0e0e0; +} + +#content #navigation a +{ + display: block; + padding: 4px 2px; +} + +#content #navigation .current +{ + border-color: #e0e0e0; +} + +#content #navigation a +{ + background-position: 5px 50%; + padding-left: 26px; + padding-top: 5px; + padding-bottom: 5px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +#content #navigation a:hover +{ + background-color: #f0f0f0; +} + +#content #navigation .current a +{ + background-color: #e0e0e0; + font-weight: bold; +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/overview.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/overview.css new file mode 100755 index 0000000000..8ee787506b --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/overview.css @@ -0,0 +1,42 @@ +/* + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#content #dashboard .collprops +{ + float: left; +} + +#content #dashboard .collprops dt, +#content #dashboard .collprops dd +{ + display: block; + float: left; +} + +#content #dashboard .collprops dt +{ + clear: left; + margin-right: 2%; + width: 48%; +} + +#content #dashboard .collprops dd +{ + width: 50%; +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/plugins.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/plugins.css new file mode 100755 index 0000000000..e19d2398c8 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/plugins.css @@ -0,0 +1,220 @@ +/* + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#content #plugins #navigation +{ + width: 20%; +} + +#content #plugins #navigation .cache a { background-image: url( ../../img/ico/disk-black.png ); } +#content #plugins #navigation .core a { background-image: url( ../../img/ico/wooden-box.png ); } +#content #plugins #navigation .other a { background-image: url( ../../img/ico/zone.png ); } +#content #plugins #navigation .highlighting a { background-image: url( ../../img/ico/highlighter-text.png ); } +#content #plugins #navigation .updatehandler a{ background-image: url( ../../img/ico/arrow-circle.png ); } +#content #plugins #navigation .queryhandler a { background-image: url( ../../img/ico/magnifier.png ); } +#content #plugins #navigation .queryparser a { background-image: url( ../../img/ico/asterisk.png ); } + +#content #plugins #navigation .PLUGINCHANGES { margin-top: 20px; } +#content #plugins #navigation .PLUGINCHANGES a { background-image: url( ../../img/ico/eye.png ); } +#content #plugins #navigation .RELOAD a { background-image: url( ../../img/ico/arrow-circle.png ); } +#content #plugins #navigation .NOTE { margin-top: 20px; } +#content #plugins #navigation .NOTE p { color: #4D4D4D; font-style: italic; } + + +#content #plugins #navigation a +{ + position: relative; +} + +#content #plugins #navigation a span +{ + background-color: #bba500; + border-radius: 5px; + color: #fff; + font-size: 10px; + font-weight: normal; + line-height: 1.4em; + padding-left: 4px; + padding-right: 4px; + position: absolute; + right: 5px; + top: 7px; +} + +#content #plugins #frame +{ + float: right; + width: 78%; +} + +#content #plugins #frame .entry +{ + margin-bottom: 10px; +} + +#content #plugins #frame .entry:last-child +{ + margin-bottom: 0; +} + +#content #plugins #frame .entry a +{ + background-image: url( ../../img/ico/chevron-small-expand.png ); + background-position: 0 50%; + display: block; + font-weight: bold; + padding-left: 21px; +} + +#content #plugins #frame .entry.changed a span +{ + color: #bba500; +} + +#content #plugins #frame .entry.expanded a +{ + background-image: url( ../../img/ico/chevron-small.png ); +} + +#content #plugins #frame .entry.expanded ul +{ + display: block; +} + +#content #plugins #frame .entry ul +{ + border-left: 9px solid #f0f3ff; + margin-left: 3px; + padding-top: 5px; + padding-left: 10px; +} + +#content #plugins #frame .entry li +{ + padding-top: 2px; + padding-bottom: 2px; +} + +#content #plugins #frame .entry li.stats +{ + border-top: 1px solid #c0c0c0; + margin-top: 5px; + padding-top: 5px; +} + +#content #plugins #frame .entry li.odd +{ + background-color: #f8f8f8; +} + +#content #plugins #frame .entry dt, +#content #plugins #frame .entry .stats span +{ + float: left; + width: 9%; +} + +#content #plugins #frame .entry dd, +#content #plugins #frame .entry .stats ul +{ + float: right; + width: 90%; +} + +#content #plugins #frame .entry .stats ul +{ + border-left: 0; + margin: 0; + padding: 0; +} + +#content #plugins #frame .entry .stats dt +{ + width: 40%; +} + +#content #plugins #frame .entry .stats dd +{ + width: 59%; +} + +#content #plugins #frame .entry.expanded a.linker { + background-image: none; + background-position: 0 0; + display: inline; + font-weight: normal; + padding:0px; +} + +#content #plugins #frame .entry.expanded a.linker:hover { + background-color:#F0F3FF; +} + +#content #plugins .active a +{ + background-color: #d0d0d0; + border-color: #d0d0d0; +} + +#recording #blockUI +{ + position: absolute; + left:0; + top:0; + width: 100%; + height: 100%; + background-color: #000; + opacity: 0.6; + z-index:1000; + padding:0; +} + +#recording .wrapper +{ + position: absolute; + top: 50%; + left: 50%; + padding: 30px; + width: 415px; + height: 100px; + border: 2px solid black; + background-color: #FFF; + opacity: 1; + z-index: 2000; + transform: translate(-50%, -50%); +} + +#recording p +{ + background-position: 0 50%; + float: left; + padding-left: 21px; + padding-top: 7px; + padding-bottom: 7px; +} + +#recording button +{ + float: right; +} + +#recording button span +{ + background-image: url( ../../img/ico/new-text.png ); +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/query.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/query.css new file mode 100755 index 0000000000..2f1e81b2ea --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/query.css @@ -0,0 +1,162 @@ +/* + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#content #query +{ + background-image: url( ../../img/div.gif ); + background-position: 22% 0; + background-repeat: repeat-y; +} + +#content #query #form +{ + float: left; + width: 21%; +} + +#content #query #form label +{ + cursor: pointer; + display: block; + margin-top: 5px; +} + +#content #query #form input, +#content #query #form select, +#content #query #form textarea +{ + margin-bottom: 2px; + width: 100%; +} + +#content #query #form input, +#content #query #form textarea +{ + width: 98%; +} + +#content #query #form .multiple input +{ + float: left; + width: 80% +} + +#content #query #form .multiple .buttons +{ + float: right; + width: 16%; +} + + +#content #query #form .multiple a +{ + background-position: 50% 50%; + display: block; + height: 25px; + width: 49%; +} + +#content #query #form .multiple a.add +{ + background-image: url( ../../img/ico/plus-button.png ); + float: right; +} + +#content #query #form .multiple a.rem +{ + background-image: url( ../../img/ico/minus-button.png ); + float: left; +} + +#content #query #form #start +{ + float: left; + width: 45%; +} + +#content #query #form #rows +{ + float: right; + width: 45%; +} + +#content #query #form .checkbox input +{ + margin-bottom: 0; + width: auto; +} + +#content #query #form fieldset, +#content #query #form .optional.expanded +{ + border: 1px solid #fff; + border-top: 1px solid #c0c0c0; + margin-bottom: 5px; +} + +#content #query #form fieldset.common +{ + margin-top: 10px; +} + +#content #query #form fieldset legend, +#content #query #form .optional.expanded legend +{ + display: block; + margin-left: 10px; + padding: 0px 5px; +} + +#content #query #form fieldset legend label +{ + margin-top: 0; +} + +#content #query #form fieldset .fieldset +{ + border-bottom: 1px solid #f0f0f0; + margin-bottom: 5px; + padding-bottom: 10px; +} + +#content #query #form .optional +{ + border: 0; +} + +#content #query #form .optional legend +{ + margin-left: 0; + padding-left: 0; +} + +#content #query #form .optional.expanded .fieldset +{ + display: block; +} + +#content #query #result +{ + float: right; + width: 77%; +} + +#content #query #result #response +{ +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/replication.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/replication.css new file mode 100755 index 0000000000..6cef74e00c --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/replication.css @@ -0,0 +1,500 @@ +/* + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#content #replication +{ + background-image: url( ../../img/div.gif ); + background-position: 21% 0; + background-repeat: repeat-y; +} + +#content #replication #frame +{ + float: right; + width: 78%; +} + +#content #replication #navigation +{ + border-right: 0; + float: left; + width: 20%; +} + +#content #replication #error +{ + background-color: #f00; + background-image: url( ../../img/ico/construction.png ); + background-position: 10px 50%; + color: #fff; + font-weight: bold; + margin-bottom: 20px; + padding: 10px; + padding-left: 35px; +} + +#content #replication .block +{ + border-bottom: 1px solid #c0c0c0; + margin-bottom: 20px; + padding-bottom: 20px; +} + +#content #replication .block.last +{ + border-bottom: 0; +} + +#content #replication .masterOnly, +#content #replication .slaveOnly +{ +} + +#content #replication.master .masterOnly +{ + display: block; +} + +#content #replication.slave .slaveOnly +{ + display: block; +} + +#content #replication .replicating +{ +} + +#content #replication.replicating .replicating +{ + display: block; +} + +#content #replication #progress +{ + padding-bottom: 80px; + position: relative; +} + +#content #replication #progress .info +{ + padding: 5px; +} + +#content #replication #progress #start +{ + margin-left: 100px; + border-left: 1px solid #c0c0c0; +} + +#content #replication #progress #bar +{ + background-color: #f0f0f0; + margin-left: 100px; + margin-right: 100px; + position: relative; +} + +#content #replication #progress #bar #bar-info, +#content #replication #progress #bar #eta +{ + position: absolute; + right: -100px; + width: 100px; +} + +#content #replication #progress #bar #bar-info +{ + border-left: 1px solid #f0f0f0; + margin-top: 30px; +} + +#content #replication #progress #eta .info +{ + color: #4D4D4D; + height: 30px; + line-height: 30px; + padding-top: 0; + padding-bottom: 0; +} + +#content #replication #progress #speed +{ + color: #4D4D4D; + position: absolute; + right: 100px; + top: 0; +} + +#content #replication #progress #bar #done +{ + background-color: #4D4D4D; + box-shadow: 5px 5px 10px #c0c0c0; + -moz-box-shadow: 5px 5px 10px #c0c0c0; + -webkit-box-shadow: 5px 5px 10px #c0c0c0; + height: 30px; + position: relative; +} + +#content #replication #progress #bar #done .percent +{ + font-weight: bold; + height: 30px; + line-height: 30px; + padding-left: 5px; + padding-right: 5px; + position: absolute; + right: 0; + text-align: right; +} + +#content #replication #progress #bar #done #done-info +{ + border-right: 1px solid #c0c0c0; + position: absolute; + right: 0; + margin-top: 30px; + text-align: right; + width: 100px; +} + +#content #replication #progress #bar #done #done-info .percent +{ + font-weight: bold; +} + +#content #replication .block .label, +#content #replication #current-file .file, +#content #replication #current-file .progress, +#content #replication #iterations .iterations +{ + float: left; +} + +#content #replication .block .label +{ + width: 100px; +} + +#content #replication .block .label span +{ + display: block; + padding-left: 21px; +} + +#content #replication #current-file +{ + border-top: 1px solid #f0f0f0; + margin-top: 10px; + padding-top: 10px; +} + +#content #replication #current-file .progress +{ + color: #4D4D4D; + margin-left: 20px; +} + +#content #replication #iterations .label span +{ + background-image: url( ../../img/ico/node-design.png ); +} + +#content #replication #iterations .iterations li +{ + background-position: 100% 50%; + padding-right: 21px; +} + +#content #replication #iterations .iterations.expanded li +{ + display: block; +} + +#content #replication #iterations .iterations .latest +{ + display: block; +} + +#content #replication #iterations .iterations .replicated +{ + color: #80c480; +} + +#content #replication #iterations .iterations ul:hover .replicated, +#content #replication #iterations .iterations .replicated.latest +{ + color: #080; +} + +#content #replication #iterations .iterations .replicated.latest +{ + background-image: url( ../../img/ico/tick.png ); +} + +#content #replication #iterations .iterations .failed +{ + color: #c48080; +} + +#content #replication #iterations .iterations ul:hover .failed, +#content #replication #iterations .iterations .failed.latest +{ + color: #800; +} + +#content #replication #iterations .iterations .failed.latest +{ + background-image: url( ../../img/ico/cross.png ); +} + +#content #replication #iterations .iterations a +{ + border-top: 1px solid #f0f0f0; + margin-top: 2px; + padding-top: 2px; +} + +#content #replication #iterations .iterations a span +{ + background-position: 0 50%; + color: #4D4D4D; + padding-left: 21px; +} + +#content #replication #iterations .iterations a span.expand +{ + background-image: url( ../../img/ico/chevron-small-expand.png ); + display: block; +} + +#content #replication #iterations .iterations a span.collapse +{ + background-image: url( ../../img/ico/chevron-small.png ); + display: block; +} + +#content #replication #details table +{ + margin-left: 20px; + border-collapse: collapse; +} + +#content #replication #details table th +{ + text-align: left; +} + +#content #replication.slave #details table .slaveOnly +{ + display: table-row; +} + +#content #replication #details table thead th +{ + color: #4D4D4D; +} + +#content #replication #details table thead th, +#content #replication #details table tbody td +{ + padding-right: 20px; +} + +#content #replication #details table thead td, +#content #replication #details table thead th, +#content #replication #details table tbody th, +#content #replication #details table tbody td div +{ + padding-top: 3px; + padding-bottom: 3px; +} + +#content #replication #details table tbody td, +#content #replication #details table tbody th +{ + border-top: 1px solid #f0f0f0; +} + +#content #replication #details table thead td +{ + width: 100px; +} + +#content #replication #details table thead td span +{ + background-image: url( ../../img/ico/clipboard-list.png ); + background-position: 0 50%; + display: block; + padding-left: 21px; +} + +#content #replication #details table tbody th +{ + padding-right: 10px; + text-align: right; + white-space: nowrap; +} + +#content #replication #details table tbody .size +{ + text-align: right; + white-space: nowrap; +} + +#content #replication #details table tbody .generation div +{ + text-align: center; +} + +#content #replication #details table tbody .diff div +{ + background-color: #fcfcc9; + padding-left: 1px; + padding-right: 1px; +} + +#content #replication .settings .label span +{ + background-image: url( ../../img/ico/hammer-screwdriver.png ); +} + +#content #replication .settings ul, +#content #replication .settings dl dt, +#content #replication .settings dl dd +{ + float: left; +} + +#content #replication .settings ul li +{ + border-top: 1px solid #f0f0f0; + padding-top: 3px; + padding-top: 3px; +} + +#content #replication .settings ul li:first-child +{ + border-top: 0; + padding-top: 0; +} + +#content #replication .settings dl dt +{ + clear: left; + margin-right: 5px; + width: 120px; +} + +#content #replication .settings dl .ico +{ + background-position: 0 50%; + padding-left: 21px; +} + +#content #replication .settings dl .ico.ico-0 +{ + background-image: url( ../../img/ico/slash.png ); +} + +#content #replication .settings dl .ico.ico-1 +{ + background-image: url( ../../img/ico/tick.png ); +} + +#content #replication .timer +{ + box-shadow: 5px 5px 10px #c0c0c0; + -moz-box-shadow: 5px 5px 10px #c0c0c0; + -webkit-box-shadow: 5px 5px 10px #c0c0c0; + margin-bottom: 20px; + padding: 10px; +} + +#content #replication .timer p, +#content #replication .timer small +{ + padding-left: 21px; +} + +#content #replication .timer p +{ + background-image: url( ../../img/ico/clock-select-remain.png ); + background-position: 0 50%; +} + +#content #replication .timer p .approx +{ + color: #4D4D4D; + margin-right: 1px; +} + +#content #replication .timer p .tick +{ + font-weight: bold; +} + +#content #replication .timer small +{ + color: #4D4D4D; +} + +#content #replication #navigation button +{ + display: block; + margin-bottom: 10px; +} + +#content #replication #navigation button.optional +{ +} + +#content #replication #navigation .replicate-now span +{ + background-image: url( ../../img/ico/document-convert.png ); +} + +#content #replication #navigation .abort-replication span +{ + background-image: url( ../../img/ico/hand.png ); +} + +#content #replication #navigation .disable-polling span +{ + background-image: url( ../../img/ico/cross.png ); +} + +#content #replication #navigation .enable-polling span +{ + background-image: url( ../../img/ico/tick.png ); +} + +#content #replication #navigation .disable-replication span +{ + background-image: url( ../../img/ico/cross.png ); +} + +#content #replication #navigation .enable-replication span +{ + background-image: url( ../../img/ico/tick.png ); +} + +#content #replication #navigation .refresh-status span +{ + background-image: url( ../../img/ico/arrow-circle.png ); +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/schema.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/schema.css new file mode 100755 index 0000000000..3be6a629ec --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/schema.css @@ -0,0 +1,732 @@ +/* + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#content #schema .loader +{ + background-position: 0 50%; + padding-left: 21px; +} + +#content #schema.loaded +{ + background-image: url( ../../img/div.gif ); + background-position: 21% 0; + background-repeat: repeat-y; +} + +#content #schema #data +{ + float: right; + width: 78%; +} + +#content #schema #related +{ + float: left; + width: 20%; +} + +#content #schema #related select +{ + width: 100%; +} + +#content #schema #related select optgroup +{ + font-style: normal; + padding: 5px; +} + +#content #schema #related select option +{ + padding-left: 10px; +} + +#content #schema #related #f-df-t +{ + border-bottom: 1px solid #f0f0f0; + padding-bottom: 15px; +} + +#content #schema #related .ukf-dsf dt +{ +} + +#content #schema #related dl +{ + margin-top: 15px; +} + +#content #schema #related dl dt, +#content #schema #related dl dd a +{ + color: #4D4D4D; +} + +#content #schema #related dl dt +{ + font-weight: bold; + margin-top: 5px; +} + +#content #schema #related dl dd a +{ + display: block; + padding-left: 10px; +} + +#content #schema #related dl dd a:hover +{ + background-color: #f8f8f8; +} + +#content #schema #related .field .field, +#content #schema #related .field .field a, +#content #schema #related .dynamic-field .dynamic-field, +#content #schema #related .dynamic-field .dynamic-field a, +#content #schema #related .type .type, +#content #schema #related .type .type a, +#content #schema #related .active, +#content #schema #related .active a +{ + color: #333; +} + +#content #schema #related .copyfield, +#content #schema #related .copyfield a +{ + color: #666; +} + +#content #schema #data +{ +} + +#content #schema #data #index dt +{ + float: left; + margin-right: 5px; + width: 150px; +} + +#content #schema #data #field .field-options +{ + margin-bottom: 10px; +} + +#content #schema #data #field .field-options .head h2 +{ + padding-left: 5px; +} + +#content #schema #data #field .partial +{ +} + +#content #schema #data #field .partial p +{ + background-image: url( ../../img/ico/exclamation-button.png ); + background-position: 0 50%; + padding-left: 21px; +} + +#content #schema #data #field .field-options .options dt, +#content #schema #data #field .field-options .options dd +{ + float: left; +} + +#content #schema #data #field .field-options .options dt +{ + clear: left; + margin-right: 5px; + width: 100px; +} + +#content #schema #data #field .field-options .flags +{ + margin-top: 10px; + margin-bottom: 20px; +} + +#content #schema #data #field .field-options .flags thead td +{ + color: #4D4D4D; + padding-right: 5px; + width: 100px; +} + +#content #schema #data #field .field-options .flags tbody td, +#content #schema #data #field .field-options .flags th +{ + padding: 2px 5px; +} + +#content #schema #data #field .field-options .flags thead td, +#content #schema #data #field .field-options .flags tbody th +{ + padding-left: 0; +} + +#content #schema #data #field .field-options .flags thead th, +#content #schema #data #field .field-options .flags tbody td +{ + border-left: 1px solid #f0f0f0; +} + +#content #schema #data #field .field-options .flags tbody th, +#content #schema #data #field .field-options .flags tbody td +{ + border-top: 1px solid #f0f0f0; +} + +#content #schema #data #field .field-options .flags tbody .check +{ + background-color: #fafdfa; + background-image: url( ../../img/ico/tick.png ); + background-position: 50% 50%; + text-align: center; +} + +#content #schema #data #field .field-options .flags tbody .check span +{ +} + +#content #schema #data #field .field-options .flags tbody .text +{ + color: #4D4D4D; +} + +#content #schema #data #field .field-options .analyzer, +#content #schema #data #field .field-options .analyzer li, +#content #schema #data #field .field-options .analyzer ul, +#content #schema #data #field .field-options .analyzer ul li +{ +} + +#content #schema #data #field .field-options .analyzer p, +#content #schema #data #field .field-options .analyzer dl +{ + float: left; +} + +#content #schema #data #field .field-options .analyzer p +{ + margin-right: 5px; + text-align: right; + width: 125px; + white-space: pre; +} + +#content #schema #data #field .field-options .analyzer p a +{ + cursor: auto; +} + +#content #schema #data #field .field-options .analyzer p a.analysis +{ + cursor: pointer; + display: block; +} + +#content #schema #data #field .field-options .analyzer p a.analysis span +{ + background-image: url( ../../img/ico/question-white.png ); + background-position: 0 50%; + padding-left: 21px; +} + +#content #schema #data #field .field-options .analyzer p a.analysis:hover span +{ + background-image: url( ../../img/ico/question.png ); + color: #008; +} + +#content #schema #data #field .field-options .analyzer a +{ + cursor: auto; +} + +#content #schema #data #field .field-options .analyzer .toggle +{ + background-image: url( ../../img/ico/chevron-small-expand.png ); + background-position: 100% 50%; + cursor: pointer; + display: block; + padding-right: 21px; +} + +#content #schema #data #field .field-options .analyzer .open .toggle +{ + background-image: url( ../../img/ico/chevron-small.png ); +} + +#content #schema #data #field .field-options .analyzer li +{ + border-top: 1px solid #f0f0f0; + margin-top: 10px; + padding-top: 10px; +} + +#content #schema #data #field .field-options .analyzer ul +{ + clear: left; + margin-left: 55px; + padding-top: 5px; +} + +#content #schema #data #field .field-options .analyzer .open ul +{ + display: block; +} + +#content #schema #data #field .field-options .analyzer ul li +{ + border-top: 1px solid #f8f8f8; + margin-top: 5px; + padding-top: 5px; +} + +#content #schema #data #field .field-options .analyzer ul p +{ + color: #4D4D4D; + margin-right: 5px; + text-align: right; + width: 70px; +} + +#content #schema #data #field .field-options .analyzer ul dd +{ + margin-left: 20px; +} + +#content #schema #data #field .field-options .analyzer ul dd +{ + background-image: url( ../../img/ico/document-list.png ); + background-position: 0 50%; + color: #4D4D4D; + padding-left: 21px; +} + +#content #schema #data #field .field-options .analyzer ul dd.ico-0 +{ + background-image: url( ../../img/ico/slash.png ); +} + +#content #schema #data #field .field-options .analyzer ul dd.ico-1 +{ + background-image: url( ../../img/ico/tick.png ); +} + +#content #schema #data #field .head +{ + margin-bottom: 5px; +} + +#content #schema #data #field .terminfo-holder +{ + border-top: 1px solid #c0c0c0; + padding-top: 10px; +} + +#content #schema #data #field .terminfo-holder .trigger +{ + float: left; + width: 140px; +} + +#content #schema #data #field .terminfo-holder .trigger button span +{ + background-image: url( ../../img/ico/information.png ); +} + +#content #schema #data #field .terminfo-holder .status +{ + border-left: 1px solid #f0f0f0; + float: left; + padding-left: 20px; + padding-right: 20px; +} + +#content #schema #data #field .terminfo-holder.disabled .trigger button span +{ + background-image: url( ../../img/ico/prohibition.png ); +} + +#content #schema #data #field .terminfo-holder.disabled .status +{ + display: block; +} + +#content #schema #data #field .terminfo-holder .trigger .autoload +{ +} + +#content #schema #data #field .terminfo-holder.loaded .trigger .autoload +{ + background-image: url( ../../img/ico/ui-check-box-uncheck.png ); + background-position: 0 50%; + color: #8D8D8D; + display: block; + margin-top: 10px; + padding-left: 21px; +} + +#content #schema #data #field .terminfo-holder .trigger .autoload:hover +{ + color: #008; +} + +#content #schema #data #field .terminfo-holder .trigger .autoload.on +{ + background-image: url( ../../img/ico/ui-check-box.png ); + color: #333; +} + +#content #schema #data #field .topterms-holder, +#content #schema #data #field .histogram-holder +{ + border-left: 1px solid #f0f0f0; + float: left; + padding-left: 20px; + padding-right: 20px; +} + +#content #schema #data #field .topterms-holder .head input +{ + height: 18px; + line-height: 16px; + text-align: right; + width: 30px; +} + +#content #schema #data #field .topterms-holder .head .max-holder +{ + color: #4D4D4D; +} + +#content #schema #data #field .topterms-holder .head .max-holder:hover .max +{ + color: #008; +} + +#content #schema #data #field .topterms-holder .head #query_link +{ + background-image: url( ../../img/ico/question-white.png ); + background-position: 0 50%; + color: #4D4D4D; + padding-left: 21px; + margin-left: 5px; +} + +#content #schema #data #field .topterms-holder .head #query_link:hover +{ + background-image: url( ../../img/ico/question.png ); +} + + +#content #schema #data #field .topterms-holder .head #query_link span +{ + visibility: hidden; +} + +#content #schema #data #field .topterms-holder .head #query_link:hover span +{ + visibility: visible; +} + +#content #schema .topterms-holder li +{ + border-top: 1px solid #999; + margin-bottom: 5px; +} + +/* possible overwrite with inline style */ +#content #schema .topterms-holder li p +{ + background-color: #999; + color: #fff; + float: left; +} + +#content #schema .topterms-holder li p span +{ + display: block; + padding-right: 2px; + text-align: right; +} + +/* possible overwrite with inline style */ +#content #schema .topterms-holder li ul +{ + margin-left: 30px; +} + +#content #schema .topterms-holder li li +{ + border-top: 0; + margin-bottom: 0; + white-space: nowrap; +} + +#content #schema .topterms-holder li li.odd +{ + background-color: #f0f0f0; +} + +#content #schema .topterms-holder li li a +{ + display: block; + padding-left: 2px; + padding-right: 2px; +} + +#content #schema .topterms-holder li li a:hover +{ + background-color: #c0c0c0; +} + +#content #schema #data #field .histogram-holder ul +{ + margin-left: 25px; +} + +#content #schema #data #field .histogram-holder li +{ + margin-bottom: 2px; + position: relative; + width: 150px; +} + +#content #schema #data #field .histogram-holder li.odd +{ + background-color: #f0f0f0; +} + +#content #schema #data #field .histogram-holder li dl, +#content #schema #data #field .histogram-holder li dt +{ + padding-top: 1px; + padding-bottom: 1px; +} + +#content #schema #data #field .histogram-holder li dl +{ + background-color: #c0c0c0; + min-width: 1px; +} + +#content #schema #data #field .histogram-holder li dt +{ + color: #a0a0a0; + position: absolute; + overflow: hidden; + left: -25px; + top: 0px; +} + +#content #schema #data #field .histogram-holder li dt span +{ + display: block; + padding-right: 4px; + text-align: right; +} + +#content #schema #data #field .histogram-holder li dd +{ + clear: left; + float: left; + margin-left: 2px; + white-space: nowrap; +} + +#content #schema #data #field .histogram-holder li:hover dl +{ + background-color: #b0b0b0; +} + +#content #schema #data #field .histogram-holder li:hover dt +{ + color: #333; +} + +#content #schema #actions { + margin-bottom: 20px; + min-height: 30px; +} + +#content #schema .actions #addField span { background-image: url( ../../img/ico/document-list.png ); } +#content #schema .actions #addDynamicField span { background-image: url( ../../img/ico/documents-stack.png ); } +#content #schema .actions #addCopyField span { background-image: url( ../../img/ico/document-import.png ); } + +#content #schema .actions div.action +{ + width: 320px; + background-color: #fff; + border: 1px solid #f0f0f0; + box-shadow: 5px 5px 10px #c0c0c0; + -moz-box-shadow: 5px 5px 10px #c0c0c0; + -webkit-box-shadow: 5px 5px 10px #c0c0c0; + position: absolute; + left: 160px; + top: 50px; + padding: 10px; + z-index: 2; +} + +#content #schema .actions p +{ + padding-bottom: 8px; +} + +#content #schema .actions label +{ + float: left; + padding-top: 3px; + padding-bottom: 3px; + text-align: right; + width: 25%; +} + +#content #schema .actions input, +#content #schema .actions select, +#content #schema .actions .buttons, +#content #schema .actions .note span +{ + float: right; + width: 71%; +} + +#content #schema .actions .chosen-container +{ + width: 71% !important; +} + +#content #schema .actions label.checkbox { + margin-left: 27%; + text-align: left; + width: 73%; + padding: 0px; + margin-top: 0px; +} +#content #schema .actions .checkbox input { + float: none; + width: auto; +} + +#content #schema .add_showhide { + background-image: url( ../../img/ico/chevron-small-expand.png ); + background-position: 100% 50%; + cursor: pointer; + padding-right: 21px; +} + +#content #schema .add_showhide.open { + background-image: url( ../../img/ico/chevron-small.png ); +} + +#content #schema label +{ + cursor: pointer; + display: block; + margin-top: 5px; + width: 100%; +} + +#content #schema .checkbox +{ + margin-bottom: 0; + width: auto; +} + +#content #schema .chosen-container { + margin-left: 6px; + width: 100%; +} +#content #schema .chosen-drop input, +#content #schema .chosen-results { + width: 100% !important; +} + +#content #schema button span +{ + background-image: url( ../../img/ico/cross.png ); +} +#content #schema button.submit span +{ + background-image: url( ../../img/ico/tick.png ); +} + +#content #schema .error +{ + background-image: url( ../../img/ico/cross-button.png ); + background-position: 22% 1px; + color: #c00; + font-weight: bold; + margin-bottom: 10px; +} + +#content #schema #actions .error span +{ + float: right; + width: 71%; + padding-left: 3px; + padding-right: 3px; +} + +#content #schema .delete-field button span { + background-image: url( ../../img/ico/cross.png ); +} + +#content #schema span.rem { + background-image: url( ../../img/ico/cross.png ); + background-position: 100% 50%; + cursor: pointer; + padding-right: 21px; + right:10px; + float:right; +} + +#content #schema .copyfield .updatable a { + float:left; + width:80%; +} + +#content #schema dd.similarity.ng-binding::after { + content: attr(data-tip) ; + + font-size: 12px; + position: relative; + white-space: nowrap; + bottom: 9999px; + left: 0; + background: lightyellow; + color: black; + padding: 4px 7px; + line-height: 24px; + height: 24px; + border: 1px solid darkgray; + opacity: 0; + transition:opacity 0.4s ease-out; +} + +#content #schema dd.similarity.ng-binding:hover::after { + opacity: 90; + bottom: -20px; +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/segments.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/segments.css new file mode 100755 index 0000000000..9de0701385 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/segments.css @@ -0,0 +1,172 @@ +/* + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#content #segments .loader +{ + background-position: 0 50%; + padding-left: 21px; +} + +#content #segments .reload +{ + background-image: url( ../../img/ico/arrow-circle.png ); + background-position: 50% 50%; + display: block; + height: 30px; + position: absolute; + right: 10px; + top: 10px; + width: 30px; +} + +#content #segments .reload.loader +{ + padding-left: 0; +} + +#content #segments .reload span +{ + display: none; +} + +#content #segments #result +{ + width: 77%; +} + +#content #segments #result #response +{ + margin-left: 25px; +} + +#content #segments .segments-holder ul { + margin-left: 25px; +} +#content #segments .segments-holder li { + margin-bottom: 2px; + position: relative; + width: 100%; +} + +#content #segments .segments-holder li .tooltip { + display: none; + background: #f0f0f0; + position: absolute; + z-index: 1000; + width:220px; + height:120px; + margin-left: 100%; + opacity: .8; + padding: 5px; + border: 1px solid; + border-radius: 5px; +} + +#content #segments .segments-holder li .tooltip .label { + float: left; + width: 20%; + opacity: 1; +} + +#content #segments .segments-holder li:hover .tooltip { + display:block; +} + +#content #segments .segments-holder li dl, +#content #segments .segments-holder li dt { + padding-bottom: 1px; + padding-top: 1px; +} +#content #segments .segments-holder li dl { + min-width: 1px; +} +#content #segments .segments-holder li dt { + color: #4D4D4D; + left: -45px; + overflow: hidden; + position: absolute; + top: 0; +} +#content #segments .segments-holder li dt div { + display: block; + padding-right: 4px; + text-align: right; +} +#content #segments .segments-holder li dd { + clear: left; + float: left; + margin-left: 2px; + white-space: nowrap; + width: 100%; +} + +#content #segments .segments-holder li dd div.deleted { + background-color: #808080; + padding-left: 5px; +} + +#content #segments .segments-holder li dd div.live { + background-color: #DDDDDD; + float: left; +} + +#content #segments .segments-holder li dd div.start { + float: left; + width: 20%; +} + +#content #segments .segments-holder li dd div.end { + text-align: right; +} + +.merge-candidate { + background-color: #FFC9F9 !important; +} + +#content #segments .segments-holder li dd div.w5 { + width: 20%; + float: left; +} + +#content #segments #auto-refresh { + margin-top: 4px; + background-position: 50% 50%; + display: block; + height: 30px; + position: absolute; + right: 50px; + top: 10px; +} + +#content #segments #auto-refresh a { + background-image: url( ../../img/ico/ui-check-box-uncheck.png ); + background-position: 0 50%; + color: #4D4D4D; + display: block; + padding-left: 21px; +} + +#content #segments #auto-refresh a.on, +#content #segments #auto-refresh a:hover { + color: #333; +} + +#content #segments #auto-refresh a.on { + background-image: url( ../../img/ico/ui-check-box.png ); +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/stream.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/stream.css new file mode 100755 index 0000000000..fb7d11f40b --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/stream.css @@ -0,0 +1,233 @@ +/* + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#content #stream +{ +} + +#content #stream #form +{ + float: top; +} + +#content #stream #form label +{ + cursor: pointer; + display: inline; + margin-top: 5px; +} + +#content #stream #form input, +#content #stream #form select, +#content #stream #form textarea +{ + margin-bottom: 2px; + width: 100%; +} + +#content #stream #form textarea +{ + height: 125px; +} + +#content #stream #form #start +{ + float: left; + width: 45%; +} + +#content #stream #form #rows +{ + float: right; + width: 45%; +} + +#content #stream #form input[type=checkbox] +{ + margin-bottom: 0; + margin-left: 5px; + margin-right: 0px; + width: 10px; + height: 10px; + display: inline; +} + +#content #stream #form fieldset +{ + border: 1px solid #fff; + border-top: 1px solid #c0c0c0; + margin-bottom: 5px; +} + +#content #stream #form fieldset.common +{ + margin-top: 10px; +} + +#content #stream #form fieldset legend +{ + display: block; + margin-left: 10px; + padding: 0px 5px; +} + +#content #stream #form fieldset legend label +{ + margin-top: 0; +} + +#content #stream #form button +{ + margin-right: 10px; +} + +#content #stream #form fieldset .fieldset +{ + border-bottom: 1px solid #f0f0f0; + margin-bottom: 5px; + padding-bottom: 10px; +} + +#content #stream #result +{ + float: bottom; +} + +#content #stream #result #response +{ +} + +/************************/ + +#content #stream #result #explanation +{ + border-top: 1px solid #f0f0f0; + border-bottom: 1px solid #f0f0f0; + border-left: 1px solid #f0f0f0; + border-right: 1px solid #f0f0f0; +} + +#content #stream #result #explanation .loader +{ + background-position: 0 50%; + padding-left: 21px; +} + +#content #stream #result #explanation #error +{ + background-color: #f00; + background-image: url( ../../img/ico/construction.png ); + background-position: 10px 12px; + color: #fff; + font-weight: bold; + margin-bottom: 20px; + padding: 10px; + padding-left: 35px; +} + +#content #stream #result #explanation #error .msg +{ + font-style: italic; + font-weight: normal; + margin-top: 10px; +} + +#content #stream #result #explanation .content +{ + padding-left: 0; + padding-right: 0; +} + +#content #stream #result #explanation .content.show +{ + background-image: url( ../../img/div.gif ); + background-repeat: repeat-y; + background-position: 31% 0; +} + +#content #stream #result #explanation #legend +{ + border: 1px solid #f0f0f0; + padding: 10px; + /*position: absolute; + right: 0; + bottom: 0;*/ +} + +#content #stream #result #explanation #legend li +{ + padding-left: 15px; + position: relative; + -webkit-box-sizing: border-box; +} + +#content #stream #result #explanation #legend li svg +{ + position: absolute; + left: 0; + top: 2px; +} + +#content #stream #result #explanation #explanation-content +{ + min-height: 50px; + width: 100% +} + +#content #stream #result #explanation #explanation-content .node circle +{ + color: #c48f00; + stroke: #c48f00; + fill: #c48f00; +} + +#content #stream #result #explanation #explanation-content .link +{ + fill: none; + stroke: #e0e0e0; + stroke-width: 1.5px; +} + +#content #stream #result #explanation #legend .datastore circle, +#content #stream #result #explanation #explanation-content .node.datastore circle +{ + stroke: #3800c4; + fill: #3800c4; +} + +#content #stream #result #explanation #legend .stream-source circle, +#content #stream #result #explanation #explanation-content .node.stream-source circle +{ + stroke: #21a9ec; + fill: #21a9ec; +} + +#content #stream #result #explanation #legend .stream-decorator circle, +#content #stream #result #explanation #explanation-content .node.stream-decorator circle +{ + stroke: #cb21ec; + fill: #cb21ec; +} + +#content #stream #result #explanation #legend .graph-source circle, +#content #stream #result #explanation #explanation-content .node.graph-source circle +{ + stroke: #21eca9; + fill: #21eca9; +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/suggestions.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/suggestions.css new file mode 100755 index 0000000000..d1836d797c --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/suggestions.css @@ -0,0 +1,64 @@ +/* + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ +#cluster-suggestions +.s-container{ + text-align:center; +} +#cluster-suggestions +.s-box1{ + background-image: url( ../../img/ico/run.png ); + background-color: transparent; + background-repeat: no-repeat; + border: none; + cursor: pointer; + vertical-align: middle; + display:inline-block; + width:20px; +} +#cluster-suggestions +.s-box2{ + display:inline-block; +} +#cluster-suggestions +.s-box3{ + display:inline-block; +} +#cluster-suggestions +.s-box4{ + display:inline-block; +} +#s-table { + border-collapse: collapse; + width: 60%; +} + +#s-table td, #customers th { + border: 1px solid #ddd; + padding: 8px; +} + +#cluster-suggestions #s-table tr:nth-child(even){background-color: #f2f2f2;} + +#cluster-suggestions #s-table th { + padding-top: 12px; + padding-bottom: 12px; + text-align: left; + background-color: #4CAF50; + color: white; +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/threads.css b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/threads.css new file mode 100755 index 0000000000..0c482c4873 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/css/angular/threads.css @@ -0,0 +1,160 @@ +/* + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#content #threads .loader +{ + background-position: 0 50%; + padding-left: 21px; +} + +#content #threads #thread-dump table +{ + border-collapse: collapse; + width: 100%; +} + +#content #threads #thread-dump table .spacer, +#content #threads #thread-dump tbody .state +{ + background-color: #fff; +} + +#content #threads #thread-dump table th, +#content #threads #thread-dump table td +{ + padding: 5px 3px; + vertical-align: top; +} + +#content #threads #thread-dump thead th +{ + background-color: #c8c8c8; + font-weight: bold; + text-align: left; +} + +#content #threads #thread-dump thead th.name +{ + width: 85%; +} + +#content #threads #thread-dump thead th.time +{ + text-align: right; + width: 15%; +} + +#content #threads #thread-dump tbody .odd +{ + background-color: #f0f0f0; +} + +#content #threads #thread-dump tbody .RUNNABLE a +{ + background-image: url( ../../img/ico/tick-circle.png ); +} + +#content #threads #thread-dump tbody .WAITING a, +#content #threads #thread-dump tbody .TIMED_WAITING a +{ + background-image: url( ../../img/ico/hourglass.png ); +} + +#content #threads #thread-dump tbody .WAITING.lock a, +#content #threads #thread-dump tbody .TIMED_WAITING.lock a +{ + background-image: url( ../../img/ico/hourglass--exclamation.png ); +} + +#content #threads #thread-dump tbody .name a +{ + background-position: 0 50%; + cursor: auto; + display: block; + padding-left: 21px; +} + +#content #threads #thread-dump tbody .stacktrace .name a +{ + cursor: pointer; +} + +#content #threads #thread-dump tbody .stacktrace .name a span +{ + background-image: url( ../../img/ico/chevron-small-expand.png ); + background-position: 100% 50%; + padding-right: 21px; +} + +#content #threads #thread-dump tbody .stacktrace.open .name a span +{ + background-image: url( ../../img/ico/chevron-small.png ); +} + +#content #threads #thread-dump tbody .name p +{ + background-image: url( ../../img/ico/arrow-000-small.png ); + background-position: 0 50%; + color: #4D4D4D; + font-size: 11px; + margin-left: 21px; + padding-left: 21px; +} + +#content #threads #thread-dump tbody .name div +{ + border-top: 1px solid #c0c0c0; + margin-left: 21px; + margin-top: 5px; + padding-top: 5px; +} + +#content #threads #thread-dump tbody .open .name div +{ + display: block; +} + +#content #threads #thread-dump tbody .name ul +{ + list-style-type: disc; + margin-left: 0.7em; + padding-left: 0.7em; +} + +#content #threads #thread-dump tbody .time +{ + text-align: right; +} + +#content #threads .controls +{ + padding-top: 5px; + padding-bottom: 5px; +} + +#content #threads .controls a +{ + background-image: url( ../../img/ico/chevron-small-expand.png ); + padding-left: 21px; +} + +#content #threads.expanded .controls a +{ + background-image: url( ../../img/ico/chevron-small.png ); +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/favicon.ico b/KeywordSearch/solr/server/solr-webapp/webapp/favicon.ico new file mode 100755 index 0000000000..e93104ccff Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/favicon.ico differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/chosen-sprite.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/chosen-sprite.png new file mode 100755 index 0000000000..c57da70b4b Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/chosen-sprite.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/chosen-sprite@2x.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/chosen-sprite@2x.png new file mode 100755 index 0000000000..6b50545202 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/chosen-sprite@2x.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/div.gif b/KeywordSearch/solr/server/solr-webapp/webapp/img/div.gif new file mode 100755 index 0000000000..963c9e97bd Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/div.gif differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/favicon.ico b/KeywordSearch/solr/server/solr-webapp/webapp/img/favicon.ico new file mode 100755 index 0000000000..e93104ccff Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/favicon.ico differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/7z.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/7z.png new file mode 100755 index 0000000000..52f7d5d720 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/7z.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/README b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/README new file mode 100755 index 0000000000..8cab20c245 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/README @@ -0,0 +1,27 @@ +http://www.splitbrain.org/projects/file_icons + +Released to the Public Domain +Free to use. Provided as is. No warranties. + +Note: The big majority of icons where created by the creators listed + below. Only a few ones where found on the net. They were too + widespread to determine the original author and thus were + considered public domain. + If you are the author of one of those icons just send a short + mail to either be included in the list below or have the icon + removed from the package. + +Creators: + + Andreas Gohr + Michael Klier + Andreas Barton + Hubert Chathi + Johan Koehne + Rudi von Staden + Daniel Darvish + Andy Pascall + Seth + David Carella + Tom N. Harris + Brandon Carmon Colvin diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/ai.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/ai.png new file mode 100755 index 0000000000..a999762c89 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/ai.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/aiff.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/aiff.png new file mode 100755 index 0000000000..82d523fdb1 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/aiff.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/asc.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/asc.png new file mode 100755 index 0000000000..d9fa4a8aae Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/asc.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/audio.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/audio.png new file mode 100755 index 0000000000..98883256d6 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/audio.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/bin.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/bin.png new file mode 100755 index 0000000000..fbd174e2d5 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/bin.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/bz2.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/bz2.png new file mode 100755 index 0000000000..d48cae0384 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/bz2.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/c.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/c.png new file mode 100755 index 0000000000..efe18f4392 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/c.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/cfc.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/cfc.png new file mode 100755 index 0000000000..09c149d642 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/cfc.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/cfm.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/cfm.png new file mode 100755 index 0000000000..d755f286f1 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/cfm.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/chm.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/chm.png new file mode 100755 index 0000000000..53d48f3b51 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/chm.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/class.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/class.png new file mode 100755 index 0000000000..a39f70c161 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/class.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/conf.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/conf.png new file mode 100755 index 0000000000..ddffe6fd1a Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/conf.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/cpp.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/cpp.png new file mode 100755 index 0000000000..79464401bd Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/cpp.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/cs.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/cs.png new file mode 100755 index 0000000000..d5db29ba5d Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/cs.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/css.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/css.png new file mode 100755 index 0000000000..04012041c1 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/css.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/csv.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/csv.png new file mode 100755 index 0000000000..3a8835360e Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/csv.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/deb.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/deb.png new file mode 100755 index 0000000000..9229d87838 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/deb.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/divx.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/divx.png new file mode 100755 index 0000000000..98dab8f808 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/divx.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/doc.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/doc.png new file mode 100755 index 0000000000..932567f8a9 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/doc.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/dot.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/dot.png new file mode 100755 index 0000000000..9f2da1add1 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/dot.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/eml.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/eml.png new file mode 100755 index 0000000000..02828e1738 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/eml.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/enc.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/enc.png new file mode 100755 index 0000000000..cb2d7d47eb Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/enc.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/file.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/file.png new file mode 100755 index 0000000000..24d5f328cc Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/file.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/gif.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/gif.png new file mode 100755 index 0000000000..b4c07a9120 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/gif.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/gz.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/gz.png new file mode 100755 index 0000000000..2426bd169c Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/gz.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/hlp.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/hlp.png new file mode 100755 index 0000000000..4417d8e2cb Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/hlp.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/htm.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/htm.png new file mode 100755 index 0000000000..1a6812185b Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/htm.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/html.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/html.png new file mode 100755 index 0000000000..672cbce420 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/html.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/image.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/image.png new file mode 100755 index 0000000000..f83e2898d5 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/image.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/iso.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/iso.png new file mode 100755 index 0000000000..1b2ff19ca7 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/iso.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/jar.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/jar.png new file mode 100755 index 0000000000..4db70a2c72 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/jar.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/java.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/java.png new file mode 100755 index 0000000000..7489b97213 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/java.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/jpeg.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/jpeg.png new file mode 100755 index 0000000000..aa4cc23a5b Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/jpeg.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/jpg.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/jpg.png new file mode 100755 index 0000000000..1fb6cc1fbf Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/jpg.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/js.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/js.png new file mode 100755 index 0000000000..7db4de7e98 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/js.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/lua.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/lua.png new file mode 100755 index 0000000000..7c07d023f9 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/lua.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/m.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/m.png new file mode 100755 index 0000000000..aa0cbae8b1 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/m.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/mm.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/mm.png new file mode 100755 index 0000000000..b737571c5e Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/mm.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/mov.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/mov.png new file mode 100755 index 0000000000..7e7aa368f7 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/mov.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/mp3.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/mp3.png new file mode 100755 index 0000000000..928705d7a5 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/mp3.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/mpg.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/mpg.png new file mode 100755 index 0000000000..9a3f8ea51e Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/mpg.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/odc.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/odc.png new file mode 100755 index 0000000000..47f65c84d3 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/odc.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/odf.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/odf.png new file mode 100755 index 0000000000..a2fbc5195a Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/odf.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/odg.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/odg.png new file mode 100755 index 0000000000..434f18262f Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/odg.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/odi.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/odi.png new file mode 100755 index 0000000000..74f6303d3d Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/odi.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/odp.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/odp.png new file mode 100755 index 0000000000..a5c77f845f Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/odp.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/ods.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/ods.png new file mode 100755 index 0000000000..2ab1273f0d Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/ods.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/odt.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/odt.png new file mode 100755 index 0000000000..b0c21fc1fd Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/odt.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/ogg.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/ogg.png new file mode 100755 index 0000000000..62cea6aaa4 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/ogg.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/pdf.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/pdf.png new file mode 100755 index 0000000000..638066dea6 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/pdf.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/pgp.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/pgp.png new file mode 100755 index 0000000000..e6b35f36ed Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/pgp.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/php.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/php.png new file mode 100755 index 0000000000..44c0fe0a08 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/php.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/pl.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/pl.png new file mode 100755 index 0000000000..ad2324e359 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/pl.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/png.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/png.png new file mode 100755 index 0000000000..f0b5b00eee Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/png.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/ppt.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/ppt.png new file mode 100755 index 0000000000..adaefc6025 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/ppt.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/ps.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/ps.png new file mode 100755 index 0000000000..487c3cb7c2 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/ps.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/py.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/py.png new file mode 100755 index 0000000000..9e31edb553 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/py.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/ram.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/ram.png new file mode 100755 index 0000000000..1a54d76543 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/ram.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/rar.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/rar.png new file mode 100755 index 0000000000..a6af4d1cac Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/rar.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/rb.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/rb.png new file mode 100755 index 0000000000..30670165f9 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/rb.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/rm.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/rm.png new file mode 100755 index 0000000000..a2db68e32d Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/rm.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/rpm.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/rpm.png new file mode 100755 index 0000000000..22212eafac Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/rpm.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/rtf.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/rtf.png new file mode 100755 index 0000000000..d8bada5fe1 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/rtf.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/sig.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/sig.png new file mode 100755 index 0000000000..3d8b19d2b3 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/sig.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/sql.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/sql.png new file mode 100755 index 0000000000..f60054a3af Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/sql.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/swf.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/swf.png new file mode 100755 index 0000000000..0729ed0203 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/swf.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/sxc.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/sxc.png new file mode 100755 index 0000000000..419c183c1f Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/sxc.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/sxd.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/sxd.png new file mode 100755 index 0000000000..5801bb23a6 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/sxd.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/sxi.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/sxi.png new file mode 100755 index 0000000000..2a94290d70 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/sxi.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/sxw.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/sxw.png new file mode 100755 index 0000000000..6da97beb35 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/sxw.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/tar.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/tar.png new file mode 100755 index 0000000000..5a2f717fc5 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/tar.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/tex.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/tex.png new file mode 100755 index 0000000000..e46a5166f9 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/tex.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/tgz.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/tgz.png new file mode 100755 index 0000000000..141acf5647 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/tgz.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/txt.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/txt.png new file mode 100755 index 0000000000..da20009c6e Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/txt.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/vcf.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/vcf.png new file mode 100755 index 0000000000..195ab38bc7 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/vcf.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/video.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/video.png new file mode 100755 index 0000000000..b89fc52995 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/video.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/vsd.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/vsd.png new file mode 100755 index 0000000000..d14b81d989 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/vsd.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/wav.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/wav.png new file mode 100755 index 0000000000..79e80760e2 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/wav.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/wma.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/wma.png new file mode 100755 index 0000000000..6854de7722 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/wma.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/wmv.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/wmv.png new file mode 100755 index 0000000000..b26f45d5f3 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/wmv.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/xls.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/xls.png new file mode 100755 index 0000000000..e8cd58dc0f Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/xls.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/xml.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/xml.png new file mode 100755 index 0000000000..eb46323979 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/xml.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/xpi.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/xpi.png new file mode 100755 index 0000000000..5e537e2375 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/xpi.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/xvid.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/xvid.png new file mode 100755 index 0000000000..d8429dc1ae Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/xvid.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/zip.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/zip.png new file mode 100755 index 0000000000..999ffbe807 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/filetypes/zip.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/arrow-000-small.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/arrow-000-small.png new file mode 100755 index 0000000000..cfc2e2493f Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/arrow-000-small.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/arrow-circle.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/arrow-circle.png new file mode 100755 index 0000000000..dda7132750 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/arrow-circle.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/arrow-switch.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/arrow-switch.png new file mode 100755 index 0000000000..ab3dd3021d Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/arrow-switch.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/asterisk.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/asterisk.png new file mode 100755 index 0000000000..c2fbed5a74 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/asterisk.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/battery.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/battery.png new file mode 100755 index 0000000000..7a825b0257 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/battery.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/block-small.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/block-small.png new file mode 100755 index 0000000000..7cc52813cd Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/block-small.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/block.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/block.png new file mode 100755 index 0000000000..ed7ec0e972 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/block.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/book-open-text.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/book-open-text.png new file mode 100755 index 0000000000..069fae7c95 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/book-open-text.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/box.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/box.png new file mode 100755 index 0000000000..3ec0ceb131 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/box.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/bug.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/bug.png new file mode 100755 index 0000000000..242d5391c1 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/bug.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/chart.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/chart.png new file mode 100755 index 0000000000..d3cb71d5c5 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/chart.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/chevron-small-expand.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/chevron-small-expand.png new file mode 100755 index 0000000000..06a8eaca13 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/chevron-small-expand.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/chevron-small.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/chevron-small.png new file mode 100755 index 0000000000..b54fd1c7c2 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/chevron-small.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/clipboard-list.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/clipboard-list.png new file mode 100755 index 0000000000..e98c567563 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/clipboard-list.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/clipboard-paste-document-text.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/clipboard-paste-document-text.png new file mode 100755 index 0000000000..08647f1bee Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/clipboard-paste-document-text.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/clipboard-paste.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/clipboard-paste.png new file mode 100755 index 0000000000..0cf8887292 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/clipboard-paste.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/clock-select-remain.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/clock-select-remain.png new file mode 100755 index 0000000000..8c665b812e Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/clock-select-remain.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/clock-select.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/clock-select.png new file mode 100755 index 0000000000..8c567916c8 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/clock-select.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/construction.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/construction.png new file mode 100755 index 0000000000..8347aa896f Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/construction.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/cross-0.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/cross-0.png new file mode 100755 index 0000000000..04fef989e7 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/cross-0.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/cross-1.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/cross-1.png new file mode 100755 index 0000000000..830879b618 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/cross-1.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/cross-button.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/cross-button.png new file mode 100755 index 0000000000..933272b493 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/cross-button.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/cross.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/cross.png new file mode 100755 index 0000000000..6b9fa6dd36 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/cross.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/dashboard.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/dashboard.png new file mode 100755 index 0000000000..ba03262f0c Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/dashboard.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/database--plus.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/database--plus.png new file mode 100755 index 0000000000..2558a7d6a6 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/database--plus.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/database.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/database.png new file mode 100755 index 0000000000..d588f422f7 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/database.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/databases.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/databases.png new file mode 100755 index 0000000000..11dcab4b1b Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/databases.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/disk-black.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/disk-black.png new file mode 100755 index 0000000000..61784784f0 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/disk-black.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/document-convert.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/document-convert.png new file mode 100755 index 0000000000..1ecdafb99a Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/document-convert.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/document-import.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/document-import.png new file mode 100755 index 0000000000..5fae085f85 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/document-import.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/document-list.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/document-list.png new file mode 100755 index 0000000000..2b4dde893e Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/document-list.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/document-text.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/document-text.png new file mode 100755 index 0000000000..ed841a02a7 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/document-text.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/documents-stack.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/documents-stack.png new file mode 100755 index 0000000000..a397f60aaa Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/documents-stack.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/download-cloud.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/download-cloud.png new file mode 100755 index 0000000000..ba0f492fa4 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/download-cloud.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/drive-upload.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/drive-upload.png new file mode 100755 index 0000000000..93589e4da3 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/drive-upload.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/exclamation-button.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/exclamation-button.png new file mode 100755 index 0000000000..e792fb01d5 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/exclamation-button.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/eye.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/eye.png new file mode 100755 index 0000000000..2aead17e09 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/eye.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/folder-export.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/folder-export.png new file mode 100755 index 0000000000..86e0cd294c Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/folder-export.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/folder-tree.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/folder-tree.png new file mode 100755 index 0000000000..24218b6dbd Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/folder-tree.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/folder.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/folder.png new file mode 100755 index 0000000000..ada85c48b8 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/folder.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/funnel-small.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/funnel-small.png new file mode 100755 index 0000000000..96e9e28f25 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/funnel-small.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/funnel.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/funnel.png new file mode 100755 index 0000000000..1f69604528 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/funnel.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/gear.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/gear.png new file mode 100755 index 0000000000..efc599dccd Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/gear.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/globe-network.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/globe-network.png new file mode 100755 index 0000000000..ec27fad42b Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/globe-network.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/globe.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/globe.png new file mode 100755 index 0000000000..48e5b6b30c Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/globe.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/hammer-screwdriver.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/hammer-screwdriver.png new file mode 100755 index 0000000000..985d44c5e7 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/hammer-screwdriver.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/hammer.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/hammer.png new file mode 100755 index 0000000000..cf0ef85a78 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/hammer.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/hand.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/hand.png new file mode 100755 index 0000000000..7b47be2dc9 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/hand.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/highlighter-text.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/highlighter-text.png new file mode 100755 index 0000000000..719c537dbb Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/highlighter-text.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/home.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/home.png new file mode 100755 index 0000000000..622a2b736d Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/home.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/hourglass--exclamation.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/hourglass--exclamation.png new file mode 100755 index 0000000000..67436681a1 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/hourglass--exclamation.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/hourglass.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/hourglass.png new file mode 100755 index 0000000000..127c5d6156 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/hourglass.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/idea.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/idea.png new file mode 100755 index 0000000000..8b3abbd5e9 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/idea.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/inbox-document-text.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/inbox-document-text.png new file mode 100755 index 0000000000..4b479cfef6 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/inbox-document-text.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/information-button.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/information-button.png new file mode 100755 index 0000000000..4ecaf370bd Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/information-button.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/information-small.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/information-small.png new file mode 100755 index 0000000000..6db2d56e97 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/information-small.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/information-white.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/information-white.png new file mode 100755 index 0000000000..bd4f552a8b Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/information-white.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/information.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/information.png new file mode 100755 index 0000000000..fa9a60b5ad Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/information.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/jar.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/jar.png new file mode 100755 index 0000000000..8711832acc Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/jar.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/magnifier.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/magnifier.png new file mode 100755 index 0000000000..7a5ae62e32 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/magnifier.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/mail.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/mail.png new file mode 100755 index 0000000000..e708416dac Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/mail.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/memory.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/memory.png new file mode 100755 index 0000000000..4c71a247d6 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/memory.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/minus-button.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/minus-button.png new file mode 100755 index 0000000000..6dc019a60b Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/minus-button.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/molecule.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/molecule.png new file mode 100755 index 0000000000..c4eac4ef4b Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/molecule.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/network-cloud.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/network-cloud.png new file mode 100755 index 0000000000..0527a92ba1 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/network-cloud.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/network-status-away.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/network-status-away.png new file mode 100755 index 0000000000..0defbb40d9 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/network-status-away.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/network-status-busy.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/network-status-busy.png new file mode 100755 index 0000000000..ba2c65473c Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/network-status-busy.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/network-status-offline.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/network-status-offline.png new file mode 100755 index 0000000000..507ff05959 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/network-status-offline.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/network-status.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/network-status.png new file mode 100755 index 0000000000..12ccc6baff Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/network-status.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/network.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/network.png new file mode 100755 index 0000000000..8224771b0d Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/network.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/node-design.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/node-design.png new file mode 100755 index 0000000000..fb2d4066c7 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/node-design.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/node-master.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/node-master.png new file mode 100755 index 0000000000..c40fcc3ee4 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/node-master.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/node-select.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/node-select.png new file mode 100755 index 0000000000..d2aba04ccb Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/node-select.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/node-slave.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/node-slave.png new file mode 100755 index 0000000000..78a41cd127 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/node-slave.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/node.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/node.png new file mode 100755 index 0000000000..88f1a2bbf1 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/node.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/pencil-small.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/pencil-small.png new file mode 100755 index 0000000000..3d81c2fb13 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/pencil-small.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/pencil.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/pencil.png new file mode 100755 index 0000000000..3ef2fa63e2 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/pencil.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/plus-button.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/plus-button.png new file mode 100755 index 0000000000..10d1f60031 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/plus-button.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/processor.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/processor.png new file mode 100755 index 0000000000..37e9794222 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/processor.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/prohibition.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/prohibition.png new file mode 100755 index 0000000000..18f151071a Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/prohibition.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/property.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/property.png new file mode 100755 index 0000000000..b0e549e453 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/property.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/question-small-white.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/question-small-white.png new file mode 100755 index 0000000000..132d3f5bad Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/question-small-white.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/question-white.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/question-white.png new file mode 100755 index 0000000000..f806468719 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/question-white.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/question.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/question.png new file mode 100755 index 0000000000..30a47032a4 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/question.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/receipt-invoice.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/receipt-invoice.png new file mode 100755 index 0000000000..fed614079f Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/receipt-invoice.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/receipt.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/receipt.png new file mode 100755 index 0000000000..1548b0ac60 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/receipt.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/run.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/run.png new file mode 100755 index 0000000000..dc35fe3cb2 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/run.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/script-code.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/script-code.png new file mode 100755 index 0000000000..d398622dfd Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/script-code.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/server-cast.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/server-cast.png new file mode 100755 index 0000000000..9213866525 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/server-cast.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/server.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/server.png new file mode 100755 index 0000000000..ee0c771797 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/server.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/sitemap.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/sitemap.png new file mode 100755 index 0000000000..298343eeab Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/sitemap.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/slash.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/slash.png new file mode 100755 index 0000000000..7af3a5189d Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/slash.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/status-away.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/status-away.png new file mode 100755 index 0000000000..c7be0abbe4 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/status-away.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/status-busy.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/status-busy.png new file mode 100755 index 0000000000..a9d5f4db20 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/status-busy.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/status-offline.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/status-offline.png new file mode 100755 index 0000000000..f148af4985 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/status-offline.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/status.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/status.png new file mode 100755 index 0000000000..680bb8a6a6 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/status.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/system-monitor--exclamation.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/system-monitor--exclamation.png new file mode 100755 index 0000000000..c6f6a5f646 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/system-monitor--exclamation.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/system-monitor.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/system-monitor.png new file mode 100755 index 0000000000..a139103e11 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/system-monitor.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/table.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/table.png new file mode 100755 index 0000000000..b0cd69fc5d Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/table.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/terminal.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/terminal.png new file mode 100755 index 0000000000..c18df24f94 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/terminal.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/tick-circle.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/tick-circle.png new file mode 100755 index 0000000000..210b1a6c3c Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/tick-circle.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/tick-red.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/tick-red.png new file mode 100755 index 0000000000..8ec99b4a69 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/tick-red.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/tick.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/tick.png new file mode 100755 index 0000000000..2414885b85 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/tick.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/toggle-small-expand.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/toggle-small-expand.png new file mode 100755 index 0000000000..79c5ff7e80 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/toggle-small-expand.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/toggle-small.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/toggle-small.png new file mode 100755 index 0000000000..f783a6f2cb Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/toggle-small.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/toolbox.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/toolbox.png new file mode 100755 index 0000000000..b581d7794d Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/toolbox.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/ui-accordion.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/ui-accordion.png new file mode 100755 index 0000000000..a9f1448e29 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/ui-accordion.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/ui-address-bar.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/ui-address-bar.png new file mode 100755 index 0000000000..1a96ac435e Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/ui-address-bar.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/ui-check-box-uncheck.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/ui-check-box-uncheck.png new file mode 100755 index 0000000000..ba447358cc Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/ui-check-box-uncheck.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/ui-check-box.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/ui-check-box.png new file mode 100755 index 0000000000..07f3522a9c Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/ui-check-box.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/ui-radio-button-uncheck.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/ui-radio-button-uncheck.png new file mode 100755 index 0000000000..ec7102b6ef Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/ui-radio-button-uncheck.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/ui-radio-button.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/ui-radio-button.png new file mode 100755 index 0000000000..f83a25496e Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/ui-radio-button.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/ui-text-field-select.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/ui-text-field-select.png new file mode 100755 index 0000000000..3cfe301ac7 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/ui-text-field-select.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/users.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/users.png new file mode 100755 index 0000000000..a6aae0404b Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/users.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/wooden-box.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/wooden-box.png new file mode 100755 index 0000000000..f64d761057 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/wooden-box.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/zone.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/zone.png new file mode 100755 index 0000000000..80fc7be9e0 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/ico/zone.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/jstree/32px.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/jstree/32px.png new file mode 100755 index 0000000000..4357b91028 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/jstree/32px.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/jstree/40px.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/jstree/40px.png new file mode 100755 index 0000000000..d0255223f4 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/jstree/40px.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/jstree/throbber.gif b/KeywordSearch/solr/server/solr-webapp/webapp/img/jstree/throbber.gif new file mode 100755 index 0000000000..64c8eebb87 Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/jstree/throbber.gif differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/loader-light.gif b/KeywordSearch/solr/server/solr-webapp/webapp/img/loader-light.gif new file mode 100755 index 0000000000..f578ca586f Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/loader-light.gif differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/loader.gif b/KeywordSearch/solr/server/solr-webapp/webapp/img/loader.gif new file mode 100755 index 0000000000..085ccaecaf Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/loader.gif differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/lucene-ico.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/lucene-ico.png new file mode 100755 index 0000000000..43327dd5ac Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/lucene-ico.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/solr-ico.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/solr-ico.png new file mode 100755 index 0000000000..91c35d846f Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/solr-ico.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/solr.svg b/KeywordSearch/solr/server/solr-webapp/webapp/img/solr.svg new file mode 100755 index 0000000000..30e93f75c7 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/img/solr.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/img/tree.png b/KeywordSearch/solr/server/solr-webapp/webapp/img/tree.png new file mode 100755 index 0000000000..61b6b3ee1a Binary files /dev/null and b/KeywordSearch/solr/server/solr-webapp/webapp/img/tree.png differ diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/index.html b/KeywordSearch/solr/server/solr-webapp/webapp/index.html new file mode 100755 index 0000000000..0e7c3ba0d7 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/index.html @@ -0,0 +1,258 @@ + + + + + + Solr Admin + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ +
+ +

SolrCore Initialization Failures

+
    +
  • {{core}}: {{error}}
  • +
+

Please check your logs for more information

+ +
+ +
 
+ +
+
+
+ +
+

Connection to Solr lost

+

Please check the Solr instance.

+
+
+

Connection recovered...

+

Continuing to load data...

+
+
+
+
{{exception.msg}}
+
+ +
+
+ +
+
+ + + + + +
+ +
+ + + diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/app.js b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/app.js new file mode 100755 index 0000000000..c2b4cbcd6b --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/app.js @@ -0,0 +1,592 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* SOLR-14120: Providing a manual definition for the methods 'includes' and 'startsWith' to support Internet Explorer 11. */ +if (!String.prototype.includes) { + String.prototype.includes = function(search, start) { 'use strict'; + if (search instanceof RegExp) { + throw TypeError('first argument must not be a RegExp'); + } + if (start === undefined) { start = 0; } + return this.indexOf(search, start) !== -1; + }; +} +if (!Array.prototype.includes) { + Object.defineProperty(Array.prototype, "includes", { + enumerable: false, + value: function(obj) { + var newArr = this.filter(function(el) { + return el == obj; + }); + return newArr.length > 0; + } + }); +} +if (!String.prototype.startsWith) { + Object.defineProperty(String.prototype, 'startsWith', { + value: function(search, rawPos) { + var pos = rawPos > 0 ? rawPos|0 : 0; + return this.substring(pos, pos + search.length) === search; + } + }); +} + +var solrAdminApp = angular.module("solrAdminApp", [ + "ngResource", + "ngRoute", + "ngCookies", + "ngtimeago", + "solrAdminServices", + "localytics.directives", + "ab-base64" +]); + +solrAdminApp.config([ + '$locationProvider', function($locationProvider) { + $locationProvider.hashPrefix(''); +}]) +.config([ + '$routeProvider', function($routeProvider) { + $routeProvider. + when('/', { + templateUrl: 'partials/index.html', + controller: 'IndexController' + }). + when('/unknown', { + templateUrl: 'partials/unknown.html', + controller: 'UnknownController' + }). + when('/login', { + templateUrl: 'partials/login.html', + controller: 'LoginController' + }). + when('/login/:route', { + templateUrl: 'partials/login.html', + controller: 'LoginController' + }). + when('/~logging', { + templateUrl: 'partials/logging.html', + controller: 'LoggingController' + }). + when('/~logging/level', { + templateUrl: 'partials/logging-levels.html', + controller: 'LoggingLevelController' + }). + when('/~cloud', { + templateUrl: 'partials/cloud.html', + controller: 'CloudController' + }). + when('/~cores', { + templateUrl: 'partials/cores.html', + controller: 'CoreAdminController' + }). + when('/~cores/:corename', { + templateUrl: 'partials/cores.html', + controller: 'CoreAdminController' + }). + when('/~collections', { + templateUrl: 'partials/collections.html', + controller: 'CollectionsController' + }). + when('/~collections/:collection', { + templateUrl: 'partials/collections.html', + controller: 'CollectionsController' + }). + when('/~threads', { + templateUrl: 'partials/threads.html', + controller: 'ThreadsController' + }). + when('/~java-properties', { + templateUrl: 'partials/java-properties.html', + controller: 'JavaPropertiesController' + }). + when('/~cluster-suggestions', { + templateUrl: 'partials/cluster_suggestions.html', + controller: 'ClusterSuggestionsController' + }). + when('/:core/core-overview', { + templateUrl: 'partials/core_overview.html', + controller: 'CoreOverviewController' + }). + when('/:core/alias-overview', { + templateUrl: 'partials/alias_overview.html', + controller: 'AliasOverviewController' + }). + when('/:core/collection-overview', { + templateUrl: 'partials/collection_overview.html', + controller: 'CollectionOverviewController' + }). + when('/:core/analysis', { + templateUrl: 'partials/analysis.html', + controller: 'AnalysisController' + }). + when('/:core/dataimport', { + templateUrl: 'partials/dataimport.html', + controller: 'DataImportController' + }). + when('/:core/dataimport/:handler*', { + templateUrl: 'partials/dataimport.html', + controller: 'DataImportController' + }). + when('/:core/documents', { + templateUrl: 'partials/documents.html', + controller: 'DocumentsController' + }). + when('/:core/files', { + templateUrl: 'partials/files.html', + controller: 'FilesController' + }). + when('/:core/plugins', { + templateUrl: 'partials/plugins.html', + controller: 'PluginsController', + reloadOnSearch: false + }). + when('/:core/plugins/:legacytype', { + templateUrl: 'partials/plugins.html', + controller: 'PluginsController', + reloadOnSearch: false + }). + when('/:core/query', { + templateUrl: 'partials/query.html', + controller: 'QueryController' + }). + when('/:core/stream', { + templateUrl: 'partials/stream.html', + controller: 'StreamController' + }). + when('/:core/replication', { + templateUrl: 'partials/replication.html', + controller: 'ReplicationController' + }). + when('/:core/dataimport', { + templateUrl: 'partials/dataimport.html', + controller: 'DataImportController' + }). + when('/:core/dataimport/:handler*', { + templateUrl: 'partials/dataimport.html', + controller: 'DataImportController' + }). + when('/:core/schema', { + templateUrl: 'partials/schema.html', + controller: 'SchemaController' + }). + when('/:core/segments', { + templateUrl: 'partials/segments.html', + controller: 'SegmentsController' + }). + otherwise({ + templateUrl: 'partials/unknown.html', + controller: 'UnknownController' + }); +}]) +.constant('Constants', { + IS_ROOT_PAGE: 1, + IS_CORE_PAGE: 2, + IS_COLLECTION_PAGE: 3, + ROOT_URL: "/" +}) +.filter('uriencode', function() { + return window.encodeURIComponent; +}) +.filter('highlight', function($sce) { + return function(input, lang) { + if (lang && input && lang!="txt" && lang!="csv") return hljs.highlight(lang, input).value; + return input; + } +}) +.filter('unsafe', function($sce) { return $sce.trustAsHtml; }) +.directive('loadingStatusMessage', function() { + return { + link: function($scope, $element, attrs) { + var show = function() {$element.css('display', 'block')}; + var hide = function() {$element.css('display', 'none')}; + $scope.$on('loadingStatusActive', show); + $scope.$on('loadingStatusInactive', hide); + } + }; +}) +.directive('escapePressed', function () { + return function (scope, element, attrs) { + element.bind("keydown keypress", function (event) { + if(event.which === 27) { + scope.$apply(function (){ + scope.$eval(attrs.escapePressed); + }); + event.preventDefault(); + } + }); + }; +}) +.directive('focusWhen', function($timeout) { + return { + link: function(scope, element, attrs) { + scope.$watch(attrs.focusWhen, function(value) { + if(value === true) { + $timeout(function() { + element[0].focus(); + }, 100); + } + }); + } + }; +}) +.directive('scrollableWhenSmall', function($window) { + return { + link: function(scope, element, attrs) { + var w = angular.element($window); + + var checkFixedMenu = function() { + var shouldScroll = w.height() < (element.height() + $('#header').height() + 40); + element.toggleClass( 'scroll', shouldScroll); + }; + w.bind('resize', checkFixedMenu); + w.bind('load', checkFixedMenu); + } + } +}) +.filter('readableSeconds', function() { + return function(input) { + seconds = parseInt(input||0, 10); + var minutes = Math.floor( seconds / 60 ); + var hours = Math.floor( minutes / 60 ); + + var text = []; + if( 0 !== hours ) { + text.push( hours + 'h' ); + seconds -= hours * 60 * 60; + minutes -= hours * 60; + } + + if( 0 !== minutes ) { + text.push( minutes + 'm' ); + seconds -= minutes * 60; + } + + if( 0 !== seconds ) { + text.push( ( '0' + seconds ).substr( -2 ) + 's' ); + } + return text.join(' '); + }; +}) +.filter('number', function($locale) { + return function(input) { + var sep = { + 'de_CH' : '\'', + 'de' : '.', + 'en' : ',', + 'es' : '.', + 'it' : '.', + 'ja' : ',', + 'sv' : ' ', + 'tr' : '.', + '_' : '' // fallback + }; + + var browser = {}; + var match = $locale.id.match( /^(\w{2})([-_](\w{2}))?$/ ); + if (match[1]) { + browser.language = match[1].toLowerCase(); + } + if (match[1] && match[3]) { + browser.locale = match[1] + '_' + match[3]; + } + + return ( input || 0 ).toString().replace(/\B(?=(\d{3})+(?!\d))/g, + sep[ browser.locale ] || sep[ browser.language ] || sep['_']); + }; +}) +.filter('orderObjectBy', function() { + return function(items, field, reverse) { + var filtered = []; + angular.forEach(items, function(item) { + filtered.push(item); + }); + filtered.sort(function (a, b) { + return (a[field] > b[field] ? 1 : -1); + }); + if(reverse) filtered.reverse(); + return filtered; + }; +}) +.directive('jstree', function($parse) { + return { + restrict: 'EA', + scope: { + data: '=', + onSelect: '&' + }, + link: function(scope, element, attrs) { + scope.$watch("data", function(newValue, oldValue) { + if (newValue && !jQuery.isEmptyObject(newValue)) { + var treeConfig = { + 'core' : { + 'animation' : 0, + 'data': scope.data, + 'worker': false + } + }; + + var tree = $(element).jstree(treeConfig); + $(element).jstree('open_node','li:first'); + if (tree) { + element.bind("select_node.jstree", function (event, data) { + scope.$apply(function() { + scope.onSelect({url: data.node.a_attr.href, data: data}); + }); + }); + } + } + }, true); + } + }; +}) +.directive('connectionMessage', function() { + return { + link: function($scope, $element, attrs) { + var show = function() {$element.css('display', 'block')}; + var hide = function() {$element.css('display', 'none')}; + $scope.$on('connectionStatusActive', show); + $scope.$on('connectionStatusInactive', hide); + } + }; +}) +.factory('httpInterceptor', function($q, $rootScope, $location, $timeout, $injector) { + var activeRequests = 0; + + var started = function(config) { + if (activeRequests == 0) { + $rootScope.$broadcast('loadingStatusActive'); + } + if ($rootScope.exceptions[config.url]) { + delete $rootScope.exceptions[config.url]; + } + activeRequests++; + if (sessionStorage.getItem("auth.header")) { + config.headers['Authorization'] = sessionStorage.getItem("auth.header"); + } + config.timeout = 10000; + return config || $q.when(config); + }; + + var ended = function(response) { + activeRequests--; + if (activeRequests == 0) { + $rootScope.$broadcast('loadingStatusInactive'); + } + if ($rootScope.retryCount>0) { + $rootScope.connectionRecovered = true; + $rootScope.retryCount=0; + $timeout(function() { + $rootScope.connectionRecovered=false; + $rootScope.$broadcast('connectionStatusInactive'); + },2000); + } + if (!$location.path().startsWith('/login') && !$location.path().startsWith('/unknown')) { + sessionStorage.removeItem("http401"); + sessionStorage.removeItem("auth.state"); + sessionStorage.removeItem("auth.statusText"); + } + return response || $q.when(response); + }; + + var failed = function(rejection) { + activeRequests--; + if (activeRequests == 0) { + $rootScope.$broadcast('loadingStatusInactive'); + } + if (rejection.config.headers.doNotIntercept) { + return rejection; + } + if (rejection.status === 0) { + $rootScope.$broadcast('connectionStatusActive'); + if (!$rootScope.retryCount) $rootScope.retryCount=0; + $rootScope.retryCount ++; + var $http = $injector.get('$http'); + var result = $http(rejection.config); + return result; + } else if (rejection.status === 401) { + // Authentication redirect + var headers = rejection.headers(); + var wwwAuthHeader = headers['www-authenticate']; + sessionStorage.setItem("auth.wwwAuthHeader", wwwAuthHeader); + sessionStorage.setItem("auth.authDataHeader", headers['x-solr-authdata']); + sessionStorage.setItem("auth.statusText", rejection.statusText); + sessionStorage.setItem("http401", "true"); + sessionStorage.removeItem("auth.scheme"); + sessionStorage.removeItem("auth.realm"); + sessionStorage.removeItem("auth.username"); + sessionStorage.removeItem("auth.header"); + sessionStorage.removeItem("auth.state"); + if ($location.path().includes('/login')) { + if (!sessionStorage.getItem("auth.location")) { + sessionStorage.setItem("auth.location", "/"); + } + } else { + sessionStorage.setItem("auth.location", $location.path()); + $location.path('/login'); + } + } else { + $rootScope.exceptions[rejection.config.url] = rejection.data.error; + } + return $q.reject(rejection); + }; + + return {request: started, response: ended, responseError: failed}; +}) +.config(function($httpProvider) { + $httpProvider.interceptors.push("httpInterceptor"); + // Force BasicAuth plugin to serve us a 'Authorization: xBasic xxxx' header so browser will not pop up login dialogue + $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; +}) +.directive('fileModel', function ($parse) { + return { + restrict: 'A', + link: function(scope, element, attrs) { + var model = $parse(attrs.fileModel); + var modelSetter = model.assign; + + element.bind('change', function(){ + scope.$apply(function(){ + modelSetter(scope, element[0].files[0]); + }); + }); + } + }; +}); + +solrAdminApp.controller('MainController', function($scope, $route, $rootScope, $location, Cores, Collections, System, Ping, Constants) { + + $rootScope.exceptions={}; + + $rootScope.toggleException = function() { + $scope.showException=!$scope.showException; + }; + + $scope.refresh = function() { + $scope.cores = []; + $scope.collections = []; + $scope.aliases = []; + } + + $scope.refresh(); + $scope.resetMenu = function(page, pageType) { + Cores.list(function(data) { + $scope.cores = []; + var currentCoreName = $route.current.params.core; + delete $scope.currentCore; + for (key in data.status) { + var core = data.status[key]; + $scope.cores.push(core); + if ((!$scope.isSolrCloud || pageType == Constants.IS_CORE_PAGE) && core.name == currentCoreName) { + $scope.currentCore = core; + } + } + $scope.showInitFailures = Object.keys(data.initFailures).length>0; + $scope.initFailures = data.initFailures; + }); + + System.get(function(data) { + $scope.isCloudEnabled = data.mode.match( /solrcloud/i ); + + var currentCollectionName = $route.current.params.core; + delete $scope.currentCollection; + if ($scope.isCloudEnabled) { + Collections.list(function (cdata) { + Collections.listaliases(function (adata) { + $scope.aliases = []; + for (var key in adata.aliases) { + props = {}; + if (key in adata.properties) { + props = adata.properties[key]; + } + var alias = {name: key, collections: adata.aliases[key], type: 'alias', properties: props}; + $scope.aliases.push(alias); + if (pageType == Constants.IS_COLLECTION_PAGE && alias.name == currentCollectionName) { + $scope.currentCollection = alias; + } + } + $scope.collections = []; + for (key in cdata.collections) { + var collection = {name: cdata.collections[key], type: 'collection'}; + $scope.collections.push(collection); + if (pageType == Constants.IS_COLLECTION_PAGE && collection.name == currentCollectionName) { + $scope.currentCollection = collection; + } + } + + $scope.aliases_and_collections = $scope.aliases; + if ($scope.aliases.length > 0) { + $scope.aliases_and_collections = $scope.aliases_and_collections.concat({name:'-----'}); + } + $scope.aliases_and_collections = $scope.aliases_and_collections.concat($scope.collections); + }); + }); + } + + $scope.showEnvironment = data.environment !== undefined; + if (data.environment) { + $scope.environment = data.environment; + var env_labels = {'prod': 'Production', 'stage': 'Staging', 'test': 'Test', 'dev': 'Development'}; + $scope.environment_label = env_labels[data.environment]; + if (data.environment_label) { + $scope.environment_label = data.environment_label; + } + if (data.environment_color) { + $scope.environment_color = data.environment_color; + } + } + }); + + $scope.showingLogging = page.lastIndexOf("logging", 0) === 0; + $scope.showingCloud = page.lastIndexOf("cloud", 0) === 0; + $scope.page = page; + $scope.currentUser = sessionStorage.getItem("auth.username"); + $scope.http401 = sessionStorage.getItem("http401"); + }; + + $scope.isMultiDestAlias = function(selectedColl) { + return selectedColl && selectedColl.type === 'alias' && selectedColl.collections.includes(','); + }; + + $scope.ping = function() { + Ping.ping({core: $scope.currentCore.name}, function(data) { + $scope.showPing = true; + $scope.pingMS = data.responseHeader.QTime; + }); + // @todo .attr( 'title', '/admin/ping is not configured (' + xhr.status + ': ' + error_thrown + ')' ); + }; + + $scope.dumpCloud = function() { + $scope.$broadcast("cloud-dump"); + } + + $scope.showCore = function(core) { + $location.url("/" + core.name + "/core-overview"); + } + + $scope.showCollection = function(collection) { + if (collection.type === 'collection') { + $location.url("/" + collection.name + "/collection-overview") + } else if (collection.type === 'alias') { + $location.url("/" + collection.name + "/alias-overview") + } + }; + + $scope.$on('$routeChangeStart', function() { + $rootScope.exceptions = {}; + }); +}); diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/alias-overview.js b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/alias-overview.js new file mode 100755 index 0000000000..a68a036231 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/alias-overview.js @@ -0,0 +1,27 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +solrAdminApp.controller('AliasOverviewController', +function($scope, $routeParams, Collections, Constants) { + $scope.resetMenu("collection-overview", Constants.IS_COLLECTION_PAGE); + + $scope.refresh = function() { + $scope.selectedCollection = $scope.currentCollection; + }; + + $scope.refresh(); +}); diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/analysis.js b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/analysis.js new file mode 100755 index 0000000000..cf04c3bcad --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/analysis.js @@ -0,0 +1,201 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +solrAdminApp.controller('AnalysisController', + function($scope, $location, $routeParams, Luke, Analysis, Constants) { + $scope.resetMenu("analysis", Constants.IS_COLLECTION_PAGE); + + $scope.refresh = function() { + Luke.schema({core: $routeParams.core}, function(data) { + $scope.fieldsAndTypes = []; + for (var field in data.schema.fields) { + $scope.fieldsAndTypes.push({ + group: "Fields", + value: "fieldname=" + field, + label: field}); + } + for (var type in data.schema.types) { + $scope.fieldsAndTypes.push({ + group: "Types", + value: "fieldtype=" + type, + label: type}); + } + $scope.core = $routeParams.core; + }); + + $scope.parseQueryString(); + // @todo - set defaultSearchField either to context["analysis.fieldname"] or context["analysis.fieldtype"] + + }; + $scope.verbose = true; + + var getShortComponentName = function(longname) { + var short = -1 !== longname.indexOf( '$' ) + ? longname.split( '$' )[1] + : longname.split( '.' ).pop(); + return short.match( /[A-Z]/g ).join( '' ); + }; + + var getCaptionsForComponent = function(data) { + var captions = []; + for (var key in data[0]) { + key = key.replace(/.*#/,''); + if (key != "match" && key!="positionHistory") { + captions.push(key.replace(/.*#/,'')); + } + } + return captions; + }; + + var getTokensForComponent = function(data) { + var tokens = []; + var previousPosition = 0; + var index=0; + for (var i in data) { + var tokenhash = data[i]; + var positionDifference = tokenhash.position - previousPosition; + for (var j=positionDifference; j>1; j--) { + tokens.push({position: tokenhash.position - j+1, blank:true, index:index++}); + } + + var token = {position: tokenhash.position, keys:[], index:index++}; + + for (key in tokenhash) { + if (key == "match" || key=="positionHistory") { + //skip, to not display these keys in the UI + } else { + var tokenInfo = new Object(); + tokenInfo.name = key; + tokenInfo.value = tokenhash[key]; + if ('text' === key || 'raw_bytes' === key ) { + if (tokenhash.match) { + tokenInfo.extraclass = 'match'; //to highlight matching text strings + } + } + token.keys.push(tokenInfo); + } + } + tokens.push(token); + previousPosition = tokenhash.position; + } + return tokens; + }; + + var extractComponents = function(data, result, name) { + if (data) { + result[name] = []; + for (var i = 0; i < data.length; i += 2) { + var component = { + name: data[i], + short: getShortComponentName(data[i]), + captions: getCaptionsForComponent(data[i + 1]), + tokens: getTokensForComponent(data[i + 1]) + }; + result[name].push(component); + } + } + }; + + var processAnalysisData = function(analysis, fieldOrType) { + var fieldname; + for (fieldname in analysis[fieldOrType]) {console.log(fieldname);break;} + var response = {}; + extractComponents(analysis[fieldOrType][fieldname].index, response, "index"); + extractComponents(analysis[fieldOrType][fieldname].query, response, "query"); + return response; + }; + + $scope.updateQueryString = function() { + + var parts = $scope.fieldOrType.split("="); + var fieldOrType = parts[0]; + var name = parts[1]; + + if ($scope.indexText) { + $location.search("analysis.fieldvalue", $scope.indexText); + } else if ($location.search()["analysis.fieldvalue"]) { + $location.search("analysis.fieldvalue", null); + } + if ($scope.queryText) { + $location.search("analysis.query", $scope.queryText); + } else if ($location.search()["analysis.query"]) { + $location.search("analysis.query", null); + } + + if (fieldOrType == "fieldname") { + $location.search("analysis.fieldname", name); + $location.search("analysis.fieldtype", null); + } else { + $location.search("analysis.fieldtype", name); + $location.search("analysis.fieldname", null); + } + $location.search("verbose_output", $scope.verbose ? "1" : "0"); + }; + + $scope.parseQueryString = function () { + var params = {}; + var search = $location.search(); + + if (Object.keys(search).length == 0) { + return; + } + for (var key in search) { + params[key]=search[key]; + } + $scope.indexText = search["analysis.fieldvalue"]; + $scope.queryText = search["analysis.query"]; + if (search["analysis.fieldname"]) { + $scope.fieldOrType = "fieldname=" + search["analysis.fieldname"]; + $scope.schemaBrowserUrl = "field=" + search["analysis.fieldname"]; + } else { + $scope.fieldOrType = "fieldtype=" + search["analysis.fieldtype"]; + $scope.schemaBrowserUrl = "type=" + search["analysis.fieldtype"]; + } + if (search["verbose_output"] == undefined) { + $scope.verbose = true; + } else { + $scope.verbose = search["verbose_output"] == "1"; + } + + if ($scope.fieldOrType || $scope.indexText || $scope.queryText) { + params.core = $routeParams.core; + var parts = $scope.fieldOrType.split("="); + var fieldOrType = parts[0] == "fieldname" ? "field_names" : "field_types"; + + Analysis.field(params, function(data) { + $scope.result = processAnalysisData(data.analysis, fieldOrType); + }); + } + }; + + $scope.changeFieldOrType = function() { + var parts = $scope.fieldOrType.split("="); + if (parts[0]=='fieldname') { + $scope.schemaBrowserUrl = "field=" + parts[1]; + } else { + $scope.schemaBrowserUrl = "type=" + parts[1]; + } + }; + + $scope.toggleVerbose = function() { + $scope.verbose = !$scope.verbose; + $scope.updateQueryString(); + }; + + $scope.refresh(); + } +); diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/cloud.js b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/cloud.js new file mode 100755 index 0000000000..976c048c96 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/cloud.js @@ -0,0 +1,1020 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +solrAdminApp.controller('CloudController', + function($scope, $location, Zookeeper, Constants, Collections, System, Metrics, ZookeeperStatus) { + + $scope.showDebug = false; + + $scope.$on("cloud-dump", function(event) { + $scope.showDebug = true; + }); + + $scope.closeDebug = function() { + $scope.showDebug = false; + }; + + var view = $location.search().view ? $location.search().view : "nodes"; + if (view === "tree") { + $scope.resetMenu("cloud-tree", Constants.IS_ROOT_PAGE); + treeSubController($scope, Zookeeper); + } else if (view === "graph") { + $scope.resetMenu("cloud-graph", Constants.IS_ROOT_PAGE); + graphSubController($scope, Zookeeper, false); + } else if (view === "nodes") { + $scope.resetMenu("cloud-nodes", Constants.IS_ROOT_PAGE); + nodesSubController($scope, Collections, System, Metrics); + } else if (view === "zkstatus") { + $scope.resetMenu("cloud-zkstatus", Constants.IS_ROOT_PAGE); + zkStatusSubController($scope, ZookeeperStatus, false); + } + } +); + +function getOrCreateObj(name, object) { + if (name in object) { + entry = object[name]; + } else { + entry = {}; + object[name] = entry; + } + return entry; +} + +function getOrCreateList(name, object) { + if (name in object) { + entry = object[name]; + } else { + entry = []; + object[name] = entry; + } + return entry; +} + +function ensureInList(string, list) { + if (list.indexOf(string) === -1) { + list.push(string); + } +} + +/* Puts a node name into the hosts structure */ +function ensureNodeInHosts(node_name, hosts) { + var hostName = node_name.split(":")[0]; + var host = getOrCreateObj(hostName, hosts); + var hostNodes = getOrCreateList("nodes", host); + ensureInList(node_name, hostNodes); +} + +// from http://scratch99.com/web-development/javascript/convert-bytes-to-mb-kb/ +function bytesToSize(bytes) { + var sizes = ['b', 'Kb', 'Mb', 'Gb', 'Tb']; + if (bytes === 0) return '0b'; + var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024))); + if (bytes === 0) return bytes + '' + sizes[i]; + return (bytes / Math.pow(1024, i)).toFixed(1) + '' + sizes[i]; +} + +function numDocsHuman(docs) { + var sizes = ['', 'k', 'mn', 'bn', 'tn']; + if (docs === 0) return '0'; + var i = parseInt(Math.floor(Math.log(docs) / Math.log(1000))); + if (i === 0) return docs + '' + sizes[i]; + return (docs / Math.pow(1000, i)).toFixed(1) + '' + sizes[i]; +} + +/* Returns a style class depending on percentage */ +var styleForPct = function (pct) { + if (pct < 60) return "pct-normal"; + if (pct < 80) return "pct-warn"; + return "pct-critical" +}; + +function isNumeric(n) { + return !isNaN(parseFloat(n)) && isFinite(n); +} + +function coreNameToLabel(name) { + return name.replace(/(.*?)_shard((\d+_?)+)_replica_?[ntp]?(\d+)/, '\$1_s\$2r\$4'); +} + +var nodesSubController = function($scope, Collections, System, Metrics) { + $scope.pageSize = 10; + $scope.showNodes = true; + $scope.showTree = false; + $scope.showGraph = false; + $scope.showData = false; + $scope.showAllDetails = false; + $scope.showDetails = {}; + $scope.from = 0; + $scope.to = $scope.pageSize - 1; + $scope.filterType = "node"; // Pre-initialize dropdown + + $scope.toggleAllDetails = function() { + $scope.showAllDetails = !$scope.showAllDetails; + for (var node in $scope.nodes) { + $scope.showDetails[node] = $scope.showAllDetails; + } + for (var host in $scope.hosts) { + $scope.showDetails[host] = $scope.showAllDetails; + } + }; + + $scope.toggleDetails = function(key) { + $scope.showDetails[key] = !$scope.showDetails[key] === true; + }; + + $scope.toggleHostDetails = function(key) { + $scope.showDetails[key] = !$scope.showDetails[key] === true; + for (var nodeId in $scope.hosts[key].nodes) { + var node = $scope.hosts[key].nodes[nodeId]; + $scope.showDetails[node] = $scope.showDetails[key]; + } + }; + + $scope.nextPage = function() { + $scope.from += parseInt($scope.pageSize); + $scope.reload(); + }; + + $scope.previousPage = function() { + $scope.from = Math.max(0, $scope.from - parseInt($scope.pageSize)); + $scope.reload(); + }; + + // Checks if this node is the first (alphabetically) for a given host. Used to decide rowspan in table + $scope.isFirstNodeForHost = function(node) { + var hostName = node.split(":")[0]; + var nodesInHost = $scope.filteredNodes.filter(function (node) { + return node.startsWith(hostName); + }); + return nodesInHost[0] === node; + }; + + // Returns the first live node for this host, to make sure we pick host-level metrics from a live node + $scope.firstLiveNodeForHost = function(key) { + var hostName = key.split(":")[0]; + var liveNodesInHost = $scope.filteredNodes.filter(function (key) { + return key.startsWith(hostName); + }).filter(function (key) { + return $scope.live_nodes.includes(key); + }); + return liveNodesInHost.length > 0 ? liveNodesInHost[0] : key; + }; + + // Initializes the cluster state, list of nodes, collections etc + $scope.initClusterState = function() { + var nodes = {}; + var hosts = {}; + var live_nodes = []; + + // We build a node-centric view of the cluster state which we can easily consume to render the table + Collections.status(function (data) { + // Fetch cluster state from collections API and invert to a nodes structure + for (var name in data.cluster.collections) { + var collection = data.cluster.collections[name]; + collection.name = name; + var shards = collection.shards; + collection.shards = []; + for (var shardName in shards) { + var shard = shards[shardName]; + shard.name = shardName; + shard.collection = collection.name; + var replicas = shard.replicas; + shard.replicas = []; + for (var replicaName in replicas) { + var core = replicas[replicaName]; + core.name = replicaName; + core.label = coreNameToLabel(core['core']); + core.collection = collection.name; + core.shard = shard.name; + core.shard_state = shard.state; + + var node_name = core['node_name']; + var node = getOrCreateObj(node_name, nodes); + var cores = getOrCreateList("cores", node); + cores.push(core); + node['base_url'] = core.base_url; + node['id'] = core.base_url.replace(/[^\w\d]/g, ''); + node['host'] = node_name.split(":")[0]; + var collections = getOrCreateList("collections", node); + ensureInList(core.collection, collections); + ensureNodeInHosts(node_name, hosts); + } + } + } + + live_nodes = data.cluster.live_nodes; + for (n in data.cluster.live_nodes) { + node = data.cluster.live_nodes[n]; + if (!(node in nodes)) { + var hostName = node.split(":")[0]; + nodes[node] = {}; + nodes[node]['host'] = hostName; + } + ensureNodeInHosts(node, hosts); + } + + // Make sure nodes are sorted alphabetically to align with rowspan in table + for (var host in hosts) { + hosts[host].nodes.sort(); + } + + $scope.nodes = nodes; + $scope.hosts = hosts; + $scope.live_nodes = live_nodes; + + $scope.Math = window.Math; + $scope.reload(); + }); + }; + + $scope.filterInput = function() { + $scope.from = 0; + $scope.to = $scope.pageSize - 1; + $scope.reload(); + }; + + /* + Reload will fetch data for the current page of the table and thus refresh numbers. + It is also called whenever a filter or paging action is executed + */ + $scope.reload = function() { + var nodes = $scope.nodes; + var node_keys = Object.keys(nodes); + var hosts = $scope.hosts; + var live_nodes = $scope.live_nodes; + var hostNames = Object.keys(hosts); + hostNames.sort(); + var pageSize = isNumeric($scope.pageSize) ? $scope.pageSize : 10; + + // Calculate what nodes that will show on this page + var nodesToShow = []; + var nodesParam; + var hostsToShow = []; + var filteredNodes; + var filteredHosts; + var isFiltered = false; + switch ($scope.filterType) { + case "node": // Find what nodes match the node filter + if ($scope.nodeFilter) { + filteredNodes = node_keys.filter(function (node) { + return node.indexOf($scope.nodeFilter) !== -1; + }); + } + break; + + case "collection": // Find what collections match the collection filter and what nodes that have these collections + if ($scope.collectionFilter) { + candidateNodes = {}; + nodesCollections = []; + for (var i = 0 ; i < node_keys.length ; i++) { + var node_name = node_keys[i]; + var node = nodes[node_name]; + nodeColl = {}; + nodeColl['node'] = node_name; + collections = {}; + node.cores.forEach(function(core) { + collections[core.collection] = true; + }); + nodeColl['collections'] = Object.keys(collections); + nodesCollections.push(nodeColl); + } + nodesCollections.forEach(function(nc) { + matchingColls = nc['collections'].filter(function (collection) { + return collection.indexOf($scope.collectionFilter) !== -1; + }); + if (matchingColls.length > 0) { + candidateNodes[nc.node] = true; + } + }); + filteredNodes = Object.keys(candidateNodes); + } + break; + + case "health": + + } + + if (filteredNodes) { + // If filtering is active, calculate what hosts contain the nodes that match the filters + isFiltered = true; + filteredHosts = filteredNodes.map(function (node) { + return node.split(":")[0]; + }).filter(function (item, index, self) { + return self.indexOf(item) === index; + }); + } else { + filteredNodes = node_keys; + filteredHosts = hostNames; + } + filteredNodes.sort(); + filteredHosts.sort(); + + // Find what hosts & nodes (from the filtered set) that should be displayed on current page + for (var id = $scope.from ; id < $scope.from + pageSize && filteredHosts[id] ; id++) { + var hostName = filteredHosts[id]; + hostsToShow.push(hostName); + if (isFiltered) { // Only show the nodes per host matching active filter + nodesToShow = nodesToShow.concat(filteredNodes.filter(function (node) { + return node.startsWith(hostName); + })); + } else { + nodesToShow = nodesToShow.concat(hosts[hostName]['nodes']); + } + } + nodesParam = nodesToShow.filter(function (node) { + return live_nodes.includes(node); + }).join(','); + var deadNodes = nodesToShow.filter(function (node) { + return !live_nodes.includes(node); + }); + deadNodes.forEach(function (node) { + nodes[node]['dead'] = true; + }); + $scope.nextEnabled = $scope.from + pageSize < filteredHosts.length; + $scope.prevEnabled = $scope.from - pageSize >= 0; + nodesToShow.sort(); + hostsToShow.sort(); + + /* + Fetch system info for all selected nodes + Pick the data we want to display and add it to the node-centric data structure + */ + System.get({"nodes": nodesParam}, function (systemResponse) { + for (var node in systemResponse) { + if (node in nodes) { + var s = systemResponse[node]; + nodes[node]['system'] = s; + var memTotal = s.system.totalPhysicalMemorySize; + var memFree = s.system.freePhysicalMemorySize; + var memPercentage = Math.floor((memTotal - memFree) / memTotal * 100); + nodes[node]['memUsedPct'] = memPercentage; + nodes[node]['memUsedPctStyle'] = styleForPct(memPercentage); + nodes[node]['memTotal'] = bytesToSize(memTotal); + nodes[node]['memFree'] = bytesToSize(memFree); + nodes[node]['memUsed'] = bytesToSize(memTotal - memFree); + + var heapTotal = s.jvm.memory.raw.total; + var heapFree = s.jvm.memory.raw.free; + var heapPercentage = Math.floor((heapTotal - heapFree) / heapTotal * 100); + nodes[node]['heapUsed'] = bytesToSize(heapTotal - heapFree); + nodes[node]['heapUsedPct'] = heapPercentage; + nodes[node]['heapUsedPctStyle'] = styleForPct(heapPercentage); + nodes[node]['heapTotal'] = bytesToSize(heapTotal); + nodes[node]['heapFree'] = bytesToSize(heapFree); + + var jvmUptime = s.jvm.jmx.upTimeMS / 1000; // Seconds + nodes[node]['jvmUptime'] = secondsForHumans(jvmUptime); + nodes[node]['jvmUptimeSec'] = jvmUptime; + + nodes[node]['uptime'] = (s.system.uptime || "unknown").replace(/.*up (.*?,.*?),.*/, "$1"); + nodes[node]['loadAvg'] = Math.round(s.system.systemLoadAverage * 100) / 100; + nodes[node]['cpuPct'] = Math.ceil(s.system.processCpuLoad); + nodes[node]['cpuPctStyle'] = styleForPct(Math.ceil(s.system.processCpuLoad)); + nodes[node]['maxFileDescriptorCount'] = s.system.maxFileDescriptorCount; + nodes[node]['openFileDescriptorCount'] = s.system.openFileDescriptorCount; + } + } + }); + + /* + Fetch metrics for all selected nodes. Only pull the metrics that we'll show to save bandwidth + Pick the data we want to display and add it to the node-centric data structure + */ + Metrics.get({ + "nodes": nodesParam, + "prefix": "CONTAINER.fs,org.eclipse.jetty.server.handler.DefaultHandler.get-requests,INDEX.sizeInBytes,SEARCHER.searcher.numDocs,SEARCHER.searcher.deletedDocs,SEARCHER.searcher.warmupTime" + }, + function (metricsResponse) { + for (var node in metricsResponse) { + if (node in nodes) { + var m = metricsResponse[node]; + nodes[node]['metrics'] = m; + var diskTotal = m.metrics['solr.node']['CONTAINER.fs.totalSpace']; + var diskFree = m.metrics['solr.node']['CONTAINER.fs.usableSpace']; + var diskPercentage = Math.floor((diskTotal - diskFree) / diskTotal * 100); + nodes[node]['diskUsedPct'] = diskPercentage; + nodes[node]['diskUsedPctStyle'] = styleForPct(diskPercentage); + nodes[node]['diskTotal'] = bytesToSize(diskTotal); + nodes[node]['diskFree'] = bytesToSize(diskFree); + + var r = m.metrics['solr.jetty']['org.eclipse.jetty.server.handler.DefaultHandler.get-requests']; + nodes[node]['req'] = r.count; + nodes[node]['req1minRate'] = Math.floor(r['1minRate'] * 100) / 100; + nodes[node]['req5minRate'] = Math.floor(r['5minRate'] * 100) / 100; + nodes[node]['req15minRate'] = Math.floor(r['15minRate'] * 100) / 100; + nodes[node]['reqp75_ms'] = Math.floor(r['p75_ms']); + nodes[node]['reqp95_ms'] = Math.floor(r['p95_ms']); + nodes[node]['reqp99_ms'] = Math.floor(r['p99_ms']); + + var cores = nodes[node]['cores']; + var indexSizeTotal = 0; + var docsTotal = 0; + var graphData = []; + if (cores) { + for (coreId in cores) { + var core = cores[coreId]; + var keyName = "solr.core." + core['core'].replace(/(.*?)_(shard(\d+_?)+)_(replica.*?)/, '\$1.\$2.\$4'); + var nodeMetric = m.metrics[keyName]; + var size = nodeMetric['INDEX.sizeInBytes']; + size = (typeof size !== 'undefined') ? size : 0; + core['sizeInBytes'] = size; + core['size'] = bytesToSize(size); + if (core['shard_state'] !== 'active' || core['state'] !== 'active') { + // If core state is not active, display the real state, or if shard is inactive, display that + var labelState = (core['state'] !== 'active') ? core['state'] : core['shard_state']; + core['label'] += "_(" + labelState + ")"; + } + indexSizeTotal += size; + var numDocs = nodeMetric['SEARCHER.searcher.numDocs']; + numDocs = (typeof numDocs !== 'undefined') ? numDocs : 0; + core['numDocs'] = numDocs; + core['numDocsHuman'] = numDocsHuman(numDocs); + core['avgSizePerDoc'] = bytesToSize(numDocs === 0 ? 0 : size / numDocs); + var deletedDocs = nodeMetric['SEARCHER.searcher.deletedDocs']; + deletedDocs = (typeof deletedDocs !== 'undefined') ? deletedDocs : 0; + core['deletedDocs'] = deletedDocs; + core['deletedDocsHuman'] = numDocsHuman(deletedDocs); + var warmupTime = nodeMetric['SEARCHER.searcher.warmupTime']; + warmupTime = (typeof warmupTime !== 'undefined') ? warmupTime : 0; + core['warmupTime'] = warmupTime; + docsTotal += core['numDocs']; + } + for (coreId in cores) { + core = cores[coreId]; + var graphObj = {}; + graphObj['label'] = core['label']; + graphObj['size'] = core['sizeInBytes']; + graphObj['sizeHuman'] = core['size']; + graphObj['pct'] = (core['sizeInBytes'] / indexSizeTotal) * 100; + graphData.push(graphObj); + } + cores.sort(function (a, b) { + return b.sizeInBytes - a.sizeInBytes + }); + } else { + cores = {}; + } + graphData.sort(function (a, b) { + return b.size - a.size + }); + nodes[node]['graphData'] = graphData; + nodes[node]['numDocs'] = numDocsHuman(docsTotal); + nodes[node]['sizeInBytes'] = indexSizeTotal; + nodes[node]['size'] = bytesToSize(indexSizeTotal); + nodes[node]['sizePerDoc'] = docsTotal === 0 ? '0b' : bytesToSize(indexSizeTotal / docsTotal); + + // Build the d3 powered bar chart + $('#chart' + nodes[node]['id']).empty(); + var chart = d3.select('#chart' + nodes[node]['id']).append('div').attr('class', 'chart'); + + // Add one div per bar which will group together both labels and bars + var g = chart.selectAll('div') + .data(nodes[node]['graphData']).enter() + .append('div'); + + // Add the bars + var bars = g.append("div") + .attr("class", "rect") + .text(function (d) { + return d.label + ':\u00A0\u00A0' + d.sizeHuman; + }); + + // Execute the transition to show the bars + bars.transition() + .ease('elastic') + .style('width', function (d) { + return d.pct + '%'; + }); + } + } + }); + $scope.nodes = nodes; + $scope.hosts = hosts; + $scope.live_nodes = live_nodes; + $scope.nodesToShow = nodesToShow; + $scope.hostsToShow = hostsToShow; + $scope.filteredNodes = filteredNodes; + $scope.filteredHosts = filteredHosts; + }; + $scope.initClusterState(); +}; + +var zkStatusSubController = function($scope, ZookeeperStatus) { + $scope.showZkStatus = true; + $scope.showNodes = false; + $scope.showTree = false; + $scope.showGraph = false; + $scope.tree = {}; + $scope.showData = false; + $scope.showDetails = false; + + $scope.toggleDetails = function() { + $scope.showDetails = !$scope.showDetails === true; + }; + + $scope.initZookeeper = function() { + ZookeeperStatus.monitor({}, function(data) { + $scope.zkState = data.zkStatus; + $scope.mainKeys = ["ok", "clientPort", "secureClientPort", "zk_server_state", "zk_version", + "zk_approximate_data_size", "zk_znode_count", "zk_num_alive_connections"]; + $scope.detailKeys = ["dataDir", "dataLogDir", + "zk_avg_latency", "zk_max_file_descriptor_count", "zk_watch_count", + "zk_packets_sent", "zk_packets_received", + "tickTime", "maxClientCnxns", "minSessionTimeout", "maxSessionTimeout"]; + $scope.ensembleMainKeys = ["serverId", "electionPort", "quorumPort", "role"]; + $scope.ensembleDetailKeys = ["peerType", "electionAlg", "initLimit", "syncLimit", + "zk_followers", "zk_synced_followers", "zk_pending_syncs"]; + $scope.notEmptyRow = function(key) { + for (hostId in $scope.zkState.details) { + if (key in $scope.zkState.details[hostId]) return true; + } + return false; + }; + }); + }; + + $scope.initZookeeper(); +}; + +var treeSubController = function($scope, Zookeeper) { + $scope.showZkStatus = false; + $scope.showTree = true; + $scope.showGraph = false; + $scope.tree = {}; + $scope.showData = false; + + $scope.showTreeLink = function(link) { + var path = decodeURIComponent(link.replace(/.*[\\?&]path=([^&#]*).*/, "$1")); + Zookeeper.detail({path: path}, function(data) { + $scope.znode = data.znode; + var path = data.znode.path.split( '.' ); + if(path.length >1) { + $scope.lang = path.pop(); + } else { + var lastPathElement = data.znode.path.split( '/' ).pop(); + if (lastPathElement == "managed-schema") { + $scope.lang = "xml"; + } + } + $scope.showData = true; + }); + }; + + $scope.hideData = function() { + $scope.showData = false; + }; + + $scope.initTree = function() { + Zookeeper.simple(function(data) { + $scope.tree = data.tree; + }); + }; + + $scope.initTree(); +}; + +/** + * Translates seconds into human readable format of seconds, minutes, hours, days, and years + * + * @param {number} seconds The number of seconds to be processed + * @return {string} The phrase describing the the amount of time + */ +function secondsForHumans ( seconds ) { + var levels = [ + [Math.floor(seconds / 31536000), 'y'], + [Math.floor((seconds % 31536000) / 86400), 'd'], + [Math.floor(((seconds % 31536000) % 86400) / 3600), 'h'], + [Math.floor((((seconds % 31536000) % 86400) % 3600) / 60), 'm'] + ]; + var returntext = ''; + + for (var i = 0, max = levels.length; i < max; i++) { + if ( levels[i][0] === 0 ) continue; + returntext += ' ' + levels[i][0] + levels[i][1]; + } + return returntext.trim() === '' ? '0m' : returntext.trim(); +} + +var graphSubController = function ($scope, Zookeeper) { + $scope.showZkStatus = false; + $scope.showTree = false; + $scope.showGraph = true; + + $scope.filterType = "status"; + + $scope.helperData = { + protocol: [], + host: [], + hostname: [], + port: [], + pathname: [], + replicaType: [], + base_url: [], + core: [], + node_name: [], + state: [], + core_node: [] + }; + + $scope.next = function() { + $scope.pos += $scope.rows; + $scope.initGraph(); + }; + + $scope.previous = function() { + $scope.pos = Math.max(0, $scope.pos - $scope.rows); + $scope.initGraph(); + }; + + $scope.resetGraph = function() { + $scope.pos = 0; + $scope.initGraph(); + }; + + $scope.initGraph = function() { + Zookeeper.liveNodes(function (data) { + var live_nodes = {}; + for (var c in data.tree[0].children) { + live_nodes[data.tree[0].children[c].text] = true; + } + + var params = {view: "graph"}; + if ($scope.rows) { + params.start = $scope.pos; + params.rows = $scope.rows; + } + + var filter = ($scope.filterType=='status') ? $scope.pagingStatusFilter : $scope.pagingFilter; + + if (filter) { + params.filterType = $scope.filterType; + params.filter = filter; + } + + Zookeeper.clusterState(params, function (data) { + var state = $.parseJSON(data.znode.data); + + var leaf_count = 0; + var graph_data = { + name: null, + children: [] + }; + + for (var c in state) { + var shards = []; + for (var s in state[c].shards) { + var shard_status = state[c].shards[s].state; + shard_status = shard_status == 'inactive' ? 'shard-inactive' : shard_status; + var nodes = []; + for (var n in state[c].shards[s].replicas) { + leaf_count++; + var replica = state[c].shards[s].replicas[n] + + var uri = replica.base_url; + var parts = uri.match(/^(\w+:)\/\/(([\w\d\.-]+)(:(\d+))?)(.+)$/); + var uri_parts = { + protocol: parts[1], + host: parts[2], + hostname: parts[3], + port: parseInt(parts[5] || 80, 10), + pathname: parts[6], + replicaType: replica.type, + base_url: replica.base_url, + core: replica.core, + node_name: replica.node_name, + state: replica.state, + core_node: n + }; + + $scope.helperData.protocol.push(uri_parts.protocol); + $scope.helperData.host.push(uri_parts.host); + $scope.helperData.hostname.push(uri_parts.hostname); + $scope.helperData.port.push(uri_parts.port); + $scope.helperData.pathname.push(uri_parts.pathname); + $scope.helperData.replicaType.push(uri_parts.replicaType); + $scope.helperData.base_url.push(uri_parts.base_url); + $scope.helperData.core.push(uri_parts.core); + $scope.helperData.node_name.push(uri_parts.node_name); + $scope.helperData.state.push(uri_parts.state); + $scope.helperData.core_node.push(uri_parts.core_node); + + var replica_status = replica.state; + + if (!live_nodes[replica.node_name]) { + replica_status = 'gone'; + } else if(shard_status=='shard-inactive') { + replica_status += ' ' + shard_status; + } + + var node = { + name: uri, + data: { + type: 'node', + state: replica_status, + leader: 'true' === replica.leader, + uri: uri_parts + } + }; + nodes.push(node); + } + + var shard = { + name: shard_status == "shard-inactive" ? s + ' (inactive)' : s, + data: { + type: 'shard', + state: shard_status, + range: state[c].shards[s].range + + }, + children: nodes + }; + shards.push(shard); + } + + var collection = { + name: c, + data: { + type: 'collection', + pullReplicas: state[c].pullReplicas, + replicationFactor: state[c].replicationFactor, + router: state[c].router.name, + maxShardsPerNode: state[c].maxShardsPerNode, + autoAddReplicas: state[c].autoAddReplicas, + nrtReplicas: state[c].nrtReplicas, + tlogReplicas: state[c].tlogReplicas, + numShards: shards.length + }, + children: shards + }; + graph_data.children.push(collection); + } + $scope.helperData.protocol = $.unique($scope.helperData.protocol); + $scope.helperData.host = $.unique($scope.helperData.host); + $scope.helperData.hostname = $.unique($scope.helperData.hostname); + $scope.helperData.port = $.unique($scope.helperData.port); + $scope.helperData.pathname = $.unique($scope.helperData.pathname); + $scope.helperData.replicaType = $.unique($scope.helperData.replicaType); + $scope.helperData.base_url = $.unique($scope.helperData.base_url); + $scope.helperData.core = $.unique($scope.helperData.core); + $scope.helperData.node_name = $.unique($scope.helperData.node_name); + $scope.helperData.state = $.unique($scope.helperData.state); + $scope.helperData.core_node = $.unique($scope.helperData.core_node); + + if (data.znode && data.znode.paging) { + $scope.showPaging = true; + + var parr = data.znode.paging.split('|'); + if (parr.length < 3) { + $scope.showPaging = false; + } else { + $scope.start = Math.max(parseInt(parr[0]), 0); + $scope.prevEnabled = ($scope.start > 0); + $scope.rows = parseInt(parr[1]); + $scope.total = parseInt(parr[2]); + + if ($scope.rows == -1) { + $scope.showPaging = false; + } else { + var filterType = parr.length > 3 ? parr[3] : ''; + + if (filterType == '' || filterType == 'none') filterType = 'status'; + + +$('#cloudGraphPagingFilterType').val(filterType); + + var filter = parr.length > 4 ? parr[4] : ''; + var page = Math.floor($scope.start / $scope.rows) + 1; + var pages = Math.ceil($scope.total / $scope.rows); + $scope.last = Math.min($scope.start + $scope.rows, $scope.total); + $scope.nextEnabled = ($scope.last < $scope.total); + } + } + } + else { + $scope.showPaging = false; + } + $scope.graphData = graph_data; + $scope.leafCount = leaf_count; + }); + }); + }; + + $scope.initGraph(); + $scope.pos = 0; +}; + +solrAdminApp.directive('graph', function(Constants) { + return { + restrict: 'EA', + scope: { + data: "=", + leafCount: "=", + helperData: "=", + }, + link: function (scope, element, attrs) { + var helper_path_class = function (p) { + var classes = ['link']; + classes.push('lvl-' + p.target.depth); + + if (p.target.data && p.target.data.leader) { + classes.push('leader'); + } + + if (p.target.data && p.target.data.state) { + classes.push(p.target.data.state); + } + + return classes.join(' '); + }; + + var helper_node_class = function (d) { + var classes = ['node']; + classes.push('lvl-' + d.depth); + + if (d.data && d.data.leader) { + classes.push('leader'); + } + + if (d.data && d.data.state) { + if(!(d.data.type=='shard' && d.data.state=='active')){ + classes.push(d.data.state); + } + } + + return classes.join(' '); + }; + + var helper_tooltip_text = function (d) { + if (!d.data) { + return tooltip; + } + var tooltip; + + if (! d.data.type) { + return tooltip; + } + + + if (d.data.type == 'collection') { + tooltip = d.name + " {
"; + tooltip += "numShards: [" + d.data.numShards + "],
"; + tooltip += "maxShardsPerNode: [" + d.data.maxShardsPerNode + "],
"; + tooltip += "router: [" + d.data.router + "],
"; + tooltip += "autoAddReplicas: [" + d.data.autoAddReplicas + "],
"; + tooltip += "replicationFactor: [" + d.data.replicationFactor + "],
"; + tooltip += "nrtReplicas: [" + d.data.nrtReplicas + "],
"; + tooltip += "pullReplicas: [" + d.data.pullReplicas + "],
"; + tooltip += "tlogReplicas: [" + d.data.tlogReplicas + "],
"; + tooltip += "}"; + } else if (d.data.type == 'shard') { + tooltip = d.name + " {
"; + tooltip += "range: [" + d.data.range + "],
"; + tooltip += "state: [" + d.data.state + "],
"; + tooltip += "}"; + } else if (d.data.type == 'node') { + tooltip = d.data.uri.core_node + " {
"; + + if (0 !== scope.helperData.core.length) { + tooltip += "core: [" + d.data.uri.core + "],
"; + } + + if (0 !== scope.helperData.node_name.length) { + tooltip += "node_name: [" + d.data.uri.node_name + "],
"; + } + tooltip += "}"; + } + + return tooltip; + }; + + var helper_node_text = function (d) { + if (!d.data || !d.data.uri) { + return d.name; + } + + var name = d.data.uri.hostname; + if (1 !== scope.helperData.protocol.length) { + name = d.data.uri.protocol + '//' + name; + } + + if (1 !== scope.helperData.port.length) { + name += ':' + d.data.uri.port; + } + + if (1 !== scope.helperData.pathname.length) { + name += d.data.uri.pathname; + } + + if(0 !== scope.helperData.replicaType.length) { + name += ' (' + d.data.uri.replicaType[0] + ')'; + } + + return name; + }; + + scope.$watch("data", function(newValue, oldValue) { + if (newValue) { + flatGraph(element, scope.data, scope.leafCount); + } + + $('text').tooltip({ + content: function() { + return $(this).attr('title'); + } + }); + }); + + + function setNodeNavigationBehavior(node, view){ + node + .attr('data-href', function (d) { + if (d.type == "node"){ + return getNodeUrl(d, view); + } + else{ + return ""; + } + }) + .on('click', function(d) { + if (d.data.type == "node"){ + location.href = getNodeUrl(d, view); + } + }); + } + + function getNodeUrl(d, view){ + var url = d.name + Constants.ROOT_URL + "#/~cloud"; + if (view != undefined){ + url += "?view=" + view; + } + return url; + } + + var flatGraph = function(element, graphData, leafCount) { + var w = element.width(), + h = leafCount * 20; + + var tree = d3.layout.tree().size([h, w - 400]); + + var diagonal = d3.svg.diagonal().projection(function (d) { + return [d.y, d.x]; + }); + + d3.select('#canvas', element).html(''); + var vis = d3.select('#canvas', element).append('svg') + .attr('width', w) + .attr('height', h) + .append('g') + .attr('transform', 'translate(100, 0)'); + + var nodes = tree.nodes(graphData); + + var link = vis.selectAll('path.link') + .data(tree.links(nodes)) + .enter().append('path') + .attr('class', helper_path_class) + .attr('d', diagonal); + + var node = vis.selectAll('g.node') + .data(nodes) + .enter().append('g') + .attr('class', helper_node_class) + .attr('transform', function (d) { + return 'translate(' + d.y + ',' + d.x + ')'; + }) + + node.append('circle') + .attr('r', 4.5); + + node.append('text') + .attr('dx', function (d) { + return 0 === d.depth ? -8 : 8; + }) + .attr('dy', function (d) { + return 5; + }) + .attr('text-anchor', function (d) { + return 0 === d.depth ? 'end' : 'start'; + }) + .attr("title", helper_tooltip_text) + .text(helper_node_text); + + setNodeNavigationBehavior(node); + }; + } + }; +}); diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/cluster-suggestions.js b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/cluster-suggestions.js new file mode 100755 index 0000000000..4e39129f2c --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/cluster-suggestions.js @@ -0,0 +1,62 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +solrAdminApp.controller('ClusterSuggestionsController', +function($scope, $http, Constants) { + $scope.resetMenu("cluster-suggestion", Constants.IS_COLLECTION_PAGE); + $scope.data={}; + var dataArr =[]; + var dataJson = {}; + //function to display suggestion + $http({ + method: 'GET', + url: '/api/cluster/autoscaling/suggestions' + }).then(function successCallback(response) { + $scope.data = response.data; + $scope.parsedData = $scope.data.suggestions; + }, function errorCallback(response) { + }); + //function to perform operation + $scope.postdata = function (x) { + x.loading = true; + var path=x.operation.path; + var command=x.operation.command; + var fullPath='/api/'+path; + console.log(fullPath); + console.log(command); + $http.post(fullPath, JSON.stringify(command)).then(function (response) { + if (response.data) + console.log(response.data); + x.loading = false; + x.done = true; + x.run=true; + $scope.msg = "Command Submitted Successfully!"; + }, function (response) { + x.failed=true; + $scope.msg = "Service does not exist"; + $scope.statusval = response.status; + $scope.statustext = response.statusText; + $scope.headers = response.headers(); + }); + }; + $scope.showPopover = function() { + $scope.popup = true; + }; + + $scope.hidePopover = function () { + $scope.popup = false; + }; +}); diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/collection-overview.js b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/collection-overview.js new file mode 100755 index 0000000000..a98456a7b3 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/collection-overview.js @@ -0,0 +1,39 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +solrAdminApp.controller('CollectionOverviewController', +function($scope, $routeParams, Collections, Constants) { + $scope.resetMenu("collection-overview", Constants.IS_COLLECTION_PAGE); + + $scope.refresh = function() { + Collections.status({}, function(data) { + $scope.selectedCollection = data.cluster.collections[$routeParams.core]; + $scope.selectedCollection.name = $routeParams.core; + $scope.rootUrl = Constants.ROOT_URL; + }); + }; + + $scope.showReplica = function(replica) { + replica.show = !replica.show; + } + + $scope.hideShard = function(shard) { + shard.hide = !shard.hide; + } + + $scope.refresh(); +}); diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/collections.js b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/collections.js new file mode 100755 index 0000000000..480a8b2fa0 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/collections.js @@ -0,0 +1,289 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +solrAdminApp.controller('CollectionsController', + function($scope, $routeParams, $location, $timeout, Collections, Zookeeper, Constants){ + $scope.resetMenu("collections", Constants.IS_ROOT_PAGE); + + $scope.refresh = function() { + + $scope.rootUrl = Constants.ROOT_URL + "#/~collections/" + $routeParams.collection; + + Collections.status(function (data) { + $scope.collections = []; + for (var name in data.cluster.collections) { + var collection = data.cluster.collections[name]; + collection.name = name; + collection.type = 'collection'; + var shards = collection.shards; + collection.shards = []; + for (var shardName in shards) { + var shard = shards[shardName]; + shard.name = shardName; + shard.collection = collection.name; + var replicas = shard.replicas; + shard.replicas = []; + for (var replicaName in replicas) { + var replica = replicas[replicaName]; + replica.name = replicaName; + replica.collection = collection.name; + replica.shard = shard.name; + shard.replicas.push(replica); + } + collection.shards.push(shard); + } + $scope.collections.push(collection); + if ($routeParams.collection == name) { + $scope.collection = collection; + } + } + // Fetch aliases using LISTALIASES to get properties + Collections.listaliases(function (adata) { + // TODO: Population of aliases array duplicated in app.js + $scope.aliases = []; + for (var key in adata.aliases) { + props = {}; + if (key in adata.properties) { + props = adata.properties[key]; + } + var alias = {name: key, collections: adata.aliases[key], type: 'alias', properties: props}; + $scope.aliases.push(alias); + if ($routeParams.collection == 'alias_' + key) { + $scope.collection = alias; + } + } + // Decide what is selected in list + if ($routeParams.collection && !$scope.collection) { + alert("No collection or alias called " + $routeParams.collection); + $location.path("/~collections"); + } + }); + + $scope.liveNodes = data.cluster.liveNodes; + }); + Zookeeper.configs(function(data) { + $scope.configs = []; + var items = data.tree[0].children; + for (var i in items) { + $scope.configs.push({name: items[i].text}); + } + }); + }; + + $scope.hideAll = function() { + $scope.showRename = false; + $scope.showAdd = false; + $scope.showDelete = false; + $scope.showSwap = false; + $scope.showCreateAlias = false; + $scope.showDeleteAlias = false; + }; + + $scope.showAddCollection = function() { + $scope.hideAll(); + $scope.showAdd = true; + $scope.newCollection = { + name: "", + routerName: "compositeId", + numShards: 1, + configName: "", + replicationFactor: 1, + maxShardsPerNode: 1, + autoAddReplicas: 'false' + }; + }; + + $scope.toggleCreateAlias = function() { + $scope.hideAll(); + $scope.showCreateAlias = true; + } + + $scope.toggleDeleteAlias = function() { + $scope.hideAll(); + $scope.showDeleteAlias = true; + } + + $scope.cancelCreateAlias = $scope.cancelDeleteAlias = function() { + $scope.hideAll(); + } + + $scope.createAlias = function() { + var collections = []; + for (var i in $scope.aliasCollections) { + collections.push($scope.aliasCollections[i].name); + } + Collections.createAlias({name: $scope.aliasToCreate, collections: collections.join(",")}, function(data) { + $scope.cancelCreateAlias(); + $scope.resetMenu("collections", Constants.IS_ROOT_PAGE); + $location.path("/~collections/alias_" + $scope.aliasToCreate); + }); + } + $scope.deleteAlias = function() { + Collections.deleteAlias({name: $scope.collection.name}, function(data) { + $scope.hideAll(); + $scope.resetMenu("collections", Constants.IS_ROOT_PAGE); + $location.path("/~collections/"); + }); + + }; + $scope.addCollection = function() { + if (!$scope.newCollection.name) { + $scope.addMessage = "Please provide a core name"; + } else if (false) { //@todo detect whether core exists + $scope.AddMessage = "A core with that name already exists"; + } else { + var coll = $scope.newCollection; + var params = { + name: coll.name, + "router.name": coll.routerName, + numShards: coll.numShards, + "collection.configName": coll.configName, + replicationFactor: coll.replicationFactor, + maxShardsPerNode: coll.maxShardsPerNode, + autoAddReplicas: coll.autoAddReplicas + }; + if (coll.shards) params.shards = coll.shards; + if (coll.routerField) params["router.field"] = coll.routerField; + Collections.add(params, function(data) { + $scope.cancelAddCollection(); + $scope.resetMenu("collections", Constants.IS_ROOT_PAGE); + $location.path("/~collections/" + $scope.newCollection.name); + }); + } + }; + + $scope.cancelAddCollection = function() { + delete $scope.addMessage; + $scope.showAdd = false; + }; + + $scope.showDeleteCollection = function() { + $scope.hideAll(); + if ($scope.collection) { + $scope.showDelete = true; + } else { + alert("No collection selected."); + } + }; + + $scope.deleteCollection = function() { + if ($scope.collection.name == $scope.collectionDeleteConfirm) { + Collections.delete({name: $scope.collection.name}, function (data) { + $location.path("/~collections"); + }); + } else { + $scope.deleteMessage = "Collection names do not match."; + } + }; + + $scope.reloadCollection = function() { + if (!$scope.collection) { + alert("No collection selected."); + return; + } + Collections.reload({name: $scope.collection.name}, + function(successData) { + $scope.reloadSuccess = true; + $timeout(function() {$scope.reloadSuccess=false}, 1000); + }, + function(failureData) { + $scope.reloadFailure = true; + $timeout(function() {$scope.reloadFailure=false}, 1000); + $location.path("/~collections"); + }); + }; + + $scope.toggleAddReplica = function(shard) { + $scope.hideAll(); + shard.showAdd = !shard.showAdd; + delete $scope.addReplicaMessage; + + Zookeeper.liveNodes({}, function(data) { + $scope.nodes = []; + var children = data.tree[0].children; + for (var child in children) { + $scope.nodes.push(children[child].data.title); + } + }); + }; + + $scope.toggleRemoveReplica = function(replica) { + $scope.hideAll(); + replica.showRemove = !replica.showRemove; + }; + + $scope.toggleRemoveShard = function(shard) { + $scope.hideAll(); + shard.showRemove = !shard.showRemove; + }; + + $scope.deleteShard = function(shard) { + Collections.deleteShard({collection: shard.collection, shard:shard.name}, function(data) { + shard.deleted = true; + $timeout(function() { + $scope.refresh(); + }, 2000); + }); + } + + $scope.deleteReplica = function(replica) { + Collections.deleteReplica({collection: replica.collection, shard:replica.shard, replica:replica.name}, function(data) { + replica.deleted = true; + $timeout(function() { + $scope.refresh(); + }, 2000); + }); + } + $scope.addReplica = function(shard) { + var params = { + collection: shard.collection, + shard: shard.name, + } + if (shard.replicaNodeName && shard.replicaNodeName != "") { + params.node = shard.replicaNodeName; + } + Collections.addReplica(params, function(data) { + shard.replicaAdded = true; + $timeout(function () { + shard.replicaAdded = false; + shard.showAdd = false; + $$scope.refresh(); + }, 2000); + }); + }; + + $scope.toggleShard = function(shard) { + shard.show = !shard.show; + } + + $scope.toggleReplica = function(replica) { + replica.show = !replica.show; + } + + $scope.refresh(); + } +); + +var flatten = function(data) { + var list = []; + for (var name in data) { + var entry = data[name]; + entry.name = name; + list.push(entry); + } + return list; +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/core-overview.js b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/core-overview.js new file mode 100755 index 0000000000..8f86575669 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/core-overview.js @@ -0,0 +1,93 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +solrAdminApp.controller('CoreOverviewController', +function($scope, $rootScope, $routeParams, Luke, CoreSystem, Update, Replication, Ping, Constants) { + $scope.resetMenu("overview", Constants.IS_CORE_PAGE); + $scope.refreshIndex = function() { + Luke.index({core: $routeParams.core}, + function(data) { + $scope.index = data.index; + delete $scope.statsMessage; + }, + function(error) { + $scope.statsMessage = "Luke is not configured"; + } + ); + }; + + $scope.refreshReplication = function() { + Replication.details({core: $routeParams.core}, + function(data) { + $scope.isSlave = data.details.isSlave == "true"; + $scope.isMaster = data.details.isMaster == "true"; + $scope.replication = data.details; + }, + function(error) { + $scope.replicationMessage = "Replication is not configured"; + }); + }; + + $scope.refreshSystem = function() { + CoreSystem.get({core: $routeParams.core}, + function(data) { + $scope.core = data.core; + delete $scope.systemMessage; + }, + function(error) { + $scope.systemMessage = "/admin/system Handler is not configured"; + } + ); + }; + + $scope.refreshPing = function() { + Ping.status({core: $routeParams.core}, function(data) { + if (data.error) { + $scope.healthcheckStatus = false; + if (data.error.code == 503) { + $scope.healthcheckMessage = 'Ping request handler is not configured with a healthcheck file.'; + } + } else { + $scope.healthcheckStatus = data.status == "enabled"; + } + }); + }; + + $scope.toggleHealthcheck = function() { + if ($scope.healthcheckStatus) { + Ping.disable( + function(data) {$scope.healthcheckStatus = false}, + function(error) {$scope.healthcheckMessage = error} + ); + } else { + Ping.enable( + function(data) {$scope.healthcheckStatus = true}, + function(error) {$scope.healthcheckMessage = error} + ); + } + }; + + $scope.refresh = function() { + $scope.refreshIndex(); + $scope.refreshReplication(); + $scope.refreshSystem(); + $scope.refreshPing(); + }; + + $scope.refresh(); +}); + diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/cores.js b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/cores.js new file mode 100755 index 0000000000..d5c4513eb6 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/cores.js @@ -0,0 +1,180 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +solrAdminApp.controller('CoreAdminController', + function($scope, $routeParams, $location, $timeout, $route, Cores, Update, Constants){ + $scope.resetMenu("cores", Constants.IS_ROOT_PAGE); + $scope.selectedCore = $routeParams.corename; // use 'corename' not 'core' to distinguish from /solr/:core/ + $scope.refresh = function() { + Cores.get(function(data) { + var coreCount = 0; + var cores = data.status; + for (_obj in cores) coreCount++; + $scope.hasCores = coreCount >0; + if (!$scope.selectedCore && coreCount==0) { + $scope.showAddCore(); + return; + } else if (!$scope.selectedCore) { + for (firstCore in cores) break; + $scope.selectedCore = firstCore; + $location.path("/~cores/" + $scope.selectedCore).replace(); + } + $scope.core = cores[$scope.selectedCore]; + $scope.corelist = []; + $scope.swapCorelist = []; + for (var core in cores) { + $scope.corelist.push(cores[core]); + if (cores[core] != $scope.core) { + $scope.swapCorelist.push(cores[core]); + } + } + if ($scope.swapCorelist.length>0) { + $scope.swapOther = $scope.swapCorelist[0].name; + } + }); + }; + $scope.showAddCore = function() { + $scope.hideAll(); + $scope.showAdd = true; + $scope.newCore = { + name: "new_core", + dataDir: "data", + instanceDir: "new_core", + config: "solrconfig.xml", + schema: "schema.xml", + collection: "", + shard: "" + }; + }; + + $scope.addCore = function() { + if (!$scope.newCore.name) { + $scope.addMessage = "Please provide a core name"; + } else if (false) { //@todo detect whether core exists + $scope.AddMessage = "A core with that name already exists"; + } else { + var params = { + name: $scope.newCore.name, + instanceDir: $scope.newCore.instanceDir, + config: $scope.newCore.config, + schema: $scope.newCore.schema, + dataDir: $scope.newCore.dataDir + }; + if ($scope.isCloud) { + params.collection = $scope.newCore.collection; + params.shard = $scope.newCore.shard; + } + Cores.add(params, function(data) { + $location.path("/~cores/" + $scope.newCore.name); + $scope.cancelAddCore(); + }); + } + }; + + $scope.cancelAddCore = function() { + delete $scope.addMessage; + $scope.showAdd = false + }; + + $scope.unloadCore = function() { + var answer = confirm( 'Do you really want to unload Core "' + $scope.selectedCore + '"?' ); + if( !answer ) return; + Cores.unload({core: $scope.selectedCore}, function(data) { + $location.path("/~cores"); + }); + }; + + $scope.showRenameCore = function() { + $scope.hideAll(); + $scope.showRename = true; + }; + + $scope.renameCore = function() { + if (!$scope.other) { + $scope.renameMessage = "Please provide a new name for the " + $scope.selectedCore + " core"; + } else if ($scope.other == $scope.selectedCore) { + $scope.renameMessage = "New name must be different from the current one"; + } else { + Cores.rename({core:$scope.selectedCore, other: $scope.other}, function(data) { + $location.path("/~cores/" + $scope.other); + $scope.cancelRename(); + }); + } + }; + + $scope.cancelRenameCore = function() { + $scope.showRename = false; + delete $scope.renameMessage; + $scope.other = ""; + }; + + $scope.showSwapCores = function() { + $scope.hideAll(); + $scope.showSwap = true; + }; + + $scope.swapCores = function() { + if (!$scope.swapOther) { + $scope.swapMessage = "Please select a core to swap with"; + } else if ($scope.swapOther == $scope.selectedCore) { + $scope.swapMessage = "Cannot swap with the same core"; + } else { + Cores.swap({core: $scope.selectedCore, other: $scope.swapOther}, function(data) { + $location.path("/~cores/" + $scope.swapOther); + delete $scope.swapOther; + $scope.cancelSwapCores(); + }); + } + }; + + $scope.cancelSwapCores = function() { + delete $scope.swapMessage; + $scope.showSwap = false; + } + + $scope.reloadCore = function() { + if ($scope.initFailures[$scope.selectedCore]) { + delete $scope.initFailures[$scope.selectedCore]; + $scope.showInitFailures = Object.keys(data.initFailures).length>0; + } + Cores.reload({core: $scope.selectedCore}, + function(data) { + if (data.error) { + $scope.reloadFailure = true; + $timeout(function() { + $scope.reloadFailure = false; + $route.reload(); + }, 1000); + } else { + $scope.reloadSuccess = true; + $timeout(function () { + $scope.reloadSuccess = false; + $route.reload(); + }, 1000); + } + }); + }; + + $scope.hideAll = function() { + $scope.showRename = false; + $scope.showAdd = false; + $scope.showSwap = false; + }; + + $scope.refresh(); + } +); diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/dataimport.js b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/dataimport.js new file mode 100755 index 0000000000..da6199eb01 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/dataimport.js @@ -0,0 +1,302 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +var dataimport_timeout = 2000; + +solrAdminApp.controller('DataImportController', + function($scope, $rootScope, $routeParams, $location, $timeout, $interval, $cookies, Mbeans, DataImport, Constants) { + $scope.resetMenu("dataimport", Constants.IS_COLLECTION_PAGE); + + $scope.refresh = function () { + Mbeans.info({core: $routeParams.core, cat: 'QUERY'}, function (data) { + var mbeans = data['solr-mbeans'][1]; + $scope.handlers = []; + for (var key in mbeans) { + if (mbeans[key]['class'] !== key && mbeans[key]['class'] === 'org.apache.solr.handler.dataimport.DataImportHandler') { + $scope.handlers.push(key); + } + } + $scope.hasHandlers = $scope.handlers.length > 0; + + if (!$routeParams.handler) { + $location.path("/" + $routeParams.core + "/dataimport/" + $scope.handlers[0]); + } else { + $scope.currentHandler = $routeParams.handler; + } + }); + + $scope.handler = $routeParams.handler; + if ($scope.handler && $scope.handler[0]=="/") { + $scope.handler = $scope.handler.substr(1); + } + if ($scope.handler) { + DataImport.config({core: $routeParams.core, name: $scope.handler}, function (data) { + try { + $scope.config = data.config; + var xml = $.parseXML(data.config); + $scope.entities = []; + $('document > entity', xml).each(function (i, element) { + $scope.entities.push($(element).attr('name')); + }); + $scope.refreshStatus(); + } catch (err) { + console.log(err); + } + }); + } + $scope.lastUpdate = "unknown"; + $scope.lastUpdateUTC = ""; + }; + + $scope.toggleDebug = function () { + $scope.isDebugMode = !$scope.isDebugMode; + if ($scope.isDebugMode) { + // also enable Debug checkbox + $scope.form.showDebug = true; + } + $scope.showConfiguration = true; + } + + $scope.toggleConfiguration = function () { + $scope.showConfiguration = !$scope.showConfiguration; + } + + $scope.toggleRawStatus = function () { + $scope.showRawStatus = !$scope.showRawStatus; + } + + $scope.toggleRawDebug = function () { + $scope.showRawDebug = !$scope.showRawDebug; + } + + $scope.reload = function () { + DataImport.reload({core: $routeParams.core, name: $scope.handler}, function () { + $scope.reloaded = true; + $timeout(function () { + $scope.reloaded = false; + }, 5000); + $scope.refresh(); + }); + } + + $scope.form = { + command: "full-import", + verbose: false, + clean: false, + commit: true, + showDebug: false, + custom: "", + core: $routeParams.core + }; + + $scope.submit = function () { + var params = {}; + for (var key in $scope.form) { + if (key == "showDebug") { + if ($scope.form.showDebug) { + params["debug"] = true; + } + } else { + params[key] = $scope.form[key]; + } + } + if (params.custom.length) { + var customParams = $scope.form.custom.split("&"); + for (var i in customParams) { + var parts = customParams[i].split("="); + params[parts[0]] = parts[1]; + } + } + delete params.custom; + + if ($scope.isDebugMode) { + params.dataConfig = $scope.config; + } + + params.core = $routeParams.core; + params.name = $scope.handler; + + DataImport.post(params, function (data) { + $scope.rawResponse = JSON.stringify(data, null, 2); + $scope.refreshStatus(); + }); + }; + + $scope.abort = function () { + $scope.isAborting = true; + DataImport.abort({core: $routeParams.core, name: $scope.handler}, function () { + $timeout(function () { + $scope.isAborting = false; + $scope.refreshStatus(); + }, 4000); + }); + } + + $scope.refreshStatus = function () { + + console.log("Refresh Status"); + + $scope.isStatusLoading = true; + DataImport.status({core: $routeParams.core, name: $scope.handler}, function (data) { + if (data[0] == "<") { + $scope.hasHandlers = false; + return; + } + + var now = new Date(); + $scope.lastUpdate = now.toTimeString().split(' ').shift(); + $scope.lastUpdateUTC = now.toUTCString(); + var messages = data.statusMessages; + var messagesCount = 0; + for( var key in messages ) { messagesCount++; } + + if (data.status == 'busy') { + $scope.status = "indexing"; + + $scope.timeElapsed = data.statusMessages['Time Elapsed']; + $scope.elapsedSeconds = parseSeconds($scope.timeElapsed); + + var info = $scope.timeElapsed ? 'Indexing since ' + $scope.timeElapsed : 'Indexing ...'; + $scope.info = showInfo(messages, true, info, $scope.elapsedSeconds); + + } else if (messages.RolledBack) { + $scope.status = "failure"; + $scope.info = showInfo(messages, true); + } else if (messages.Aborted) { + $scope.status = "aborted"; + $scope.info = showInfo(messages, true, 'Aborting current Import ...'); + } else if (data.status == "idle" && messagesCount != 0) { + $scope.status = "success"; + $scope.info = showInfo(messages, true); + } else { + $scope.status = "idle"; + $scope.info = showInfo(messages, false, 'No information available (idle)'); + } + + delete data.$promise; + delete data.$resolved; + + $scope.rawStatus = JSON.stringify(data, null, 2); + + $scope.isStatusLoading = false; + $scope.statusUpdated = true; + $timeout(function () { + $scope.statusUpdated = false; + }, dataimport_timeout / 2); + }); + }; + + $scope.updateAutoRefresh = function () { + $scope.autorefresh = !$scope.autorefresh; + $cookies.dataimport_autorefresh = $scope.autorefresh ? true : null; + if ($scope.autorefresh) { + $scope.refreshTimeout = $interval($scope.refreshStatus, dataimport_timeout); + var onRouteChangeOff = $scope.$on('$routeChangeStart', function() { + $interval.cancel($scope.refreshTimeout); + onRouteChangeOff(); + }); + + } else if ($scope.refreshTimeout) { + $interval.cancel($scope.refreshTimeout); + } + $scope.refreshStatus(); + }; + + $scope.refresh(); + +}); + +var showInfo = function (messages, showFull, info_text, elapsed_seconds) { + + var info = {}; + if (info_text) { + info.text = info_text; + } else { + info.text = messages[''] || ''; + // format numbers included in status nicely + /* @todo this pretty printing is hard to work out how to do in an Angularesque way: + info.text = info.text.replace(/\d{4,}/g, + function (match, position, string) { + return app.format_number(parseInt(match, 10)); + } + ); + */ + + var time_taken_text = messages['Time taken']; + info.timeTaken = parseSeconds(time_taken_text); + } + info.showDetails = false; + + if (showFull) { + if (!elapsed_seconds) { + var time_taken_text = messages['Time taken']; + elapsed_seconds = parseSeconds(time_taken_text); + } + + info.showDetails = true; + + var document_config = { + 'Requests': 'Total Requests made to DataSource', + 'Fetched': 'Total Rows Fetched', + 'Skipped': 'Total Documents Skipped', + 'Processed': 'Total Documents Processed' + }; + + info.docs = []; + for (var key in document_config) { + var value = parseInt(messages[document_config[key]], 10); + var doc = {desc: document_config[key], name: key, value: value}; + if (elapsed_seconds && key != 'Skipped') { + doc.speed = Math.round(value / elapsed_seconds); + } + info.docs.push(doc); + } + + var dates_config = { + 'Started': 'Full Dump Started', + 'Aborted': 'Aborted', + 'Rolledback': 'Rolledback' + }; + + info.dates = []; + for (var key in dates_config) { + var value = messages[dates_config[key]]; + if (value) { + value = value.replace(" ", "T")+".000Z"; + console.log(value); + var date = {desc: dates_config[key], name: key, value: value}; + info.dates.push(date); + } + } + } + return info; +} + +var parseSeconds = function(time) { + var seconds = 0; + var arr = new String(time || '').split('.'); + var parts = arr[0].split(':').reverse(); + + for (var i = 0; i < parts.length; i++) { + seconds += ( parseInt(parts[i], 10) || 0 ) * Math.pow(60, i); + } + + if (arr[1] && 5 <= parseInt(arr[1][0], 10)) { + seconds++; // treat more or equal than .5 as additional second + } + return seconds; +} diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/documents.js b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/documents.js new file mode 100755 index 0000000000..69f763cd44 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/documents.js @@ -0,0 +1,137 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ +//helper for formatting JSON and others + +var DOC_PLACEHOLDER = '\n' + + 'change.me' + + 'change.me' + + ''; + +var ADD_PLACEHOLDER = '\n' + DOC_PLACEHOLDER + '\n'; + +solrAdminApp.controller('DocumentsController', + function($scope, $rootScope, $routeParams, $location, Luke, Update, FileUpload, Constants) { + $scope.resetMenu("documents", Constants.IS_COLLECTION_PAGE); + + $scope.refresh = function () { + Luke.schema({core: $routeParams.core}, function(data) { + //TODO: handle dynamic fields + delete data.schema.fields._version_; + $scope.fields = Object.keys(data.schema.fields); + }); + $scope.document = ""; + $scope.handler = "/update"; + $scope.type = "json"; + $scope.commitWithin = 1000; + $scope.overwrite = true; + }; + + $scope.refresh(); + + $scope.changeDocumentType = function () { + $scope.placeholder = ""; + if ($scope.type == 'json') { + $scope.placeholder = '{"id":"change.me","title":"change.me"}'; + } else if ($scope.type == 'csv') { + $scope.placeholder = "id,title\nchange.me,change.me"; + } else if ($scope.type == 'solr') { + $scope.placeholder = ADD_PLACEHOLDER; + } else if ($scope.type == 'xml') { + $scope.placeholder = DOC_PLACEHOLDER; + } + }; + + $scope.addWizardField = function () { + if ($scope.document == "") $scope.document = "{}"; + var doc = JSON.parse($scope.document); + doc[$scope.fieldName] = $scope.fieldData; + $scope.document = JSON.stringify(doc, null, '\t'); + $scope.fieldData = ""; + }; + + $scope.submit = function () { + var contentType = ""; + var postData = ""; + var params = {}; + var doingFileUpload = false; + + if ($scope.handler[0] == '/') { + params.handler = $scope.handler.substring(1); + } else { + params.handler = 'update'; + params.qt = $scope.handler; + } + + params.commitWithin = $scope.commitWithin; + params.overwrite = $scope.overwrite; + params.core = $routeParams.core; + params.wt = "json"; + + if ($scope.type == "json" || $scope.type == "wizard") { + postData = "[" + $scope.document + "]"; + contentType = "json"; + } else if ($scope.type == "csv") { + postData = $scope.document; + contentType = "csv"; + } else if ($scope.type == "xml") { + postData = "" + $scope.document + ""; + contentType = "xml"; + } else if ($scope.type == "upload") { + doingFileUpload = true; + params.raw = $scope.literalParams; + } else if ($scope.type == "solr") { + postData = $scope.document; + if (postData[0] == "<") { + contentType = "xml"; + } else if (postData[0] == "{" || postData[0] == '[') { + contentType = "json"; + } else { + alert("Cannot identify content type") + } + } + if (!doingFileUpload) { + var callback = function (success) { + $scope.responseStatus = "success"; + delete success.$promise; + delete success.$resolved; + $scope.response = JSON.stringify(success, null, ' '); + }; + var failure = function (failure) { + $scope.responseStatus = failure; + }; + if (contentType == "json") { + Update.postJson(params, postData, callback, failure); + } else if (contentType == "xml") { + Update.postXml(params, postData, callback, failure); + } else if (contentType == "csv") { + Update.postCsv(params, postData, callback, failure); + } + } else { + var file = $scope.fileUpload; + console.log('file is ' + JSON.stringify(file)); + var uploadUrl = "/fileUpload"; + FileUpload.upload(params, $scope.fileUpload, function (success) { + $scope.responseStatus = "success"; + $scope.response = JSON.stringify(success, null, ' '); + }, function (failure) { + $scope.responseStatus = "failure"; + $scope.response = JSON.stringify(failure, null, ' '); + }); + } + } + }); + diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/files.js b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/files.js new file mode 100755 index 0000000000..6155d3ea96 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/js/angular/controllers/files.js @@ -0,0 +1,98 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +var contentTypeMap = { xml : 'text/xml', html : 'text/html', js : 'text/javascript', json : 'application/json', 'css' : 'text/css' }; +var languages = {js: "javascript", xml:"xml", xsl:"xml", vm: "xml", html: "xml", json: "json", css: "css"}; + +solrAdminApp.controller('FilesController', + function($scope, $rootScope, $routeParams, $location, Files, Constants) { + $scope.resetMenu("files", Constants.IS_COLLECTION_PAGE); + + $scope.file = $location.search().file; + $scope.content = null; + + $scope.baseurl = $location.absUrl().substr(0,$location.absUrl().indexOf("#")); // Including /solr/ context + + $scope.refresh = function () { + + var process = function (path, tree) { + var params = {core: $routeParams.core}; + if (path.slice(-1) == '/') { + params.file = path.slice(0, -1); + } else if (path!='') { + params.file = path; + } + + Files.list(params, function (data) { + var filenames = Object.keys(data.files); + filenames.sort(); + for (var i in filenames) { + var file = filenames[i]; + var filedata = data.files[file]; + var state = undefined; + var children = undefined; + + if (filedata.directory) { + file = file + "/"; + if ($scope.file && $scope.file.indexOf(path + file) == 0) { + state = "open"; + } else { + state = "closed"; + } + children = []; + process(path + file, children); + } + tree.push({ + text: file, + a_attr: { id: path + file}, + children: children, + state: state + }); + } + }); + }; + $scope.tree = []; + process("", $scope.tree); + + if ($scope.file && $scope.file != '' && $scope.file.split('').pop()!='/') { + var extension; + if ($scope.file == "managed-schema") { + extension = contentTypeMap['xml']; + } else { + extension = $scope.file.match( /\.(\w+)$/)[1] || ''; + } + var contentType = (contentTypeMap[extension] || 'text/plain' ) + ';charset=utf-8'; + + Files.get({core: $routeParams.core, file: $scope.file, contentType: contentType}, function(data) { + $scope.content = data.data; + $scope.url = data.config.url + "?" + $.param(data.config.params); // relative URL + if (contentType.indexOf("text/plain") && (data.data.indexOf("=0) || data.data.indexOf("",r:10},{cN:"cdata",b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{cN:"tag",b:"|$)",e:">",k:{title:"style"},c:[b],starts:{e:"",rE:true,sL:"css"}},{cN:"tag",b:"|$)",e:">",k:{title:"script"},c:[b],starts:{e:"<\/script>",rE:true,sL:"javascript"}},{b:"<%",e:"%>",sL:"vbscript"},{cN:"tag",b:"",c:[{cN:"title",b:"[^ />]+"},b]}]}}(hljs);hljs.LANGUAGES.php=function(a){var e={cN:"variable",b:"\\$+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*"};var b=[a.inherit(a.ASM,{i:null}),a.inherit(a.QSM,{i:null}),{cN:"string",b:'b"',e:'"',c:[a.BE]},{cN:"string",b:"b'",e:"'",c:[a.BE]}];var c=[a.BNM,a.CNM];var d={cN:"title",b:a.UIR};return{cI:true,k:"and include_once list abstract global private echo interface as static endswitch array null if endwhile or const for endforeach self var while isset public protected exit foreach throw elseif include __FILE__ empty require_once do xor return implements parent clone use __CLASS__ __LINE__ else break print eval new catch __METHOD__ case exception php_user_filter default die require __FUNCTION__ enddeclare final try this switch continue endfor endif declare unset true false namespace trait goto instanceof insteadof __DIR__ __NAMESPACE__ __halt_compiler",c:[a.CLCM,a.HCM,{cN:"comment",b:"/\\*",e:"\\*/",c:[{cN:"phpdoc",b:"\\s@[A-Za-z]+"}]},{cN:"comment",eB:true,b:"__halt_compiler.+?;",eW:true},{cN:"string",b:"<<<['\"]?\\w+['\"]?$",e:"^\\w+;",c:[a.BE]},{cN:"preprocessor",b:"<\\?php",r:10},{cN:"preprocessor",b:"\\?>"},e,{cN:"function",bWK:true,e:"{",k:"function",i:"\\$|\\[|%",c:[d,{cN:"params",b:"\\(",e:"\\)",c:["self",e,a.CBLCLM].concat(b).concat(c)}]},{cN:"class",bWK:true,e:"{",k:"class",i:"[:\\(\\$]",c:[{bWK:true,eW:true,k:"extends",c:[d]},d]},{b:"=>"}].concat(b).concat(c)}}(hljs);hljs.LANGUAGES.python=function(a){var f={cN:"prompt",b:"^(>>>|\\.\\.\\.) "};var c=[{cN:"string",b:"(u|b)?r?'''",e:"'''",c:[f],r:10},{cN:"string",b:'(u|b)?r?"""',e:'"""',c:[f],r:10},{cN:"string",b:"(u|r|ur)'",e:"'",c:[a.BE],r:10},{cN:"string",b:'(u|r|ur)"',e:'"',c:[a.BE],r:10},{cN:"string",b:"(b|br)'",e:"'",c:[a.BE]},{cN:"string",b:'(b|br)"',e:'"',c:[a.BE]}].concat([a.ASM,a.QSM]);var e={cN:"title",b:a.UIR};var d={cN:"params",b:"\\(",e:"\\)",c:["self",a.CNM,f].concat(c)};var b={bWK:true,e:":",i:"[${=;\\n]",c:[e,d],r:10};return{k:{keyword:"and elif is global as in if from raise for except finally print import pass return exec else break not with class assert yield try while continue del or def lambda nonlocal|10",built_in:"None True False Ellipsis NotImplemented"},i:"(|\\?)",c:c.concat([f,a.HCM,a.inherit(b,{cN:"function",k:"def"}),a.inherit(b,{cN:"class",k:"class"}),a.CNM,{cN:"decorator",b:"@",e:"$"},{b:"\\b(print|exec)\\("}])}}(hljs);hljs.LANGUAGES.json=function(a){var e={literal:"true false null"};var d=[a.QSM,a.CNM];var c={cN:"value",e:",",eW:true,eE:true,c:d,k:e};var b={b:"{",e:"}",c:[{cN:"attribute",b:'\\s*"',e:'"\\s*:\\s*',eB:true,eE:true,c:[a.BE],i:"\\n",starts:c}],i:"\\S"};var f={b:"\\[",e:"\\]",c:[a.inherit(c,{cN:null})],i:"\\S"};d.splice(d.length,0,b,f);return{c:d,k:e,i:"\\S"}}(hljs); diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/libs/jquery-3.4.1.min.js b/KeywordSearch/solr/server/solr-webapp/webapp/libs/jquery-3.4.1.min.js new file mode 100755 index 0000000000..b612235b75 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/libs/jquery-3.4.1.min.js @@ -0,0 +1,28 @@ +/*! + +Copyright 2020 jQuery Foundation and other contributors +http://jquery.com/ + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + +/*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;nx",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="
",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0a;a++)for(i in o[a])n=o[a][i],o[a].hasOwnProperty(i)&&void 0!==n&&(e[i]=t.isPlainObject(n)?t.isPlainObject(e[i])?t.widget.extend({},e[i],n):t.widget.extend({},n):n);return e},t.widget.bridge=function(e,i){var n=i.prototype.widgetFullName||e;t.fn[e]=function(o){var a="string"==typeof o,r=s.call(arguments,1),l=this;return a?this.length||"instance"!==o?this.each(function(){var i,s=t.data(this,n);return"instance"===o?(l=s,!1):s?t.isFunction(s[o])&&"_"!==o.charAt(0)?(i=s[o].apply(s,r),i!==s&&void 0!==i?(l=i&&i.jquery?l.pushStack(i.get()):i,!1):void 0):t.error("no such method '"+o+"' for "+e+" widget instance"):t.error("cannot call methods on "+e+" prior to initialization; "+"attempted to call method '"+o+"'")}):l=void 0:(r.length&&(o=t.widget.extend.apply(null,[o].concat(r))),this.each(function(){var e=t.data(this,n);e?(e.option(o||{}),e._init&&e._init()):t.data(this,n,new i(o,this))})),l}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
",options:{classes:{},disabled:!1,create:null},_createWidget:function(e,s){s=t(s||this.defaultElement||this)[0],this.element=t(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=t(),this.hoverable=t(),this.focusable=t(),this.classesElementLookup={},s!==this&&(t.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===s&&this.destroy()}}),this.document=t(s.style?s.ownerDocument:s.document||s),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this.options=t.widget.extend({},this.options,this._getCreateOptions(),e),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){var e=this;this._destroy(),t.each(this.classesElementLookup,function(t,i){e._removeClass(i,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:t.noop,widget:function(){return this.element},option:function(e,i){var s,n,o,a=e;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof e)if(a={},s=e.split("."),e=s.shift(),s.length){for(n=a[e]=t.widget.extend({},this.options[e]),o=0;s.length-1>o;o++)n[s[o]]=n[s[o]]||{},n=n[s[o]];if(e=s.pop(),1===arguments.length)return void 0===n[e]?null:n[e];n[e]=i}else{if(1===arguments.length)return void 0===this.options[e]?null:this.options[e];a[e]=i}return this._setOptions(a),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return"classes"===t&&this._setOptionClasses(e),this.options[t]=e,"disabled"===t&&this._setOptionDisabled(e),this},_setOptionClasses:function(e){var i,s,n;for(i in e)n=this.classesElementLookup[i],e[i]!==this.options.classes[i]&&n&&n.length&&(s=t(n.get()),this._removeClass(n,i),s.addClass(this._classes({element:s,keys:i,classes:e,add:!0})))},_setOptionDisabled:function(t){this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!!t),t&&(this._removeClass(this.hoverable,null,"ui-state-hover"),this._removeClass(this.focusable,null,"ui-state-focus"))},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_classes:function(e){function i(i,o){var a,r;for(r=0;i.length>r;r++)a=n.classesElementLookup[i[r]]||t(),a=e.add?t(t.unique(a.get().concat(e.element.get()))):t(a.not(e.element).get()),n.classesElementLookup[i[r]]=a,s.push(i[r]),o&&e.classes[i[r]]&&s.push(e.classes[i[r]])}var s=[],n=this;return e=t.extend({element:this.element,classes:this.options.classes||{}},e),this._on(e.element,{remove:"_untrackClassesElement"}),e.keys&&i(e.keys.match(/\S+/g)||[],!0),e.extra&&i(e.extra.match(/\S+/g)||[]),s.join(" ")},_untrackClassesElement:function(e){var i=this;t.each(i.classesElementLookup,function(s,n){-1!==t.inArray(e.target,n)&&(i.classesElementLookup[s]=t(n.not(e.target).get()))})},_removeClass:function(t,e,i){return this._toggleClass(t,e,i,!1)},_addClass:function(t,e,i){return this._toggleClass(t,e,i,!0)},_toggleClass:function(t,e,i,s){s="boolean"==typeof s?s:i;var n="string"==typeof t||null===t,o={extra:n?e:i,keys:n?t:e,element:n?this.element:t,add:s};return o.element.toggleClass(this._classes(o),s),this},_on:function(e,i,s){var n,o=this;"boolean"!=typeof e&&(s=i,i=e,e=!1),s?(i=n=t(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),t.each(s,function(s,a){function r(){return e||o.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof a?o[a]:a).apply(o,arguments):void 0}"string"!=typeof a&&(r.guid=a.guid=a.guid||r.guid||t.guid++);var l=s.match(/^([\w:-]*)\s*(.*)$/),h=l[1]+o.eventNamespace,c=l[2];c?n.on(h,c,r):i.on(h,r)})},_off:function(e,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.off(i).off(i),this.bindings=t(this.bindings.not(e).get()),this.focusable=t(this.focusable.not(e).get()),this.hoverable=t(this.hoverable.not(e).get())},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){this._addClass(t(e.currentTarget),null,"ui-state-hover")},mouseleave:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){this._addClass(t(e.currentTarget),null,"ui-state-focus")},focusout:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-focus")}})},_trigger:function(e,i,s){var n,o,a=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n in o)n in i||(i[n]=o[n]);return this.element.trigger(i,s),!(t.isFunction(a)&&a.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof n&&(n={effect:n});var a,r=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),a=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),a&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}}),t.widget,function(){function e(t,e,i){return[parseFloat(t[0])*(u.test(t[0])?e/100:1),parseFloat(t[1])*(u.test(t[1])?i/100:1)]}function i(e,i){return parseInt(t.css(e,i),10)||0}function s(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}var n,o=Math.max,a=Math.abs,r=/left|center|right/,l=/top|center|bottom/,h=/[\+\-]\d+(\.[\d]+)?%?/,c=/^\w+/,u=/%$/,d=t.fn.position;t.position={scrollbarWidth:function(){if(void 0!==n)return n;var e,i,s=t("
"),o=s.children()[0];return t("body").append(s),e=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,e===i&&(i=s[0].clientWidth),s.remove(),n=e-i},getScrollInfo:function(e){var i=e.isWindow||e.isDocument?"":e.element.css("overflow-x"),s=e.isWindow||e.isDocument?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.widthi?"left":e>0?"right":"center",vertical:0>r?"top":s>0?"bottom":"middle"};h>p&&p>a(e+i)&&(u.horizontal="center"),c>f&&f>a(s+r)&&(u.vertical="middle"),u.important=o(a(e),a(i))>o(a(s),a(r))?"horizontal":"vertical",n.using.call(this,t,u)}),l.offset(t.extend(D,{using:r}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=t.left-e.collisionPosition.marginLeft,l=n-r,h=r+e.collisionWidth-a-n;e.collisionWidth>a?l>0&&0>=h?(i=t.left+l+e.collisionWidth-a-n,t.left+=l-i):t.left=h>0&&0>=l?n:l>h?n+a-e.collisionWidth:n:l>0?t.left+=l:h>0?t.left-=h:t.left=o(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,a=e.within.height,r=t.top-e.collisionPosition.marginTop,l=n-r,h=r+e.collisionHeight-a-n;e.collisionHeight>a?l>0&&0>=h?(i=t.top+l+e.collisionHeight-a-n,t.top+=l-i):t.top=h>0&&0>=l?n:l>h?n+a-e.collisionHeight:n:l>0?t.top+=l:h>0?t.top-=h:t.top=o(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,o=n.offset.left+n.scrollLeft,r=n.width,l=n.isWindow?n.scrollLeft:n.offset.left,h=t.left-e.collisionPosition.marginLeft,c=h-l,u=h+e.collisionWidth-r-l,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-r-o,(0>i||a(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-l,(s>0||u>a(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,o=n.offset.top+n.scrollTop,r=n.height,l=n.isWindow?n.scrollTop:n.offset.top,h=t.top-e.collisionPosition.marginTop,c=h-l,u=h+e.collisionHeight-r-l,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,g=-2*e.offset[1];0>c?(s=t.top+p+f+g+e.collisionHeight-r-o,(0>s||a(c)>s)&&(t.top+=p+f+g)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+g-l,(i>0||u>a(i))&&(t.top+=p+f+g))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,arguments)}}}}(),t.ui.position,t.extend(t.expr[":"],{data:t.expr.createPseudo?t.expr.createPseudo(function(e){return function(i){return!!t.data(i,e)}}):function(e,i,s){return!!t.data(e,s[3])}}),t.fn.extend({disableSelection:function(){var t="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.on(t+".ui-disableSelection",function(t){t.preventDefault()})}}(),enableSelection:function(){return this.off(".ui-disableSelection")}}),t.ui.focusable=function(i,s){var n,o,a,r,l,h=i.nodeName.toLowerCase();return"area"===h?(n=i.parentNode,o=n.name,i.href&&o&&"map"===n.nodeName.toLowerCase()?(a=t("img[usemap='#"+o+"']"),a.length>0&&a.is(":visible")):!1):(/^(input|select|textarea|button|object)$/.test(h)?(r=!i.disabled,r&&(l=t(i).closest("fieldset")[0],l&&(r=!l.disabled))):r="a"===h?i.href||s:s,r&&t(i).is(":visible")&&e(t(i)))},t.extend(t.expr[":"],{focusable:function(e){return t.ui.focusable(e,null!=t.attr(e,"tabindex"))}}),t.ui.focusable,t.fn.form=function(){return"string"==typeof this[0].form?this.closest("form"):t(this[0].form)},t.ui.formResetMixin={_formResetHandler:function(){var e=t(this);setTimeout(function(){var i=e.data("ui-form-reset-instances");t.each(i,function(){this.refresh()})})},_bindFormResetHandler:function(){if(this.form=this.element.form(),this.form.length){var t=this.form.data("ui-form-reset-instances")||[];t.length||this.form.on("reset.ui-form-reset",this._formResetHandler),t.push(this),this.form.data("ui-form-reset-instances",t)}},_unbindFormResetHandler:function(){if(this.form.length){var e=this.form.data("ui-form-reset-instances");e.splice(t.inArray(this,e),1),e.length?this.form.data("ui-form-reset-instances",e):this.form.removeData("ui-form-reset-instances").off("reset.ui-form-reset")}}},"1.7"===t.fn.jquery.substring(0,3)&&(t.each(["Width","Height"],function(e,i){function s(e,i,s,o){return t.each(n,function(){i-=parseFloat(t.css(e,"padding"+this))||0,s&&(i-=parseFloat(t.css(e,"border"+this+"Width"))||0),o&&(i-=parseFloat(t.css(e,"margin"+this))||0)}),i}var n="Width"===i?["Left","Right"]:["Top","Bottom"],o=i.toLowerCase(),a={innerWidth:t.fn.innerWidth,innerHeight:t.fn.innerHeight,outerWidth:t.fn.outerWidth,outerHeight:t.fn.outerHeight};t.fn["inner"+i]=function(e){return void 0===e?a["inner"+i].call(this):this.each(function(){t(this).css(o,s(this,e)+"px")})},t.fn["outer"+i]=function(e,n){return"number"!=typeof e?a["outer"+i].call(this,e):this.each(function(){t(this).css(o,s(this,e,!0,n)+"px")})}}),t.fn.addBack=function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}),t.ui.keyCode={BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38},t.ui.escapeSelector=function(){var t=/([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g;return function(e){return e.replace(t,"\\$1")}}(),t.fn.labels=function(){var e,i,s,n,o;return this[0].labels&&this[0].labels.length?this.pushStack(this[0].labels):(n=this.eq(0).parents("label"),s=this.attr("id"),s&&(e=this.eq(0).parents().last(),o=e.add(e.length?e.siblings():this.siblings()),i="label[for='"+t.ui.escapeSelector(s)+"']",n=n.add(o.find(i).addBack(i))),this.pushStack(n))},t.fn.scrollParent=function(e){var i=this.css("position"),s="absolute"===i,n=e?/(auto|scroll|hidden)/:/(auto|scroll)/,o=this.parents().filter(function(){var e=t(this);return s&&"static"===e.css("position")?!1:n.test(e.css("overflow")+e.css("overflow-y")+e.css("overflow-x"))}).eq(0);return"fixed"!==i&&o.length?o:t(this[0].ownerDocument||document)},t.extend(t.expr[":"],{tabbable:function(e){var i=t.attr(e,"tabindex"),s=null!=i;return(!s||i>=0)&&t.ui.focusable(e,s)}}),t.fn.extend({uniqueId:function(){var t=0;return function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++t)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&t(this).removeAttr("id")})}}),t.widget("ui.tooltip",{version:"1.12.1",options:{classes:{"ui-tooltip":"ui-corner-all ui-widget-shadow"},content:function(){var e=t(this).attr("title")||"";return t("").text(e).html()},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,track:!1,close:null,open:null},_addDescribedBy:function(e,i){var s=(e.attr("aria-describedby")||"").split(/\s+/);s.push(i),e.data("ui-tooltip-id",i).attr("aria-describedby",t.trim(s.join(" ")))},_removeDescribedBy:function(e){var i=e.data("ui-tooltip-id"),s=(e.attr("aria-describedby")||"").split(/\s+/),n=t.inArray(i,s);-1!==n&&s.splice(n,1),e.removeData("ui-tooltip-id"),s=t.trim(s.join(" ")),s?e.attr("aria-describedby",s):e.removeAttr("aria-describedby")},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.liveRegion=t("
").attr({role:"log","aria-live":"assertive","aria-relevant":"additions"}).appendTo(this.document[0].body),this._addClass(this.liveRegion,null,"ui-helper-hidden-accessible"),this.disabledTitles=t([])},_setOption:function(e,i){var s=this;this._super(e,i),"content"===e&&t.each(this.tooltips,function(t,e){s._updateContent(e.element)})},_setOptionDisabled:function(t){this[t?"_disable":"_enable"]()},_disable:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur");n.target=n.currentTarget=s.element[0],e.close(n,!0)}),this.disabledTitles=this.disabledTitles.add(this.element.find(this.options.items).addBack().filter(function(){var e=t(this);return e.is("[title]")?e.data("ui-tooltip-title",e.attr("title")).removeAttr("title"):void 0}))},_enable:function(){this.disabledTitles.each(function(){var e=t(this);e.data("ui-tooltip-title")&&e.attr("title",e.data("ui-tooltip-title"))}),this.disabledTitles=t([])},open:function(e){var i=this,s=t(e?e.target:this.element).closest(this.options.items);s.length&&!s.data("ui-tooltip-id")&&(s.attr("title")&&s.data("ui-tooltip-title",s.attr("title")),s.data("ui-tooltip-open",!0),e&&"mouseover"===e.type&&s.parents().each(function(){var e,s=t(this);s.data("ui-tooltip-open")&&(e=t.Event("blur"),e.target=e.currentTarget=this,i.close(e,!0)),s.attr("title")&&(s.uniqueId(),i.parents[this.id]={element:this,title:s.attr("title")},s.attr("title",""))}),this._registerCloseHandlers(e,s),this._updateContent(s,e))},_updateContent:function(t,e){var i,s=this.options.content,n=this,o=e?e.type:null;return"string"==typeof s||s.nodeType||s.jquery?this._open(e,t,s):(i=s.call(t[0],function(i){n._delay(function(){t.data("ui-tooltip-open")&&(e&&(e.type=o),this._open(e,t,i))})}),i&&this._open(e,t,i),void 0)},_open:function(e,i,s){function n(t){h.of=t,a.is(":hidden")||a.position(h)}var o,a,r,l,h=t.extend({},this.options.position);if(s){if(o=this._find(i))return o.tooltip.find(".ui-tooltip-content").html(s),void 0;i.is("[title]")&&(e&&"mouseover"===e.type?i.attr("title",""):i.removeAttr("title")),o=this._tooltip(i),a=o.tooltip,this._addDescribedBy(i,a.attr("id")),a.find(".ui-tooltip-content").html(s),this.liveRegion.children().hide(),l=t("
").html(a.find(".ui-tooltip-content").html()),l.removeAttr("name").find("[name]").removeAttr("name"),l.removeAttr("id").find("[id]").removeAttr("id"),l.appendTo(this.liveRegion),this.options.track&&e&&/^mouse/.test(e.type)?(this._on(this.document,{mousemove:n}),n(e)):a.position(t.extend({of:i},this.options.position)),a.hide(),this._show(a,this.options.show),this.options.track&&this.options.show&&this.options.show.delay&&(r=this.delayedShow=setInterval(function(){a.is(":visible")&&(n(h.of),clearInterval(r))},t.fx.interval)),this._trigger("open",e,{tooltip:a})}},_registerCloseHandlers:function(e,i){var s={keyup:function(e){if(e.keyCode===t.ui.keyCode.ESCAPE){var s=t.Event(e);s.currentTarget=i[0],this.close(s,!0)}}};i[0]!==this.element[0]&&(s.remove=function(){this._removeTooltip(this._find(i).tooltip)}),e&&"mouseover"!==e.type||(s.mouseleave="close"),e&&"focusin"!==e.type||(s.focusout="close"),this._on(!0,i,s)},close:function(e){var i,s=this,n=t(e?e.currentTarget:this.element),o=this._find(n);return o?(i=o.tooltip,o.closing||(clearInterval(this.delayedShow),n.data("ui-tooltip-title")&&!n.attr("title")&&n.attr("title",n.data("ui-tooltip-title")),this._removeDescribedBy(n),o.hiding=!0,i.stop(!0),this._hide(i,this.options.hide,function(){s._removeTooltip(t(this))}),n.removeData("ui-tooltip-open"),this._off(n,"mouseleave focusout keyup"),n[0]!==this.element[0]&&this._off(n,"remove"),this._off(this.document,"mousemove"),e&&"mouseleave"===e.type&&t.each(this.parents,function(e,i){t(i.element).attr("title",i.title),delete s.parents[e]}),o.closing=!0,this._trigger("close",e,{tooltip:i}),o.hiding||(o.closing=!1)),void 0):(n.removeData("ui-tooltip-open"),void 0)},_tooltip:function(e){var i=t("
").attr("role","tooltip"),s=t("
").appendTo(i),n=i.uniqueId().attr("id");return this._addClass(s,"ui-tooltip-content"),this._addClass(i,"ui-tooltip","ui-widget ui-widget-content"),i.appendTo(this._appendTo(e)),this.tooltips[n]={element:e,tooltip:i}},_find:function(t){var e=t.data("ui-tooltip-id");return e?this.tooltips[e]:null},_removeTooltip:function(t){t.remove(),delete this.tooltips[t.attr("id")]},_appendTo:function(t){var e=t.closest(".ui-front, dialog");return e.length||(e=this.document[0].body),e},_destroy:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur"),o=s.element;n.target=n.currentTarget=o[0],e.close(n,!0),t("#"+i).remove(),o.data("ui-tooltip-title")&&(o.attr("title")||o.attr("title",o.data("ui-tooltip-title")),o.removeData("ui-tooltip-title"))}),this.liveRegion.remove()}}),t.uiBackCompat!==!1&&t.widget("ui.tooltip",t.ui.tooltip,{options:{tooltipClass:null},_tooltip:function(){var t=this._superApply(arguments);return this.options.tooltipClass&&t.tooltip.addClass(this.options.tooltipClass),t}}),t.ui.tooltip}); diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/libs/jstree.min.js b/KeywordSearch/solr/server/solr-webapp/webapp/libs/jstree.min.js new file mode 100755 index 0000000000..e3cc3441e3 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/libs/jstree.min.js @@ -0,0 +1,29 @@ +/* + +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ +/*! jsTree - v3.3.8 - 2019-04-29 - (MIT) */ +!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):"undefined"!=typeof module&&module.exports?module.exports=a(require("jquery")):a(jQuery)}(function(a,b){"use strict";if(!a.jstree){var c=0,d=!1,e=!1,f=!1,g=[],h=a("script:last").attr("src"),i=window.document;a.jstree={version:"3.3.8",defaults:{plugins:[]},plugins:{},path:h&&-1!==h.indexOf("/")?h.replace(/\/[^\/]+$/,""):"",idregex:/[\\:&!^|()\[\]<>@*'+~#";.,=\- \/${}%?`]/g,root:"#"},a.jstree.create=function(b,d){var e=new a.jstree.core(++c),f=d;return d=a.extend(!0,{},a.jstree.defaults,d),f&&f.plugins&&(d.plugins=f.plugins),a.each(d.plugins,function(a,b){"core"!==a&&(e=e.plugin(b,d[b]))}),a(b).data("jstree",e),e.init(b,d),e},a.jstree.destroy=function(){a(".jstree:jstree").jstree("destroy"),a(i).off(".jstree")},a.jstree.core=function(a){this._id=a,this._cnt=0,this._wrk=null,this._data={core:{themes:{name:!1,dots:!1,icons:!1,ellipsis:!1},selected:[],last_error:{},working:!1,worker_queue:[],focused:null}}},a.jstree.reference=function(b){var c=null,d=null;if(!b||!b.id||b.tagName&&b.nodeType||(b=b.id),!d||!d.length)try{d=a(b)}catch(e){}if(!d||!d.length)try{d=a("#"+b.replace(a.jstree.idregex,"\\$&"))}catch(e){}return d&&d.length&&(d=d.closest(".jstree")).length&&(d=d.data("jstree"))?c=d:a(".jstree").each(function(){var d=a(this).data("jstree");return d&&d._model.data[b]?(c=d,!1):void 0}),c},a.fn.jstree=function(c){var d="string"==typeof c,e=Array.prototype.slice.call(arguments,1),f=null;return c!==!0||this.length?(this.each(function(){var g=a.jstree.reference(this),h=d&&g?g[c]:null;return f=d&&h?h.apply(g,e):null,g||d||c!==b&&!a.isPlainObject(c)||a.jstree.create(this,c),(g&&!d||c===!0)&&(f=g||!1),null!==f&&f!==b?!1:void 0}),null!==f&&f!==b?f:this):!1},a.expr.pseudos.jstree=a.expr.createPseudo(function(c){return function(c){return a(c).hasClass("jstree")&&a(c).data("jstree")!==b}}),a.jstree.defaults.core={data:!1,strings:!1,check_callback:!1,error:a.noop,animation:200,multiple:!0,themes:{name:!1,url:!1,dir:!1,dots:!0,icons:!0,ellipsis:!1,stripes:!1,variant:!1,responsive:!1},expand_selected_onload:!0,worker:!0,force_text:!1,dblclick_toggle:!0,loaded_state:!1,restore_focus:!0,keyboard:{"ctrl-space":function(b){b.type="click",a(b.currentTarget).trigger(b)},enter:function(b){b.type="click",a(b.currentTarget).trigger(b)},left:function(b){if(b.preventDefault(),this.is_open(b.currentTarget))this.close_node(b.currentTarget);else{var c=this.get_parent(b.currentTarget);c&&c.id!==a.jstree.root&&this.get_node(c,!0).children(".jstree-anchor").focus()}},up:function(a){a.preventDefault();var b=this.get_prev_dom(a.currentTarget);b&&b.length&&b.children(".jstree-anchor").focus()},right:function(b){if(b.preventDefault(),this.is_closed(b.currentTarget))this.open_node(b.currentTarget,function(a){this.get_node(a,!0).children(".jstree-anchor").focus()});else if(this.is_open(b.currentTarget)){var c=this.get_node(b.currentTarget,!0).children(".jstree-children")[0];c&&a(this._firstChild(c)).children(".jstree-anchor").focus()}},down:function(a){a.preventDefault();var b=this.get_next_dom(a.currentTarget);b&&b.length&&b.children(".jstree-anchor").focus()},"*":function(a){this.open_all()},home:function(b){b.preventDefault();var c=this._firstChild(this.get_container_ul()[0]);c&&a(c).children(".jstree-anchor").filter(":visible").focus()},end:function(a){a.preventDefault(),this.element.find(".jstree-anchor").filter(":visible").last().focus()},f2:function(a){a.preventDefault(),this.edit(a.currentTarget)}}},a.jstree.core.prototype={plugin:function(b,c){var d=a.jstree.plugins[b];return d?(this._data[b]={},d.prototype=this,new d(c,this)):this},init:function(b,c){this._model={data:{},changed:[],force_full_redraw:!1,redraw_timeout:!1,default_state:{loaded:!0,opened:!1,selected:!1,disabled:!1}},this._model.data[a.jstree.root]={id:a.jstree.root,parent:null,parents:[],children:[],children_d:[],state:{loaded:!1}},this.element=a(b).addClass("jstree jstree-"+this._id),this.settings=c,this._data.core.ready=!1,this._data.core.loaded=!1,this._data.core.rtl="rtl"===this.element.css("direction"),this.element[this._data.core.rtl?"addClass":"removeClass"]("jstree-rtl"),this.element.attr("role","tree"),this.settings.core.multiple&&this.element.attr("aria-multiselectable",!0),this.element.attr("tabindex")||this.element.attr("tabindex","0"),this.bind(),this.trigger("init"),this._data.core.original_container_html=this.element.find(" > ul > li").clone(!0),this._data.core.original_container_html.find("li").addBack().contents().filter(function(){return 3===this.nodeType&&(!this.nodeValue||/^\s+$/.test(this.nodeValue))}).remove(),this.element.html(""),this.element.attr("aria-activedescendant","j"+this._id+"_loading"),this._data.core.li_height=this.get_container_ul().children("li").first().outerHeight()||24,this._data.core.node=this._create_prototype_node(),this.trigger("loading"),this.load_node(a.jstree.root)},destroy:function(a){if(this.trigger("destroy"),this._wrk)try{window.URL.revokeObjectURL(this._wrk),this._wrk=null}catch(b){}a||this.element.empty(),this.teardown()},_create_prototype_node:function(){var a=i.createElement("LI"),b,c;return a.setAttribute("role","treeitem"),b=i.createElement("I"),b.className="jstree-icon jstree-ocl",b.setAttribute("role","presentation"),a.appendChild(b),b=i.createElement("A"),b.className="jstree-anchor",b.setAttribute("href","#"),b.setAttribute("tabindex","-1"),c=i.createElement("I"),c.className="jstree-icon jstree-themeicon",c.setAttribute("role","presentation"),b.appendChild(c),a.appendChild(b),b=c=null,a},_kbevent_to_func:function(a){var b={8:"Backspace",9:"Tab",13:"Enter",19:"Pause",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"Print",45:"Insert",46:"Delete",96:"Numpad0",97:"Numpad1",98:"Numpad2",99:"Numpad3",100:"Numpad4",101:"Numpad5",102:"Numpad6",103:"Numpad7",104:"Numpad8",105:"Numpad9","-13":"NumpadEnter",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"Numlock",145:"Scrolllock",16:"Shift",17:"Ctrl",18:"Alt",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",59:";",61:"=",65:"a",66:"b",67:"c",68:"d",69:"e",70:"f",71:"g",72:"h",73:"i",74:"j",75:"k",76:"l",77:"m",78:"n",79:"o",80:"p",81:"q",82:"r",83:"s",84:"t",85:"u",86:"v",87:"w",88:"x",89:"y",90:"z",107:"+",109:"-",110:".",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",111:"/",106:"*",173:"-"},c=[];a.ctrlKey&&c.push("ctrl"),a.altKey&&c.push("alt"),a.shiftKey&&c.push("shift"),c.push(b[a.which]||a.which),c=c.sort().join("-").toLowerCase();var d=this.settings.core.keyboard,e,f;for(e in d)if(d.hasOwnProperty(e)&&(f=e,"-"!==f&&"+"!==f&&(f=f.replace("--","-MINUS").replace("+-","-MINUS").replace("++","-PLUS").replace("-+","-PLUS"),f=f.split(/-|\+/).sort().join("-").replace("MINUS","-").replace("PLUS","+").toLowerCase()),f===c))return d[e];return null},teardown:function(){this.unbind(),this.element.removeClass("jstree").removeData("jstree").find("[class^='jstree']").addBack().attr("class",function(){return this.className.replace(/jstree[^ ]*|$/gi,"")}),this.element=null},bind:function(){var b="",c=null,d=0;this.element.on("dblclick.jstree",function(a){if(a.target.tagName&&"input"===a.target.tagName.toLowerCase())return!0;if(i.selection&&i.selection.empty)i.selection.empty();else if(window.getSelection){var b=window.getSelection();try{b.removeAllRanges(),b.collapse()}catch(c){}}}).on("mousedown.jstree",a.proxy(function(a){a.target===this.element[0]&&(a.preventDefault(),d=+new Date)},this)).on("mousedown.jstree",".jstree-ocl",function(a){a.preventDefault()}).on("click.jstree",".jstree-ocl",a.proxy(function(a){this.toggle_node(a.target)},this)).on("dblclick.jstree",".jstree-anchor",a.proxy(function(a){return a.target.tagName&&"input"===a.target.tagName.toLowerCase()?!0:void(this.settings.core.dblclick_toggle&&this.toggle_node(a.target))},this)).on("click.jstree",".jstree-anchor",a.proxy(function(b){b.preventDefault(),b.currentTarget!==i.activeElement&&a(b.currentTarget).focus(),this.activate_node(b.currentTarget,b)},this)).on("keydown.jstree",".jstree-anchor",a.proxy(function(a){if(a.target.tagName&&"input"===a.target.tagName.toLowerCase())return!0;this._data.core.rtl&&(37===a.which?a.which=39:39===a.which&&(a.which=37));var b=this._kbevent_to_func(a);if(b){var c=b.call(this,a);if(c===!1||c===!0)return c}},this)).on("load_node.jstree",a.proxy(function(b,c){c.status&&(c.node.id!==a.jstree.root||this._data.core.loaded||(this._data.core.loaded=!0,this._firstChild(this.get_container_ul()[0])&&this.element.attr("aria-activedescendant",this._firstChild(this.get_container_ul()[0]).id),this.trigger("loaded")),this._data.core.ready||setTimeout(a.proxy(function(){if(this.element&&!this.get_container_ul().find(".jstree-loading").length){if(this._data.core.ready=!0,this._data.core.selected.length){if(this.settings.core.expand_selected_onload){var b=[],c,d;for(c=0,d=this._data.core.selected.length;d>c;c++)b=b.concat(this._model.data[this._data.core.selected[c]].parents);for(b=a.vakata.array_unique(b),c=0,d=b.length;d>c;c++)this.open_node(b[c],!1,0)}this.trigger("changed",{action:"ready",selected:this._data.core.selected})}this.trigger("ready")}},this),0))},this)).on("keypress.jstree",a.proxy(function(d){if(d.target.tagName&&"input"===d.target.tagName.toLowerCase())return!0;c&&clearTimeout(c),c=setTimeout(function(){b=""},500);var e=String.fromCharCode(d.which).toLowerCase(),f=this.element.find(".jstree-anchor").filter(":visible"),g=f.index(i.activeElement)||0,h=!1;if(b+=e,b.length>1){if(f.slice(g).each(a.proxy(function(c,d){return 0===a(d).text().toLowerCase().indexOf(b)?(a(d).focus(),h=!0,!1):void 0},this)),h)return;if(f.slice(0,g).each(a.proxy(function(c,d){return 0===a(d).text().toLowerCase().indexOf(b)?(a(d).focus(),h=!0,!1):void 0},this)),h)return}if(new RegExp("^"+e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")+"+$").test(b)){if(f.slice(g+1).each(a.proxy(function(b,c){return a(c).text().toLowerCase().charAt(0)===e?(a(c).focus(),h=!0,!1):void 0},this)),h)return;if(f.slice(0,g+1).each(a.proxy(function(b,c){return a(c).text().toLowerCase().charAt(0)===e?(a(c).focus(),h=!0,!1):void 0},this)),h)return}},this)).on("init.jstree",a.proxy(function(){var a=this.settings.core.themes;this._data.core.themes.dots=a.dots,this._data.core.themes.stripes=a.stripes,this._data.core.themes.icons=a.icons,this._data.core.themes.ellipsis=a.ellipsis,this.set_theme(a.name||"default",a.url),this.set_theme_variant(a.variant)},this)).on("loading.jstree",a.proxy(function(){this[this._data.core.themes.dots?"show_dots":"hide_dots"](),this[this._data.core.themes.icons?"show_icons":"hide_icons"](),this[this._data.core.themes.stripes?"show_stripes":"hide_stripes"](),this[this._data.core.themes.ellipsis?"show_ellipsis":"hide_ellipsis"]()},this)).on("blur.jstree",".jstree-anchor",a.proxy(function(b){this._data.core.focused=null,a(b.currentTarget).filter(".jstree-hovered").trigger("mouseleave"),this.element.attr("tabindex","0")},this)).on("focus.jstree",".jstree-anchor",a.proxy(function(b){var c=this.get_node(b.currentTarget);c&&c.id&&(this._data.core.focused=c.id),this.element.find(".jstree-hovered").not(b.currentTarget).trigger("mouseleave"),a(b.currentTarget).trigger("mouseenter"),this.element.attr("tabindex","-1")},this)).on("focus.jstree",a.proxy(function(){if(+new Date-d>500&&!this._data.core.focused&&this.settings.core.restore_focus){d=0;var a=this.get_node(this.element.attr("aria-activedescendant"),!0);a&&a.find("> .jstree-anchor").focus()}},this)).on("mouseenter.jstree",".jstree-anchor",a.proxy(function(a){this.hover_node(a.currentTarget)},this)).on("mouseleave.jstree",".jstree-anchor",a.proxy(function(a){this.dehover_node(a.currentTarget)},this))},unbind:function(){this.element.off(".jstree"),a(i).off(".jstree-"+this._id)},trigger:function(a,b){b||(b={}),b.instance=this,this.element.triggerHandler(a.replace(".jstree","")+".jstree",b)},get_container:function(){return this.element},get_container_ul:function(){return this.element.children(".jstree-children").first()},get_string:function(b){var c=this.settings.core.strings;return a.isFunction(c)?c.call(this,b):c&&c[b]?c[b]:b},_firstChild:function(a){a=a?a.firstChild:null;while(null!==a&&1!==a.nodeType)a=a.nextSibling;return a},_nextSibling:function(a){a=a?a.nextSibling:null;while(null!==a&&1!==a.nodeType)a=a.nextSibling;return a},_previousSibling:function(a){a=a?a.previousSibling:null;while(null!==a&&1!==a.nodeType)a=a.previousSibling;return a},get_node:function(b,c){b&&b.id&&(b=b.id),b instanceof a&&b.length&&b[0].id&&(b=b[0].id);var d;try{if(this._model.data[b])b=this._model.data[b];else if("string"==typeof b&&this._model.data[b.replace(/^#/,"")])b=this._model.data[b.replace(/^#/,"")];else if("string"==typeof b&&(d=a("#"+b.replace(a.jstree.idregex,"\\$&"),this.element)).length&&this._model.data[d.closest(".jstree-node").attr("id")])b=this._model.data[d.closest(".jstree-node").attr("id")];else if((d=this.element.find(b)).length&&this._model.data[d.closest(".jstree-node").attr("id")])b=this._model.data[d.closest(".jstree-node").attr("id")];else{if(!(d=this.element.find(b)).length||!d.hasClass("jstree"))return!1;b=this._model.data[a.jstree.root]}return c&&(b=b.id===a.jstree.root?this.element:a("#"+b.id.replace(a.jstree.idregex,"\\$&"),this.element)),b}catch(e){return!1}},get_path:function(b,c,d){if(b=b.parents?b:this.get_node(b),!b||b.id===a.jstree.root||!b.parents)return!1;var e,f,g=[];for(g.push(d?b.id:b.text),e=0,f=b.parents.length;f>e;e++)g.push(d?b.parents[e]:this.get_text(b.parents[e]));return g=g.reverse().slice(1),c?g.join(c):g},get_next_dom:function(b,c){var d;if(b=this.get_node(b,!0),b[0]===this.element[0]){d=this._firstChild(this.get_container_ul()[0]);while(d&&0===d.offsetHeight)d=this._nextSibling(d);return d?a(d):!1}if(!b||!b.length)return!1;if(c){d=b[0];do d=this._nextSibling(d);while(d&&0===d.offsetHeight);return d?a(d):!1}if(b.hasClass("jstree-open")){d=this._firstChild(b.children(".jstree-children")[0]);while(d&&0===d.offsetHeight)d=this._nextSibling(d);if(null!==d)return a(d)}d=b[0];do d=this._nextSibling(d);while(d&&0===d.offsetHeight);return null!==d?a(d):b.parentsUntil(".jstree",".jstree-node").nextAll(".jstree-node:visible").first()},get_prev_dom:function(b,c){var d;if(b=this.get_node(b,!0),b[0]===this.element[0]){d=this.get_container_ul()[0].lastChild;while(d&&0===d.offsetHeight)d=this._previousSibling(d);return d?a(d):!1}if(!b||!b.length)return!1;if(c){d=b[0];do d=this._previousSibling(d);while(d&&0===d.offsetHeight);return d?a(d):!1}d=b[0];do d=this._previousSibling(d);while(d&&0===d.offsetHeight);if(null!==d){b=a(d);while(b.hasClass("jstree-open"))b=b.children(".jstree-children").first().children(".jstree-node:visible:last");return b}return d=b[0].parentNode.parentNode,d&&d.className&&-1!==d.className.indexOf("jstree-node")?a(d):!1},get_parent:function(b){return b=this.get_node(b),b&&b.id!==a.jstree.root?b.parent:!1},get_children_dom:function(a){return a=this.get_node(a,!0),a[0]===this.element[0]?this.get_container_ul().children(".jstree-node"):a&&a.length?a.children(".jstree-children").children(".jstree-node"):!1},is_parent:function(a){return a=this.get_node(a),a&&(a.state.loaded===!1||a.children.length>0)},is_loaded:function(a){return a=this.get_node(a),a&&a.state.loaded},is_loading:function(a){return a=this.get_node(a),a&&a.state&&a.state.loading},is_open:function(a){return a=this.get_node(a),a&&a.state.opened},is_closed:function(a){return a=this.get_node(a),a&&this.is_parent(a)&&!a.state.opened},is_leaf:function(a){return!this.is_parent(a)},load_node:function(b,c){var d,e,f,g,h;if(a.isArray(b))return this._load_nodes(b.slice(),c),!0;if(b=this.get_node(b),!b)return c&&c.call(this,b,!1),!1;if(b.state.loaded){for(b.state.loaded=!1,f=0,g=b.parents.length;g>f;f++)this._model.data[b.parents[f]].children_d=a.vakata.array_filter(this._model.data[b.parents[f]].children_d,function(c){return-1===a.inArray(c,b.children_d)});for(d=0,e=b.children_d.length;e>d;d++)this._model.data[b.children_d[d]].state.selected&&(h=!0),delete this._model.data[b.children_d[d]];h&&(this._data.core.selected=a.vakata.array_filter(this._data.core.selected,function(c){return-1===a.inArray(c,b.children_d)})),b.children=[],b.children_d=[],h&&this.trigger("changed",{action:"load_node",node:b,selected:this._data.core.selected})}return b.state.failed=!1,b.state.loading=!0,this.get_node(b,!0).addClass("jstree-loading").attr("aria-busy",!0),this._load_node(b,a.proxy(function(a){b=this._model.data[b.id],b.state.loading=!1,b.state.loaded=a,b.state.failed=!b.state.loaded;var d=this.get_node(b,!0),e=0,f=0,g=this._model.data,h=!1;for(e=0,f=b.children.length;f>e;e++)if(g[b.children[e]]&&!g[b.children[e]].state.hidden){h=!0;break}b.state.loaded&&d&&d.length&&(d.removeClass("jstree-closed jstree-open jstree-leaf"),h?"#"!==b.id&&d.addClass(b.state.opened?"jstree-open":"jstree-closed"):d.addClass("jstree-leaf")),d.removeClass("jstree-loading").attr("aria-busy",!1),this.trigger("load_node",{node:b,status:a}),c&&c.call(this,b,a)},this)),!0},_load_nodes:function(a,b,c,d){var e=!0,f=function(){this._load_nodes(a,b,!0)},g=this._model.data,h,i,j=[];for(h=0,i=a.length;i>h;h++)g[a[h]]&&(!g[a[h]].state.loaded&&!g[a[h]].state.failed||!c&&d)&&(this.is_loading(a[h])||this.load_node(a[h],f),e=!1);if(e){for(h=0,i=a.length;i>h;h++)g[a[h]]&&g[a[h]].state.loaded&&j.push(a[h]);b&&!b.done&&(b.call(this,j),b.done=!0)}},load_all:function(b,c){if(b||(b=a.jstree.root),b=this.get_node(b),!b)return!1;var d=[],e=this._model.data,f=e[b.id].children_d,g,h;for(b.state&&!b.state.loaded&&d.push(b.id),g=0,h=f.length;h>g;g++)e[f[g]]&&e[f[g]].state&&!e[f[g]].state.loaded&&d.push(f[g]);d.length?this._load_nodes(d,function(){this.load_all(b,c)}):(c&&c.call(this,b),this.trigger("load_all",{node:b}))},_load_node:function(b,c){var d=this.settings.core.data,e,f=function g(){return 3!==this.nodeType&&8!==this.nodeType};return d?a.isFunction(d)?d.call(this,b,a.proxy(function(d){d===!1?c.call(this,!1):this["string"==typeof d?"_append_html_data":"_append_json_data"](b,"string"==typeof d?a(a.parseHTML(d)).filter(f):d,function(a){c.call(this,a)})},this)):"object"==typeof d?d.url?(d=a.extend(!0,{},d),a.isFunction(d.url)&&(d.url=d.url.call(this,b)),a.isFunction(d.data)&&(d.data=d.data.call(this,b)),a.ajax(d).done(a.proxy(function(d,e,g){var h=g.getResponseHeader("Content-Type");return h&&-1!==h.indexOf("json")||"object"==typeof d?this._append_json_data(b,d,function(a){c.call(this,a)}):h&&-1!==h.indexOf("html")||"string"==typeof d?this._append_html_data(b,a(a.parseHTML(d)).filter(f),function(a){c.call(this,a)}):(this._data.core.last_error={error:"ajax",plugin:"core",id:"core_04",reason:"Could not load node",data:JSON.stringify({id:b.id,xhr:g})},this.settings.core.error.call(this,this._data.core.last_error),c.call(this,!1))},this)).fail(a.proxy(function(a){this._data.core.last_error={error:"ajax",plugin:"core",id:"core_04",reason:"Could not load node",data:JSON.stringify({id:b.id,xhr:a})},c.call(this,!1),this.settings.core.error.call(this,this._data.core.last_error)},this))):(e=a.isArray(d)?a.extend(!0,[],d):a.isPlainObject(d)?a.extend(!0,{},d):d,b.id===a.jstree.root?this._append_json_data(b,e,function(a){c.call(this,a)}):(this._data.core.last_error={error:"nodata",plugin:"core",id:"core_05",reason:"Could not load node",data:JSON.stringify({id:b.id})},this.settings.core.error.call(this,this._data.core.last_error),c.call(this,!1))):"string"==typeof d?b.id===a.jstree.root?this._append_html_data(b,a(a.parseHTML(d)).filter(f),function(a){c.call(this,a)}):(this._data.core.last_error={error:"nodata",plugin:"core",id:"core_06",reason:"Could not load node",data:JSON.stringify({id:b.id})},this.settings.core.error.call(this,this._data.core.last_error),c.call(this,!1)):c.call(this,!1):b.id===a.jstree.root?this._append_html_data(b,this._data.core.original_container_html.clone(!0),function(a){c.call(this,a)}):c.call(this,!1)},_node_changed:function(b){b=this.get_node(b),b&&-1===a.inArray(b.id,this._model.changed)&&this._model.changed.push(b.id)},_append_html_data:function(b,c,d){b=this.get_node(b),b.children=[],b.children_d=[];var e=c.is("ul")?c.children():c,f=b.id,g=[],h=[],i=this._model.data,j=i[f],k=this._data.core.selected.length,l,m,n;for(e.each(a.proxy(function(b,c){l=this._parse_model_from_html(a(c),f,j.parents.concat()),l&&(g.push(l),h.push(l),i[l].children_d.length&&(h=h.concat(i[l].children_d)))},this)),j.children=g,j.children_d=h,m=0,n=j.parents.length;n>m;m++)i[j.parents[m]].children_d=i[j.parents[m]].children_d.concat(h);this.trigger("model",{nodes:h,parent:f}),f!==a.jstree.root?(this._node_changed(f),this.redraw()):(this.get_container_ul().children(".jstree-initial-node").remove(),this.redraw(!0)),this._data.core.selected.length!==k&&this.trigger("changed",{action:"model",selected:this._data.core.selected}),d.call(this,!0)},_append_json_data:function(b,c,d,e){if(null!==this.element){b=this.get_node(b),b.children=[],b.children_d=[],c.d&&(c=c.d,"string"==typeof c&&(c=JSON.parse(c))),a.isArray(c)||(c=[c]);var f=null,g={df:this._model.default_state,dat:c,par:b.id,m:this._model.data,t_id:this._id,t_cnt:this._cnt,sel:this._data.core.selected},h=this,i=function(a,b){a.data&&(a=a.data);var c=a.dat,d=a.par,e=[],f=[],g=[],i=a.df,j=a.t_id,k=a.t_cnt,l=a.m,m=l[d],n=a.sel,o,p,q,r,s=function(a,c,d){d=d?d.concat():[],c&&d.unshift(c);var e=a.id.toString(),f,h,j,k,m={id:e,text:a.text||"",icon:a.icon!==b?a.icon:!0,parent:c,parents:d,children:a.children||[],children_d:a.children_d||[],data:a.data,state:{},li_attr:{id:!1},a_attr:{href:"#"},original:!1};for(f in i)i.hasOwnProperty(f)&&(m.state[f]=i[f]);if(a&&a.data&&a.data.jstree&&a.data.jstree.icon&&(m.icon=a.data.jstree.icon),(m.icon===b||null===m.icon||""===m.icon)&&(m.icon=!0),a&&a.data&&(m.data=a.data,a.data.jstree))for(f in a.data.jstree)a.data.jstree.hasOwnProperty(f)&&(m.state[f]=a.data.jstree[f]);if(a&&"object"==typeof a.state)for(f in a.state)a.state.hasOwnProperty(f)&&(m.state[f]=a.state[f]);if(a&&"object"==typeof a.li_attr)for(f in a.li_attr)a.li_attr.hasOwnProperty(f)&&(m.li_attr[f]=a.li_attr[f]);if(m.li_attr.id||(m.li_attr.id=e),a&&"object"==typeof a.a_attr)for(f in a.a_attr)a.a_attr.hasOwnProperty(f)&&(m.a_attr[f]=a.a_attr[f]);for(a&&a.children&&a.children===!0&&(m.state.loaded=!1,m.children=[],m.children_d=[]),l[m.id]=m,f=0,h=m.children.length;h>f;f++)j=s(l[m.children[f]],m.id,d),k=l[j],m.children_d.push(j),k.children_d.length&&(m.children_d=m.children_d.concat(k.children_d));return delete a.data,delete a.children,l[m.id].original=a,m.state.selected&&g.push(m.id),m.id},t=function(a,c,d){d=d?d.concat():[],c&&d.unshift(c);var e=!1,f,h,m,n,o;do e="j"+j+"_"+ ++k;while(l[e]);o={id:!1,text:"string"==typeof a?a:"",icon:"object"==typeof a&&a.icon!==b?a.icon:!0,parent:c,parents:d,children:[],children_d:[],data:null,state:{},li_attr:{id:!1},a_attr:{href:"#"},original:!1};for(f in i)i.hasOwnProperty(f)&&(o.state[f]=i[f]);if(a&&a.id&&(o.id=a.id.toString()),a&&a.text&&(o.text=a.text),a&&a.data&&a.data.jstree&&a.data.jstree.icon&&(o.icon=a.data.jstree.icon),(o.icon===b||null===o.icon||""===o.icon)&&(o.icon=!0),a&&a.data&&(o.data=a.data,a.data.jstree))for(f in a.data.jstree)a.data.jstree.hasOwnProperty(f)&&(o.state[f]=a.data.jstree[f]);if(a&&"object"==typeof a.state)for(f in a.state)a.state.hasOwnProperty(f)&&(o.state[f]=a.state[f]);if(a&&"object"==typeof a.li_attr)for(f in a.li_attr)a.li_attr.hasOwnProperty(f)&&(o.li_attr[f]=a.li_attr[f]);if(o.li_attr.id&&!o.id&&(o.id=o.li_attr.id.toString()),o.id||(o.id=e),o.li_attr.id||(o.li_attr.id=o.id),a&&"object"==typeof a.a_attr)for(f in a.a_attr)a.a_attr.hasOwnProperty(f)&&(o.a_attr[f]=a.a_attr[f]);if(a&&a.children&&a.children.length){for(f=0,h=a.children.length;h>f;f++)m=t(a.children[f],o.id,d),n=l[m],o.children.push(m),n.children_d.length&&(o.children_d=o.children_d.concat(n.children_d));o.children_d=o.children_d.concat(o.children)}return a&&a.children&&a.children===!0&&(o.state.loaded=!1,o.children=[],o.children_d=[]),delete a.data,delete a.children,o.original=a,l[o.id]=o,o.state.selected&&g.push(o.id),o.id};if(c.length&&c[0].id!==b&&c[0].parent!==b){for(p=0,q=c.length;q>p;p++)c[p].children||(c[p].children=[]),c[p].state||(c[p].state={}),l[c[p].id.toString()]=c[p];for(p=0,q=c.length;q>p;p++)l[c[p].parent.toString()]?(l[c[p].parent.toString()].children.push(c[p].id.toString()),m.children_d.push(c[p].id.toString())):"undefined"!=typeof h&&(h._data.core.last_error={error:"parse",plugin:"core",id:"core_07",reason:"Node with invalid parent",data:JSON.stringify({id:c[p].id.toString(),parent:c[p].parent.toString()})},h.settings.core.error.call(h,h._data.core.last_error));for(p=0,q=m.children.length;q>p;p++)o=s(l[m.children[p]],d,m.parents.concat()),f.push(o),l[o].children_d.length&&(f=f.concat(l[o].children_d));for(p=0,q=m.parents.length;q>p;p++)l[m.parents[p]].children_d=l[m.parents[p]].children_d.concat(f);r={cnt:k,mod:l,sel:n,par:d,dpc:f,add:g}}else{for(p=0,q=c.length;q>p;p++)o=t(c[p],d,m.parents.concat()),o&&(e.push(o),f.push(o),l[o].children_d.length&&(f=f.concat(l[o].children_d)));for(m.children=e,m.children_d=f,p=0,q=m.parents.length;q>p;p++)l[m.parents[p]].children_d=l[m.parents[p]].children_d.concat(f);r={cnt:k,mod:l,sel:n,par:d,dpc:f,add:g}}return"undefined"!=typeof window&&"undefined"!=typeof window.document?r:void postMessage(r)},j=function(b,c){if(null!==this.element){this._cnt=b.cnt;var e,f=this._model.data;for(e in f)f.hasOwnProperty(e)&&f[e].state&&f[e].state.loading&&b.mod[e]&&(b.mod[e].state.loading=!0);if(this._model.data=b.mod,c){var g,h=b.add,i=b.sel,j=this._data.core.selected.slice();if(f=this._model.data,i.length!==j.length||a.vakata.array_unique(i.concat(j)).length!==i.length){for(e=0,g=i.length;g>e;e++)-1===a.inArray(i[e],h)&&-1===a.inArray(i[e],j)&&(f[i[e]].state.selected=!1);for(e=0,g=j.length;g>e;e++)-1===a.inArray(j[e],i)&&(f[j[e]].state.selected=!0)}}b.add.length&&(this._data.core.selected=this._data.core.selected.concat(b.add)),this.trigger("model",{nodes:b.dpc,parent:b.par}),b.par!==a.jstree.root?(this._node_changed(b.par),this.redraw()):this.redraw(!0),b.add.length&&this.trigger("changed",{action:"model",selected:this._data.core.selected}),d.call(this,!0)}};if(this.settings.core.worker&&window.Blob&&window.URL&&window.Worker)try{null===this._wrk&&(this._wrk=window.URL.createObjectURL(new window.Blob(["self.onmessage = "+i.toString()],{type:"text/javascript"}))),!this._data.core.working||e?(this._data.core.working=!0,f=new window.Worker(this._wrk),f.onmessage=a.proxy(function(a){j.call(this,a.data,!0);try{f.terminate(),f=null}catch(b){}this._data.core.worker_queue.length?this._append_json_data.apply(this,this._data.core.worker_queue.shift()):this._data.core.working=!1},this),g.par?f.postMessage(g):this._data.core.worker_queue.length?this._append_json_data.apply(this,this._data.core.worker_queue.shift()):this._data.core.working=!1):this._data.core.worker_queue.push([b,c,d,!0])}catch(k){j.call(this,i(g),!1),this._data.core.worker_queue.length?this._append_json_data.apply(this,this._data.core.worker_queue.shift()):this._data.core.working=!1}else j.call(this,i(g),!1)}},_parse_model_from_html:function(c,d,e){e=e?[].concat(e):[],d&&e.unshift(d);var f,g,h=this._model.data,i={id:!1,text:!1,icon:!0,parent:d,parents:e,children:[],children_d:[],data:null,state:{},li_attr:{id:!1},a_attr:{href:"#"},original:!1},j,k,l;for(j in this._model.default_state)this._model.default_state.hasOwnProperty(j)&&(i.state[j]=this._model.default_state[j]);if(k=a.vakata.attributes(c,!0),a.each(k,function(b,c){return c=a.trim(c),c.length?(i.li_attr[b]=c,void("id"===b&&(i.id=c.toString()))):!0}),k=c.children("a").first(),k.length&&(k=a.vakata.attributes(k,!0),a.each(k,function(b,c){c=a.trim(c),c.length&&(i.a_attr[b]=c)})),k=c.children("a").first().length?c.children("a").first().clone():c.clone(),k.children("ins, i, ul").remove(),k=k.html(),k=a("
").html(k),i.text=this.settings.core.force_text?k.text():k.html(),k=c.data(),i.data=k?a.extend(!0,{},k):null,i.state.opened=c.hasClass("jstree-open"),i.state.selected=c.children("a").hasClass("jstree-clicked"),i.state.disabled=c.children("a").hasClass("jstree-disabled"),i.data&&i.data.jstree)for(j in i.data.jstree)i.data.jstree.hasOwnProperty(j)&&(i.state[j]=i.data.jstree[j]);k=c.children("a").children(".jstree-themeicon"),k.length&&(i.icon=k.hasClass("jstree-themeicon-hidden")?!1:k.attr("rel")),i.state.icon!==b&&(i.icon=i.state.icon),(i.icon===b||null===i.icon||""===i.icon)&&(i.icon=!0),k=c.children("ul").children("li");do l="j"+this._id+"_"+ ++this._cnt;while(h[l]);return i.id=i.li_attr.id?i.li_attr.id.toString():l,k.length?(k.each(a.proxy(function(b,c){f=this._parse_model_from_html(a(c),i.id,e),g=this._model.data[f],i.children.push(f),g.children_d.length&&(i.children_d=i.children_d.concat(g.children_d))},this)),i.children_d=i.children_d.concat(i.children)):c.hasClass("jstree-closed")&&(i.state.loaded=!1),i.li_attr["class"]&&(i.li_attr["class"]=i.li_attr["class"].replace("jstree-closed","").replace("jstree-open","")),i.a_attr["class"]&&(i.a_attr["class"]=i.a_attr["class"].replace("jstree-clicked","").replace("jstree-disabled","")),h[i.id]=i,i.state.selected&&this._data.core.selected.push(i.id),i.id},_parse_model_from_flat_json:function(a,c,d){d=d?d.concat():[],c&&d.unshift(c);var e=a.id.toString(),f=this._model.data,g=this._model.default_state,h,i,j,k,l={id:e,text:a.text||"",icon:a.icon!==b?a.icon:!0,parent:c,parents:d,children:a.children||[],children_d:a.children_d||[],data:a.data,state:{},li_attr:{id:!1},a_attr:{href:"#"},original:!1};for(h in g)g.hasOwnProperty(h)&&(l.state[h]=g[h]);if(a&&a.data&&a.data.jstree&&a.data.jstree.icon&&(l.icon=a.data.jstree.icon),(l.icon===b||null===l.icon||""===l.icon)&&(l.icon=!0),a&&a.data&&(l.data=a.data,a.data.jstree))for(h in a.data.jstree)a.data.jstree.hasOwnProperty(h)&&(l.state[h]=a.data.jstree[h]);if(a&&"object"==typeof a.state)for(h in a.state)a.state.hasOwnProperty(h)&&(l.state[h]=a.state[h]);if(a&&"object"==typeof a.li_attr)for(h in a.li_attr)a.li_attr.hasOwnProperty(h)&&(l.li_attr[h]=a.li_attr[h]);if(l.li_attr.id||(l.li_attr.id=e),a&&"object"==typeof a.a_attr)for(h in a.a_attr)a.a_attr.hasOwnProperty(h)&&(l.a_attr[h]=a.a_attr[h]);for(a&&a.children&&a.children===!0&&(l.state.loaded=!1,l.children=[],l.children_d=[]),f[l.id]=l,h=0,i=l.children.length;i>h;h++)j=this._parse_model_from_flat_json(f[l.children[h]],l.id,d),k=f[j],l.children_d.push(j),k.children_d.length&&(l.children_d=l.children_d.concat(k.children_d));return delete a.data,delete a.children,f[l.id].original=a,l.state.selected&&this._data.core.selected.push(l.id),l.id},_parse_model_from_json:function(a,c,d){d=d?d.concat():[],c&&d.unshift(c);var e=!1,f,g,h,i,j=this._model.data,k=this._model.default_state,l;do e="j"+this._id+"_"+ ++this._cnt;while(j[e]);l={id:!1,text:"string"==typeof a?a:"",icon:"object"==typeof a&&a.icon!==b?a.icon:!0,parent:c,parents:d,children:[],children_d:[],data:null,state:{},li_attr:{id:!1},a_attr:{href:"#"},original:!1};for(f in k)k.hasOwnProperty(f)&&(l.state[f]=k[f]);if(a&&a.id&&(l.id=a.id.toString()),a&&a.text&&(l.text=a.text),a&&a.data&&a.data.jstree&&a.data.jstree.icon&&(l.icon=a.data.jstree.icon),(l.icon===b||null===l.icon||""===l.icon)&&(l.icon=!0),a&&a.data&&(l.data=a.data,a.data.jstree))for(f in a.data.jstree)a.data.jstree.hasOwnProperty(f)&&(l.state[f]=a.data.jstree[f]);if(a&&"object"==typeof a.state)for(f in a.state)a.state.hasOwnProperty(f)&&(l.state[f]=a.state[f]);if(a&&"object"==typeof a.li_attr)for(f in a.li_attr)a.li_attr.hasOwnProperty(f)&&(l.li_attr[f]=a.li_attr[f]); +if(l.li_attr.id&&!l.id&&(l.id=l.li_attr.id.toString()),l.id||(l.id=e),l.li_attr.id||(l.li_attr.id=l.id),a&&"object"==typeof a.a_attr)for(f in a.a_attr)a.a_attr.hasOwnProperty(f)&&(l.a_attr[f]=a.a_attr[f]);if(a&&a.children&&a.children.length){for(f=0,g=a.children.length;g>f;f++)h=this._parse_model_from_json(a.children[f],l.id,d),i=j[h],l.children.push(h),i.children_d.length&&(l.children_d=l.children_d.concat(i.children_d));l.children_d=l.children.concat(l.children_d)}return a&&a.children&&a.children===!0&&(l.state.loaded=!1,l.children=[],l.children_d=[]),delete a.data,delete a.children,l.original=a,j[l.id]=l,l.state.selected&&this._data.core.selected.push(l.id),l.id},_redraw:function(){var b=this._model.force_full_redraw?this._model.data[a.jstree.root].children.concat([]):this._model.changed.concat([]),c=i.createElement("UL"),d,e,f,g=this._data.core.focused;for(e=0,f=b.length;f>e;e++)d=this.redraw_node(b[e],!0,this._model.force_full_redraw),d&&this._model.force_full_redraw&&c.appendChild(d);this._model.force_full_redraw&&(c.className=this.get_container_ul()[0].className,c.setAttribute("role","group"),this.element.empty().append(c)),null!==g&&this.settings.core.restore_focus&&(d=this.get_node(g,!0),d&&d.length&&d.children(".jstree-anchor")[0]!==i.activeElement?d.children(".jstree-anchor").focus():this._data.core.focused=null),this._model.force_full_redraw=!1,this._model.changed=[],this.trigger("redraw",{nodes:b})},redraw:function(a){a&&(this._model.force_full_redraw=!0),this._redraw()},draw_children:function(b){var c=this.get_node(b),d=!1,e=!1,f=!1,g=i;if(!c)return!1;if(c.id===a.jstree.root)return this.redraw(!0);if(b=this.get_node(b,!0),!b||!b.length)return!1;if(b.children(".jstree-children").remove(),b=b[0],c.children.length&&c.state.loaded){for(f=g.createElement("UL"),f.setAttribute("role","group"),f.className="jstree-children",d=0,e=c.children.length;e>d;d++)f.appendChild(this.redraw_node(c.children[d],!0,!0));b.appendChild(f)}},redraw_node:function(b,c,d,e){var f=this.get_node(b),g=!1,h=!1,j=!1,k=!1,l=!1,m=!1,n="",o=i,p=this._model.data,q=!1,r=!1,s=null,t=0,u=0,v=!1,w=!1;if(!f)return!1;if(f.id===a.jstree.root)return this.redraw(!0);if(c=c||0===f.children.length,b=i.querySelector?this.element[0].querySelector("#"+(-1!=="0123456789".indexOf(f.id[0])?"\\3"+f.id[0]+" "+f.id.substr(1).replace(a.jstree.idregex,"\\$&"):f.id.replace(a.jstree.idregex,"\\$&"))):i.getElementById(f.id))b=a(b),d||(g=b.parent().parent()[0],g===this.element[0]&&(g=null),h=b.index()),c||!f.children.length||b.children(".jstree-children").length||(c=!0),c||(j=b.children(".jstree-children")[0]),q=b.children(".jstree-anchor")[0]===i.activeElement,b.remove();else if(c=!0,!d){if(g=f.parent!==a.jstree.root?a("#"+f.parent.replace(a.jstree.idregex,"\\$&"),this.element)[0]:null,!(null===g||g&&p[f.parent].state.opened))return!1;h=a.inArray(f.id,null===g?p[a.jstree.root].children:p[f.parent].children)}b=this._data.core.node.cloneNode(!0),n="jstree-node ";for(k in f.li_attr)if(f.li_attr.hasOwnProperty(k)){if("id"===k)continue;"class"!==k?b.setAttribute(k,f.li_attr[k]):n+=f.li_attr[k]}for(f.a_attr.id||(f.a_attr.id=f.id+"_anchor"),b.setAttribute("aria-selected",!!f.state.selected),b.setAttribute("aria-level",f.parents.length),b.setAttribute("aria-labelledby",f.a_attr.id),f.state.disabled&&b.setAttribute("aria-disabled",!0),k=0,l=f.children.length;l>k;k++)if(!p[f.children[k]].state.hidden){v=!0;break}if(null!==f.parent&&p[f.parent]&&!f.state.hidden&&(k=a.inArray(f.id,p[f.parent].children),w=f.id,-1!==k))for(k++,l=p[f.parent].children.length;l>k;k++)if(p[p[f.parent].children[k]].state.hidden||(w=p[f.parent].children[k]),w!==f.id)break;f.state.hidden&&(n+=" jstree-hidden"),f.state.loading&&(n+=" jstree-loading"),f.state.loaded&&!v?n+=" jstree-leaf":(n+=f.state.opened&&f.state.loaded?" jstree-open":" jstree-closed",b.setAttribute("aria-expanded",f.state.opened&&f.state.loaded)),w===f.id&&(n+=" jstree-last"),b.id=f.id,b.className=n,n=(f.state.selected?" jstree-clicked":"")+(f.state.disabled?" jstree-disabled":"");for(l in f.a_attr)if(f.a_attr.hasOwnProperty(l)){if("href"===l&&"#"===f.a_attr[l])continue;"class"!==l?b.childNodes[1].setAttribute(l,f.a_attr[l]):n+=" "+f.a_attr[l]}if(n.length&&(b.childNodes[1].className="jstree-anchor "+n),(f.icon&&f.icon!==!0||f.icon===!1)&&(f.icon===!1?b.childNodes[1].childNodes[0].className+=" jstree-themeicon-hidden":-1===f.icon.indexOf("/")&&-1===f.icon.indexOf(".")?b.childNodes[1].childNodes[0].className+=" "+f.icon+" jstree-themeicon-custom":(b.childNodes[1].childNodes[0].style.backgroundImage='url("'+f.icon+'")',b.childNodes[1].childNodes[0].style.backgroundPosition="center center",b.childNodes[1].childNodes[0].style.backgroundSize="auto",b.childNodes[1].childNodes[0].className+=" jstree-themeicon-custom")),this.settings.core.force_text?b.childNodes[1].appendChild(o.createTextNode(f.text)):b.childNodes[1].innerHTML+=f.text,c&&f.children.length&&(f.state.opened||e)&&f.state.loaded){for(m=o.createElement("UL"),m.setAttribute("role","group"),m.className="jstree-children",k=0,l=f.children.length;l>k;k++)m.appendChild(this.redraw_node(f.children[k],c,!0));b.appendChild(m)}if(j&&b.appendChild(j),!d){for(g||(g=this.element[0]),k=0,l=g.childNodes.length;l>k;k++)if(g.childNodes[k]&&g.childNodes[k].className&&-1!==g.childNodes[k].className.indexOf("jstree-children")){s=g.childNodes[k];break}s||(s=o.createElement("UL"),s.setAttribute("role","group"),s.className="jstree-children",g.appendChild(s)),g=s,hf;f++)this.open_node(c[f],d,e);return!0}return c=this.get_node(c),c&&c.id!==a.jstree.root?(e=e===b?this.settings.core.animation:e,this.is_closed(c)?this.is_loaded(c)?(h=this.get_node(c,!0),i=this,h.length&&(e&&h.children(".jstree-children").length&&h.children(".jstree-children").stop(!0,!0),c.children.length&&!this._firstChild(h.children(".jstree-children")[0])&&this.draw_children(c),e?(this.trigger("before_open",{node:c}),h.children(".jstree-children").css("display","none").end().removeClass("jstree-closed").addClass("jstree-open").attr("aria-expanded",!0).children(".jstree-children").stop(!0,!0).slideDown(e,function(){this.style.display="",i.element&&i.trigger("after_open",{node:c})})):(this.trigger("before_open",{node:c}),h[0].className=h[0].className.replace("jstree-closed","jstree-open"),h[0].setAttribute("aria-expanded",!0))),c.state.opened=!0,d&&d.call(this,c,!0),h.length||this.trigger("before_open",{node:c}),this.trigger("open_node",{node:c}),e&&h.length||this.trigger("after_open",{node:c}),!0):this.is_loading(c)?setTimeout(a.proxy(function(){this.open_node(c,d,e)},this),500):void this.load_node(c,function(a,b){return b?this.open_node(a,d,e):d?d.call(this,a,!1):!1}):(d&&d.call(this,c,!1),!1)):!1},_open_to:function(b){if(b=this.get_node(b),!b||b.id===a.jstree.root)return!1;var c,d,e=b.parents;for(c=0,d=e.length;d>c;c+=1)c!==a.jstree.root&&this.open_node(e[c],!1,0);return a("#"+b.id.replace(a.jstree.idregex,"\\$&"),this.element)},close_node:function(c,d){var e,f,g,h;if(a.isArray(c)){for(c=c.slice(),e=0,f=c.length;f>e;e++)this.close_node(c[e],d);return!0}return c=this.get_node(c),c&&c.id!==a.jstree.root?this.is_closed(c)?!1:(d=d===b?this.settings.core.animation:d,g=this,h=this.get_node(c,!0),c.state.opened=!1,this.trigger("close_node",{node:c}),void(h.length?d?h.children(".jstree-children").attr("style","display:block !important").end().removeClass("jstree-open").addClass("jstree-closed").attr("aria-expanded",!1).children(".jstree-children").stop(!0,!0).slideUp(d,function(){this.style.display="",h.children(".jstree-children").remove(),g.element&&g.trigger("after_close",{node:c})}):(h[0].className=h[0].className.replace("jstree-open","jstree-closed"),h.attr("aria-expanded",!1).children(".jstree-children").remove(),this.trigger("after_close",{node:c})):this.trigger("after_close",{node:c}))):!1},toggle_node:function(b){var c,d;if(a.isArray(b)){for(b=b.slice(),c=0,d=b.length;d>c;c++)this.toggle_node(b[c]);return!0}return this.is_closed(b)?this.open_node(b):this.is_open(b)?this.close_node(b):void 0},open_all:function(b,c,d){if(b||(b=a.jstree.root),b=this.get_node(b),!b)return!1;var e=b.id===a.jstree.root?this.get_container_ul():this.get_node(b,!0),f,g,h;if(!e.length){for(f=0,g=b.children_d.length;g>f;f++)this.is_closed(this._model.data[b.children_d[f]])&&(this._model.data[b.children_d[f]].state.opened=!0);return this.trigger("open_all",{node:b})}d=d||e,h=this,e=this.is_closed(b)?e.find(".jstree-closed").addBack():e.find(".jstree-closed"),e.each(function(){h.open_node(this,function(a,b){b&&this.is_parent(a)&&this.open_all(a,c,d)},c||0)}),0===d.find(".jstree-closed").length&&this.trigger("open_all",{node:this.get_node(d)})},close_all:function(b,c){if(b||(b=a.jstree.root),b=this.get_node(b),!b)return!1;var d=b.id===a.jstree.root?this.get_container_ul():this.get_node(b,!0),e=this,f,g;for(d.length&&(d=this.is_open(b)?d.find(".jstree-open").addBack():d.find(".jstree-open"),a(d.get().reverse()).each(function(){e.close_node(this,c||0)})),f=0,g=b.children_d.length;g>f;f++)this._model.data[b.children_d[f]].state.opened=!1;this.trigger("close_all",{node:b})},is_disabled:function(a){return a=this.get_node(a),a&&a.state&&a.state.disabled},enable_node:function(b){var c,d;if(a.isArray(b)){for(b=b.slice(),c=0,d=b.length;d>c;c++)this.enable_node(b[c]);return!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?(b.state.disabled=!1,this.get_node(b,!0).children(".jstree-anchor").removeClass("jstree-disabled").attr("aria-disabled",!1),void this.trigger("enable_node",{node:b})):!1},disable_node:function(b){var c,d;if(a.isArray(b)){for(b=b.slice(),c=0,d=b.length;d>c;c++)this.disable_node(b[c]);return!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?(b.state.disabled=!0,this.get_node(b,!0).children(".jstree-anchor").addClass("jstree-disabled").attr("aria-disabled",!0),void this.trigger("disable_node",{node:b})):!1},is_hidden:function(a){return a=this.get_node(a),a.state.hidden===!0},hide_node:function(b,c){var d,e;if(a.isArray(b)){for(b=b.slice(),d=0,e=b.length;e>d;d++)this.hide_node(b[d],!0);return c||this.redraw(),!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?void(b.state.hidden||(b.state.hidden=!0,this._node_changed(b.parent),c||this.redraw(),this.trigger("hide_node",{node:b}))):!1},show_node:function(b,c){var d,e;if(a.isArray(b)){for(b=b.slice(),d=0,e=b.length;e>d;d++)this.show_node(b[d],!0);return c||this.redraw(),!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?void(b.state.hidden&&(b.state.hidden=!1,this._node_changed(b.parent),c||this.redraw(),this.trigger("show_node",{node:b}))):!1},hide_all:function(b){var c,d=this._model.data,e=[];for(c in d)d.hasOwnProperty(c)&&c!==a.jstree.root&&!d[c].state.hidden&&(d[c].state.hidden=!0,e.push(c));return this._model.force_full_redraw=!0,b||this.redraw(),this.trigger("hide_all",{nodes:e}),e},show_all:function(b){var c,d=this._model.data,e=[];for(c in d)d.hasOwnProperty(c)&&c!==a.jstree.root&&d[c].state.hidden&&(d[c].state.hidden=!1,e.push(c));return this._model.force_full_redraw=!0,b||this.redraw(),this.trigger("show_all",{nodes:e}),e},activate_node:function(a,c){if(this.is_disabled(a))return!1;if(c&&"object"==typeof c||(c={}),this._data.core.last_clicked=this._data.core.last_clicked&&this._data.core.last_clicked.id!==b?this.get_node(this._data.core.last_clicked.id):null,this._data.core.last_clicked&&!this._data.core.last_clicked.state.selected&&(this._data.core.last_clicked=null),!this._data.core.last_clicked&&this._data.core.selected.length&&(this._data.core.last_clicked=this.get_node(this._data.core.selected[this._data.core.selected.length-1])),this.settings.core.multiple&&(c.metaKey||c.ctrlKey||c.shiftKey)&&(!c.shiftKey||this._data.core.last_clicked&&this.get_parent(a)&&this.get_parent(a)===this._data.core.last_clicked.parent))if(c.shiftKey){var d=this.get_node(a).id,e=this._data.core.last_clicked.id,f=this.get_node(this._data.core.last_clicked.parent).children,g=!1,h,i;for(h=0,i=f.length;i>h;h+=1)f[h]===d&&(g=!g),f[h]===e&&(g=!g),this.is_disabled(f[h])||!g&&f[h]!==d&&f[h]!==e?this.deselect_node(f[h],!0,c):this.is_hidden(f[h])||this.select_node(f[h],!0,!1,c);this.trigger("changed",{action:"select_node",node:this.get_node(a),selected:this._data.core.selected,event:c})}else this.is_selected(a)?this.deselect_node(a,!1,c):this.select_node(a,!1,!1,c);else!this.settings.core.multiple&&(c.metaKey||c.ctrlKey||c.shiftKey)&&this.is_selected(a)?this.deselect_node(a,!1,c):(this.deselect_all(!0),this.select_node(a,!1,!1,c),this._data.core.last_clicked=this.get_node(a));this.trigger("activate_node",{node:this.get_node(a),event:c})},hover_node:function(a){if(a=this.get_node(a,!0),!a||!a.length||a.children(".jstree-hovered").length)return!1;var b=this.element.find(".jstree-hovered"),c=this.element;b&&b.length&&this.dehover_node(b),a.children(".jstree-anchor").addClass("jstree-hovered"),this.trigger("hover_node",{node:this.get_node(a)}),setTimeout(function(){c.attr("aria-activedescendant",a[0].id)},0)},dehover_node:function(a){return a=this.get_node(a,!0),a&&a.length&&a.children(".jstree-hovered").length?(a.children(".jstree-anchor").removeClass("jstree-hovered"),void this.trigger("dehover_node",{node:this.get_node(a)})):!1},select_node:function(b,c,d,e){var f,g,h,i;if(a.isArray(b)){for(b=b.slice(),g=0,h=b.length;h>g;g++)this.select_node(b[g],c,d,e);return!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?(f=this.get_node(b,!0),void(b.state.selected||(b.state.selected=!0,this._data.core.selected.push(b.id),d||(f=this._open_to(b)),f&&f.length&&f.attr("aria-selected",!0).children(".jstree-anchor").addClass("jstree-clicked"),this.trigger("select_node",{node:b,selected:this._data.core.selected,event:e}),c||this.trigger("changed",{action:"select_node",node:b,selected:this._data.core.selected,event:e})))):!1},deselect_node:function(b,c,d){var e,f,g;if(a.isArray(b)){for(b=b.slice(),e=0,f=b.length;f>e;e++)this.deselect_node(b[e],c,d);return!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?(g=this.get_node(b,!0),void(b.state.selected&&(b.state.selected=!1,this._data.core.selected=a.vakata.array_remove_item(this._data.core.selected,b.id),g.length&&g.attr("aria-selected",!1).children(".jstree-anchor").removeClass("jstree-clicked"),this.trigger("deselect_node",{node:b,selected:this._data.core.selected,event:d}),c||this.trigger("changed",{action:"deselect_node",node:b,selected:this._data.core.selected,event:d})))):!1},select_all:function(b){var c=this._data.core.selected.concat([]),d,e;for(this._data.core.selected=this._model.data[a.jstree.root].children_d.concat(),d=0,e=this._data.core.selected.length;e>d;d++)this._model.data[this._data.core.selected[d]]&&(this._model.data[this._data.core.selected[d]].state.selected=!0);this.redraw(!0),this.trigger("select_all",{selected:this._data.core.selected}),b||this.trigger("changed",{action:"select_all",selected:this._data.core.selected,old_selection:c})},deselect_all:function(a){var b=this._data.core.selected.concat([]),c,d;for(c=0,d=this._data.core.selected.length;d>c;c++)this._model.data[this._data.core.selected[c]]&&(this._model.data[this._data.core.selected[c]].state.selected=!1);this._data.core.selected=[],this.element.find(".jstree-clicked").removeClass("jstree-clicked").parent().attr("aria-selected",!1),this.trigger("deselect_all",{selected:this._data.core.selected,node:b}),a||this.trigger("changed",{action:"deselect_all",selected:this._data.core.selected,old_selection:b})},is_selected:function(b){return b=this.get_node(b),b&&b.id!==a.jstree.root?b.state.selected:!1},get_selected:function(b){return b?a.map(this._data.core.selected,a.proxy(function(a){return this.get_node(a)},this)):this._data.core.selected.slice()},get_top_selected:function(b){var c=this.get_selected(!0),d={},e,f,g,h;for(e=0,f=c.length;f>e;e++)d[c[e].id]=c[e];for(e=0,f=c.length;f>e;e++)for(g=0,h=c[e].children_d.length;h>g;g++)d[c[e].children_d[g]]&&delete d[c[e].children_d[g]];c=[];for(e in d)d.hasOwnProperty(e)&&c.push(e);return b?a.map(c,a.proxy(function(a){return this.get_node(a)},this)):c},get_bottom_selected:function(b){var c=this.get_selected(!0),d=[],e,f;for(e=0,f=c.length;f>e;e++)c[e].children.length||d.push(c[e].id);return b?a.map(d,a.proxy(function(a){return this.get_node(a)},this)):d},get_state:function(){var b={core:{open:[],loaded:[],scroll:{left:this.element.scrollLeft(),top:this.element.scrollTop()},selected:[]}},c;for(c in this._model.data)this._model.data.hasOwnProperty(c)&&c!==a.jstree.root&&(this._model.data[c].state.loaded&&this.settings.core.loaded_state&&b.core.loaded.push(c),this._model.data[c].state.opened&&b.core.open.push(c),this._model.data[c].state.selected&&b.core.selected.push(c));return b},set_state:function(c,d){if(c){if(c.core&&c.core.selected&&c.core.initial_selection===b&&(c.core.initial_selection=this._data.core.selected.concat([]).sort().join(",")),c.core){var e,f,g,h,i;if(c.core.loaded)return this.settings.core.loaded_state&&a.isArray(c.core.loaded)&&c.core.loaded.length?this._load_nodes(c.core.loaded,function(a){delete c.core.loaded,this.set_state(c,d)}):(delete c.core.loaded,this.set_state(c,d)),!1;if(c.core.open)return a.isArray(c.core.open)&&c.core.open.length?this._load_nodes(c.core.open,function(a){this.open_node(a,!1,0),delete c.core.open,this.set_state(c,d)}):(delete c.core.open,this.set_state(c,d)),!1;if(c.core.scroll)return c.core.scroll&&c.core.scroll.left!==b&&this.element.scrollLeft(c.core.scroll.left),c.core.scroll&&c.core.scroll.top!==b&&this.element.scrollTop(c.core.scroll.top),delete c.core.scroll,this.set_state(c,d),!1;if(c.core.selected)return h=this,(c.core.initial_selection===b||c.core.initial_selection===this._data.core.selected.concat([]).sort().join(","))&&(this.deselect_all(),a.each(c.core.selected,function(a,b){h.select_node(b,!1,!0)})),delete c.core.initial_selection,delete c.core.selected,this.set_state(c,d),!1;for(i in c)c.hasOwnProperty(i)&&"core"!==i&&-1===a.inArray(i,this.settings.plugins)&&delete c[i];if(a.isEmptyObject(c.core))return delete c.core,this.set_state(c,d),!1}return a.isEmptyObject(c)?(c=null,d&&d.call(this),this.trigger("set_state"),!1):!0}return!1},refresh:function(b,c){this._data.core.state=c===!0?{}:this.get_state(),c&&a.isFunction(c)&&(this._data.core.state=c.call(this,this._data.core.state)),this._cnt=0,this._model.data={},this._model.data[a.jstree.root]={id:a.jstree.root,parent:null,parents:[],children:[],children_d:[],state:{loaded:!1}},this._data.core.selected=[],this._data.core.last_clicked=null,this._data.core.focused=null;var d=this.get_container_ul()[0].className;b||(this.element.html(""),this.element.attr("aria-activedescendant","j"+this._id+"_loading")),this.load_node(a.jstree.root,function(b,c){c&&(this.get_container_ul()[0].className=d,this._firstChild(this.get_container_ul()[0])&&this.element.attr("aria-activedescendant",this._firstChild(this.get_container_ul()[0]).id),this.set_state(a.extend(!0,{},this._data.core.state),function(){this.trigger("refresh")})),this._data.core.state=null})},refresh_node:function(b){if(b=this.get_node(b),!b||b.id===a.jstree.root)return!1;var c=[],d=[],e=this._data.core.selected.concat([]);d.push(b.id),b.state.opened===!0&&c.push(b.id),this.get_node(b,!0).find(".jstree-open").each(function(){d.push(this.id),c.push(this.id)}),this._load_nodes(d,a.proxy(function(a){this.open_node(c,!1,0),this.select_node(e),this.trigger("refresh_node",{node:b,nodes:a})},this),!1,!0)},set_id:function(b,c){if(b=this.get_node(b),!b||b.id===a.jstree.root)return!1;var d,e,f=this._model.data,g=b.id;for(c=c.toString(),f[b.parent].children[a.inArray(b.id,f[b.parent].children)]=c,d=0,e=b.parents.length;e>d;d++)f[b.parents[d]].children_d[a.inArray(b.id,f[b.parents[d]].children_d)]=c;for(d=0,e=b.children.length;e>d;d++)f[b.children[d]].parent=c;for(d=0,e=b.children_d.length;e>d;d++)f[b.children_d[d]].parents[a.inArray(b.id,f[b.children_d[d]].parents)]=c;return d=a.inArray(b.id,this._data.core.selected),-1!==d&&(this._data.core.selected[d]=c),d=this.get_node(b.id,!0),d&&(d.attr("id",c),this.element.attr("aria-activedescendant")===b.id&&this.element.attr("aria-activedescendant",c)),delete f[b.id],b.id=c,b.li_attr.id=c,f[c]=b,this.trigger("set_id",{node:b,"new":b.id,old:g}),!0},get_text:function(b){return b=this.get_node(b),b&&b.id!==a.jstree.root?b.text:!1},set_text:function(b,c){var d,e;if(a.isArray(b)){for(b=b.slice(),d=0,e=b.length;e>d;d++)this.set_text(b[d],c);return!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?(b.text=c,this.get_node(b,!0).length&&this.redraw_node(b.id),this.trigger("set_text",{obj:b,text:c}),!0):!1},get_json:function(b,c,d){if(b=this.get_node(b||a.jstree.root),!b)return!1;c&&c.flat&&!d&&(d=[]);var e={id:b.id,text:b.text,icon:this.get_icon(b),li_attr:a.extend(!0,{},b.li_attr),a_attr:a.extend(!0,{},b.a_attr),state:{},data:c&&c.no_data?!1:a.extend(!0,a.isArray(b.data)?[]:{},b.data)},f,g;if(c&&c.flat?e.parent=b.parent:e.children=[],c&&c.no_state)delete e.state;else for(f in b.state)b.state.hasOwnProperty(f)&&(e.state[f]=b.state[f]);if(c&&c.no_li_attr&&delete e.li_attr,c&&c.no_a_attr&&delete e.a_attr,c&&c.no_id&&(delete e.id,e.li_attr&&e.li_attr.id&&delete e.li_attr.id,e.a_attr&&e.a_attr.id&&delete e.a_attr.id),c&&c.flat&&b.id!==a.jstree.root&&d.push(e),!c||!c.no_children)for(f=0,g=b.children.length;g>f;f++)c&&c.flat?this.get_json(b.children[f],c,d):e.children.push(this.get_json(b.children[f],c));return c&&c.flat?d:b.id===a.jstree.root?e.children:e},create_node:function(c,d,e,f,g){if(null===c&&(c=a.jstree.root),c=this.get_node(c),!c)return!1;if(e=e===b?"last":e,!e.toString().match(/^(before|after)$/)&&!g&&!this.is_loaded(c))return this.load_node(c,function(){this.create_node(c,d,e,f,!0)});d||(d={text:this.get_string("New node")}),d="string"==typeof d?{text:d}:a.extend(!0,{},d),d.text===b&&(d.text=this.get_string("New node"));var h,i,j,k;switch(c.id===a.jstree.root&&("before"===e&&(e="first"),"after"===e&&(e="last")),e){case"before":h=this.get_node(c.parent),e=a.inArray(c.id,h.children),c=h;break;case"after":h=this.get_node(c.parent),e=a.inArray(c.id,h.children)+1,c=h;break;case"inside":case"first":e=0;break;case"last":e=c.children.length;break;default:e||(e=0)}if(e>c.children.length&&(e=c.children.length),d.id||(d.id=!0),!this.check("create_node",d,c,e))return this.settings.core.error.call(this,this._data.core.last_error),!1;if(d.id===!0&&delete d.id,d=this._parse_model_from_json(d,c.id,c.parents.concat()),!d)return!1;for(h=this.get_node(d),i=[],i.push(d),i=i.concat(h.children_d),this.trigger("model",{nodes:i,parent:c.id}),c.children_d=c.children_d.concat(i),j=0,k=c.parents.length;k>j;j++)this._model.data[c.parents[j]].children_d=this._model.data[c.parents[j]].children_d.concat(i);for(d=h,h=[],j=0,k=c.children.length;k>j;j++)h[j>=e?j+1:j]=c.children[j];return h[e]=d.id,c.children=h,this.redraw_node(c,!0),this.trigger("create_node",{node:this.get_node(d),parent:c.id,position:e}),f&&f.call(this,this.get_node(d)),d.id},rename_node:function(b,c){var d,e,f;if(a.isArray(b)){for(b=b.slice(),d=0,e=b.length;e>d;d++)this.rename_node(b[d],c);return!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?(f=b.text,this.check("rename_node",b,this.get_parent(b),c)?(this.set_text(b,c),this.trigger("rename_node",{node:b,text:c,old:f}),!0):(this.settings.core.error.call(this,this._data.core.last_error),!1)):!1},delete_node:function(b){var c,d,e,f,g,h,i,j,k,l,m,n;if(a.isArray(b)){for(b=b.slice(),c=0,d=b.length;d>c;c++)this.delete_node(b[c]);return!0}if(b=this.get_node(b),!b||b.id===a.jstree.root)return!1;if(e=this.get_node(b.parent),f=a.inArray(b.id,e.children),l=!1,!this.check("delete_node",b,e,f))return this.settings.core.error.call(this,this._data.core.last_error),!1;for(-1!==f&&(e.children=a.vakata.array_remove(e.children,f)),g=b.children_d.concat([]),g.push(b.id),h=0,i=b.parents.length;i>h;h++)this._model.data[b.parents[h]].children_d=a.vakata.array_filter(this._model.data[b.parents[h]].children_d,function(b){return-1===a.inArray(b,g)});for(j=0,k=g.length;k>j;j++)if(this._model.data[g[j]].state.selected){l=!0;break}for(l&&(this._data.core.selected=a.vakata.array_filter(this._data.core.selected,function(b){return-1===a.inArray(b,g)})),this.trigger("delete_node",{node:b,parent:e.id}),l&&this.trigger("changed",{action:"delete_node",node:b,selected:this._data.core.selected,parent:e.id}),j=0,k=g.length;k>j;j++)delete this._model.data[g[j]];return-1!==a.inArray(this._data.core.focused,g)&&(this._data.core.focused=null,m=this.element[0].scrollTop,n=this.element[0].scrollLeft,e.id===a.jstree.root?this._model.data[a.jstree.root].children[0]&&this.get_node(this._model.data[a.jstree.root].children[0],!0).children(".jstree-anchor").focus():this.get_node(e,!0).children(".jstree-anchor").focus(),this.element[0].scrollTop=m,this.element[0].scrollLeft=n),this.redraw_node(e,!0),!0},check:function(b,c,d,e,f){c=c&&c.id?c:this.get_node(c),d=d&&d.id?d:this.get_node(d);var g=b.match(/^move_node|copy_node|create_node$/i)?d:c,h=this.settings.core.check_callback;if("move_node"===b||"copy_node"===b){if(!(f&&f.is_multi||"move_node"!==b||a.inArray(c.id,d.children)!==e))return this._data.core.last_error={error:"check",plugin:"core",id:"core_08",reason:"Moving node to its current position",data:JSON.stringify({chk:b,pos:e,obj:c&&c.id?c.id:!1,par:d&&d.id?d.id:!1})},!1;if(!(f&&f.is_multi||c.id!==d.id&&("move_node"!==b||a.inArray(c.id,d.children)!==e)&&-1===a.inArray(d.id,c.children_d)))return this._data.core.last_error={error:"check",plugin:"core",id:"core_01",reason:"Moving parent inside child",data:JSON.stringify({chk:b,pos:e,obj:c&&c.id?c.id:!1,par:d&&d.id?d.id:!1})},!1}return g&&g.data&&(g=g.data),g&&g.functions&&(g.functions[b]===!1||g.functions[b]===!0)?(g.functions[b]===!1&&(this._data.core.last_error={error:"check",plugin:"core",id:"core_02",reason:"Node data prevents function: "+b,data:JSON.stringify({chk:b,pos:e,obj:c&&c.id?c.id:!1,par:d&&d.id?d.id:!1})}),g.functions[b]):h===!1||a.isFunction(h)&&h.call(this,b,c,d,e,f)===!1||h&&h[b]===!1?(this._data.core.last_error={error:"check",plugin:"core",id:"core_03",reason:"User config for core.check_callback prevents function: "+b,data:JSON.stringify({chk:b,pos:e,obj:c&&c.id?c.id:!1,par:d&&d.id?d.id:!1})},!1):!0},last_error:function(){return this._data.core.last_error},move_node:function(c,d,e,f,g,h,i){var j,k,l,m,n,o,p,q,r,s,t,u,v,w;if(d=this.get_node(d),e=e===b?0:e,!d)return!1;if(!e.toString().match(/^(before|after)$/)&&!g&&!this.is_loaded(d))return this.load_node(d,function(){this.move_node(c,d,e,f,!0,!1,i)});if(a.isArray(c)){if(1!==c.length){for(j=0,k=c.length;k>j;j++)(r=this.move_node(c[j],d,e,f,g,!1,i))&&(d=r,e="after");return this.redraw(),!0}c=c[0]}if(c=c&&c.id?c:this.get_node(c),!c||c.id===a.jstree.root)return!1;if(l=(c.parent||a.jstree.root).toString(),n=e.toString().match(/^(before|after)$/)&&d.id!==a.jstree.root?this.get_node(d.parent):d,o=i?i:this._model.data[c.id]?this:a.jstree.reference(c.id),p=!o||!o._id||this._id!==o._id,m=o&&o._id&&l&&o._model.data[l]&&o._model.data[l].children?a.inArray(c.id,o._model.data[l].children):-1,o&&o._id&&(c=o._model.data[c.id]),p)return(r=this.copy_node(c,d,e,f,g,!1,i))?(o&&o.delete_node(c),r):!1;switch(d.id===a.jstree.root&&("before"===e&&(e="first"),"after"===e&&(e="last")),e){case"before":e=a.inArray(d.id,n.children);break;case"after":e=a.inArray(d.id,n.children)+1;break;case"inside":case"first":e=0;break;case"last":e=n.children.length;break;default:e||(e=0)}if(e>n.children.length&&(e=n.children.length),!this.check("move_node",c,n,e,{core:!0,origin:i,is_multi:o&&o._id&&o._id!==this._id,is_foreign:!o||!o._id}))return this.settings.core.error.call(this,this._data.core.last_error),!1;if(c.parent===n.id){for(q=n.children.concat(),r=a.inArray(c.id,q),-1!==r&&(q=a.vakata.array_remove(q,r),e>r&&e--),r=[],s=0,t=q.length;t>s;s++)r[s>=e?s+1:s]=q[s];r[e]=c.id,n.children=r,this._node_changed(n.id),this.redraw(n.id===a.jstree.root)}else{for(r=c.children_d.concat(),r.push(c.id),s=0,t=c.parents.length;t>s;s++){for(q=[],w=o._model.data[c.parents[s]].children_d,u=0,v=w.length;v>u;u++)-1===a.inArray(w[u],r)&&q.push(w[u]);o._model.data[c.parents[s]].children_d=q}for(o._model.data[l].children=a.vakata.array_remove_item(o._model.data[l].children,c.id),s=0,t=n.parents.length;t>s;s++)this._model.data[n.parents[s]].children_d=this._model.data[n.parents[s]].children_d.concat(r);for(q=[],s=0,t=n.children.length;t>s;s++)q[s>=e?s+1:s]=n.children[s];for(q[e]=c.id,n.children=q,n.children_d.push(c.id),n.children_d=n.children_d.concat(c.children_d),c.parent=n.id,r=n.parents.concat(),r.unshift(n.id),w=c.parents.length,c.parents=r,r=r.concat(),s=0,t=c.children_d.length;t>s;s++)this._model.data[c.children_d[s]].parents=this._model.data[c.children_d[s]].parents.slice(0,-1*w),Array.prototype.push.apply(this._model.data[c.children_d[s]].parents,r);(l===a.jstree.root||n.id===a.jstree.root)&&(this._model.force_full_redraw=!0),this._model.force_full_redraw||(this._node_changed(l),this._node_changed(n.id)),h||this.redraw()}return f&&f.call(this,c,n,e),this.trigger("move_node",{node:c,parent:n.id,position:e,old_parent:l,old_position:m,is_multi:o&&o._id&&o._id!==this._id,is_foreign:!o||!o._id,old_instance:o,new_instance:this}),c.id},copy_node:function(c,d,e,f,g,h,i){var j,k,l,m,n,o,p,q,r,s,t;if(d=this.get_node(d),e=e===b?0:e,!d)return!1;if(!e.toString().match(/^(before|after)$/)&&!g&&!this.is_loaded(d))return this.load_node(d,function(){this.copy_node(c,d,e,f,!0,!1,i)});if(a.isArray(c)){if(1!==c.length){for(j=0,k=c.length;k>j;j++)(m=this.copy_node(c[j],d,e,f,g,!0,i))&&(d=m,e="after");return this.redraw(),!0}c=c[0]}if(c=c&&c.id?c:this.get_node(c),!c||c.id===a.jstree.root)return!1;switch(q=(c.parent||a.jstree.root).toString(),r=e.toString().match(/^(before|after)$/)&&d.id!==a.jstree.root?this.get_node(d.parent):d,s=i?i:this._model.data[c.id]?this:a.jstree.reference(c.id),t=!s||!s._id||this._id!==s._id,s&&s._id&&(c=s._model.data[c.id]),d.id===a.jstree.root&&("before"===e&&(e="first"),"after"===e&&(e="last")),e){case"before":e=a.inArray(d.id,r.children);break;case"after":e=a.inArray(d.id,r.children)+1;break;case"inside":case"first":e=0;break;case"last":e=r.children.length;break;default:e||(e=0)}if(e>r.children.length&&(e=r.children.length),!this.check("copy_node",c,r,e,{core:!0,origin:i,is_multi:s&&s._id&&s._id!==this._id,is_foreign:!s||!s._id}))return this.settings.core.error.call(this,this._data.core.last_error),!1;if(p=s?s.get_json(c,{no_id:!0,no_data:!0,no_state:!0}):c,!p)return!1;if(p.id===!0&&delete p.id,p=this._parse_model_from_json(p,r.id,r.parents.concat()),!p)return!1;for(m=this.get_node(p),c&&c.state&&c.state.loaded===!1&&(m.state.loaded=!1),l=[],l.push(p),l=l.concat(m.children_d),this.trigger("model",{nodes:l,parent:r.id}),n=0,o=r.parents.length;o>n;n++)this._model.data[r.parents[n]].children_d=this._model.data[r.parents[n]].children_d.concat(l);for(l=[],n=0,o=r.children.length;o>n;n++)l[n>=e?n+1:n]=r.children[n];return l[e]=m.id,r.children=l,r.children_d.push(m.id),r.children_d=r.children_d.concat(m.children_d),r.id===a.jstree.root&&(this._model.force_full_redraw=!0),this._model.force_full_redraw||this._node_changed(r.id),h||this.redraw(r.id===a.jstree.root),f&&f.call(this,m,r,e),this.trigger("copy_node",{node:m,original:c,parent:r.id,position:e,old_parent:q,old_position:s&&s._id&&q&&s._model.data[q]&&s._model.data[q].children?a.inArray(c.id,s._model.data[q].children):-1, +is_multi:s&&s._id&&s._id!==this._id,is_foreign:!s||!s._id,old_instance:s,new_instance:this}),m.id},cut:function(b){if(b||(b=this._data.core.selected.concat()),a.isArray(b)||(b=[b]),!b.length)return!1;var c=[],g,h,i;for(h=0,i=b.length;i>h;h++)g=this.get_node(b[h]),g&&g.id&&g.id!==a.jstree.root&&c.push(g);return c.length?(d=c,f=this,e="move_node",void this.trigger("cut",{node:b})):!1},copy:function(b){if(b||(b=this._data.core.selected.concat()),a.isArray(b)||(b=[b]),!b.length)return!1;var c=[],g,h,i;for(h=0,i=b.length;i>h;h++)g=this.get_node(b[h]),g&&g.id&&g.id!==a.jstree.root&&c.push(g);return c.length?(d=c,f=this,e="copy_node",void this.trigger("copy",{node:b})):!1},get_buffer:function(){return{mode:e,node:d,inst:f}},can_paste:function(){return e!==!1&&d!==!1},paste:function(a,b){return a=this.get_node(a),a&&e&&e.match(/^(copy_node|move_node)$/)&&d?(this[e](d,a,b,!1,!1,!1,f)&&this.trigger("paste",{parent:a.id,node:d,mode:e}),d=!1,e=!1,void(f=!1)):!1},clear_buffer:function(){d=!1,e=!1,f=!1,this.trigger("clear_buffer")},edit:function(b,c,d){var e,f,g,h,j,k,l,m,n,o=!1;return(b=this.get_node(b))?this.check("edit",b,this.get_parent(b))?(n=b,c="string"==typeof c?c:b.text,this.set_text(b,""),b=this._open_to(b),n.text=c,e=this._data.core.rtl,f=this.element.width(),this._data.core.focused=n.id,g=b.children(".jstree-anchor").focus(),h=a(""),j=c,k=a("
",{css:{position:"absolute",top:"-200px",left:e?"0px":"-1000px",visibility:"hidden"}}).appendTo(i.body),l=a("",{value:j,"class":"jstree-rename-input",css:{padding:"0",border:"1px solid silver","box-sizing":"border-box",display:"inline-block",height:this._data.core.li_height+"px",lineHeight:this._data.core.li_height+"px",width:"150px"},blur:a.proxy(function(c){c.stopImmediatePropagation(),c.preventDefault();var e=h.children(".jstree-rename-input"),f=e.val(),i=this.settings.core.force_text,m;""===f&&(f=j),k.remove(),h.replaceWith(g),h.remove(),j=i?j:a("
").append(a.parseHTML(j)).html(),b=this.get_node(b),this.set_text(b,j),m=!!this.rename_node(b,i?a("
").text(f).text():a("
").append(a.parseHTML(f)).html()),m||this.set_text(b,j),this._data.core.focused=n.id,setTimeout(a.proxy(function(){var a=this.get_node(n.id,!0);a.length&&(this._data.core.focused=n.id,a.children(".jstree-anchor").focus())},this),0),d&&d.call(this,n,m,o),l=null},this),keydown:function(a){var b=a.which;27===b&&(o=!0,this.value=j),(27===b||13===b||37===b||38===b||39===b||40===b||32===b)&&a.stopImmediatePropagation(),(27===b||13===b)&&(a.preventDefault(),this.blur())},click:function(a){a.stopImmediatePropagation()},mousedown:function(a){a.stopImmediatePropagation()},keyup:function(a){l.width(Math.min(k.text("pW"+this.value).width(),f))},keypress:function(a){return 13===a.which?!1:void 0}}),m={fontFamily:g.css("fontFamily")||"",fontSize:g.css("fontSize")||"",fontWeight:g.css("fontWeight")||"",fontStyle:g.css("fontStyle")||"",fontStretch:g.css("fontStretch")||"",fontVariant:g.css("fontVariant")||"",letterSpacing:g.css("letterSpacing")||"",wordSpacing:g.css("wordSpacing")||""},h.attr("class",g.attr("class")).append(g.contents().clone()).append(l),g.replaceWith(h),k.css(m),l.css(m).width(Math.min(k.text("pW"+l[0].value).width(),f))[0].select(),void a(i).one("mousedown.jstree touchstart.jstree dnd_start.vakata",function(b){l&&b.target!==l&&a(l).blur()})):(this.settings.core.error.call(this,this._data.core.last_error),!1):!1},set_theme:function(b,c){if(!b)return!1;if(c===!0){var d=this.settings.core.themes.dir;d||(d=a.jstree.path+"/themes"),c=d+"/"+b+"/style.css"}c&&-1===a.inArray(c,g)&&(a("head").append(''),g.push(c)),this._data.core.themes.name&&this.element.removeClass("jstree-"+this._data.core.themes.name),this._data.core.themes.name=b,this.element.addClass("jstree-"+b),this.element[this.settings.core.themes.responsive?"addClass":"removeClass"]("jstree-"+b+"-responsive"),this.trigger("set_theme",{theme:b})},get_theme:function(){return this._data.core.themes.name},set_theme_variant:function(a){this._data.core.themes.variant&&this.element.removeClass("jstree-"+this._data.core.themes.name+"-"+this._data.core.themes.variant),this._data.core.themes.variant=a,a&&this.element.addClass("jstree-"+this._data.core.themes.name+"-"+this._data.core.themes.variant)},get_theme_variant:function(){return this._data.core.themes.variant},show_stripes:function(){this._data.core.themes.stripes=!0,this.get_container_ul().addClass("jstree-striped"),this.trigger("show_stripes")},hide_stripes:function(){this._data.core.themes.stripes=!1,this.get_container_ul().removeClass("jstree-striped"),this.trigger("hide_stripes")},toggle_stripes:function(){this._data.core.themes.stripes?this.hide_stripes():this.show_stripes()},show_dots:function(){this._data.core.themes.dots=!0,this.get_container_ul().removeClass("jstree-no-dots"),this.trigger("show_dots")},hide_dots:function(){this._data.core.themes.dots=!1,this.get_container_ul().addClass("jstree-no-dots"),this.trigger("hide_dots")},toggle_dots:function(){this._data.core.themes.dots?this.hide_dots():this.show_dots()},show_icons:function(){this._data.core.themes.icons=!0,this.get_container_ul().removeClass("jstree-no-icons"),this.trigger("show_icons")},hide_icons:function(){this._data.core.themes.icons=!1,this.get_container_ul().addClass("jstree-no-icons"),this.trigger("hide_icons")},toggle_icons:function(){this._data.core.themes.icons?this.hide_icons():this.show_icons()},show_ellipsis:function(){this._data.core.themes.ellipsis=!0,this.get_container_ul().addClass("jstree-ellipsis"),this.trigger("show_ellipsis")},hide_ellipsis:function(){this._data.core.themes.ellipsis=!1,this.get_container_ul().removeClass("jstree-ellipsis"),this.trigger("hide_ellipsis")},toggle_ellipsis:function(){this._data.core.themes.ellipsis?this.hide_ellipsis():this.show_ellipsis()},set_icon:function(c,d){var e,f,g,h;if(a.isArray(c)){for(c=c.slice(),e=0,f=c.length;f>e;e++)this.set_icon(c[e],d);return!0}return c=this.get_node(c),c&&c.id!==a.jstree.root?(h=c.icon,c.icon=d===!0||null===d||d===b||""===d?!0:d,g=this.get_node(c,!0).children(".jstree-anchor").children(".jstree-themeicon"),d===!1?(g.removeClass("jstree-themeicon-custom "+h).css("background","").removeAttr("rel"),this.hide_icon(c)):d===!0||null===d||d===b||""===d?(g.removeClass("jstree-themeicon-custom "+h).css("background","").removeAttr("rel"),h===!1&&this.show_icon(c)):-1===d.indexOf("/")&&-1===d.indexOf(".")?(g.removeClass(h).css("background",""),g.addClass(d+" jstree-themeicon-custom").attr("rel",d),h===!1&&this.show_icon(c)):(g.removeClass(h).css("background",""),g.addClass("jstree-themeicon-custom").css("background","url('"+d+"') center center no-repeat").attr("rel",d),h===!1&&this.show_icon(c)),!0):!1},get_icon:function(b){return b=this.get_node(b),b&&b.id!==a.jstree.root?b.icon:!1},hide_icon:function(b){var c,d;if(a.isArray(b)){for(b=b.slice(),c=0,d=b.length;d>c;c++)this.hide_icon(b[c]);return!0}return b=this.get_node(b),b&&b!==a.jstree.root?(b.icon=!1,this.get_node(b,!0).children(".jstree-anchor").children(".jstree-themeicon").addClass("jstree-themeicon-hidden"),!0):!1},show_icon:function(b){var c,d,e;if(a.isArray(b)){for(b=b.slice(),c=0,d=b.length;d>c;c++)this.show_icon(b[c]);return!0}return b=this.get_node(b),b&&b!==a.jstree.root?(e=this.get_node(b,!0),b.icon=e.length?e.children(".jstree-anchor").children(".jstree-themeicon").attr("rel"):!0,b.icon||(b.icon=!0),e.children(".jstree-anchor").children(".jstree-themeicon").removeClass("jstree-themeicon-hidden"),!0):!1}},a.vakata={},a.vakata.attributes=function(b,c){b=a(b)[0];var d=c?{}:[];return b&&b.attributes&&a.each(b.attributes,function(b,e){-1===a.inArray(e.name.toLowerCase(),["style","contenteditable","hasfocus","tabindex"])&&null!==e.value&&""!==a.trim(e.value)&&(c?d[e.name]=e.value:d.push(e.name))}),d},a.vakata.array_unique=function(a){var c=[],d,e,f,g={};for(d=0,f=a.length;f>d;d++)g[a[d]]===b&&(c.push(a[d]),g[a[d]]=!0);return c},a.vakata.array_remove=function(a,b){return a.splice(b,1),a},a.vakata.array_remove_item=function(b,c){var d=a.inArray(c,b);return-1!==d?a.vakata.array_remove(b,d):b},a.vakata.array_filter=function(a,b,c,d,e){if(a.filter)return a.filter(b,c);d=[];for(e in a)~~e+""==e+""&&e>=0&&b.call(c,a[e],+e,a)&&d.push(a[e]);return d},a.jstree.plugins.changed=function(a,b){var c=[];this.trigger=function(a,d){var e,f;if(d||(d={}),"changed"===a.replace(".jstree","")){d.changed={selected:[],deselected:[]};var g={};for(e=0,f=c.length;f>e;e++)g[c[e]]=1;for(e=0,f=d.selected.length;f>e;e++)g[d.selected[e]]?g[d.selected[e]]=2:d.changed.selected.push(d.selected[e]);for(e=0,f=c.length;f>e;e++)1===g[c[e]]&&d.changed.deselected.push(c[e]);c=d.selected.slice()}b.trigger.call(this,a,d)},this.refresh=function(a,d){return c=[],b.refresh.apply(this,arguments)}};var j=i.createElement("I");j.className="jstree-icon jstree-checkbox",j.setAttribute("role","presentation"),a.jstree.defaults.checkbox={visible:!0,three_state:!0,whole_node:!0,keep_selected_style:!0,cascade:"",tie_selection:!0,cascade_to_disabled:!0,cascade_to_hidden:!0},a.jstree.plugins.checkbox=function(c,d){this.bind=function(){d.bind.call(this),this._data.checkbox.uto=!1,this._data.checkbox.selected=[],this.settings.checkbox.three_state&&(this.settings.checkbox.cascade="up+down+undetermined"),this.element.on("init.jstree",a.proxy(function(){this._data.checkbox.visible=this.settings.checkbox.visible,this.settings.checkbox.keep_selected_style||this.element.addClass("jstree-checkbox-no-clicked"),this.settings.checkbox.tie_selection&&this.element.addClass("jstree-checkbox-selection")},this)).on("loading.jstree",a.proxy(function(){this[this._data.checkbox.visible?"show_checkboxes":"hide_checkboxes"]()},this)),-1!==this.settings.checkbox.cascade.indexOf("undetermined")&&this.element.on("changed.jstree uncheck_node.jstree check_node.jstree uncheck_all.jstree check_all.jstree move_node.jstree copy_node.jstree redraw.jstree open_node.jstree",a.proxy(function(){this._data.checkbox.uto&&clearTimeout(this._data.checkbox.uto),this._data.checkbox.uto=setTimeout(a.proxy(this._undetermined,this),50)},this)),this.settings.checkbox.tie_selection||this.element.on("model.jstree",a.proxy(function(a,b){var c=this._model.data,d=c[b.parent],e=b.nodes,f,g;for(f=0,g=e.length;g>f;f++)c[e[f]].state.checked=c[e[f]].state.checked||c[e[f]].original&&c[e[f]].original.state&&c[e[f]].original.state.checked,c[e[f]].state.checked&&this._data.checkbox.selected.push(e[f])},this)),(-1!==this.settings.checkbox.cascade.indexOf("up")||-1!==this.settings.checkbox.cascade.indexOf("down"))&&this.element.on("model.jstree",a.proxy(function(b,c){var d=this._model.data,e=d[c.parent],f=c.nodes,g=[],h,i,j,k,l,m,n=this.settings.checkbox.cascade,o=this.settings.checkbox.tie_selection;if(-1!==n.indexOf("down"))if(e.state[o?"selected":"checked"]){for(i=0,j=f.length;j>i;i++)d[f[i]].state[o?"selected":"checked"]=!0;this._data[o?"core":"checkbox"].selected=this._data[o?"core":"checkbox"].selected.concat(f)}else for(i=0,j=f.length;j>i;i++)if(d[f[i]].state[o?"selected":"checked"]){for(k=0,l=d[f[i]].children_d.length;l>k;k++)d[d[f[i]].children_d[k]].state[o?"selected":"checked"]=!0;this._data[o?"core":"checkbox"].selected=this._data[o?"core":"checkbox"].selected.concat(d[f[i]].children_d)}if(-1!==n.indexOf("up")){for(i=0,j=e.children_d.length;j>i;i++)d[e.children_d[i]].children.length||g.push(d[e.children_d[i]].parent);for(g=a.vakata.array_unique(g),k=0,l=g.length;l>k;k++){e=d[g[k]];while(e&&e.id!==a.jstree.root){for(h=0,i=0,j=e.children.length;j>i;i++)h+=d[e.children[i]].state[o?"selected":"checked"];if(h!==j)break;e.state[o?"selected":"checked"]=!0,this._data[o?"core":"checkbox"].selected.push(e.id),m=this.get_node(e,!0),m&&m.length&&m.attr("aria-selected",!0).children(".jstree-anchor").addClass(o?"jstree-clicked":"jstree-checked"),e=this.get_node(e.parent)}}}this._data[o?"core":"checkbox"].selected=a.vakata.array_unique(this._data[o?"core":"checkbox"].selected)},this)).on(this.settings.checkbox.tie_selection?"select_node.jstree":"check_node.jstree",a.proxy(function(b,c){var d=this,e=c.node,f=this._model.data,g=this.get_node(e.parent),h,i,j,k,l=this.settings.checkbox.cascade,m=this.settings.checkbox.tie_selection,n={},o=this._data[m?"core":"checkbox"].selected;for(h=0,i=o.length;i>h;h++)n[o[h]]=!0;if(-1!==l.indexOf("down")){var p=this._cascade_new_checked_state(e.id,!0),q=e.children_d.concat(e.id);for(h=0,i=q.length;i>h;h++)p.indexOf(q[h])>-1?n[q[h]]=!0:delete n[q[h]]}if(-1!==l.indexOf("up"))while(g&&g.id!==a.jstree.root){for(j=0,h=0,i=g.children.length;i>h;h++)j+=f[g.children[h]].state[m?"selected":"checked"];if(j!==i)break;g.state[m?"selected":"checked"]=!0,n[g.id]=!0,k=this.get_node(g,!0),k&&k.length&&k.attr("aria-selected",!0).children(".jstree-anchor").addClass(m?"jstree-clicked":"jstree-checked"),g=this.get_node(g.parent)}o=[];for(h in n)n.hasOwnProperty(h)&&o.push(h);this._data[m?"core":"checkbox"].selected=o},this)).on(this.settings.checkbox.tie_selection?"deselect_all.jstree":"uncheck_all.jstree",a.proxy(function(b,c){var d=this.get_node(a.jstree.root),e=this._model.data,f,g,h;for(f=0,g=d.children_d.length;g>f;f++)h=e[d.children_d[f]],h&&h.original&&h.original.state&&h.original.state.undetermined&&(h.original.state.undetermined=!1)},this)).on(this.settings.checkbox.tie_selection?"deselect_node.jstree":"uncheck_node.jstree",a.proxy(function(b,c){var d=this,e=c.node,f=this.get_node(e,!0),g,h,i,j=this.settings.checkbox.cascade,k=this.settings.checkbox.tie_selection,l=this._data[k?"core":"checkbox"].selected,m={},n=[],o=e.children_d.concat(e.id);if(-1!==j.indexOf("down")){var p=this._cascade_new_checked_state(e.id,!1);l=a.vakata.array_filter(l,function(a){return-1===o.indexOf(a)||p.indexOf(a)>-1})}if(-1!==j.indexOf("up")&&-1===l.indexOf(e.id)){for(g=0,h=e.parents.length;h>g;g++)i=this._model.data[e.parents[g]],i.state[k?"selected":"checked"]=!1,i&&i.original&&i.original.state&&i.original.state.undetermined&&(i.original.state.undetermined=!1),i=this.get_node(e.parents[g],!0),i&&i.length&&i.attr("aria-selected",!1).children(".jstree-anchor").removeClass(k?"jstree-clicked":"jstree-checked");l=a.vakata.array_filter(l,function(a){return-1===e.parents.indexOf(a)})}this._data[k?"core":"checkbox"].selected=l},this)),-1!==this.settings.checkbox.cascade.indexOf("up")&&this.element.on("delete_node.jstree",a.proxy(function(b,c){var d=this.get_node(c.parent),e=this._model.data,f,g,h,i,j=this.settings.checkbox.tie_selection;while(d&&d.id!==a.jstree.root&&!d.state[j?"selected":"checked"]){for(h=0,f=0,g=d.children.length;g>f;f++)h+=e[d.children[f]].state[j?"selected":"checked"];if(!(g>0&&h===g))break;d.state[j?"selected":"checked"]=!0,this._data[j?"core":"checkbox"].selected.push(d.id),i=this.get_node(d,!0),i&&i.length&&i.attr("aria-selected",!0).children(".jstree-anchor").addClass(j?"jstree-clicked":"jstree-checked"),d=this.get_node(d.parent)}},this)).on("move_node.jstree",a.proxy(function(b,c){var d=c.is_multi,e=c.old_parent,f=this.get_node(c.parent),g=this._model.data,h,i,j,k,l,m=this.settings.checkbox.tie_selection;if(!d){h=this.get_node(e);while(h&&h.id!==a.jstree.root&&!h.state[m?"selected":"checked"]){for(i=0,j=0,k=h.children.length;k>j;j++)i+=g[h.children[j]].state[m?"selected":"checked"];if(!(k>0&&i===k))break;h.state[m?"selected":"checked"]=!0,this._data[m?"core":"checkbox"].selected.push(h.id),l=this.get_node(h,!0),l&&l.length&&l.attr("aria-selected",!0).children(".jstree-anchor").addClass(m?"jstree-clicked":"jstree-checked"),h=this.get_node(h.parent)}}h=f;while(h&&h.id!==a.jstree.root){for(i=0,j=0,k=h.children.length;k>j;j++)i+=g[h.children[j]].state[m?"selected":"checked"];if(i===k)h.state[m?"selected":"checked"]||(h.state[m?"selected":"checked"]=!0,this._data[m?"core":"checkbox"].selected.push(h.id),l=this.get_node(h,!0),l&&l.length&&l.attr("aria-selected",!0).children(".jstree-anchor").addClass(m?"jstree-clicked":"jstree-checked"));else{if(!h.state[m?"selected":"checked"])break;h.state[m?"selected":"checked"]=!1,this._data[m?"core":"checkbox"].selected=a.vakata.array_remove_item(this._data[m?"core":"checkbox"].selected,h.id),l=this.get_node(h,!0),l&&l.length&&l.attr("aria-selected",!1).children(".jstree-anchor").removeClass(m?"jstree-clicked":"jstree-checked")}h=this.get_node(h.parent)}},this))},this.get_undetermined=function(c){if(-1===this.settings.checkbox.cascade.indexOf("undetermined"))return[];var d,e,f,g,h={},i=this._model.data,j=this.settings.checkbox.tie_selection,k=this._data[j?"core":"checkbox"].selected,l=[],m=this,n=[];for(d=0,e=k.length;e>d;d++)if(i[k[d]]&&i[k[d]].parents)for(f=0,g=i[k[d]].parents.length;g>f;f++){if(h[i[k[d]].parents[f]]!==b)break;i[k[d]].parents[f]!==a.jstree.root&&(h[i[k[d]].parents[f]]=!0,l.push(i[k[d]].parents[f]))}for(this.element.find(".jstree-closed").not(":has(.jstree-children)").each(function(){var c=m.get_node(this),j;if(c)if(c.state.loaded){for(d=0,e=c.children_d.length;e>d;d++)if(j=i[c.children_d[d]],!j.state.loaded&&j.original&&j.original.state&&j.original.state.undetermined&&j.original.state.undetermined===!0)for(h[j.id]===b&&j.id!==a.jstree.root&&(h[j.id]=!0,l.push(j.id)),f=0,g=j.parents.length;g>f;f++)h[j.parents[f]]===b&&j.parents[f]!==a.jstree.root&&(h[j.parents[f]]=!0,l.push(j.parents[f]))}else if(c.original&&c.original.state&&c.original.state.undetermined&&c.original.state.undetermined===!0)for(h[c.id]===b&&c.id!==a.jstree.root&&(h[c.id]=!0,l.push(c.id)),f=0,g=c.parents.length;g>f;f++)h[c.parents[f]]===b&&c.parents[f]!==a.jstree.root&&(h[c.parents[f]]=!0,l.push(c.parents[f]))}),d=0,e=l.length;e>d;d++)i[l[d]].state[j?"selected":"checked"]||n.push(c?i[l[d]]:l[d]);return n},this._undetermined=function(){if(null!==this.element){var a=this.get_undetermined(!1),b,c,d;for(this.element.find(".jstree-undetermined").removeClass("jstree-undetermined"),b=0,c=a.length;c>b;b++)d=this.get_node(a[b],!0),d&&d.length&&d.children(".jstree-anchor").children(".jstree-checkbox").addClass("jstree-undetermined")}},this.redraw_node=function(b,c,e,f){if(b=d.redraw_node.apply(this,arguments)){var g,h,i=null,k=null;for(g=0,h=b.childNodes.length;h>g;g++)if(b.childNodes[g]&&b.childNodes[g].className&&-1!==b.childNodes[g].className.indexOf("jstree-anchor")){i=b.childNodes[g];break}i&&(!this.settings.checkbox.tie_selection&&this._model.data[b.id].state.checked&&(i.className+=" jstree-checked"),k=j.cloneNode(!1),this._model.data[b.id].state.checkbox_disabled&&(k.className+=" jstree-checkbox-disabled"),i.insertBefore(k,i.childNodes[0]))}return e||-1===this.settings.checkbox.cascade.indexOf("undetermined")||(this._data.checkbox.uto&&clearTimeout(this._data.checkbox.uto),this._data.checkbox.uto=setTimeout(a.proxy(this._undetermined,this),50)),b},this.show_checkboxes=function(){this._data.core.themes.checkboxes=!0,this.get_container_ul().removeClass("jstree-no-checkboxes")},this.hide_checkboxes=function(){this._data.core.themes.checkboxes=!1,this.get_container_ul().addClass("jstree-no-checkboxes")},this.toggle_checkboxes=function(){this._data.core.themes.checkboxes?this.hide_checkboxes():this.show_checkboxes()},this.is_undetermined=function(b){b=this.get_node(b);var c=this.settings.checkbox.cascade,d,e,f=this.settings.checkbox.tie_selection,g=this._data[f?"core":"checkbox"].selected,h=this._model.data;if(!b||b.state[f?"selected":"checked"]===!0||-1===c.indexOf("undetermined")||-1===c.indexOf("down")&&-1===c.indexOf("up"))return!1;if(!b.state.loaded&&b.original.state.undetermined===!0)return!0;for(d=0,e=b.children_d.length;e>d;d++)if(-1!==a.inArray(b.children_d[d],g)||!h[b.children_d[d]].state.loaded&&h[b.children_d[d]].original.state.undetermined)return!0;return!1},this.disable_checkbox=function(b){var c,d,e;if(a.isArray(b)){for(b=b.slice(),c=0,d=b.length;d>c;c++)this.disable_checkbox(b[c]);return!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?(e=this.get_node(b,!0),void(b.state.checkbox_disabled||(b.state.checkbox_disabled=!0,e&&e.length&&e.children(".jstree-anchor").children(".jstree-checkbox").addClass("jstree-checkbox-disabled"),this.trigger("disable_checkbox",{node:b})))):!1},this.enable_checkbox=function(b){var c,d,e;if(a.isArray(b)){for(b=b.slice(),c=0,d=b.length;d>c;c++)this.enable_checkbox(b[c]);return!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?(e=this.get_node(b,!0),void(b.state.checkbox_disabled&&(b.state.checkbox_disabled=!1,e&&e.length&&e.children(".jstree-anchor").children(".jstree-checkbox").removeClass("jstree-checkbox-disabled"),this.trigger("enable_checkbox",{node:b})))):!1},this.activate_node=function(b,c){return a(c.target).hasClass("jstree-checkbox-disabled")?!1:(this.settings.checkbox.tie_selection&&(this.settings.checkbox.whole_node||a(c.target).hasClass("jstree-checkbox"))&&(c.ctrlKey=!0),this.settings.checkbox.tie_selection||!this.settings.checkbox.whole_node&&!a(c.target).hasClass("jstree-checkbox")?d.activate_node.call(this,b,c):this.is_disabled(b)?!1:(this.is_checked(b)?this.uncheck_node(b,c):this.check_node(b,c),void this.trigger("activate_node",{node:this.get_node(b)})))},this._cascade_new_checked_state=function(a,b){var c=this,d=this.settings.checkbox.tie_selection,e=this._model.data[a],f=[],g=[],h,i,j;if(!this.settings.checkbox.cascade_to_disabled&&e.state.disabled||!this.settings.checkbox.cascade_to_hidden&&e.state.hidden)j=this.get_checked_descendants(a),e.state[d?"selected":"checked"]&&j.push(e.id),f=f.concat(j);else{if(e.children)for(h=0,i=e.children.length;i>h;h++){var k=e.children[h];j=c._cascade_new_checked_state(k,b),f=f.concat(j),j.indexOf(k)>-1&&g.push(k)}var l=c.get_node(e,!0),m=g.length>0&&g.lengthe;e++)this.check_node(b[e],c);return!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?(d=this.get_node(b,!0),void(b.state.checked||(b.state.checked=!0,this._data.checkbox.selected.push(b.id),d&&d.length&&d.children(".jstree-anchor").addClass("jstree-checked"),this.trigger("check_node",{node:b,selected:this._data.checkbox.selected,event:c})))):!1},this.uncheck_node=function(b,c){if(this.settings.checkbox.tie_selection)return this.deselect_node(b,!1,c);var d,e,f;if(a.isArray(b)){for(b=b.slice(),d=0,e=b.length;e>d;d++)this.uncheck_node(b[d],c);return!0}return b=this.get_node(b),b&&b.id!==a.jstree.root?(f=this.get_node(b,!0),void(b.state.checked&&(b.state.checked=!1,this._data.checkbox.selected=a.vakata.array_remove_item(this._data.checkbox.selected,b.id),f.length&&f.children(".jstree-anchor").removeClass("jstree-checked"),this.trigger("uncheck_node",{node:b,selected:this._data.checkbox.selected,event:c})))):!1},this.check_all=function(){if(this.settings.checkbox.tie_selection)return this.select_all();var b=this._data.checkbox.selected.concat([]),c,d;for(this._data.checkbox.selected=this._model.data[a.jstree.root].children_d.concat(),c=0,d=this._data.checkbox.selected.length;d>c;c++)this._model.data[this._data.checkbox.selected[c]]&&(this._model.data[this._data.checkbox.selected[c]].state.checked=!0);this.redraw(!0),this.trigger("check_all",{selected:this._data.checkbox.selected})},this.uncheck_all=function(){if(this.settings.checkbox.tie_selection)return this.deselect_all();var a=this._data.checkbox.selected.concat([]),b,c;for(b=0,c=this._data.checkbox.selected.length;c>b;b++)this._model.data[this._data.checkbox.selected[b]]&&(this._model.data[this._data.checkbox.selected[b]].state.checked=!1);this._data.checkbox.selected=[],this.element.find(".jstree-checked").removeClass("jstree-checked"),this.trigger("uncheck_all",{selected:this._data.checkbox.selected,node:a})},this.is_checked=function(b){return this.settings.checkbox.tie_selection?this.is_selected(b):(b=this.get_node(b),b&&b.id!==a.jstree.root?b.state.checked:!1)},this.get_checked=function(b){return this.settings.checkbox.tie_selection?this.get_selected(b):b?a.map(this._data.checkbox.selected,a.proxy(function(a){return this.get_node(a)},this)):this._data.checkbox.selected.slice()},this.get_top_checked=function(b){if(this.settings.checkbox.tie_selection)return this.get_top_selected(b);var c=this.get_checked(!0),d={},e,f,g,h;for(e=0,f=c.length;f>e;e++)d[c[e].id]=c[e];for(e=0,f=c.length;f>e;e++)for(g=0,h=c[e].children_d.length;h>g;g++)d[c[e].children_d[g]]&&delete d[c[e].children_d[g]];c=[];for(e in d)d.hasOwnProperty(e)&&c.push(e);return b?a.map(c,a.proxy(function(a){return this.get_node(a)},this)):c},this.get_bottom_checked=function(b){if(this.settings.checkbox.tie_selection)return this.get_bottom_selected(b);var c=this.get_checked(!0),d=[],e,f;for(e=0,f=c.length;f>e;e++)c[e].children.length||d.push(c[e].id);return b?a.map(d,a.proxy(function(a){return this.get_node(a)},this)):d},this.load_node=function(b,c){var e,f,g,h,i,j;if(!a.isArray(b)&&!this.settings.checkbox.tie_selection&&(j=this.get_node(b),j&&j.state.loaded))for(e=0,f=j.children_d.length;f>e;e++)this._model.data[j.children_d[e]].state.checked&&(i=!0,this._data.checkbox.selected=a.vakata.array_remove_item(this._data.checkbox.selected,j.children_d[e]));return d.load_node.apply(this,arguments)},this.get_state=function(){var a=d.get_state.apply(this,arguments);return this.settings.checkbox.tie_selection?a:(a.checkbox=this._data.checkbox.selected.slice(),a)},this.set_state=function(b,c){var e=d.set_state.apply(this,arguments);if(e&&b.checkbox){if(!this.settings.checkbox.tie_selection){this.uncheck_all();var f=this;a.each(b.checkbox,function(a,b){f.check_node(b)})}return delete b.checkbox,this.set_state(b,c),!1}return e},this.refresh=function(a,b){return this.settings.checkbox.tie_selection&&(this._data.checkbox.selected=[]),d.refresh.apply(this,arguments)}},a.jstree.defaults.conditionalselect=function(){return!0},a.jstree.plugins.conditionalselect=function(a,b){this.activate_node=function(a,c){return this.settings.conditionalselect.call(this,this.get_node(a),c)?b.activate_node.call(this,a,c):void 0}},a.jstree.defaults.contextmenu={select_node:!0,show_at_node:!0,items:function(b,c){return{create:{separator_before:!1,separator_after:!0,_disabled:!1,label:"Create",action:function(b){var c=a.jstree.reference(b.reference),d=c.get_node(b.reference);c.create_node(d,{},"last",function(a){try{c.edit(a)}catch(b){setTimeout(function(){c.edit(a)},0)}})}},rename:{separator_before:!1,separator_after:!1,_disabled:!1,label:"Rename",action:function(b){var c=a.jstree.reference(b.reference),d=c.get_node(b.reference);c.edit(d)}},remove:{separator_before:!1,icon:!1,separator_after:!1,_disabled:!1,label:"Delete",action:function(b){var c=a.jstree.reference(b.reference),d=c.get_node(b.reference);c.is_selected(d)?c.delete_node(c.get_selected()):c.delete_node(d)}},ccp:{separator_before:!0,icon:!1,separator_after:!1,label:"Edit",action:!1,submenu:{cut:{separator_before:!1,separator_after:!1,label:"Cut",action:function(b){var c=a.jstree.reference(b.reference),d=c.get_node(b.reference);c.is_selected(d)?c.cut(c.get_top_selected()):c.cut(d)}},copy:{separator_before:!1,icon:!1,separator_after:!1,label:"Copy",action:function(b){var c=a.jstree.reference(b.reference),d=c.get_node(b.reference);c.is_selected(d)?c.copy(c.get_top_selected()):c.copy(d)}},paste:{separator_before:!1,icon:!1,_disabled:function(b){return!a.jstree.reference(b.reference).can_paste()},separator_after:!1,label:"Paste",action:function(b){var c=a.jstree.reference(b.reference),d=c.get_node(b.reference);c.paste(d)}}}}}}},a.jstree.plugins.contextmenu=function(c,d){this.bind=function(){d.bind.call(this);var b=0,c=null,e,f;this.element.on("init.jstree loading.jstree ready.jstree",a.proxy(function(){this.get_container_ul().addClass("jstree-contextmenu")},this)).on("contextmenu.jstree",".jstree-anchor",a.proxy(function(a,d){"input"!==a.target.tagName.toLowerCase()&&(a.preventDefault(),b=a.ctrlKey?+new Date:0,(d||c)&&(b=+new Date+1e4),c&&clearTimeout(c),this.is_loading(a.currentTarget)||this.show_contextmenu(a.currentTarget,a.pageX,a.pageY,a))},this)).on("click.jstree",".jstree-anchor",a.proxy(function(c){this._data.contextmenu.visible&&(!b||+new Date-b>250)&&a.vakata.context.hide(),b=0},this)).on("touchstart.jstree",".jstree-anchor",function(b){b.originalEvent&&b.originalEvent.changedTouches&&b.originalEvent.changedTouches[0]&&(e=b.originalEvent.changedTouches[0].clientX,f=b.originalEvent.changedTouches[0].clientY,c=setTimeout(function(){a(b.currentTarget).trigger("contextmenu",!0)},750))}).on("touchmove.vakata.jstree",function(b){c&&b.originalEvent&&b.originalEvent.changedTouches&&b.originalEvent.changedTouches[0]&&(Math.abs(e-b.originalEvent.changedTouches[0].clientX)>10||Math.abs(f-b.originalEvent.changedTouches[0].clientY)>10)&&(clearTimeout(c),a.vakata.context.hide())}).on("touchend.vakata.jstree",function(a){c&&clearTimeout(c)}),a(i).on("context_hide.vakata.jstree",a.proxy(function(b,c){this._data.contextmenu.visible=!1,a(c.reference).removeClass("jstree-context")},this))},this.teardown=function(){this._data.contextmenu.visible&&a.vakata.context.hide(),d.teardown.call(this)},this.show_contextmenu=function(c,d,e,f){if(c=this.get_node(c),!c||c.id===a.jstree.root)return!1;var g=this.settings.contextmenu,h=this.get_node(c,!0),i=h.children(".jstree-anchor"),j=!1,k=!1;(g.show_at_node||d===b||e===b)&&(j=i.offset(),d=j.left,e=j.top+this._data.core.li_height),this.settings.contextmenu.select_node&&!this.is_selected(c)&&this.activate_node(c,f),k=g.items,a.isFunction(k)&&(k=k.call(this,c,a.proxy(function(a){this._show_contextmenu(c,d,e,a)},this))),a.isPlainObject(k)&&this._show_contextmenu(c,d,e,k)},this._show_contextmenu=function(b,c,d,e){var f=this.get_node(b,!0),g=f.children(".jstree-anchor");a(i).one("context_show.vakata.jstree",a.proxy(function(b,c){var d="jstree-contextmenu jstree-"+this.get_theme()+"-contextmenu";a(c.element).addClass(d),g.addClass("jstree-context")},this)),this._data.contextmenu.visible=!0,a.vakata.context.show(g,{x:c,y:d},e),this.trigger("show_contextmenu",{node:b,x:c,y:d})}},function(a){var b=!1,c={element:!1,reference:!1,position_x:0,position_y:0,items:[],html:"",is_visible:!1};a.vakata.context={settings:{hide_onmouseleave:0,icons:!0},_trigger:function(b){a(i).triggerHandler("context_"+b+".vakata",{reference:c.reference,element:c.element,position:{x:c.position_x,y:c.position_y}})},_execute:function(b){return b=c.items[b],b&&(!b._disabled||a.isFunction(b._disabled)&&!b._disabled({item:b,reference:c.reference,element:c.element}))&&b.action?b.action.call(null,{item:b,reference:c.reference,element:c.element,position:{x:c.position_x,y:c.position_y}}):!1},_parse:function(b,d){if(!b)return!1;d||(c.html="",c.items=[]);var e="",f=!1,g;return d&&(e+=""),d||(c.html=e,a.vakata.context._trigger("parse")),e.length>10?e:!1},_show_submenu:function(c){if(c=a(c),c.length&&c.children("ul").length){var d=c.children("ul"),e=c.offset().left,f=e+c.outerWidth(),g=c.offset().top,h=d.width(),i=d.height(),j=a(window).width()+a(window).scrollLeft(),k=a(window).height()+a(window).scrollTop();b?c[f-(h+10+c.outerWidth())<0?"addClass":"removeClass"]("vakata-context-left"):c[f+h>j&&e>j-f?"addClass":"removeClass"]("vakata-context-right"),g+i+10>k&&d.css("bottom","-1px"),c.hasClass("vakata-context-right")?h>e&&d.css("margin-right",e-h):h>j-f&&d.css("margin-left",j-f-h),d.show()}},show:function(d,e,f){var g,h,j,k,l,m,n,o,p=!0;switch(c.element&&c.element.length&&c.element.width(""),p){case!e&&!d:return!1;case!!e&&!!d:c.reference=d,c.position_x=e.x,c.position_y=e.y;break;case!e&&!!d:c.reference=d,g=d.offset(),c.position_x=g.left+d.outerHeight(),c.position_y=g.top;break;case!!e&&!d:c.position_x=e.x,c.position_y=e.y}d&&!f&&a(d).data("vakata_contextmenu")&&(f=a(d).data("vakata_contextmenu")),a.vakata.context._parse(f)&&c.element.html(c.html),c.items.length&&(c.element.appendTo(i.body),h=c.element,j=c.position_x,k=c.position_y,l=h.width(),m=h.height(),n=a(window).width()+a(window).scrollLeft(),o=a(window).height()+a(window).scrollTop(),b&&(j-=h.outerWidth()-a(d).outerWidth(),jn&&(j=n-(l+20)),k+m+20>o&&(k=o-(m+20)),c.element.css({left:j,top:k}).show().find("a").first().focus().parent().addClass("vakata-context-hover"),c.is_visible=!0,a.vakata.context._trigger("show"))},hide:function(){c.is_visible&&(c.element.hide().find("ul").hide().end().find(":focus").blur().end().detach(),c.is_visible=!1,a.vakata.context._trigger("hide"))}},a(function(){b="rtl"===a(i.body).css("direction");var d=!1;c.element=a("
    "),c.element.on("mouseenter","li",function(b){b.stopImmediatePropagation(),a.contains(this,b.relatedTarget)||(d&&clearTimeout(d),c.element.find(".vakata-context-hover").removeClass("vakata-context-hover").end(),a(this).siblings().find("ul").hide().end().end().parentsUntil(".vakata-context","li").addBack().addClass("vakata-context-hover"),a.vakata.context._show_submenu(this))}).on("mouseleave","li",function(b){a.contains(this,b.relatedTarget)||a(this).find(".vakata-context-hover").addBack().removeClass("vakata-context-hover")}).on("mouseleave",function(b){a(this).find(".vakata-context-hover").removeClass("vakata-context-hover"),a.vakata.context.settings.hide_onmouseleave&&(d=setTimeout(function(b){return function(){a.vakata.context.hide()}}(this),a.vakata.context.settings.hide_onmouseleave))}).on("click","a",function(b){b.preventDefault(),a(this).blur().parent().hasClass("vakata-context-disabled")||a.vakata.context._execute(a(this).attr("rel"))===!1||a.vakata.context.hide()}).on("keydown","a",function(b){var d=null;switch(b.which){case 13:case 32:b.type="click",b.preventDefault(),a(b.currentTarget).trigger(b);break;case 37:c.is_visible&&(c.element.find(".vakata-context-hover").last().closest("li").first().find("ul").hide().find(".vakata-context-hover").removeClass("vakata-context-hover").end().end().children("a").focus(),b.stopImmediatePropagation(),b.preventDefault());break;case 38:c.is_visible&&(d=c.element.find("ul:visible").addBack().last().children(".vakata-context-hover").removeClass("vakata-context-hover").prevAll("li:not(.vakata-context-separator)").first(),d.length||(d=c.element.find("ul:visible").addBack().last().children("li:not(.vakata-context-separator)").last()),d.addClass("vakata-context-hover").children("a").focus(),b.stopImmediatePropagation(),b.preventDefault());break;case 39:c.is_visible&&(c.element.find(".vakata-context-hover").last().children("ul").show().children("li:not(.vakata-context-separator)").removeClass("vakata-context-hover").first().addClass("vakata-context-hover").children("a").focus(),b.stopImmediatePropagation(),b.preventDefault());break;case 40:c.is_visible&&(d=c.element.find("ul:visible").addBack().last().children(".vakata-context-hover").removeClass("vakata-context-hover").nextAll("li:not(.vakata-context-separator)").first(),d.length||(d=c.element.find("ul:visible").addBack().last().children("li:not(.vakata-context-separator)").first()),d.addClass("vakata-context-hover").children("a").focus(),b.stopImmediatePropagation(),b.preventDefault());break;case 27:a.vakata.context.hide(),b.preventDefault()}}).on("keydown",function(a){a.preventDefault();var b=c.element.find(".vakata-contextmenu-shortcut-"+a.which).parent();b.parent().not(".vakata-context-disabled")&&b.click()}),a(i).on("mousedown.vakata.jstree",function(b){c.is_visible&&c.element[0]!==b.target&&!a.contains(c.element[0],b.target)&&a.vakata.context.hide()}).on("context_show.vakata.jstree",function(a,d){c.element.find("li:has(ul)").children("a").addClass("vakata-context-parent"),b&&c.element.addClass("vakata-context-rtl").css("direction","rtl"),c.element.find("ul").hide().end()})})}(a),a.jstree.defaults.dnd={copy:!0,open_timeout:500,is_draggable:!0,check_while_dragging:!0,always_copy:!1,inside_pos:0,drag_selection:!0,touch:!0,large_drop_target:!1,large_drag_target:!1,use_html5:!1};var k,l;a.jstree.plugins.dnd=function(b,c){this.init=function(a,b){c.init.call(this,a,b),this.settings.dnd.use_html5=this.settings.dnd.use_html5&&"draggable"in i.createElement("span")},this.bind=function(){c.bind.call(this),this.element.on(this.settings.dnd.use_html5?"dragstart.jstree":"mousedown.jstree touchstart.jstree",this.settings.dnd.large_drag_target?".jstree-node":".jstree-anchor",a.proxy(function(b){if(this.settings.dnd.large_drag_target&&a(b.target).closest(".jstree-node")[0]!==b.currentTarget)return!0;if("touchstart"===b.type&&(!this.settings.dnd.touch||"selected"===this.settings.dnd.touch&&!a(b.currentTarget).closest(".jstree-node").children(".jstree-anchor").hasClass("jstree-clicked")))return!0;var c=this.get_node(b.target),d=this.is_selected(c)&&this.settings.dnd.drag_selection?this.get_top_selected().length:1,e=d>1?d+" "+this.get_string("nodes"):this.get_text(b.currentTarget);if(this.settings.core.force_text&&(e=a.vakata.html.escape(e)),c&&c.id&&c.id!==a.jstree.root&&(1===b.which||"touchstart"===b.type||"dragstart"===b.type)&&(this.settings.dnd.is_draggable===!0||a.isFunction(this.settings.dnd.is_draggable)&&this.settings.dnd.is_draggable.call(this,d>1?this.get_top_selected(!0):[c],b))){if(k={jstree:!0,origin:this,obj:this.get_node(c,!0),nodes:d>1?this.get_top_selected():[c.id]},l=b.currentTarget,!this.settings.dnd.use_html5)return this.element.trigger("mousedown.jstree"),a.vakata.dnd.start(b,k,'
    '+e+'
    ');a.vakata.dnd._trigger("start",b,{helper:a(),element:l,data:k})}},this)),this.settings.dnd.use_html5&&this.element.on("dragover.jstree",function(b){return b.preventDefault(),a.vakata.dnd._trigger("move",b,{helper:a(),element:l,data:k}),!1}).on("drop.jstree",a.proxy(function(b){return b.preventDefault(),a.vakata.dnd._trigger("stop",b,{helper:a(),element:l,data:k}),!1},this))},this.redraw_node=function(a,b,d,e){if(a=c.redraw_node.apply(this,arguments),a&&this.settings.dnd.use_html5)if(this.settings.dnd.large_drag_target)a.setAttribute("draggable",!0);else{var f,g,h=null;for(f=0,g=a.childNodes.length;g>f;f++)if(a.childNodes[f]&&a.childNodes[f].className&&-1!==a.childNodes[f].className.indexOf("jstree-anchor")){h=a.childNodes[f];break}h&&h.setAttribute("draggable",!0)}return a}},a(function(){var c=!1,d=!1,e=!1,f=!1,g=a('
     
    ').hide();a(i).on("dragover.vakata.jstree",function(b){l&&a.vakata.dnd._trigger("move",b,{helper:a(),element:l,data:k})}).on("drop.vakata.jstree",function(b){l&&(a.vakata.dnd._trigger("stop",b,{helper:a(),element:l,data:k}),l=null,k=null)}).on("dnd_start.vakata.jstree",function(a,b){c=!1,e=!1,b&&b.data&&b.data.jstree&&g.appendTo(i.body)}).on("dnd_move.vakata.jstree",function(h,i){var j=i.event.target!==e.target;if(f&&(!i.event||"dragover"!==i.event.type||j)&&clearTimeout(f),i&&i.data&&i.data.jstree&&(!i.event.target.id||"jstree-marker"!==i.event.target.id)){e=i.event;var k=a.jstree.reference(i.event.target),l=!1,m=!1,n=!1,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E;if(k&&k._data&&k._data.dnd)if(g.attr("class","jstree-"+k.get_theme()+(k.settings.core.themes.responsive?" jstree-dnd-responsive":"")),D=i.data.origin&&(i.data.origin.settings.dnd.always_copy||i.data.origin.settings.dnd.copy&&(i.event.metaKey||i.event.ctrlKey)),i.helper.children().attr("class","jstree-"+k.get_theme()+" jstree-"+k.get_theme()+"-"+k.get_theme_variant()+" "+(k.settings.core.themes.responsive?" jstree-dnd-responsive":"")).find(".jstree-copy").first()[D?"show":"hide"](),i.event.target!==k.element[0]&&i.event.target!==k.get_container_ul()[0]||0!==k.get_container_ul().children().length){if(l=k.settings.dnd.large_drop_target?a(i.event.target).closest(".jstree-node").children(".jstree-anchor"):a(i.event.target).closest(".jstree-anchor"),l&&l.length&&l.parent().is(".jstree-closed, .jstree-open, .jstree-leaf")&&(m=l.offset(),n=(i.event.pageY!==b?i.event.pageY:i.event.originalEvent.pageY)-m.top,r=l.outerHeight(),u=r/3>n?["b","i","a"]:n>r-r/3?["a","i","b"]:n>r/2?["i","a","b"]:["i","b","a"],a.each(u,function(b,e){switch(e){case"b":p=m.left-6,q=m.top,s=k.get_parent(l),t=l.parent().index();break;case"i":B=k.settings.dnd.inside_pos,C=k.get_node(l.parent()),p=m.left-2,q=m.top+r/2+1,s=C.id,t="first"===B?0:"last"===B?C.children.length:Math.min(B,C.children.length);break;case"a":p=m.left-6,q=m.top+r,s=k.get_parent(l),t=l.parent().index()+1}for(v=!0,w=0,x=i.data.nodes.length;x>w;w++)if(y=i.data.origin&&(i.data.origin.settings.dnd.always_copy||i.data.origin.settings.dnd.copy&&(i.event.metaKey||i.event.ctrlKey))?"copy_node":"move_node",z=t,"move_node"===y&&"a"===e&&i.data.origin&&i.data.origin===k&&s===k.get_parent(i.data.nodes[w])&&(A=k.get_node(s),z>a.inArray(i.data.nodes[w],A.children)&&(z-=1)),v=v&&(k&&k.settings&&k.settings.dnd&&k.settings.dnd.check_while_dragging===!1||k.check(y,i.data.origin&&i.data.origin!==k?i.data.origin.get_node(i.data.nodes[w]):i.data.nodes[w],s,z,{dnd:!0,ref:k.get_node(l.parent()),pos:e,origin:i.data.origin,is_multi:i.data.origin&&i.data.origin!==k,is_foreign:!i.data.origin})),!v){k&&k.last_error&&(d=k.last_error());break}return"i"===e&&l.parent().is(".jstree-closed")&&k.settings.dnd.open_timeout&&(!i.event||"dragover"!==i.event.type||j)&&(f&&clearTimeout(f),f=setTimeout(function(a,b){return function(){a.open_node(b)}}(k,l),k.settings.dnd.open_timeout)),v?(E=k.get_node(s,!0),E.hasClass(".jstree-dnd-parent")||(a(".jstree-dnd-parent").removeClass("jstree-dnd-parent"),E.addClass("jstree-dnd-parent")),c={ins:k,par:s,pos:"i"!==e||"last"!==B||0!==t||k.is_loaded(C)?t:"last"},g.css({left:p+"px",top:q+"px"}).show(),i.helper.find(".jstree-icon").first().removeClass("jstree-er").addClass("jstree-ok"),i.event.originalEvent&&i.event.originalEvent.dataTransfer&&(i.event.originalEvent.dataTransfer.dropEffect=D?"copy":"move"),d={},u=!0,!1):void 0}),u===!0))return}else{for(v=!0,w=0,x=i.data.nodes.length;x>w;w++)if(v=v&&k.check(i.data.origin&&(i.data.origin.settings.dnd.always_copy||i.data.origin.settings.dnd.copy&&(i.event.metaKey||i.event.ctrlKey))?"copy_node":"move_node",i.data.origin&&i.data.origin!==k?i.data.origin.get_node(i.data.nodes[w]):i.data.nodes[w],a.jstree.root,"last",{dnd:!0,ref:k.get_node(a.jstree.root),pos:"i",origin:i.data.origin,is_multi:i.data.origin&&i.data.origin!==k,is_foreign:!i.data.origin}),!v)break;if(v)return c={ins:k,par:a.jstree.root,pos:"last"},g.hide(),i.helper.find(".jstree-icon").first().removeClass("jstree-er").addClass("jstree-ok"),void(i.event.originalEvent&&i.event.originalEvent.dataTransfer&&(i.event.originalEvent.dataTransfer.dropEffect=D?"copy":"move"))}a(".jstree-dnd-parent").removeClass("jstree-dnd-parent"),c=!1,i.helper.find(".jstree-icon").removeClass("jstree-ok").addClass("jstree-er"),i.event.originalEvent&&i.event.originalEvent.dataTransfer,g.hide()}}).on("dnd_scroll.vakata.jstree",function(a,b){b&&b.data&&b.data.jstree&&(g.hide(),c=!1,e=!1,b.helper.find(".jstree-icon").first().removeClass("jstree-ok").addClass("jstree-er"))}).on("dnd_stop.vakata.jstree",function(b,h){if(a(".jstree-dnd-parent").removeClass("jstree-dnd-parent"),f&&clearTimeout(f),h&&h.data&&h.data.jstree){g.hide().detach();var i,j,k=[];if(c){for(i=0,j=h.data.nodes.length;j>i;i++)k[i]=h.data.origin?h.data.origin.get_node(h.data.nodes[i]):h.data.nodes[i];c.ins[h.data.origin&&(h.data.origin.settings.dnd.always_copy||h.data.origin.settings.dnd.copy&&(h.event.metaKey||h.event.ctrlKey))?"copy_node":"move_node"](k,c.par,c.pos,!1,!1,!1,h.data.origin)}else i=a(h.event.target).closest(".jstree"),i.length&&d&&d.error&&"check"===d.error&&(i=i.jstree(!0),i&&i.settings.core.error.call(this,d));e=!1,c=!1}}).on("keyup.jstree keydown.jstree",function(b,h){h=a.vakata.dnd._get(),h&&h.data&&h.data.jstree&&("keyup"===b.type&&27===b.which?(f&&clearTimeout(f),c=!1,d=!1,e=!1,f=!1,g.hide().detach(),a.vakata.dnd._clean()):(h.helper.find(".jstree-copy").first()[h.data.origin&&(h.data.origin.settings.dnd.always_copy||h.data.origin.settings.dnd.copy&&(b.metaKey||b.ctrlKey))?"show":"hide"](),e&&(e.metaKey=b.metaKey,e.ctrlKey=b.ctrlKey,a.vakata.dnd._trigger("move",e))))})}),function(a){a.vakata.html={div:a("
    "),escape:function(b){return a.vakata.html.div.text(b).html()},strip:function(b){return a.vakata.html.div.empty().append(a.parseHTML(b)).text()}};var c={element:!1,target:!1,is_down:!1,is_drag:!1,helper:!1,helper_w:0,data:!1,init_x:0,init_y:0,scroll_l:0,scroll_t:0,scroll_e:!1,scroll_i:!1,is_touch:!1};a.vakata.dnd={settings:{scroll_speed:10,scroll_proximity:20,helper_left:5,helper_top:10,threshold:5,threshold_touch:10},_trigger:function(c,d,e){e===b&&(e=a.vakata.dnd._get()),e.event=d,a(i).triggerHandler("dnd_"+c+".vakata",e)},_get:function(){return{data:c.data,element:c.element,helper:c.helper}},_clean:function(){c.helper&&c.helper.remove(),c.scroll_i&&(clearInterval(c.scroll_i),c.scroll_i=!1),c={element:!1,target:!1,is_down:!1,is_drag:!1,helper:!1,helper_w:0,data:!1,init_x:0,init_y:0,scroll_l:0,scroll_t:0,scroll_e:!1,scroll_i:!1,is_touch:!1},a(i).off("mousemove.vakata.jstree touchmove.vakata.jstree",a.vakata.dnd.drag),a(i).off("mouseup.vakata.jstree touchend.vakata.jstree",a.vakata.dnd.stop)},_scroll:function(b){if(!c.scroll_e||!c.scroll_l&&!c.scroll_t)return c.scroll_i&&(clearInterval(c.scroll_i),c.scroll_i=!1),!1;if(!c.scroll_i)return c.scroll_i=setInterval(a.vakata.dnd._scroll,100),!1;if(b===!0)return!1;var d=c.scroll_e.scrollTop(),e=c.scroll_e.scrollLeft();c.scroll_e.scrollTop(d+c.scroll_t*a.vakata.dnd.settings.scroll_speed),c.scroll_e.scrollLeft(e+c.scroll_l*a.vakata.dnd.settings.scroll_speed),(d!==c.scroll_e.scrollTop()||e!==c.scroll_e.scrollLeft())&&a.vakata.dnd._trigger("scroll",c.scroll_e)},start:function(b,d,e){"touchstart"===b.type&&b.originalEvent&&b.originalEvent.changedTouches&&b.originalEvent.changedTouches[0]&&(b.pageX=b.originalEvent.changedTouches[0].pageX,b.pageY=b.originalEvent.changedTouches[0].pageY,b.target=i.elementFromPoint(b.originalEvent.changedTouches[0].pageX-window.pageXOffset,b.originalEvent.changedTouches[0].pageY-window.pageYOffset)),c.is_drag&&a.vakata.dnd.stop({});try{b.currentTarget.unselectable="on",b.currentTarget.onselectstart=function(){return!1},b.currentTarget.style&&(b.currentTarget.style.touchAction="none",b.currentTarget.style.msTouchAction="none",b.currentTarget.style.MozUserSelect="none")}catch(f){}return c.init_x=b.pageX,c.init_y=b.pageY,c.data=d,c.is_down=!0,c.element=b.currentTarget,c.target=b.target,c.is_touch="touchstart"===b.type,e!==!1&&(c.helper=a("
    ").html(e).css({display:"block",margin:"0",padding:"0",position:"absolute",top:"-2000px",lineHeight:"16px",zIndex:"10000"})),a(i).on("mousemove.vakata.jstree touchmove.vakata.jstree",a.vakata.dnd.drag),a(i).on("mouseup.vakata.jstree touchend.vakata.jstree",a.vakata.dnd.stop),!1},drag:function(b){if("touchmove"===b.type&&b.originalEvent&&b.originalEvent.changedTouches&&b.originalEvent.changedTouches[0]&&(b.pageX=b.originalEvent.changedTouches[0].pageX,b.pageY=b.originalEvent.changedTouches[0].pageY,b.target=i.elementFromPoint(b.originalEvent.changedTouches[0].pageX-window.pageXOffset,b.originalEvent.changedTouches[0].pageY-window.pageYOffset)),c.is_down){if(!c.is_drag){if(!(Math.abs(b.pageX-c.init_x)>(c.is_touch?a.vakata.dnd.settings.threshold_touch:a.vakata.dnd.settings.threshold)||Math.abs(b.pageY-c.init_y)>(c.is_touch?a.vakata.dnd.settings.threshold_touch:a.vakata.dnd.settings.threshold)))return;c.helper&&(c.helper.appendTo(i.body),c.helper_w=c.helper.outerWidth()),c.is_drag=!0,a(c.target).one("click.vakata",!1),a.vakata.dnd._trigger("start",b)}var d=!1,e=!1,f=!1,g=!1,h=!1,j=!1,k=!1,l=!1,m=!1,n=!1;return c.scroll_t=0,c.scroll_l=0,c.scroll_e=!1,a(a(b.target).parentsUntil("body").addBack().get().reverse()).filter(function(){return/^auto|scroll$/.test(a(this).css("overflow"))&&(this.scrollHeight>this.offsetHeight||this.scrollWidth>this.offsetWidth)}).each(function(){var d=a(this),e=d.offset();return this.scrollHeight>this.offsetHeight&&(e.top+d.height()-b.pageYthis.offsetWidth&&(e.left+d.width()-b.pageXg&&b.pageY-kg&&g-(b.pageY-k)j&&b.pageX-lj&&j-(b.pageX-l)f&&(m=f-50),h&&n+c.helper_w>h&&(n=h-(c.helper_w+2)),c.helper.css({left:n+"px",top:m+"px"})),a.vakata.dnd._trigger("move",b),!1}},stop:function(b){if("touchend"===b.type&&b.originalEvent&&b.originalEvent.changedTouches&&b.originalEvent.changedTouches[0]&&(b.pageX=b.originalEvent.changedTouches[0].pageX,b.pageY=b.originalEvent.changedTouches[0].pageY,b.target=i.elementFromPoint(b.originalEvent.changedTouches[0].pageX-window.pageXOffset,b.originalEvent.changedTouches[0].pageY-window.pageYOffset)),c.is_drag)b.target!==c.target&&a(c.target).off("click.vakata"),a.vakata.dnd._trigger("stop",b);else if("touchend"===b.type&&b.target===c.target){var d=setTimeout(function(){a(b.target).click()},100);a(b.target).one("click",function(){d&&clearTimeout(d)})}return a.vakata.dnd._clean(),!1}}}(a),a.jstree.defaults.massload=null,a.jstree.plugins.massload=function(b,c){this.init=function(a,b){this._data.massload={},c.init.call(this,a,b)},this._load_nodes=function(b,d,e,f){var g=this.settings.massload,h=JSON.stringify(b),i=[],j=this._model.data,k,l,m;if(!e){for(k=0,l=b.length;l>k;k++)(!j[b[k]]||!j[b[k]].state.loaded&&!j[b[k]].state.failed||f)&&(i.push(b[k]),m=this.get_node(b[k],!0),m&&m.length&&m.addClass("jstree-loading").attr("aria-busy",!0));if(this._data.massload={},i.length){if(a.isFunction(g))return g.call(this,i,a.proxy(function(a){var g,h;if(a)for(g in a)a.hasOwnProperty(g)&&(this._data.massload[g]=a[g]);for(g=0,h=b.length;h>g;g++)m=this.get_node(b[g],!0),m&&m.length&&m.removeClass("jstree-loading").attr("aria-busy",!1);c._load_nodes.call(this,b,d,e,f)},this));if("object"==typeof g&&g&&g.url)return g=a.extend(!0,{},g),a.isFunction(g.url)&&(g.url=g.url.call(this,i)),a.isFunction(g.data)&&(g.data=g.data.call(this,i)),a.ajax(g).done(a.proxy(function(a,g,h){var i,j;if(a)for(i in a)a.hasOwnProperty(i)&&(this._data.massload[i]=a[i]);for(i=0,j=b.length;j>i;i++)m=this.get_node(b[i],!0),m&&m.length&&m.removeClass("jstree-loading").attr("aria-busy",!1);c._load_nodes.call(this,b,d,e,f)},this)).fail(a.proxy(function(a){c._load_nodes.call(this,b,d,e,f)},this))}}return c._load_nodes.call(this,b,d,e,f)},this._load_node=function(b,d){var e=this._data.massload[b.id],f=null,g;return e?(f=this["string"==typeof e?"_append_html_data":"_append_json_data"](b,"string"==typeof e?a(a.parseHTML(e)).filter(function(){return 3!==this.nodeType}):e,function(a){d.call(this,a)}),g=this.get_node(b.id,!0),g&&g.length&&g.removeClass("jstree-loading").attr("aria-busy",!1),delete this._data.massload[b.id],f):c._load_node.call(this,b,d)}},a.jstree.defaults.search={ajax:!1,fuzzy:!1,case_sensitive:!1,show_only_matches:!1,show_only_matches_children:!1,close_opened_onclear:!0,search_leaves_only:!1,search_callback:!1},a.jstree.plugins.search=function(c,d){this.bind=function(){d.bind.call(this),this._data.search.str="",this._data.search.dom=a(),this._data.search.res=[],this._data.search.opn=[],this._data.search.som=!1,this._data.search.smc=!1,this._data.search.hdn=[],this.element.on("search.jstree",a.proxy(function(b,c){if(this._data.search.som&&c.res.length){var d=this._model.data,e,f,g=[],h,i;for(e=0,f=c.res.length;f>e;e++)if(d[c.res[e]]&&!d[c.res[e]].state.hidden&&(g.push(c.res[e]),g=g.concat(d[c.res[e]].parents),this._data.search.smc))for(h=0,i=d[c.res[e]].children_d.length;i>h;h++)d[d[c.res[e]].children_d[h]]&&!d[d[c.res[e]].children_d[h]].state.hidden&&g.push(d[c.res[e]].children_d[h]);g=a.vakata.array_remove_item(a.vakata.array_unique(g),a.jstree.root),this._data.search.hdn=this.hide_all(!0),this.show_node(g,!0),this.redraw(!0)}},this)).on("clear_search.jstree",a.proxy(function(a,b){this._data.search.som&&b.res.length&&(this.show_node(this._data.search.hdn,!0),this.redraw(!0))},this))},this.search=function(c,d,e,f,g,h){if(c===!1||""===a.trim(c.toString()))return this.clear_search();f=this.get_node(f),f=f&&f.id?f.id:null,c=c.toString();var i=this.settings.search,j=i.ajax?i.ajax:!1,k=this._model.data,l=null,m=[],n=[],o,p;if(this._data.search.res.length&&!g&&this.clear_search(),e===b&&(e=i.show_only_matches),h===b&&(h=i.show_only_matches_children),!d&&j!==!1)return a.isFunction(j)?j.call(this,c,a.proxy(function(b){b&&b.d&&(b=b.d),this._load_nodes(a.isArray(b)?a.vakata.array_unique(b):[],function(){this.search(c,!0,e,f,g,h)})},this),f):(j=a.extend({},j),j.data||(j.data={}),j.data.str=c,f&&(j.data.inside=f),this._data.search.lastRequest&&this._data.search.lastRequest.abort(),this._data.search.lastRequest=a.ajax(j).fail(a.proxy(function(){this._data.core.last_error={error:"ajax",plugin:"search",id:"search_01",reason:"Could not load search parents",data:JSON.stringify(j)},this.settings.core.error.call(this,this._data.core.last_error)},this)).done(a.proxy(function(b){b&&b.d&&(b=b.d),this._load_nodes(a.isArray(b)?a.vakata.array_unique(b):[],function(){this.search(c,!0,e,f,g,h)})},this)),this._data.search.lastRequest);if(g||(this._data.search.str=c,this._data.search.dom=a(),this._data.search.res=[],this._data.search.opn=[],this._data.search.som=e,this._data.search.smc=h),l=new a.vakata.search(c,!0,{caseSensitive:i.case_sensitive,fuzzy:i.fuzzy}),a.each(k[f?f:a.jstree.root].children_d,function(a,b){var d=k[b];d.text&&!d.state.hidden&&(!i.search_leaves_only||d.state.loaded&&0===d.children.length)&&(i.search_callback&&i.search_callback.call(this,c,d)||!i.search_callback&&l.search(d.text).isMatch)&&(m.push(b),n=n.concat(d.parents))}),m.length){for(n=a.vakata.array_unique(n),o=0,p=n.length;p>o;o++)n[o]!==a.jstree.root&&k[n[o]]&&this.open_node(n[o],null,0)===!0&&this._data.search.opn.push(n[o]);g?(this._data.search.dom=this._data.search.dom.add(a(this.element[0].querySelectorAll("#"+a.map(m,function(b){return-1!=="0123456789".indexOf(b[0])?"\\3"+b[0]+" "+b.substr(1).replace(a.jstree.idregex,"\\$&"):b.replace(a.jstree.idregex,"\\$&")}).join(", #")))),this._data.search.res=a.vakata.array_unique(this._data.search.res.concat(m))):(this._data.search.dom=a(this.element[0].querySelectorAll("#"+a.map(m,function(b){return-1!=="0123456789".indexOf(b[0])?"\\3"+b[0]+" "+b.substr(1).replace(a.jstree.idregex,"\\$&"):b.replace(a.jstree.idregex,"\\$&")}).join(", #"))),this._data.search.res=m),this._data.search.dom.children(".jstree-anchor").addClass("jstree-search")}this.trigger("search",{nodes:this._data.search.dom,str:c,res:this._data.search.res,show_only_matches:e})},this.clear_search=function(){this.settings.search.close_opened_onclear&&this.close_node(this._data.search.opn,0),this.trigger("clear_search",{nodes:this._data.search.dom,str:this._data.search.str,res:this._data.search.res}),this._data.search.res.length&&(this._data.search.dom=a(this.element[0].querySelectorAll("#"+a.map(this._data.search.res,function(b){return-1!=="0123456789".indexOf(b[0])?"\\3"+b[0]+" "+b.substr(1).replace(a.jstree.idregex,"\\$&"):b.replace(a.jstree.idregex,"\\$&")}).join(", #"))),this._data.search.dom.children(".jstree-anchor").removeClass("jstree-search")),this._data.search.str="",this._data.search.res=[],this._data.search.opn=[],this._data.search.dom=a()},this.redraw_node=function(b,c,e,f){if(b=d.redraw_node.apply(this,arguments),b&&-1!==a.inArray(b.id,this._data.search.res)){var g,h,i=null;for(g=0,h=b.childNodes.length;h>g;g++)if(b.childNodes[g]&&b.childNodes[g].className&&-1!==b.childNodes[g].className.indexOf("jstree-anchor")){i=b.childNodes[g];break}i&&(i.className+=" jstree-search")}return b}},function(a){a.vakata.search=function(b,c,d){d=d||{},d=a.extend({},a.vakata.search.defaults,d),d.fuzzy!==!1&&(d.fuzzy=!0),b=d.caseSensitive?b:b.toLowerCase();var e=d.location,f=d.distance,g=d.threshold,h=b.length,i,j,k,l;return h>32&&(d.fuzzy=!1),d.fuzzy&&(i=1<c;c++)a[b.charAt(c)]=0;for(c=0;h>c;c++)a[b.charAt(c)]|=1<c;c++){o=0,p=q;while(p>o)k(c,e+p)<=m?o=p:q=p,p=Math.floor((q-o)/2+o);for(q=p,s=Math.max(1,e-p+1),t=Math.min(e+p,l)+h,u=new Array(t+2),u[t+1]=(1<=s;f--)if(v=j[a.charAt(f-1)],0===c?u[f]=(u[f+1]<<1|1)&v:u[f]=(u[f+1]<<1|1)&v|((r[f+1]|r[f])<<1|1)|r[f+1],u[f]&i&&(w=k(c,f-1),m>=w)){if(m=w,n=f-1,x.push(n),!(n>e))break;s=Math.max(1,2*e-n)}if(k(c+1,e)>m)break;r=u}return{isMatch:n>=0,score:w}},c===!0?{search:l}:l(c)},a.vakata.search.defaults={location:0,distance:100,threshold:.6,fuzzy:!1,caseSensitive:!1}}(a),a.jstree.defaults.sort=function(a,b){return this.get_text(a)>this.get_text(b)?1:-1},a.jstree.plugins.sort=function(b,c){this.bind=function(){c.bind.call(this),this.element.on("model.jstree",a.proxy(function(a,b){this.sort(b.parent,!0)},this)).on("rename_node.jstree create_node.jstree",a.proxy(function(a,b){this.sort(b.parent||b.node.parent,!1),this.redraw_node(b.parent||b.node.parent,!0)},this)).on("move_node.jstree copy_node.jstree",a.proxy(function(a,b){this.sort(b.parent,!1),this.redraw_node(b.parent,!0)},this))},this.sort=function(b,c){var d,e;if(b=this.get_node(b),b&&b.children&&b.children.length&&(b.children.sort(a.proxy(this.settings.sort,this)),c))for(d=0,e=b.children_d.length;e>d;d++)this.sort(b.children_d[d],!1)}};var m=!1;a.jstree.defaults.state={key:"jstree",events:"changed.jstree open_node.jstree close_node.jstree check_node.jstree uncheck_node.jstree",ttl:!1,filter:!1,preserve_loaded:!1},a.jstree.plugins.state=function(b,c){this.bind=function(){c.bind.call(this);var b=a.proxy(function(){this.element.on(this.settings.state.events,a.proxy(function(){m&&clearTimeout(m),m=setTimeout(a.proxy(function(){this.save_state()},this),100)},this)),this.trigger("state_ready")},this);this.element.on("ready.jstree",a.proxy(function(a,c){this.element.one("restore_state.jstree",b),this.restore_state()||b()},this))},this.save_state=function(){var b=this.get_state();this.settings.state.preserve_loaded||delete b.core.loaded;var c={state:b,ttl:this.settings.state.ttl,sec:+new Date};a.vakata.storage.set(this.settings.state.key,JSON.stringify(c))},this.restore_state=function(){var b=a.vakata.storage.get(this.settings.state.key);if(b)try{b=JSON.parse(b)}catch(c){return!1}return b&&b.ttl&&b.sec&&+new Date-b.sec>b.ttl?!1:(b&&b.state&&(b=b.state),b&&a.isFunction(this.settings.state.filter)&&(b=this.settings.state.filter.call(this,b)),b?(this.settings.state.preserve_loaded||delete b.core.loaded,this.element.one("set_state.jstree",function(c,d){d.instance.trigger("restore_state",{state:a.extend(!0,{},b)})}),this.set_state(b),!0):!1)},this.clear_state=function(){return a.vakata.storage.del(this.settings.state.key)}},function(a,b){a.vakata.storage={set:function(a,b){return window.localStorage.setItem(a,b)},get:function(a){return window.localStorage.getItem(a)},del:function(a){return window.localStorage.removeItem(a)}}}(a),a.jstree.defaults.types={"default":{}},a.jstree.defaults.types[a.jstree.root]={},a.jstree.plugins.types=function(c,d){this.init=function(c,e){var f,g;if(e&&e.types&&e.types["default"])for(f in e.types)if("default"!==f&&f!==a.jstree.root&&e.types.hasOwnProperty(f))for(g in e.types["default"])e.types["default"].hasOwnProperty(g)&&e.types[f][g]===b&&(e.types[f][g]=e.types["default"][g]);d.init.call(this,c,e),this._model.data[a.jstree.root].type=a.jstree.root},this.refresh=function(b,c){d.refresh.call(this,b,c),this._model.data[a.jstree.root].type=a.jstree.root},this.bind=function(){this.element.on("model.jstree",a.proxy(function(c,d){var e=this._model.data,f=d.nodes,g=this.settings.types,h,i,j="default",k;for(h=0,i=f.length;i>h;h++){if(j="default",e[f[h]].original&&e[f[h]].original.type&&g[e[f[h]].original.type]&&(j=e[f[h]].original.type),e[f[h]].data&&e[f[h]].data.jstree&&e[f[h]].data.jstree.type&&g[e[f[h]].data.jstree.type]&&(j=e[f[h]].data.jstree.type),e[f[h]].type=j,e[f[h]].icon===!0&&g[j].icon!==b&&(e[f[h]].icon=g[j].icon),g[j].li_attr!==b&&"object"==typeof g[j].li_attr)for(k in g[j].li_attr)if(g[j].li_attr.hasOwnProperty(k)){if("id"===k)continue;e[f[h]].li_attr[k]===b?e[f[h]].li_attr[k]=g[j].li_attr[k]:"class"===k&&(e[f[h]].li_attr["class"]=g[j].li_attr["class"]+" "+e[f[h]].li_attr["class"])}if(g[j].a_attr!==b&&"object"==typeof g[j].a_attr)for(k in g[j].a_attr)if(g[j].a_attr.hasOwnProperty(k)){if("id"===k)continue;e[f[h]].a_attr[k]===b?e[f[h]].a_attr[k]=g[j].a_attr[k]:"href"===k&&"#"===e[f[h]].a_attr[k]?e[f[h]].a_attr.href=g[j].a_attr.href:"class"===k&&(e[f[h]].a_attr["class"]=g[j].a_attr["class"]+" "+e[f[h]].a_attr["class"])}}e[a.jstree.root].type=a.jstree.root},this)),d.bind.call(this)},this.get_json=function(b,c,e){var f,g,h=this._model.data,i=c?a.extend(!0,{},c,{no_id:!1}):{},j=d.get_json.call(this,b,i,e);if(j===!1)return!1;if(a.isArray(j))for(f=0,g=j.length;g>f;f++)j[f].type=j[f].id&&h[j[f].id]&&h[j[f].id].type?h[j[f].id].type:"default", +c&&c.no_id&&(delete j[f].id,j[f].li_attr&&j[f].li_attr.id&&delete j[f].li_attr.id,j[f].a_attr&&j[f].a_attr.id&&delete j[f].a_attr.id);else j.type=j.id&&h[j.id]&&h[j.id].type?h[j.id].type:"default",c&&c.no_id&&(j=this._delete_ids(j));return j},this._delete_ids=function(b){if(a.isArray(b)){for(var c=0,d=b.length;d>c;c++)b[c]=this._delete_ids(b[c]);return b}return delete b.id,b.li_attr&&b.li_attr.id&&delete b.li_attr.id,b.a_attr&&b.a_attr.id&&delete b.a_attr.id,b.children&&a.isArray(b.children)&&(b.children=this._delete_ids(b.children)),b},this.check=function(c,e,f,g,h){if(d.check.call(this,c,e,f,g,h)===!1)return!1;e=e&&e.id?e:this.get_node(e),f=f&&f.id?f:this.get_node(f);var i=e&&e.id?h&&h.origin?h.origin:a.jstree.reference(e.id):null,j,k,l,m;switch(i=i&&i._model&&i._model.data?i._model.data:null,c){case"create_node":case"move_node":case"copy_node":if("move_node"!==c||-1===a.inArray(e.id,f.children)){if(j=this.get_rules(f),j.max_children!==b&&-1!==j.max_children&&j.max_children===f.children.length)return this._data.core.last_error={error:"check",plugin:"types",id:"types_01",reason:"max_children prevents function: "+c,data:JSON.stringify({chk:c,pos:g,obj:e&&e.id?e.id:!1,par:f&&f.id?f.id:!1})},!1;if(j.valid_children!==b&&-1!==j.valid_children&&-1===a.inArray(e.type||"default",j.valid_children))return this._data.core.last_error={error:"check",plugin:"types",id:"types_02",reason:"valid_children prevents function: "+c,data:JSON.stringify({chk:c,pos:g,obj:e&&e.id?e.id:!1,par:f&&f.id?f.id:!1})},!1;if(i&&e.children_d&&e.parents){for(k=0,l=0,m=e.children_d.length;m>l;l++)k=Math.max(k,i[e.children_d[l]].parents.length);k=k-e.parents.length+1}(0>=k||k===b)&&(k=1);do{if(j.max_depth!==b&&-1!==j.max_depth&&j.max_depthg;g++)this.set_type(c[g],d);return!0}if(f=this.settings.types,c=this.get_node(c),!f[d]||!c)return!1;if(l=this.get_node(c,!0),l&&l.length&&(m=l.children(".jstree-anchor")),i=c.type,j=this.get_icon(c),c.type=d,(j===!0||!f[i]||f[i].icon!==b&&j===f[i].icon)&&this.set_icon(c,f[d].icon!==b?f[d].icon:!0),f[i]&&f[i].li_attr!==b&&"object"==typeof f[i].li_attr)for(k in f[i].li_attr)if(f[i].li_attr.hasOwnProperty(k)){if("id"===k)continue;"class"===k?(e[c.id].li_attr["class"]=(e[c.id].li_attr["class"]||"").replace(f[i].li_attr[k],""),l&&l.removeClass(f[i].li_attr[k])):e[c.id].li_attr[k]===f[i].li_attr[k]&&(e[c.id].li_attr[k]=null,l&&l.removeAttr(k))}if(f[i]&&f[i].a_attr!==b&&"object"==typeof f[i].a_attr)for(k in f[i].a_attr)if(f[i].a_attr.hasOwnProperty(k)){if("id"===k)continue;"class"===k?(e[c.id].a_attr["class"]=(e[c.id].a_attr["class"]||"").replace(f[i].a_attr[k],""),m&&m.removeClass(f[i].a_attr[k])):e[c.id].a_attr[k]===f[i].a_attr[k]&&("href"===k?(e[c.id].a_attr[k]="#",m&&m.attr("href","#")):(delete e[c.id].a_attr[k],m&&m.removeAttr(k)))}if(f[d].li_attr!==b&&"object"==typeof f[d].li_attr)for(k in f[d].li_attr)if(f[d].li_attr.hasOwnProperty(k)){if("id"===k)continue;e[c.id].li_attr[k]===b?(e[c.id].li_attr[k]=f[d].li_attr[k],l&&("class"===k?l.addClass(f[d].li_attr[k]):l.attr(k,f[d].li_attr[k]))):"class"===k&&(e[c.id].li_attr["class"]=f[d].li_attr[k]+" "+e[c.id].li_attr["class"],l&&l.addClass(f[d].li_attr[k]))}if(f[d].a_attr!==b&&"object"==typeof f[d].a_attr)for(k in f[d].a_attr)if(f[d].a_attr.hasOwnProperty(k)){if("id"===k)continue;e[c.id].a_attr[k]===b?(e[c.id].a_attr[k]=f[d].a_attr[k],m&&("class"===k?m.addClass(f[d].a_attr[k]):m.attr(k,f[d].a_attr[k]))):"href"===k&&"#"===e[c.id].a_attr[k]?(e[c.id].a_attr.href=f[d].a_attr.href,m&&m.attr("href",f[d].a_attr.href)):"class"===k&&(e[c.id].a_attr["class"]=f[d].a_attr["class"]+" "+e[c.id].a_attr["class"],m&&m.addClass(f[d].a_attr[k]))}return!0}},a.jstree.defaults.unique={case_sensitive:!1,trim_whitespace:!1,duplicate:function(a,b){return a+" ("+b+")"}},a.jstree.plugins.unique=function(c,d){this.check=function(b,c,e,f,g){if(d.check.call(this,b,c,e,f,g)===!1)return!1;if(c=c&&c.id?c:this.get_node(c),e=e&&e.id?e:this.get_node(e),!e||!e.children)return!0;var h="rename_node"===b?f:c.text,i=[],j=this.settings.unique.case_sensitive,k=this.settings.unique.trim_whitespace,l=this._model.data,m,n,o;for(m=0,n=e.children.length;n>m;m++)o=l[e.children[m]].text,j||(o=o.toLowerCase()),k&&(o=o.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")),i.push(o);switch(j||(h=h.toLowerCase()),k&&(h=h.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")),b){case"delete_node":return!0;case"rename_node":return o=c.text||"",j||(o=o.toLowerCase()),k&&(o=o.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")),m=-1===a.inArray(h,i)||c.text&&o===h,m||(this._data.core.last_error={error:"check",plugin:"unique",id:"unique_01",reason:"Child with name "+h+" already exists. Preventing: "+b,data:JSON.stringify({chk:b,pos:f,obj:c&&c.id?c.id:!1,par:e&&e.id?e.id:!1})}),m;case"create_node":return m=-1===a.inArray(h,i),m||(this._data.core.last_error={error:"check",plugin:"unique",id:"unique_04",reason:"Child with name "+h+" already exists. Preventing: "+b,data:JSON.stringify({chk:b,pos:f,obj:c&&c.id?c.id:!1,par:e&&e.id?e.id:!1})}),m;case"copy_node":return m=-1===a.inArray(h,i),m||(this._data.core.last_error={error:"check",plugin:"unique",id:"unique_02",reason:"Child with name "+h+" already exists. Preventing: "+b,data:JSON.stringify({chk:b,pos:f,obj:c&&c.id?c.id:!1,par:e&&e.id?e.id:!1})}),m;case"move_node":return m=c.parent===e.id&&(!g||!g.is_multi)||-1===a.inArray(h,i),m||(this._data.core.last_error={error:"check",plugin:"unique",id:"unique_03",reason:"Child with name "+h+" already exists. Preventing: "+b,data:JSON.stringify({chk:b,pos:f,obj:c&&c.id?c.id:!1,par:e&&e.id?e.id:!1})}),m}return!0},this.create_node=function(c,e,f,g,h){if(!e||e.text===b){if(null===c&&(c=a.jstree.root),c=this.get_node(c),!c)return d.create_node.call(this,c,e,f,g,h);if(f=f===b?"last":f,!f.toString().match(/^(before|after)$/)&&!h&&!this.is_loaded(c))return d.create_node.call(this,c,e,f,g,h);e||(e={});var i,j,k,l,m,n=this._model.data,o=this.settings.unique.case_sensitive,p=this.settings.unique.trim_whitespace,q=this.settings.unique.duplicate,r;for(j=i=this.get_string("New node"),k=[],l=0,m=c.children.length;m>l;l++)r=n[c.children[l]].text,o||(r=r.toLowerCase()),p&&(r=r.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")),k.push(r);l=1,r=j,o||(r=r.toLowerCase()),p&&(r=r.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,""));while(-1!==a.inArray(r,k))j=q.call(this,i,++l).toString(),r=j,o||(r=r.toLowerCase()),p&&(r=r.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,""));e.text=j}return d.create_node.call(this,c,e,f,g,h)}};var n=i.createElement("DIV");if(n.setAttribute("unselectable","on"),n.setAttribute("role","presentation"),n.className="jstree-wholerow",n.innerHTML=" ",a.jstree.plugins.wholerow=function(b,c){this.bind=function(){c.bind.call(this),this.element.on("ready.jstree set_state.jstree",a.proxy(function(){this.hide_dots()},this)).on("init.jstree loading.jstree ready.jstree",a.proxy(function(){this.get_container_ul().addClass("jstree-wholerow-ul")},this)).on("deselect_all.jstree",a.proxy(function(a,b){this.element.find(".jstree-wholerow-clicked").removeClass("jstree-wholerow-clicked")},this)).on("changed.jstree",a.proxy(function(a,b){this.element.find(".jstree-wholerow-clicked").removeClass("jstree-wholerow-clicked");var c=!1,d,e;for(d=0,e=b.selected.length;e>d;d++)c=this.get_node(b.selected[d],!0),c&&c.length&&c.children(".jstree-wholerow").addClass("jstree-wholerow-clicked")},this)).on("open_node.jstree",a.proxy(function(a,b){this.get_node(b.node,!0).find(".jstree-clicked").parent().children(".jstree-wholerow").addClass("jstree-wholerow-clicked")},this)).on("hover_node.jstree dehover_node.jstree",a.proxy(function(a,b){"hover_node"===a.type&&this.is_disabled(b.node)||this.get_node(b.node,!0).children(".jstree-wholerow")["hover_node"===a.type?"addClass":"removeClass"]("jstree-wholerow-hovered")},this)).on("contextmenu.jstree",".jstree-wholerow",a.proxy(function(b){if(this._data.contextmenu){b.preventDefault();var c=a.Event("contextmenu",{metaKey:b.metaKey,ctrlKey:b.ctrlKey,altKey:b.altKey,shiftKey:b.shiftKey,pageX:b.pageX,pageY:b.pageY});a(b.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(c)}},this)).on("click.jstree",".jstree-wholerow",function(b){b.stopImmediatePropagation();var c=a.Event("click",{metaKey:b.metaKey,ctrlKey:b.ctrlKey,altKey:b.altKey,shiftKey:b.shiftKey});a(b.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(c).focus()}).on("dblclick.jstree",".jstree-wholerow",function(b){b.stopImmediatePropagation();var c=a.Event("dblclick",{metaKey:b.metaKey,ctrlKey:b.ctrlKey,altKey:b.altKey,shiftKey:b.shiftKey});a(b.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(c).focus()}).on("click.jstree",".jstree-leaf > .jstree-ocl",a.proxy(function(b){b.stopImmediatePropagation();var c=a.Event("click",{metaKey:b.metaKey,ctrlKey:b.ctrlKey,altKey:b.altKey,shiftKey:b.shiftKey});a(b.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(c).focus()},this)).on("mouseover.jstree",".jstree-wholerow, .jstree-icon",a.proxy(function(a){return a.stopImmediatePropagation(),this.is_disabled(a.currentTarget)||this.hover_node(a.currentTarget),!1},this)).on("mouseleave.jstree",".jstree-node",a.proxy(function(a){this.dehover_node(a.currentTarget)},this))},this.teardown=function(){this.settings.wholerow&&this.element.find(".jstree-wholerow").remove(),c.teardown.call(this)},this.redraw_node=function(b,d,e,f){if(b=c.redraw_node.apply(this,arguments)){var g=n.cloneNode(!0);-1!==a.inArray(b.id,this._data.core.selected)&&(g.className+=" jstree-wholerow-clicked"),this._data.core.focused&&this._data.core.focused===b.id&&(g.className+=" jstree-wholerow-hovered"),b.insertBefore(g,b.childNodes[0])}return b}},window.customElements&&Object&&Object.create){var o=Object.create(HTMLElement.prototype);o.createdCallback=function(){var b={core:{},plugins:[]},c;for(c in a.jstree.plugins)a.jstree.plugins.hasOwnProperty(c)&&this.attributes[c]&&(b.plugins.push(c),this.getAttribute(c)&&JSON.parse(this.getAttribute(c))&&(b[c]=JSON.parse(this.getAttribute(c))));for(c in a.jstree.defaults.core)a.jstree.defaults.core.hasOwnProperty(c)&&this.attributes[c]&&(b.core[c]=JSON.parse(this.getAttribute(c))||this.getAttribute(c));a(this).jstree(b)};try{window.customElements.define("vakata-jstree",function(){},{prototype:o})}catch(p){}}}}); diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/libs/ngtimeago.js b/KeywordSearch/solr/server/solr-webapp/webapp/libs/ngtimeago.js new file mode 100755 index 0000000000..46a9d4b435 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/libs/ngtimeago.js @@ -0,0 +1,100 @@ +/* +Copyright (c) 2014 Uttesh Kumar + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +'use strict'; + +var catalyst = angular.module('ngtimeago', []); + + +catalyst.filter('timeago', function() { + return function(input, p_allowFuture) { + + if (input === undefined) { + return "-"; + } + + var substitute = function (stringOrFunction, number, strings) { + var string = angular.isFunction(stringOrFunction) ? stringOrFunction(number, dateDifference) : stringOrFunction; + var value = (strings.numbers && strings.numbers[number]) || number; + return string.replace(/%d/i, value); + }, + nowTime = (new Date()).getTime(), + date = (new Date(input)).getTime(), + //refreshMillis= 6e4, //A minute + allowFuture = p_allowFuture || false, + strings= { + prefixAgo: ' ', + prefixFromNow: '', + suffixAgo: "ago", + suffixFromNow: "from now", + seconds: "less than a minute", + minute: "about a minute", + minutes: "%d minutes", + hour: "about an hour", + hours: "about %d hours", + day: "a day", + days: "%d days", + month: "about a month", + months: "%d months", + year: "about a year", + years: "%d years" + }, + dateDifference = nowTime - date, + words, + seconds = Math.abs(dateDifference) / 1000, + minutes = seconds / 60, + hours = minutes / 60, + days = hours / 24, + years = days / 365, + separator = strings.wordSeparator === undefined ? " " : strings.wordSeparator, + + + prefix = strings.prefixAgo, + suffix = strings.suffixAgo; + + if (allowFuture) { + if (dateDifference < 0) { + prefix = strings.prefixFromNow; + suffix = strings.suffixFromNow; + } + } + + words = seconds < 45 && substitute(strings.seconds, Math.round(seconds), strings) || + seconds < 90 && substitute(strings.minute, 1, strings) || + minutes < 45 && substitute(strings.minutes, Math.round(minutes), strings) || + minutes < 90 && substitute(strings.hour, 1, strings) || + hours < 24 && substitute(strings.hours, Math.round(hours), strings) || + hours < 42 && substitute(strings.day, 1, strings) || + days < 30 && substitute(strings.days, Math.round(days), strings) || + days < 45 && substitute(strings.month, 1, strings) || + days < 365 && substitute(strings.months, Math.round(days / 30), strings) || + years < 1.5 && substitute(strings.year, 1, strings) || + substitute(strings.years, Math.round(years), strings); + prefix.replace(/ /g, ''); + words.replace(/ /g, ''); + suffix.replace(/ /g, ''); + return (prefix+' '+words+' '+suffix+' '+separator); + }; + }); + + + diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/alias_overview.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/alias_overview.html new file mode 100755 index 0000000000..0cf8124b53 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/alias_overview.html @@ -0,0 +1,46 @@ + +
    + +
    + +
    + +

    Alias: {{selectedCollection.name}}

    + +
    + +
    + +
    Collections:
    +
    + + {{coll}}{{$last ? '' : ', '}} + +
    + + +
    {{ key }}
    +
    {{ value }}
    +
    +
    + +
    +
    +
    + +
    diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/analysis.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/analysis.html new file mode 100755 index 0000000000..23527f7351 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/analysis.html @@ -0,0 +1,128 @@ + +
    + +
    +
    This Functionality requires the /analysis/field Handler to be registered and active!
    +
    + +
    +
    {{analysisError}}
    +
    + +
    + +
    + +
    + +
      + +
    • + + + + +
    • + +
    • + + + + +
    • + +
    • +
      + + + + Schema Browser  + +
      + + + + + +
      + +
      +
    • + +
    + +
    + +
    + +
    +
    + + + + + + + + + +
    +
    + {{component.short}} +
    +
    +
    + + + + +
    + + + + +
    {{ caption }}
    +
    +
    +
    +
    + + + + + + +
    + + + + + + +
    {{value.value}}
    +
    +
    +
     
    +
    +
    +
    +
    + +
    diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/cloud.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/cloud.html new file mode 100755 index 0000000000..01d63499ee --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/cloud.html @@ -0,0 +1,303 @@ + +
    + +
    + +
    + + +
    Status: {{zkState.status}}
    +
    + Errors: +
      +
    • {{error}}
    • +
    +
    +
    ZK connection string: {{zkState.zkHost}}
    +
    Ensemble size: {{zkState.ensembleSize}}
    +
    Ensemble mode: {{zkState.mode}}
    +
    Dynamic reconfig enabled: {{zkState.dynamicReconfig}}
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    {{host.host}}
    {{key}} + {{key === 'zk_version' ? host[key].split("-")[0] : host[key]}} +
    {{key}} + {{host[key]}} +
    {{key}} + {{host[key]}} +
    {{key}} + {{host[key]}} +
    +
    + +
    + + +
    + + Metadata +
    +
      +
    • +
      +
      {{ key }}
      +
      {{ prop }}
      +
      +
    • +
    +
    + +
    + Node "{{znode.path }}" has no utf8 Content +
    +          
    +   +
    + + +
    + +
    + +
    + +
    +
    + + No hosts found. + Hosts {{from+1}} - {{from + hostsToShow.length}} of {{filteredHosts.length}}.  + + Filter by:   + + +   + + +   + + Show hosts per page. + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    HostNodeCPUHeapDisk usageRequestsCollectionsReplicas
    +
    {{h.host}}
    + + {{h.system.system.name}} + {{h.memTotal}} + Java {{h.system.jvm.spec.version}} +
    Load: {{h.loadAvg}} +
    +
    + {{h.system.system.name}} {{h.system.system.version}}, {{h.system.system.availableProcessors}}cpu
    + Uptime: {{h.uptime}}
    + Memory: {{h.memTotal}}
    + File descriptors: {{h.openFileDescriptorCount}}/{{h.maxFileDescriptorCount}}
    + Disk: {{h.diskTotal}} used: {{h.diskUsedPct}}%
    + Load: {{h.loadAvg}} +
    + +
    +
    (DEAD)
    +
    + Uptime: {{n.jvmUptime}}
    +
    + Java {{n.system.jvm.jre.version}}
    + Solr {{n.system.lucene['solr-impl-version'].split(" ")[0]}}
    +
    + +
    +
    +
    + {{n.cpuPct}}% +
    +
    +
    + {{n.heapUsedPct}}% +
    +
    + Max: {{n.heapTotal}}
    + Used: {{n.heapUsed}} +
    +
    +
    +
    + {{n.size}} +
    +
    + Total #docs: {{n.numDocs}}
    + Avg size/doc: {{n.sizePerDoc}} +
    +
    +
    +
    + RPM: {{n.req15minRate}}
    p95: {{n.reqp95_ms}}ms
    +
    +
    (none)
    +
    + {{ c }} +
    + +
    +
    (none)
    +
    +
    {{ core.label }} ({{core.numDocsHuman}} docs)
    +
    {{ core.label }}
    +
      +
    • deleted: {{core.deletedDocsHuman}}
    • +
    • warmupTime: {{core.warmupTime}}
    • +
    • avg size/doc: {{core.avgSizePerDoc}}
    • +
    +
    + +
    +
    + +
    + +
    + +
    +
      +
    • Leader
    • +
    • Active
    • +
    • Recovering
    • +
    • Down
    • +
    • Recovery Failed
    • +
    • Inactive
    • +
    • Gone
    • +
    • Replica Type:
      N(NRT),T(TLOG),
      P(PULL)
    • +
    +
    +
    +
    + + No collections found. + Collections {{start}} - {{last}} of {{total}}.  + + Filter by:  T:{{filterType}} + + + + + +   + + Show per page. + +
    +
    + +
    + +
    + + + +
    diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/cluster_suggestions.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/cluster_suggestions.html new file mode 100755 index 0000000000..892b0bbc97 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/cluster_suggestions.html @@ -0,0 +1,49 @@ + + +
    +

    Cluster Suggestions

    +
    + + + + + + + + + + + + + + + + +
    TypeReasonDetailsAction
    NA
    {{ x.type }}{{ x.violation.clause }}node: {{ x.violation.node }}, collection : {{ x.violation.collection }}, shard : {{ x.violation.shard }}   +
    + +
    +
    +
    +
    +
    + +
    + diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/collection_overview.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/collection_overview.html new file mode 100755 index 0000000000..cf1c18c314 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/collection_overview.html @@ -0,0 +1,85 @@ + +
    + +
    + +
    + +

    Collection: {{selectedCollection.name}}

    + +
    + +
    + +
    Config name:
    +
    {{selectedCollection.configName}}
    + +
    Max shards per node:
    +
    {{selectedCollection.maxShardsPerNode}}
    + +
    Replication factor:
    +
    {{selectedCollection.replicationFactor}}
    + +
    Auto-add replicas:
    +
    yes
    + +
    Router name:
    +
    {{selectedCollection.router.name}}
    + +
    + +
    +
    + +
    + +

    Shards

    + +
    + +
    +

    {{name}}

    +
    +
    Range:
    +
    {{ shard.range }}
    + +
    Active:
    +
    yes
    + +
    Replicas:
    +
    +
    +

    {{replica.core}}

    +
    +
    Base URL:
    {{replica.base_url}}
    +
    Core:
    {{replica.core}}
    +
    Active:
    +
    yes
    +
    Leader:
    +
    yes
    +
    +
    + +
    +
    +
    +
    + +
    + +
    diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/collections.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/collections.html new file mode 100755 index 0000000000..198030c744 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/collections.html @@ -0,0 +1,395 @@ + +
    + + + +
    +
    + +
    + +

    +

    + +

      + +

    + +

    +

    + +

    +

    + +

    + Show advanced

    +
    + +

    Advanced options:

    +

    + +

    + +

    +

    + +

    +

    + +

    +

    + +

    + +

    + +
    +

    + {{addMessage}} +

    + +

    + + +

    + +
    + +
    +
    + +
    + + + +

    +

    + +

    +

    + + +

    + {{renameMessage}} +

    + +

    + + +

    +
    + +
    +
    + +
    + +
    + + + + + +
    + +
    + +

    Please type collection name to confirm deletion:

    +

    +

    + +

    + {{deleteMessage}} +

    + +

    + + +

    +
    + +
    + +
    + +
    +

    Are you sure you want to delete alias {{ collection.name }}?

    + +

    + + +

    +
    + +
    + +
    + + +
    +

    Please select a collection or alias

    +
    + +
    + +
    + +

    Alias: {{collection.name}}

    + +
    +
    +
    + +
    + +
      + +
    • +
      +
      Collections:
      +
      + + {{coll}}{{$last ? '' : ', '}} + +
      +
      +
      {{ key }}
      +
      {{ value }}
      +
      +
      +
    • +
    +
    +
    + +
    + +

    Collection: {{collection.name}}

    + +
    +
    +
    + +
    + +
      + +
    • +
      +
      Shard count:
      +
      {{collection.shards.length}}
      +
      +
    • +
    • +
      configName:
      +
      {{collection.configName}}
      +
    • + +
    • +
      replicationFactor:
      +
      {{collection.replicationFactor}}
      +
    • + +
    • +
      maxShardsPerNode:
      +
      {{collection.maxShardsPerNode}}
      +
    • + +
    • +
      router:
      +
      {{collection.router.name}}
      +
    • + +
    • +
      autoAddReplicas:
      +
      {{collection.autoAddReplicas}}
      +
    • + +
    • +
      aliases:
      +
      + + {{coll}}{{$last ? '' : ', '}} + +
      +
    • +
    + +
    +
    + +
    +
    + +

    + Shard: {{shard.name}} +
    +

    + +
      +
    • +
      +

      Are you sure you want to delete this shard?

      +

      + + +

      +
      +
    • +
    +
      +
    • +
        +
      • +
        +
        state:
        +
        {{shard.state}}
        +
        +
      • +
      • +
        +
        range:
        +
        {{shard.range}}
        +
        +
        +
      • +
      • +
          +
        • +

          + + Replica: {{replica.name}} + +
          +

          +
        • +
        • +
            +
          • +
            + +

            Are you sure you want to delete this replica?

            + +

            + + +

            +
            +
          • +
          +
            +
          • +
            +
            core:
            +
            {{replica.core}}
            +
            +
          • + +
          • +
            +
            base URL:
            +
            {{replica.base_url}}
            +
            +
          • + +
          • +
            +
            node name:
            +
            {{replica.node_name}}
            +
            +
          • + +
          • +
            +
            state:
            +
            {{replica.state}}
            +
            +
          • + +
          • +
            +
            leader:
            +
            +
            +
          • +
          +
        • + +
        +
      • +
      • + + + +
      • +
      +
      + +
      + +

      + + node: {{shard.replicaNodeName}} +

      + +

      + {{createReplicaMessage}} +

      + +

      + + +

      +

       

      +
      + +
      +
    • +
    +
    +
    + +
    + +
    + + + +
    diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/core_overview.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/core_overview.html new file mode 100755 index 0000000000..f1826f65c0 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/core_overview.html @@ -0,0 +1,206 @@ + +
    + +
    + +
    + +

    Statistics

    + +
    +
    {{statsMessage}}
    +
    + +
    + +
    + +
    Last Modified:
    +
    {{index.lastModified | timeago}}
    + +
    Num Docs:
    +
    {{index.numDocs}}
    + +
    Max Doc:
    +
    {{index.maxDoc}}
    + +
    Heap Memory Usage:
    +
    {{index.indexHeapUsageBytes}}
    + +
    Deleted Docs:
    +
    {{index.deletedDocs}}
    + +
    Version:
    +
    {{index.version}}
    + +
    Segment Count:
    +
    {{index.segmentCount}}
    + +
    Current:
    +
    + +
    + +
    +
    + +
    + +

    Instance

    + +
    +
    {{indexMessage}}
    +
    + +
    + +
    + +
    CWD:
    +
    {{ core.directory.cwd }}
    + +
    Instance:
    +
    {{ core.directory.instance }}
    + +
    Data:
    +
    {{ core.directory.data }}
    + +
    Index:
    +
    {{ core.directory.index }}
    + +
    Impl:
    +
    {{ core.directory.dirimpl }}
    + +
    + +
    +
    + +
    +
    + +
    + +

    + + Replication + (Slave) + (Master) + +

    + +
    +
    {{replicationMessage}}
    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    IndexVersionGenSize
    Master (Searching)
    {{replication.indexVersion}}
    {{replication.generation}}
    {{replication.indexSize || '-'}}
    Master (Replicable)
    {{replication.master.replicableVersion || '-'}}
    {{replication.master.replicableGeneration || '-'}}
    -
    Master (Replicable)
    {{replication.master.replicableVersion || '-'}}
    {{replication.master.replicableGeneration || '-'}}
    -
    Master (Searching)
    {{replication.slave.masterDetails.indexVersion}}
    {{replication.slave.masterDetails.generation}}
    {{replication.slave.masterDetails.indexSize || '-'}}
    Slave (Searching)
    {{replication.indexVersion}}
    {{replication.generation}}
    {{replication.indexSize || '-'}}
    + +
    +
    + +
    + +

    Healthcheck

    + +
    +
    {{healthcheckMessage}}
    +
    + +
    +
    + +
    Status:
    +
    + +
    +
    + +
    +
    +
    + +
    + +
    + + +
    diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/cores.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/cores.html new file mode 100755 index 0000000000..1615769564 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/cores.html @@ -0,0 +1,224 @@ + +
    + + + +
    + +
    + + + + + + + + +
    + +
    + +

    +

    + +

    +

    + +

    +

    + +

    +

    + +

    +

    + +
    + +

    +

    + +

    +

    + +
    + +

    + + instanceDir and dataDir need to exist before you can create the core + +

    + +

    + {{addMessage}} +

    + +

    + + +

    + +
    + +
    + +
    + +
    + + + +

    +

    + +

    + {{renameMessage}} +

    + +

    + + +

    +
    + +
    + +
    + +
    + +

    +

    + +

    +

    + +

    + {{swapMessage}} +

    + +

    + + +

    + +
    + +
    + +
    + +
    + +
    + +

    Core

    + +
    +
    +
    + +
    + +
      + +
    • +
      startTime:
      +
      {{core.startTime | timeago}}
      +
    • + +
    • +
      instanceDir:
      +
      {{core.instanceDir}}
      +
    • + +
    • +
      dataDir:
      +
      {{core.dataDir}}
      +
    • + +
    + +
    +
    + +
    + +

    Index

    + +
    +
    {{core.message}}
    +
    + +
    + +
      + +
    • +
      lastModified:
      +
      {{core.index.lastModified | timeago}}
      +
    • + +
    • +
      version:
      +
      {{core.index.version}}
      +
    • + +
    • +
      numDocs:
      +
      {{core.index.numDocs}}
      +
    • + +
    • +
      maxDoc:
      +
      {{core.index.maxDoc}}
      +
    • + +
    • +
      deletedDocs:
      +
      {{core.index.deletedDocs}}
      +
    • + +
    • +
      current:
      +
      +
    • + +
    • +
      directory:
      +
      {{core.index.directory}}
      +
    • + +
    + +
    +
    + +
    + +
    + + + +
    diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/dataimport.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/dataimport.html new file mode 100755 index 0000000000..a27be07a5a --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/dataimport.html @@ -0,0 +1,210 @@ + +
    + +
    The solrconfig.xml file for this index does not have an operational DataImportHandler defined!
    +
    +
    The Data Import Handler is deprecated as of Solr 8.6 and may be removed in a future release. A community supported package for may be used instead (See SOLR-14066 for details).
    + +
    + +
    + +

    Last Update: {{lastUpdate}}

    +
    + + {{info.text}} (Duration: {{info.timeTaken | readableSeconds }}) + +
    +
    + + {{ doc.name }}: {{doc.value | number}} {{ doc.speed | number}}/s, + +
    +
    + + {{ date.name }}: + {{ date.value | timeago }} + +
    +
    + + + +
    + +
    + +
    + +

    + Raw Status-Output +

    + +
    +
    +
    + +
    + +
    + +
    + +
    + +
    + +

    + Configuration + Reload + Debug-Mode +

    + +
    +
    +
    + +
    +
    + +
    + +
    + +
    + +
    + + + +
    + +
    + +
    + +
    + +
    + +

    + Raw Debug-Response +

    + +
    +
    +
    + +
    + + No Request executed + + +
    +
    +
    + +
    + +
    + +
    + + + +
    + + + + + + + + + + + + + + + + + + +
    + + +
    + + + +
    + + + +

    Auto-Refresh Status

    + +
    + +
    diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/documents.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/documents.html new file mode 100755 index 0000000000..2bf3f12982 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/documents.html @@ -0,0 +1,111 @@ + + +
    +
    +
    + + + + +
    +
    +
    +
    +
    +
    Field: +
    +
    Field Data: + +
    +
    + +
    + + + +
    + +
    +
    + +
    + +
    + +
    + + + + +
    +
    +
    + + +
    +
    +
    +
    +
    + Status: {{ responseStatus }} +
    +
    + Response: +
    +
    +
    + +
    +
    + + diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/files.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/files.html new file mode 100755 index 0000000000..6a31096f09 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/files.html @@ -0,0 +1,47 @@ + +
    + +
    + +
    + + + +
    +
    + + + +
    + +
    +
    +
    + + +
    + +
    + +
    + +
    diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/index.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/index.html new file mode 100755 index 0000000000..5f77bffae3 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/index.html @@ -0,0 +1,295 @@ + +
    + +
    + +
    + +
    + +

    Instance

    + +
    + +
      + +
    • +
      Start
      +
      {{system.jvm.jmx.startTime | timeago}}
      +
    • + + +
    + +
    + +
    + +
    + +

    Versions

    + +
    + +
      + +
    • +
      solr-spec
      +
      {{system.lucene["solr-spec-version"]}}
      +
    • + +
    • +
      solr-impl
      +
      {{system.lucene["solr-impl-version"]}}
      +
    • + +
    • +
      lucene-spec
      +
      {{system.lucene["lucene-spec-version"]}}
      +
    • + +
    • +
      lucene-impl
      +
      {{system.lucene["lucene-impl-version"]}}
      +
    • + +
    + +
    + +
    + +
    + +
    + +
    + +

    System + {{load_average}} +

    + reload + +
    + +
    + +

    Physical Memory + {{memoryPercentage}} +

    +
    + +
    + {{memoryMax}} + +
    + {{memoryTotalDisplay}} + +
    + +
    + +
    + +
    + +
    + +

    Swap Space + {{swapPercentage}} +

    +
    + +
    + {{swapMax}} + +
    + {{swapTotalDisplay}} + +
    + +
    + +
    + +
    + +
    + +

    File Descriptor Count + {{fileDescriptorPercentage}} +

    +
    + +
    + {{system.system.maxFileDescriptorCount}} + +
    + {{system.system.openFileDescriptorCount}} + +
    + +
    + +
    + +
    + +

    Sorry, no information available

    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +

    JVM

    + +
    + +
      + +
    • +
      Runtime
      +
      {{system.jvm.name}} {{system.jvm.version}}
      +
    • + +
    • +
      Processors
      +
      {{system.jvm.processors}}
      +
    • + +
    • +
      Args
      +
      {{arg}}
      +
    • + +
    + +
    + +
    + +
    +
    + +
    + +

    JVM-Memory + {{javaMemoryPercentage}} +

    + +
    + +
    +
    + +
    + {{javaMemoryMax}} + +
    + {{javaMemoryTotalDisplay}} + +
    + {{javaMemoryUsedDisplay}} + +
    + +
    + +
    + +
    +
    + +
    + +
    +
    + +

    Security

    + +
    + +
      + +
    • +
      Authentication Plugin
      +
      {{system.security["authenticationPlugin"]}}
      +
    • + +
    • +
      Authorization Plugin
      +
      {{system.security["authorizationPlugin"]}}
      +
    • + +
    • +
      Current Username
      +
      {{system.security["username"]}}
      +
    • + +
    • +
      User Roles
      +
      {{system.security["roles"]}}
      +
    • + +
    + + +
    + +
    + +
    + +
    + +
    diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/java-properties.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/java-properties.html new file mode 100755 index 0000000000..9c67c7b759 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/java-properties.html @@ -0,0 +1,27 @@ + +
    +
      +
    • +
      +
      +
      {{val}}{{pathSeparator}}{{"​"}}
      +
      +
    • +
    +
    + diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/logging-levels.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/logging-levels.html new file mode 100755 index 0000000000..14c6c085dd --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/logging-levels.html @@ -0,0 +1,55 @@ + +
    +
    +
    +

    {{watcher}}

    +
    +
      +
    • +
    +
    +
    +
    +
    + + diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/logging.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/logging.html new file mode 100755 index 0000000000..9952360b30 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/logging.html @@ -0,0 +1,57 @@ + +
    + +
    +
    +

    {{watcher}}

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Time ({{timezone}})LevelCoreLoggerMessage
    {{ timezone == "UTC" ? event.utc_time : event.local_time }}{{ event.level }} {{event.showTrace}}{{ event.core }}{{event.loggerBase}}{{ event.message }}
    {{event.trace}}
    No Events available
    + +
    +
    diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/login.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/login.html new file mode 100755 index 0000000000..29c8c71501 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/login.html @@ -0,0 +1,160 @@ + +
    + +
    +

    Basic Authentication

    + +
    +

    + Solr requires authentication for resource {{authLocation === '/' ? 'Dashboard' : authLocation}}.
    + Please log in with your username and password for realm {{authRealm}}. +

    +
    +
    {{error}}
    +
    +
    + + + Username is required +
    +
    + + + Password is required +
    +
    +
    + +
    +
    +
    + +
    +

    + Logged in as user {{authLoggedinUser}}. Realm={{authRealm}}.
    +

    +
    +
    +
    + +
    +
    +
    + +
    + +
    +

    Kerberos Authentication

    +

    Your browser did not provide the required information to authenticate using Kerberos. + Please check that your computer has a valid ticket for communicating with Solr, + and that your browser is properly configured to provide that ticket when required. + For more information, consult + + Solr's Kerberos documentation + . +

    + The response from the server was: +
    +
    HTTP 401 {{statusText}}
    +WWW-Authenticate: {{wwwAuthHeader}}
    +
    +
    + +
    +

    OpenID Connect (JWT) authentication

    + +
    + Callback from ID Provider received. +

    + There were errors during login with ID Provider. Please try again.
    +

    +
    +
    +

    + Solr requires authentication for resource {{authLocation === '/' ? 'Dashboard' : authLocation}}. +

    +
    +

    + Please log in with your Identity Provider (IdP) for realm {{authRealm}}. +

    +

    + Clicking the button below, you will be redirected to the authorization endpoint of the ID provider:
    + {{authData['authorizationEndpoint']}} +

    +
    +
    {{error}}
    +
    +
    + +
    +
    +
    +
    +

    + In order to log in to the identity provider, you need to load this page from the Solr node registered as callback node:
    + {{jwtFindLoginNode()}}
    + After successful login you will be able to navigate to other nodes. +

    +

    +

    +
    + +
    +
    +

    +
    + +
    + +
    +

    + Logged in as user {{authLoggedinUser}}. Realm={{authRealm}}.
    +

    +
    +
    +
    + +
    +
    +
    + +
    + +
    +

    Authentication scheme not supported

    + + + +

    Some or all Solr operations are protected by an authentication scheme that is not yet supported by this Admin UI ({{authScheme}}).

    +

    Solr returned an error response: +


    +
    HTTP 401 {{statusText}}
    +WWW-Authenticate: {{wwwAuthHeader}}
    +
    +

    +

    A possible workaround may be to use another client that supports this scheme.

    +
    +
    diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/plugins.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/plugins.html new file mode 100755 index 0000000000..aaa424d3b8 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/plugins.html @@ -0,0 +1,72 @@ + +
    + +
    +
      +
    • + + {{ plugin.name }} + +
        +
      • +
        +
        {{ key }}:
        + +
        {{value}}
        +
        +
      • +
      • + stats: +
          +
        • +
          +
          {{key}}:
          +
          {{value}}
          +
          +
        • +
        +
      • +
      +
    +
    + + + +
    +
    + +

    Watching for Changes

    + + +
    +
    +
    + +
    diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/query.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/query.html new file mode 100755 index 0000000000..3d329ea77e --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/query.html @@ -0,0 +1,369 @@ + +
    + +
    +
    + + + +
    + common +
    + + + + + +
    +
    + +
    + + +
    +
    +
    + + + + + +
    + + +
    + + + + + + + + + + + + + + + +
    +
    + +
    + + + +
    + + + +
    +
    + +
    + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    + + + +
    + + + + + + + + + + + + + + + + +
    +
    + +
    + + + +
    + + + + + + + + + + +
    +
    + +
    + + + +
    + + + + + + + + + + +
    +
    + +
    + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    +
    + +
    + + {{hostPortContext}}{{url}} + +
    +
    +
    + +
    + +
    diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/replication.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/replication.html new file mode 100755 index 0000000000..b3d668422a --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/replication.html @@ -0,0 +1,239 @@ + +
    + +
    + +
    {{ progress.ERROR }}
    + +
    + +
    + +
    + + {{progress.replicationStartTime}} + +
    + +
    + + 5.1 MB/s + +
    + +
    + +
    + +
    {{progress.numFilesToDownload}} Files
    +
    {{progress.bytesToDownload}}
    + +
    + +
    + + ETA: {{progress.timeRemaining | readableSeconds }} + +
    + +
    + +
    + + {{progress.totalPercent}}% + +
    + +
    + +
    {{progress.numFilesDownloaded}} Files
    +
    {{progress.bytesDownloaded}}
    + +
    + +
    + +
    + +
    + +
    + +
    Current File:
    +
    {{progress.currentFile}}
    +
    + {{progress.currentFileSizeDownloaded}} / {{progress.currentFileSize}} [{{progress.currentFileSizePercent}}%] +
    + +
    + +
    + +
    + +
    Iterations:
    +
    +
      +
    • {{iteration.date}}
    • +
    + + Show all Iterations + Hide past Iterations + + +
    + +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    IndexVersionGenSize
    Master (Searching) +
    {{versions.masterSearch.version}}
    +
    +
    {{versions.masterSearch.generation}}
    +
    +
    {{versions.masterSearch.size}}
    +
    Master (Replicable) +
    {{versions.master.version}}
    +
    +
    {{versions.master.generation}}
    +
    +
    {{versions.master.size}}
    +
    Slave (Searching) +
    {{versions.slave.version}}
    +
    +
    {{versions.slave.generation}}
    +
    +
    {{versions.slave.size}}
    +
    + +
    + +
    + +
    Settings:
    +
      +
    • +
      +
      master url:
      +
      {{settings.masterUrl}}
      +
      +
    • +
    • +
      polling enable:
      +
      + (interval: {{settings.pollInterval}})  +
      +
    • +
    + +
    + +
    + +
    Settings (Master):
    +
      +
    • +
      replication enable:
      +
       
      +
    • +
    • +
      replicateAfter:
      +
      {{master.replicateAfter}}
      +
    • +
    • +
      confFiles:
      +
      {{file.name}}{{ $last ? '' :', '}}
      +
    • +
    + +
    + +
    + + + +
    diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/schema.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/schema.html new file mode 100755 index 0000000000..e94b6dab47 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/schema.html @@ -0,0 +1,455 @@ + +
    + +
    + +
    +
    + + + + +
    + +

    +

    + +

    + +

    + +

    +

    + +

    + +

    + +

    + +

    + +

    + +

    + +

    + +

    + +

    + +

    + +

    + +

    + +

    + + Show omit options + Hide omit options + +

    + +
    + +

    + +

    + +

    + +

    + +

    + +

    +
    + +

    + + Show term vector options + Hide term vector options + +

    +
    + +

    + +

    + +

    + +

    + +

    + +

    + +

    + +

    + +
    + +

    + + Show sort options + Show sort options + +

    +
    +

    + +

    + +

    + +

    + +
    + +
    + {{error}}
    + +

    + + + +

    + + + +
    + +
    + +
    + +

    +

    + +

    +

    + +
    + {{error}}
    + +

    + + +

    + +
    + +
    +
    + +
    + +
    + +
    + +
    +

    + {{selectedType}}: + {{name}} +

    +
    + +
    + +

    Because your Index is empty, we do not have enough Information about this Field

    + +
    + +
    + +
    Field-Type:
    +
    {{analysis.data.className}}
    + +
    Similarity:
    +
    {{ display.similarity.details }}
    + +
    PI Gap:
    +
    {{ display.positionIncrementGap }}
    + +
    Docs:
    +
    {{display.docs | number}}
    + +
    Distinct:
    +
    {{display.distinct}}
    + +
    + + + + + + + + + + + + + + + + + + + + + +
    Flags:{{key.name}}
    {{row.name}}{{row.comment}} + +   +
    + + + +
    + +
    + +
    + + +
    + N.B. Loaded from a single core - not from the whole collection. + + Autoload + +
    + +

    Sorry, no Term Info available :(

    + +
    + +
    +

    + + /{{termInfo.maxTerms | number}} Top-Terms: + Query  +

    +
    + +
      +
    • +

      {{countGroup.count}}

      + +
    • + +
    + +
    + +
    + +

    Histogram:

    +
      +
    • +
      +
      {{ row.key | number}}
      +
      {{ row.value | number }}
      +
      +
    • + +
    + +
    + +
    + +
    + +
    + + +
    + +
    + +
    diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/segments.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/segments.html new file mode 100755 index 0000000000..e1174aba56 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/segments.html @@ -0,0 +1,99 @@ + +
    +
    + +
    + +

    Segments

    +

    Auto-Refresh

    + reload + +
    +
    +
    + +
    + +
    + +
    + +
    + +
      +
    • +
      +
      +
      Size
      +
      +
      +
      0
      +
      + {{x.value}} +   +
      +
      {{segmentMB | number}} MB
      +
      +
      +
    • +
    • +
      +
      +
      {{ segment.name }}
      +
      +
      +
       
      +
      +
      Segment {{segment.name}}:
      +
      #docs:
      +
      {{ segment.size | number }}
      +
      #dels:
      +
      {{ segment.delCount | number }}
      +
      size:
      +
      {{ segment.sizeInBytes | number }} bytes
      +
      age:
      +
      {{ segment.age }}
      +
      source:
      +
      {{ segment.source }}
      +
      +
      +  
      +
      +
      +
    • +
    • +
      +
      +
      Deletions: {{ deletionsPercentage }}%
      +
      +
    • +
    + +
    + +
    + +
    +
    +
    + +
    + +
    diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/stream.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/stream.html new file mode 100755 index 0000000000..683cf76d94 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/stream.html @@ -0,0 +1,64 @@ + +
    + +
    +
    + + + + + + + +
    +
    + +
    + + {{hostPortContext}}{{url}} + +
    +
    +
    +
    + + + Stream Decorator + + Stream Source + + Graph Source + + Datastore + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + +
    diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/threads.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/threads.html new file mode 100755 index 0000000000..f1e6fdeb29 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/threads.html @@ -0,0 +1,65 @@ + +
    + + + +
    + + + + + + + + + + + + + + + + + + + + + +
    namecpuTime / userTime
    + {{thread.name}} ({{thread.id}}) +

    {{thread.lock}}

    +
    +
      +
    • {{trace.trace}}
    • +
    +
    +
    {{thread.cpuTime}}
    {{thread.userTime}}
    + +
    + + + +
    diff --git a/KeywordSearch/solr/server/solr-webapp/webapp/partials/unknown.html b/KeywordSearch/solr/server/solr-webapp/webapp/partials/unknown.html new file mode 100755 index 0000000000..51895ab8b5 --- /dev/null +++ b/KeywordSearch/solr/server/solr-webapp/webapp/partials/unknown.html @@ -0,0 +1,23 @@ + +
    + +
    + Oops, this URL is unknown to us, redirecting you back to Dashboard +
    + +
    diff --git a/KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/admin-extra.html b/KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/admin-extra.html old mode 100644 new mode 100755 similarity index 100% rename from KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/admin-extra.html rename to KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/admin-extra.html diff --git a/KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/elevate.xml b/KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/elevate.xml old mode 100644 new mode 100755 similarity index 100% rename from KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/elevate.xml rename to KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/elevate.xml diff --git a/KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/lang/stoptags_ja.txt b/KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/lang/stoptags_ja.txt similarity index 100% rename from KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/lang/stoptags_ja.txt rename to KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/lang/stoptags_ja.txt diff --git a/KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/lang/stopwords_ja.txt b/KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/lang/stopwords_ja.txt similarity index 100% rename from KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/lang/stopwords_ja.txt rename to KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/lang/stopwords_ja.txt diff --git a/KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/logging-development.properties b/KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/logging-development.properties old mode 100644 new mode 100755 similarity index 100% rename from KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/logging-development.properties rename to KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/logging-development.properties diff --git a/KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/logging-release.properties b/KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/logging-release.properties old mode 100644 new mode 100755 similarity index 100% rename from KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/logging-release.properties rename to KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/logging-release.properties diff --git a/KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/mapping-FoldToASCII.txt b/KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/mapping-FoldToASCII.txt old mode 100644 new mode 100755 similarity index 100% rename from KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/mapping-FoldToASCII.txt rename to KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/mapping-FoldToASCII.txt diff --git a/KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/mapping-ISOLatin1Accent.txt b/KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/mapping-ISOLatin1Accent.txt old mode 100644 new mode 100755 similarity index 100% rename from KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/mapping-ISOLatin1Accent.txt rename to KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/mapping-ISOLatin1Accent.txt diff --git a/KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/protwords.txt b/KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/protwords.txt old mode 100644 new mode 100755 similarity index 100% rename from KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/protwords.txt rename to KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/protwords.txt diff --git a/KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/schema.xml b/KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/schema.xml new file mode 100755 index 0000000000..3bebad7be7 --- /dev/null +++ b/KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/schema.xml @@ -0,0 +1,702 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + id + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/scripts.conf b/KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/scripts.conf old mode 100644 new mode 100755 similarity index 100% rename from KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/scripts.conf rename to KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/scripts.conf diff --git a/KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/solrconfig.xml b/KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/solrconfig.xml new file mode 100755 index 0000000000..9fde79cd36 --- /dev/null +++ b/KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/solrconfig.xml @@ -0,0 +1,1789 @@ + + + + + + + + + 8.6.3 + + + + + + + + + + + + + + + + + + + + + + + + ${solr.data.dir:} + + + + + + + + + + + + + 10000 + + + false + + + 256 + + + + + + + + + + + + native + + + + + + true + + + + + + + 1 + + 0 + + + + + + false + + + + + + + + + + + + + + + + 300000 + + true + + + + + + + + + + + + + ${solr.ulog.dir:} + ${solr.ulog.numVersionBuckets:65536} + + + + + + + + + + + + + 3000 + + + 1024 + + + + + + + + + + + + + + + + + + + + + + true + + + + + + 5 + + + 16 + + + + + + + + + + + + static firstSearcher warming in solrconfig.xml + + + + + + false + + + 2 + + + + + + + + + + + + + + + + + + + + + + + explicit + 10 + text + + + + + + + + + + + + + + explicit + json + true + text + + + + + + + + true + json + true + + + + + + + + explicit + + + velocity + browse + layout + Solritas + + + edismax + + text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4 + title^10.0 description^5.0 keywords^5.0 author^2.0 resourcename^1.0 + + text + 100% + *:* + 10 + *,score + + + text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4 + title^10.0 description^5.0 keywords^5.0 author^2.0 resourcename^1.0 + + text,features,name,sku,id,manu,cat,title,description,keywords,author,resourcename + 3 + + + + + + on + text content file_name + html + 0 + file_name + + <b> + </b> + 0 + title + + 3 + 200 + content + 750 + + + + + + + + + spellcheck + + + + + + + + + + + + + + + + + application/json + + + + + application/csv + + + + + + + true + ignored_ + + + true + links + ignored_ + + + + + + + + + + + + + + + + + + + + + + + + search + solrpingquery + + + all + + + + + + + + + explicit + true + + + + + + + + + + + + + + + + textSpell + + + + + + default + name + solr.DirectSolrSpellChecker + + internal + + 0.5 + + 2 + + 1 + + 5 + + 4 + + 0.01 + + + + + + wordbreak + solr.WordBreakSolrSpellChecker + name + true + true + 10 + + + + + + + + + + + + + + + + text + + default + wordbreak + on + true + 10 + 5 + 5 + true + true + 10 + 5 + + + spellcheck + + + + + + + + + + text + true + + + tvComponent + + + + + + + + + default + + + org.carrot2.clustering.lingo.LingoClusteringAlgorithm + + + 20 + + + clustering/carrot2 + + + ENGLISH + + + stc + org.carrot2.clustering.stc.STCClusteringAlgorithm + + + + + + + true + default + true + + name + id + + features + + true + + + + false + + edismax + + text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4 + + *:* + 10 + *,score + + + clustering + + + + + + + + + + true + false + + + terms + + + + + + + + string + elevate.xml + + + + + + explicit + text + + + elevator + + + + + + + + + + + 100 + + + + + + + + 70 + + 0.5 + + [-\w ,/\n\"']{20,200} + + + + + + + ]]> + ]]> + + + + + + + + + + + + + + + + + + + + + + + + ,, + ,, + ,, + ,, + ,]]> + ]]> + + + + + + 10 + .,!? + + + + + + + WORD + + + en + US + + + + + + + + + + + + + + + + + + + + + + text/plain; charset=UTF-8 + + + + + + + + + 5 + + + + + + + + + + + + + + + + + + *:* + + + diff --git a/KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/spellings.txt b/KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/spellings.txt old mode 100644 new mode 100755 similarity index 100% rename from KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/spellings.txt rename to KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/spellings.txt diff --git a/KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/stopwords.txt b/KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/stopwords.txt old mode 100644 new mode 100755 similarity index 100% rename from KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/stopwords.txt rename to KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/stopwords.txt diff --git a/KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/stopwords_en.txt b/KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/stopwords_en.txt old mode 100644 new mode 100755 similarity index 100% rename from KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/stopwords_en.txt rename to KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/stopwords_en.txt diff --git a/KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/synonyms.txt b/KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/synonyms.txt old mode 100644 new mode 100755 similarity index 100% rename from KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/synonyms.txt rename to KeywordSearch/solr/server/solr/configsets/AutopsyConfig/conf/synonyms.txt diff --git a/KeywordSearch/solr/server/solr/solr.xml b/KeywordSearch/solr/server/solr/solr.xml new file mode 100755 index 0000000000..1341e89836 --- /dev/null +++ b/KeywordSearch/solr/server/solr/solr.xml @@ -0,0 +1,58 @@ + + + + + + + + ${solr.max.booleanClauses:1024} + ${solr.sharedLib:} + ${solr.allowPaths:*} + + + + ${host:} + ${jetty.port:8983} + ${hostContext:solr} + + ${genericCoreNodeNames:true} + + ${zkClientTimeout:60000} + ${distribUpdateSoTimeout:600000} + ${distribUpdateConnTimeout:600000} + ${zkCredentialsProvider:org.apache.solr.common.cloud.DefaultZkCredentialsProvider} + ${zkACLProvider:org.apache.solr.common.cloud.DefaultZkACLProvider} + + + + + ${socketTimeout:600000} + ${connTimeout:600000} + ${solr.shardsWhitelist:} + + + diff --git a/KeywordSearch/solr/server/solr/zoo.cfg b/KeywordSearch/solr/server/solr/zoo.cfg new file mode 100755 index 0000000000..d0cfaefbf8 --- /dev/null +++ b/KeywordSearch/solr/server/solr/zoo.cfg @@ -0,0 +1,34 @@ +# The number of milliseconds of each tick +tickTime=2000 +# The number of ticks that the initial +# synchronization phase can take +initLimit=10 +# The number of ticks that can pass between +# sending a request and getting an acknowledgement +syncLimit=5 + +# the directory where the snapshot is stored. +# dataDir=/opt/zookeeper/data +# NOTE: Solr defaults the dataDir to /zoo_data + +# the port at which the clients will connect +# clientPort=2181 +# NOTE: Solr sets this based on zkRun / zkHost params + +# the maximum number of client connections. +# increase this if you need to handle more clients +#maxClientCnxns=60 +# +# Be sure to read the maintenance section of the +# administrator guide before turning on autopurge. +# +# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance +# +# The number of snapshots to retain in dataDir +#autopurge.snapRetainCount=3 +# Purge task interval in hours +# Set to "0" to disable auto purge feature +#autopurge.purgeInterval=1 + +# Disable ZK AdminServer since we do not use it +admin.enableServer=false diff --git a/KeywordSearch/solr/server/start.jar b/KeywordSearch/solr/server/start.jar new file mode 100755 index 0000000000..49aa128dd7 Binary files /dev/null and b/KeywordSearch/solr/server/start.jar differ diff --git a/KeywordSearch/solr/contexts/solr-jetty-context.xml b/KeywordSearch/solr4/contexts/solr-jetty-context.xml old mode 100644 new mode 100755 similarity index 100% rename from KeywordSearch/solr/contexts/solr-jetty-context.xml rename to KeywordSearch/solr4/contexts/solr-jetty-context.xml diff --git a/KeywordSearch/solr/etc/jetty.xml b/KeywordSearch/solr4/etc/jetty.xml old mode 100644 new mode 100755 similarity index 100% rename from KeywordSearch/solr/etc/jetty.xml rename to KeywordSearch/solr4/etc/jetty.xml diff --git a/KeywordSearch/solr/etc/webdefault.xml b/KeywordSearch/solr4/etc/webdefault.xml old mode 100644 new mode 100755 similarity index 100% rename from KeywordSearch/solr/etc/webdefault.xml rename to KeywordSearch/solr4/etc/webdefault.xml diff --git a/KeywordSearch/solr/resources/log4j.properties b/KeywordSearch/solr4/resources/log4j.properties old mode 100644 new mode 100755 similarity index 100% rename from KeywordSearch/solr/resources/log4j.properties rename to KeywordSearch/solr4/resources/log4j.properties diff --git a/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/admin-extra.html b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/admin-extra.html new file mode 100755 index 0000000000..aa739da862 --- /dev/null +++ b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/admin-extra.html @@ -0,0 +1,31 @@ + + + diff --git a/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/elevate.xml b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/elevate.xml new file mode 100755 index 0000000000..7630ebe20f --- /dev/null +++ b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/elevate.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + diff --git a/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/lang/stoptags_ja.txt b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/lang/stoptags_ja.txt new file mode 100755 index 0000000000..71b750845e --- /dev/null +++ b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/lang/stoptags_ja.txt @@ -0,0 +1,420 @@ +# +# This file defines a Japanese stoptag set for JapanesePartOfSpeechStopFilter. +# +# Any token with a part-of-speech tag that exactly matches those defined in this +# file are removed from the token stream. +# +# Set your own stoptags by uncommenting the lines below. Note that comments are +# not allowed on the same line as a stoptag. See LUCENE-3745 for frequency lists, +# etc. that can be useful for building you own stoptag set. +# +# The entire possible tagset is provided below for convenience. +# +##### +# noun: unclassified nouns +#名詞 +# +# noun-common: Common nouns or nouns where the sub-classification is undefined +#名詞-一般 +# +# noun-proper: Proper nouns where the sub-classification is undefined +#名詞-固有名詞 +# +# noun-proper-misc: miscellaneous proper nouns +#名詞-固有名詞-一般 +# +# noun-proper-person: Personal names where the sub-classification is undefined +#名詞-固有名詞-人名 +# +# noun-proper-person-misc: names that cannot be divided into surname and +# given name; foreign names; names where the surname or given name is unknown. +# e.g. お市の方 +#名詞-固有名詞-人名-一般 +# +# noun-proper-person-surname: Mainly Japanese surnames. +# e.g. 山田 +#名詞-固有名詞-人名-姓 +# +# noun-proper-person-given_name: Mainly Japanese given names. +# e.g. 太郎 +#名詞-固有名詞-人名-名 +# +# noun-proper-organization: Names representing organizations. +# e.g. 通産省, NHK +#名詞-固有名詞-組織 +# +# noun-proper-place: Place names where the sub-classification is undefined +#名詞-固有名詞-地域 +# +# noun-proper-place-misc: Place names excluding countries. +# e.g. アジア, バルセロナ, 京都 +#名詞-固有名詞-地域-一般 +# +# noun-proper-place-country: Country names. +# e.g. 日本, オーストラリア +#名詞-固有名詞-地域-国 +# +# noun-pronoun: Pronouns where the sub-classification is undefined +#名詞-代名詞 +# +# noun-pronoun-misc: miscellaneous pronouns: +# e.g. それ, ここ, あいつ, あなた, あちこち, いくつ, どこか, なに, みなさん, みんな, わたくし, われわれ +#名詞-代名詞-一般 +# +# noun-pronoun-contraction: Spoken language contraction made by combining a +# pronoun and the particle 'wa'. +# e.g. ありゃ, こりゃ, こりゃあ, そりゃ, そりゃあ +#名詞-代名詞-縮約 +# +# noun-adverbial: Temporal nouns such as names of days or months that behave +# like adverbs. Nouns that represent amount or ratios and can be used adverbially, +# e.g. 金曜, 一月, 午後, 少量 +#名詞-副詞可能 +# +# noun-verbal: Nouns that take arguments with case and can appear followed by +# 'suru' and related verbs (する, できる, なさる, くださる) +# e.g. インプット, 愛着, 悪化, 悪戦苦闘, 一安心, 下取り +#名詞-サ変接続 +# +# noun-adjective-base: The base form of adjectives, words that appear before な ("na") +# e.g. 健康, 安易, 駄目, だめ +#名詞-形容動詞語幹 +# +# noun-numeric: Arabic numbers, Chinese numerals, and counters like 何 (回), 数. +# e.g. 0, 1, 2, 何, 数, 幾 +#名詞-数 +# +# noun-affix: noun affixes where the sub-classification is undefined +#名詞-非自立 +# +# noun-affix-misc: Of adnominalizers, the case-marker の ("no"), and words that +# attach to the base form of inflectional words, words that cannot be classified +# into any of the other categories below. This category includes indefinite nouns. +# e.g. あかつき, 暁, かい, 甲斐, 気, きらい, 嫌い, くせ, 癖, こと, 事, ごと, 毎, しだい, 次第, +# 順, せい, 所為, ついで, 序で, つもり, 積もり, 点, どころ, の, はず, 筈, はずみ, 弾み, +# 拍子, ふう, ふり, 振り, ほう, 方, 旨, もの, 物, 者, ゆえ, 故, ゆえん, 所以, わけ, 訳, +# わり, 割り, 割, ん-口語/, もん-口語/ +#名詞-非自立-一般 +# +# noun-affix-adverbial: noun affixes that that can behave as adverbs. +# e.g. あいだ, 間, あげく, 挙げ句, あと, 後, 余り, 以外, 以降, 以後, 以上, 以前, 一方, うえ, +# 上, うち, 内, おり, 折り, かぎり, 限り, きり, っきり, 結果, ころ, 頃, さい, 際, 最中, さなか, +# 最中, じたい, 自体, たび, 度, ため, 為, つど, 都度, とおり, 通り, とき, 時, ところ, 所, +# とたん, 途端, なか, 中, のち, 後, ばあい, 場合, 日, ぶん, 分, ほか, 他, まえ, 前, まま, +# 儘, 侭, みぎり, 矢先 +#名詞-非自立-副詞可能 +# +# noun-affix-aux: noun affixes treated as 助動詞 ("auxiliary verb") in school grammars +# with the stem よう(だ) ("you(da)"). +# e.g. よう, やう, 様 (よう) +#名詞-非自立-助動詞語幹 +# +# noun-affix-adjective-base: noun affixes that can connect to the indeclinable +# connection form な (aux "da"). +# e.g. みたい, ふう +#名詞-非自立-形容動詞語幹 +# +# noun-special: special nouns where the sub-classification is undefined. +#名詞-特殊 +# +# noun-special-aux: The そうだ ("souda") stem form that is used for reporting news, is +# treated as 助動詞 ("auxiliary verb") in school grammars, and attach to the base +# form of inflectional words. +# e.g. そう +#名詞-特殊-助動詞語幹 +# +# noun-suffix: noun suffixes where the sub-classification is undefined. +#名詞-接尾 +# +# noun-suffix-misc: Of the nouns or stem forms of other parts of speech that connect +# to ガル or タイ and can combine into compound nouns, words that cannot be classified into +# any of the other categories below. In general, this category is more inclusive than +# 接尾語 ("suffix") and is usually the last element in a compound noun. +# e.g. おき, かた, 方, 甲斐 (がい), がかり, ぎみ, 気味, ぐるみ, (~した) さ, 次第, 済 (ず) み, +# よう, (でき)っこ, 感, 観, 性, 学, 類, 面, 用 +#名詞-接尾-一般 +# +# noun-suffix-person: Suffixes that form nouns and attach to person names more often +# than other nouns. +# e.g. 君, 様, 著 +#名詞-接尾-人名 +# +# noun-suffix-place: Suffixes that form nouns and attach to place names more often +# than other nouns. +# e.g. 町, 市, 県 +#名詞-接尾-地域 +# +# noun-suffix-verbal: Of the suffixes that attach to nouns and form nouns, those that +# can appear before スル ("suru"). +# e.g. 化, 視, 分け, 入り, 落ち, 買い +#名詞-接尾-サ変接続 +# +# noun-suffix-aux: The stem form of そうだ (様態) that is used to indicate conditions, +# is treated as 助動詞 ("auxiliary verb") in school grammars, and attach to the +# conjunctive form of inflectional words. +# e.g. そう +#名詞-接尾-助動詞語幹 +# +# noun-suffix-adjective-base: Suffixes that attach to other nouns or the conjunctive +# form of inflectional words and appear before the copula だ ("da"). +# e.g. 的, げ, がち +#名詞-接尾-形容動詞語幹 +# +# noun-suffix-adverbial: Suffixes that attach to other nouns and can behave as adverbs. +# e.g. 後 (ご), 以後, 以降, 以前, 前後, 中, 末, 上, 時 (じ) +#名詞-接尾-副詞可能 +# +# noun-suffix-classifier: Suffixes that attach to numbers and form nouns. This category +# is more inclusive than 助数詞 ("classifier") and includes common nouns that attach +# to numbers. +# e.g. 個, つ, 本, 冊, パーセント, cm, kg, カ月, か国, 区画, 時間, 時半 +#名詞-接尾-助数詞 +# +# noun-suffix-special: Special suffixes that mainly attach to inflecting words. +# e.g. (楽し) さ, (考え) 方 +#名詞-接尾-特殊 +# +# noun-suffix-conjunctive: Nouns that behave like conjunctions and join two words +# together. +# e.g. (日本) 対 (アメリカ), 対 (アメリカ), (3) 対 (5), (女優) 兼 (主婦) +#名詞-接続詞的 +# +# noun-verbal_aux: Nouns that attach to the conjunctive particle て ("te") and are +# semantically verb-like. +# e.g. ごらん, ご覧, 御覧, 頂戴 +#名詞-動詞非自立的 +# +# noun-quotation: text that cannot be segmented into words, proverbs, Chinese poetry, +# dialects, English, etc. Currently, the only entry for 名詞 引用文字列 ("noun quotation") +# is いわく ("iwaku"). +#名詞-引用文字列 +# +# noun-nai_adjective: Words that appear before the auxiliary verb ない ("nai") and +# behave like an adjective. +# e.g. 申し訳, 仕方, とんでも, 違い +#名詞-ナイ形容詞語幹 +# +##### +# prefix: unclassified prefixes +#接頭詞 +# +# prefix-nominal: Prefixes that attach to nouns (including adjective stem forms) +# excluding numerical expressions. +# e.g. お (水), 某 (氏), 同 (社), 故 (~氏), 高 (品質), お (見事), ご (立派) +#接頭詞-名詞接続 +# +# prefix-verbal: Prefixes that attach to the imperative form of a verb or a verb +# in conjunctive form followed by なる/なさる/くださる. +# e.g. お (読みなさい), お (座り) +#接頭詞-動詞接続 +# +# prefix-adjectival: Prefixes that attach to adjectives. +# e.g. お (寒いですねえ), バカ (でかい) +#接頭詞-形容詞接続 +# +# prefix-numerical: Prefixes that attach to numerical expressions. +# e.g. 約, およそ, 毎時 +#接頭詞-数接続 +# +##### +# verb: unclassified verbs +#動詞 +# +# verb-main: +#動詞-自立 +# +# verb-auxiliary: +#動詞-非自立 +# +# verb-suffix: +#動詞-接尾 +# +##### +# adjective: unclassified adjectives +#形容詞 +# +# adjective-main: +#形容詞-自立 +# +# adjective-auxiliary: +#形容詞-非自立 +# +# adjective-suffix: +#形容詞-接尾 +# +##### +# adverb: unclassified adverbs +#副詞 +# +# adverb-misc: Words that can be segmented into one unit and where adnominal +# modification is not possible. +# e.g. あいかわらず, 多分 +#副詞-一般 +# +# adverb-particle_conjunction: Adverbs that can be followed by の, は, に, +# な, する, だ, etc. +# e.g. こんなに, そんなに, あんなに, なにか, なんでも +#副詞-助詞類接続 +# +##### +# adnominal: Words that only have noun-modifying forms. +# e.g. この, その, あの, どの, いわゆる, なんらかの, 何らかの, いろんな, こういう, そういう, ああいう, +# どういう, こんな, そんな, あんな, どんな, 大きな, 小さな, おかしな, ほんの, たいした, +# 「(, も) さる (ことながら)」, 微々たる, 堂々たる, 単なる, いかなる, 我が」「同じ, 亡き +#連体詞 +# +##### +# conjunction: Conjunctions that can occur independently. +# e.g. が, けれども, そして, じゃあ, それどころか +接続詞 +# +##### +# particle: unclassified particles. +助詞 +# +# particle-case: case particles where the subclassification is undefined. +助詞-格助詞 +# +# particle-case-misc: Case particles. +# e.g. から, が, で, と, に, へ, より, を, の, にて +助詞-格助詞-一般 +# +# particle-case-quote: the "to" that appears after nouns, a person’s speech, +# quotation marks, expressions of decisions from a meeting, reasons, judgements, +# conjectures, etc. +# e.g. ( だ) と (述べた.), ( である) と (して執行猶予...) +助詞-格助詞-引用 +# +# particle-case-compound: Compounds of particles and verbs that mainly behave +# like case particles. +# e.g. という, といった, とかいう, として, とともに, と共に, でもって, にあたって, に当たって, に当って, +# にあたり, に当たり, に当り, に当たる, にあたる, において, に於いて,に於て, における, に於ける, +# にかけ, にかけて, にかんし, に関し, にかんして, に関して, にかんする, に関する, に際し, +# に際して, にしたがい, に従い, に従う, にしたがって, に従って, にたいし, に対し, にたいして, +# に対して, にたいする, に対する, について, につき, につけ, につけて, につれ, につれて, にとって, +# にとり, にまつわる, によって, に依って, に因って, により, に依り, に因り, による, に依る, に因る, +# にわたって, にわたる, をもって, を以って, を通じ, を通じて, を通して, をめぐって, をめぐり, をめぐる, +# って-口語/, ちゅう-関西弁「という」/, (何) ていう (人)-口語/, っていう-口語/, といふ, とかいふ +助詞-格助詞-連語 +# +# particle-conjunctive: +# e.g. から, からには, が, けれど, けれども, けど, し, つつ, て, で, と, ところが, どころか, とも, ども, +# ながら, なり, ので, のに, ば, ものの, や ( した), やいなや, (ころん) じゃ(いけない)-口語/, +# (行っ) ちゃ(いけない)-口語/, (言っ) たって (しかたがない)-口語/, (それがなく)ったって (平気)-口語/ +助詞-接続助詞 +# +# particle-dependency: +# e.g. こそ, さえ, しか, すら, は, も, ぞ +助詞-係助詞 +# +# particle-adverbial: +# e.g. がてら, かも, くらい, 位, ぐらい, しも, (学校) じゃ(これが流行っている)-口語/, +# (それ)じゃあ (よくない)-口語/, ずつ, (私) なぞ, など, (私) なり (に), (先生) なんか (大嫌い)-口語/, +# (私) なんぞ, (先生) なんて (大嫌い)-口語/, のみ, だけ, (私) だって-口語/, だに, +# (彼)ったら-口語/, (お茶) でも (いかが), 等 (とう), (今後) とも, ばかり, ばっか-口語/, ばっかり-口語/, +# ほど, 程, まで, 迄, (誰) も (が)([助詞-格助詞] および [助詞-係助詞] の前に位置する「も」) +助詞-副助詞 +# +# particle-interjective: particles with interjective grammatical roles. +# e.g. (松島) や +助詞-間投助詞 +# +# particle-coordinate: +# e.g. と, たり, だの, だり, とか, なり, や, やら +助詞-並立助詞 +# +# particle-final: +# e.g. かい, かしら, さ, ぜ, (だ)っけ-口語/, (とまってる) で-方言/, な, ナ, なあ-口語/, ぞ, ね, ネ, +# ねぇ-口語/, ねえ-口語/, ねん-方言/, の, のう-口語/, や, よ, ヨ, よぉ-口語/, わ, わい-口語/ +助詞-終助詞 +# +# particle-adverbial/conjunctive/final: The particle "ka" when unknown whether it is +# adverbial, conjunctive, or sentence final. For example: +# (a) 「A か B か」. Ex:「(国内で運用する) か,(海外で運用する) か (.)」 +# (b) Inside an adverb phrase. Ex:「(幸いという) か (, 死者はいなかった.)」 +# 「(祈りが届いたせい) か (, 試験に合格した.)」 +# (c) 「かのように」. Ex:「(何もなかった) か (のように振る舞った.)」 +# e.g. か +助詞-副助詞/並立助詞/終助詞 +# +# particle-adnominalizer: The "no" that attaches to nouns and modifies +# non-inflectional words. +助詞-連体化 +# +# particle-adnominalizer: The "ni" and "to" that appear following nouns and adverbs +# that are giongo, giseigo, or gitaigo. +# e.g. に, と +助詞-副詞化 +# +# particle-special: A particle that does not fit into one of the above classifications. +# This includes particles that are used in Tanka, Haiku, and other poetry. +# e.g. かな, けむ, ( しただろう) に, (あんた) にゃ(わからん), (俺) ん (家) +助詞-特殊 +# +##### +# auxiliary-verb: +助動詞 +# +##### +# interjection: Greetings and other exclamations. +# e.g. おはよう, おはようございます, こんにちは, こんばんは, ありがとう, どうもありがとう, ありがとうございます, +# いただきます, ごちそうさま, さよなら, さようなら, はい, いいえ, ごめん, ごめんなさい +#感動詞 +# +##### +# symbol: unclassified Symbols. +記号 +# +# symbol-misc: A general symbol not in one of the categories below. +# e.g. [○◎@$〒→+] +記号-一般 +# +# symbol-comma: Commas +# e.g. [,、] +記号-読点 +# +# symbol-period: Periods and full stops. +# e.g. [..。] +記号-句点 +# +# symbol-space: Full-width whitespace. +記号-空白 +# +# symbol-open_bracket: +# e.g. [({‘“『【] +記号-括弧開 +# +# symbol-close_bracket: +# e.g. [)}’”』」】] +記号-括弧閉 +# +# symbol-alphabetic: +#記号-アルファベット +# +##### +# other: unclassified other +#その他 +# +# other-interjection: Words that are hard to classify as noun-suffixes or +# sentence-final particles. +# e.g. (だ)ァ +その他-間投 +# +##### +# filler: Aizuchi that occurs during a conversation or sounds inserted as filler. +# e.g. あの, うんと, えと +フィラー +# +##### +# non-verbal: non-verbal sound. +非言語音 +# +##### +# fragment: +#語断片 +# +##### +# unknown: unknown part of speech. +#未知語 +# +##### End of file diff --git a/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/lang/stopwords_ja.txt b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/lang/stopwords_ja.txt new file mode 100755 index 0000000000..d4321be6b1 --- /dev/null +++ b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/lang/stopwords_ja.txt @@ -0,0 +1,127 @@ +# +# This file defines a stopword set for Japanese. +# +# This set is made up of hand-picked frequent terms from segmented Japanese Wikipedia. +# Punctuation characters and frequent kanji have mostly been left out. See LUCENE-3745 +# for frequency lists, etc. that can be useful for making your own set (if desired) +# +# Note that there is an overlap between these stopwords and the terms stopped when used +# in combination with the JapanesePartOfSpeechStopFilter. When editing this file, note +# that comments are not allowed on the same line as stopwords. +# +# Also note that stopping is done in a case-insensitive manner. Change your StopFilter +# configuration if you need case-sensitive stopping. Lastly, note that stopping is done +# using the same character width as the entries in this file. Since this StopFilter is +# normally done after a CJKWidthFilter in your chain, you would usually want your romaji +# entries to be in half-width and your kana entries to be in full-width. +# +の +に +は +を +た +が +で +て +と +し +れ +さ +ある +いる +も +する +から +な +こと +として +い +や +れる +など +なっ +ない +この +ため +その +あっ +よう +また +もの +という +あり +まで +られ +なる +へ +か +だ +これ +によって +により +おり +より +による +ず +なり +られる +において +ば +なかっ +なく +しかし +について +せ +だっ +その後 +できる +それ +う +ので +なお +のみ +でき +き +つ +における +および +いう +さらに +でも +ら +たり +その他 +に関する +たち +ます +ん +なら +に対して +特に +せる +及び +これら +とき +では +にて +ほか +ながら +うち +そして +とともに +ただし +かつて +それぞれ +または +お +ほど +ものの +に対する +ほとんど +と共に +といった +です +とも +ところ +ここ +##### End of file diff --git a/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/logging-development.properties b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/logging-development.properties new file mode 100755 index 0000000000..34bb6c9b96 --- /dev/null +++ b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/logging-development.properties @@ -0,0 +1,4 @@ +.level = INFO + +# Write to the console, we will forward it to a file determined at runtime +handlers = java.util.logging.ConsoleHandler \ No newline at end of file diff --git a/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/logging-release.properties b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/logging-release.properties new file mode 100755 index 0000000000..1aaff5afa2 --- /dev/null +++ b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/logging-release.properties @@ -0,0 +1,4 @@ +.level = WARNING + +# Write to the console, we will forward it to a file determined at runtime +handlers = java.util.logging.ConsoleHandler \ No newline at end of file diff --git a/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/mapping-FoldToASCII.txt b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/mapping-FoldToASCII.txt new file mode 100755 index 0000000000..9a84b6eac3 --- /dev/null +++ b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/mapping-FoldToASCII.txt @@ -0,0 +1,3813 @@ +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# This map converts alphabetic, numeric, and symbolic Unicode characters +# which are not in the first 127 ASCII characters (the "Basic Latin" Unicode +# block) into their ASCII equivalents, if one exists. +# +# Characters from the following Unicode blocks are converted; however, only +# those characters with reasonable ASCII alternatives are converted: +# +# - C1 Controls and Latin-1 Supplement: http://www.unicode.org/charts/PDF/U0080.pdf +# - Latin Extended-A: http://www.unicode.org/charts/PDF/U0100.pdf +# - Latin Extended-B: http://www.unicode.org/charts/PDF/U0180.pdf +# - Latin Extended Additional: http://www.unicode.org/charts/PDF/U1E00.pdf +# - Latin Extended-C: http://www.unicode.org/charts/PDF/U2C60.pdf +# - Latin Extended-D: http://www.unicode.org/charts/PDF/UA720.pdf +# - IPA Extensions: http://www.unicode.org/charts/PDF/U0250.pdf +# - Phonetic Extensions: http://www.unicode.org/charts/PDF/U1D00.pdf +# - Phonetic Extensions Supplement: http://www.unicode.org/charts/PDF/U1D80.pdf +# - General Punctuation: http://www.unicode.org/charts/PDF/U2000.pdf +# - Superscripts and Subscripts: http://www.unicode.org/charts/PDF/U2070.pdf +# - Enclosed Alphanumerics: http://www.unicode.org/charts/PDF/U2460.pdf +# - Dingbats: http://www.unicode.org/charts/PDF/U2700.pdf +# - Supplemental Punctuation: http://www.unicode.org/charts/PDF/U2E00.pdf +# - Alphabetic Presentation Forms: http://www.unicode.org/charts/PDF/UFB00.pdf +# - Halfwidth and Fullwidth Forms: http://www.unicode.org/charts/PDF/UFF00.pdf +# +# See: http://en.wikipedia.org/wiki/Latin_characters_in_Unicode +# +# The set of character conversions supported by this map is a superset of +# those supported by the map represented by mapping-ISOLatin1Accent.txt. +# +# See the bottom of this file for the Perl script used to generate the contents +# of this file (without this header) from ASCIIFoldingFilter.java. + + +# Syntax: +# "source" => "target" +# "source".length() > 0 (source cannot be empty.) +# "target".length() >= 0 (target can be empty.) + + +# À [LATIN CAPITAL LETTER A WITH GRAVE] +"\u00C0" => "A" + +# Á [LATIN CAPITAL LETTER A WITH ACUTE] +"\u00C1" => "A" + +#  [LATIN CAPITAL LETTER A WITH CIRCUMFLEX] +"\u00C2" => "A" + +# à [LATIN CAPITAL LETTER A WITH TILDE] +"\u00C3" => "A" + +# Ä [LATIN CAPITAL LETTER A WITH DIAERESIS] +"\u00C4" => "A" + +# Å [LATIN CAPITAL LETTER A WITH RING ABOVE] +"\u00C5" => "A" + +# Ā [LATIN CAPITAL LETTER A WITH MACRON] +"\u0100" => "A" + +# Ă [LATIN CAPITAL LETTER A WITH BREVE] +"\u0102" => "A" + +# Ą [LATIN CAPITAL LETTER A WITH OGONEK] +"\u0104" => "A" + +# Ə http://en.wikipedia.org/wiki/Schwa [LATIN CAPITAL LETTER SCHWA] +"\u018F" => "A" + +# Ǎ [LATIN CAPITAL LETTER A WITH CARON] +"\u01CD" => "A" + +# Ǟ [LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON] +"\u01DE" => "A" + +# Ǡ [LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON] +"\u01E0" => "A" + +# Ǻ [LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE] +"\u01FA" => "A" + +# Ȁ [LATIN CAPITAL LETTER A WITH DOUBLE GRAVE] +"\u0200" => "A" + +# Ȃ [LATIN CAPITAL LETTER A WITH INVERTED BREVE] +"\u0202" => "A" + +# Ȧ [LATIN CAPITAL LETTER A WITH DOT ABOVE] +"\u0226" => "A" + +# Ⱥ [LATIN CAPITAL LETTER A WITH STROKE] +"\u023A" => "A" + +# ᴀ [LATIN LETTER SMALL CAPITAL A] +"\u1D00" => "A" + +# Ḁ [LATIN CAPITAL LETTER A WITH RING BELOW] +"\u1E00" => "A" + +# Ạ [LATIN CAPITAL LETTER A WITH DOT BELOW] +"\u1EA0" => "A" + +# Ả [LATIN CAPITAL LETTER A WITH HOOK ABOVE] +"\u1EA2" => "A" + +# Ấ [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE] +"\u1EA4" => "A" + +# Ầ [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE] +"\u1EA6" => "A" + +# Ẩ [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE] +"\u1EA8" => "A" + +# Ẫ [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE] +"\u1EAA" => "A" + +# Ậ [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW] +"\u1EAC" => "A" + +# Ắ [LATIN CAPITAL LETTER A WITH BREVE AND ACUTE] +"\u1EAE" => "A" + +# Ằ [LATIN CAPITAL LETTER A WITH BREVE AND GRAVE] +"\u1EB0" => "A" + +# Ẳ [LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE] +"\u1EB2" => "A" + +# Ẵ [LATIN CAPITAL LETTER A WITH BREVE AND TILDE] +"\u1EB4" => "A" + +# Ặ [LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW] +"\u1EB6" => "A" + +# Ⓐ [CIRCLED LATIN CAPITAL LETTER A] +"\u24B6" => "A" + +# A [FULLWIDTH LATIN CAPITAL LETTER A] +"\uFF21" => "A" + +# à [LATIN SMALL LETTER A WITH GRAVE] +"\u00E0" => "a" + +# á [LATIN SMALL LETTER A WITH ACUTE] +"\u00E1" => "a" + +# â [LATIN SMALL LETTER A WITH CIRCUMFLEX] +"\u00E2" => "a" + +# ã [LATIN SMALL LETTER A WITH TILDE] +"\u00E3" => "a" + +# ä [LATIN SMALL LETTER A WITH DIAERESIS] +"\u00E4" => "a" + +# å [LATIN SMALL LETTER A WITH RING ABOVE] +"\u00E5" => "a" + +# ā [LATIN SMALL LETTER A WITH MACRON] +"\u0101" => "a" + +# ă [LATIN SMALL LETTER A WITH BREVE] +"\u0103" => "a" + +# ą [LATIN SMALL LETTER A WITH OGONEK] +"\u0105" => "a" + +# ǎ [LATIN SMALL LETTER A WITH CARON] +"\u01CE" => "a" + +# ǟ [LATIN SMALL LETTER A WITH DIAERESIS AND MACRON] +"\u01DF" => "a" + +# ǡ [LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON] +"\u01E1" => "a" + +# ǻ [LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE] +"\u01FB" => "a" + +# ȁ [LATIN SMALL LETTER A WITH DOUBLE GRAVE] +"\u0201" => "a" + +# ȃ [LATIN SMALL LETTER A WITH INVERTED BREVE] +"\u0203" => "a" + +# ȧ [LATIN SMALL LETTER A WITH DOT ABOVE] +"\u0227" => "a" + +# ɐ [LATIN SMALL LETTER TURNED A] +"\u0250" => "a" + +# ə [LATIN SMALL LETTER SCHWA] +"\u0259" => "a" + +# ɚ [LATIN SMALL LETTER SCHWA WITH HOOK] +"\u025A" => "a" + +# ᶏ [LATIN SMALL LETTER A WITH RETROFLEX HOOK] +"\u1D8F" => "a" + +# ᶕ [LATIN SMALL LETTER SCHWA WITH RETROFLEX HOOK] +"\u1D95" => "a" + +# ạ [LATIN SMALL LETTER A WITH RING BELOW] +"\u1E01" => "a" + +# ả [LATIN SMALL LETTER A WITH RIGHT HALF RING] +"\u1E9A" => "a" + +# ạ [LATIN SMALL LETTER A WITH DOT BELOW] +"\u1EA1" => "a" + +# ả [LATIN SMALL LETTER A WITH HOOK ABOVE] +"\u1EA3" => "a" + +# ấ [LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE] +"\u1EA5" => "a" + +# ầ [LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE] +"\u1EA7" => "a" + +# ẩ [LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE] +"\u1EA9" => "a" + +# ẫ [LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE] +"\u1EAB" => "a" + +# ậ [LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW] +"\u1EAD" => "a" + +# ắ [LATIN SMALL LETTER A WITH BREVE AND ACUTE] +"\u1EAF" => "a" + +# ằ [LATIN SMALL LETTER A WITH BREVE AND GRAVE] +"\u1EB1" => "a" + +# ẳ [LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE] +"\u1EB3" => "a" + +# ẵ [LATIN SMALL LETTER A WITH BREVE AND TILDE] +"\u1EB5" => "a" + +# ặ [LATIN SMALL LETTER A WITH BREVE AND DOT BELOW] +"\u1EB7" => "a" + +# ₐ [LATIN SUBSCRIPT SMALL LETTER A] +"\u2090" => "a" + +# ₔ [LATIN SUBSCRIPT SMALL LETTER SCHWA] +"\u2094" => "a" + +# ⓐ [CIRCLED LATIN SMALL LETTER A] +"\u24D0" => "a" + +# ⱥ [LATIN SMALL LETTER A WITH STROKE] +"\u2C65" => "a" + +# Ɐ [LATIN CAPITAL LETTER TURNED A] +"\u2C6F" => "a" + +# a [FULLWIDTH LATIN SMALL LETTER A] +"\uFF41" => "a" + +# Ꜳ [LATIN CAPITAL LETTER AA] +"\uA732" => "AA" + +# Æ [LATIN CAPITAL LETTER AE] +"\u00C6" => "AE" + +# Ǣ [LATIN CAPITAL LETTER AE WITH MACRON] +"\u01E2" => "AE" + +# Ǽ [LATIN CAPITAL LETTER AE WITH ACUTE] +"\u01FC" => "AE" + +# ᴁ [LATIN LETTER SMALL CAPITAL AE] +"\u1D01" => "AE" + +# Ꜵ [LATIN CAPITAL LETTER AO] +"\uA734" => "AO" + +# Ꜷ [LATIN CAPITAL LETTER AU] +"\uA736" => "AU" + +# Ꜹ [LATIN CAPITAL LETTER AV] +"\uA738" => "AV" + +# Ꜻ [LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR] +"\uA73A" => "AV" + +# Ꜽ [LATIN CAPITAL LETTER AY] +"\uA73C" => "AY" + +# ⒜ [PARENTHESIZED LATIN SMALL LETTER A] +"\u249C" => "(a)" + +# ꜳ [LATIN SMALL LETTER AA] +"\uA733" => "aa" + +# æ [LATIN SMALL LETTER AE] +"\u00E6" => "ae" + +# ǣ [LATIN SMALL LETTER AE WITH MACRON] +"\u01E3" => "ae" + +# ǽ [LATIN SMALL LETTER AE WITH ACUTE] +"\u01FD" => "ae" + +# ᴂ [LATIN SMALL LETTER TURNED AE] +"\u1D02" => "ae" + +# ꜵ [LATIN SMALL LETTER AO] +"\uA735" => "ao" + +# ꜷ [LATIN SMALL LETTER AU] +"\uA737" => "au" + +# ꜹ [LATIN SMALL LETTER AV] +"\uA739" => "av" + +# ꜻ [LATIN SMALL LETTER AV WITH HORIZONTAL BAR] +"\uA73B" => "av" + +# ꜽ [LATIN SMALL LETTER AY] +"\uA73D" => "ay" + +# Ɓ [LATIN CAPITAL LETTER B WITH HOOK] +"\u0181" => "B" + +# Ƃ [LATIN CAPITAL LETTER B WITH TOPBAR] +"\u0182" => "B" + +# Ƀ [LATIN CAPITAL LETTER B WITH STROKE] +"\u0243" => "B" + +# ʙ [LATIN LETTER SMALL CAPITAL B] +"\u0299" => "B" + +# ᴃ [LATIN LETTER SMALL CAPITAL BARRED B] +"\u1D03" => "B" + +# Ḃ [LATIN CAPITAL LETTER B WITH DOT ABOVE] +"\u1E02" => "B" + +# Ḅ [LATIN CAPITAL LETTER B WITH DOT BELOW] +"\u1E04" => "B" + +# Ḇ [LATIN CAPITAL LETTER B WITH LINE BELOW] +"\u1E06" => "B" + +# Ⓑ [CIRCLED LATIN CAPITAL LETTER B] +"\u24B7" => "B" + +# B [FULLWIDTH LATIN CAPITAL LETTER B] +"\uFF22" => "B" + +# ƀ [LATIN SMALL LETTER B WITH STROKE] +"\u0180" => "b" + +# ƃ [LATIN SMALL LETTER B WITH TOPBAR] +"\u0183" => "b" + +# ɓ [LATIN SMALL LETTER B WITH HOOK] +"\u0253" => "b" + +# ᵬ [LATIN SMALL LETTER B WITH MIDDLE TILDE] +"\u1D6C" => "b" + +# ᶀ [LATIN SMALL LETTER B WITH PALATAL HOOK] +"\u1D80" => "b" + +# ḃ [LATIN SMALL LETTER B WITH DOT ABOVE] +"\u1E03" => "b" + +# ḅ [LATIN SMALL LETTER B WITH DOT BELOW] +"\u1E05" => "b" + +# ḇ [LATIN SMALL LETTER B WITH LINE BELOW] +"\u1E07" => "b" + +# ⓑ [CIRCLED LATIN SMALL LETTER B] +"\u24D1" => "b" + +# b [FULLWIDTH LATIN SMALL LETTER B] +"\uFF42" => "b" + +# ⒝ [PARENTHESIZED LATIN SMALL LETTER B] +"\u249D" => "(b)" + +# Ç [LATIN CAPITAL LETTER C WITH CEDILLA] +"\u00C7" => "C" + +# Ć [LATIN CAPITAL LETTER C WITH ACUTE] +"\u0106" => "C" + +# Ĉ [LATIN CAPITAL LETTER C WITH CIRCUMFLEX] +"\u0108" => "C" + +# Ċ [LATIN CAPITAL LETTER C WITH DOT ABOVE] +"\u010A" => "C" + +# Č [LATIN CAPITAL LETTER C WITH CARON] +"\u010C" => "C" + +# Ƈ [LATIN CAPITAL LETTER C WITH HOOK] +"\u0187" => "C" + +# Ȼ [LATIN CAPITAL LETTER C WITH STROKE] +"\u023B" => "C" + +# ʗ [LATIN LETTER STRETCHED C] +"\u0297" => "C" + +# ᴄ [LATIN LETTER SMALL CAPITAL C] +"\u1D04" => "C" + +# Ḉ [LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE] +"\u1E08" => "C" + +# Ⓒ [CIRCLED LATIN CAPITAL LETTER C] +"\u24B8" => "C" + +# C [FULLWIDTH LATIN CAPITAL LETTER C] +"\uFF23" => "C" + +# ç [LATIN SMALL LETTER C WITH CEDILLA] +"\u00E7" => "c" + +# ć [LATIN SMALL LETTER C WITH ACUTE] +"\u0107" => "c" + +# ĉ [LATIN SMALL LETTER C WITH CIRCUMFLEX] +"\u0109" => "c" + +# ċ [LATIN SMALL LETTER C WITH DOT ABOVE] +"\u010B" => "c" + +# č [LATIN SMALL LETTER C WITH CARON] +"\u010D" => "c" + +# ƈ [LATIN SMALL LETTER C WITH HOOK] +"\u0188" => "c" + +# ȼ [LATIN SMALL LETTER C WITH STROKE] +"\u023C" => "c" + +# ɕ [LATIN SMALL LETTER C WITH CURL] +"\u0255" => "c" + +# ḉ [LATIN SMALL LETTER C WITH CEDILLA AND ACUTE] +"\u1E09" => "c" + +# ↄ [LATIN SMALL LETTER REVERSED C] +"\u2184" => "c" + +# ⓒ [CIRCLED LATIN SMALL LETTER C] +"\u24D2" => "c" + +# Ꜿ [LATIN CAPITAL LETTER REVERSED C WITH DOT] +"\uA73E" => "c" + +# ꜿ [LATIN SMALL LETTER REVERSED C WITH DOT] +"\uA73F" => "c" + +# c [FULLWIDTH LATIN SMALL LETTER C] +"\uFF43" => "c" + +# ⒞ [PARENTHESIZED LATIN SMALL LETTER C] +"\u249E" => "(c)" + +# Ð [LATIN CAPITAL LETTER ETH] +"\u00D0" => "D" + +# Ď [LATIN CAPITAL LETTER D WITH CARON] +"\u010E" => "D" + +# Đ [LATIN CAPITAL LETTER D WITH STROKE] +"\u0110" => "D" + +# Ɖ [LATIN CAPITAL LETTER AFRICAN D] +"\u0189" => "D" + +# Ɗ [LATIN CAPITAL LETTER D WITH HOOK] +"\u018A" => "D" + +# Ƌ [LATIN CAPITAL LETTER D WITH TOPBAR] +"\u018B" => "D" + +# ᴅ [LATIN LETTER SMALL CAPITAL D] +"\u1D05" => "D" + +# ᴆ [LATIN LETTER SMALL CAPITAL ETH] +"\u1D06" => "D" + +# Ḋ [LATIN CAPITAL LETTER D WITH DOT ABOVE] +"\u1E0A" => "D" + +# Ḍ [LATIN CAPITAL LETTER D WITH DOT BELOW] +"\u1E0C" => "D" + +# Ḏ [LATIN CAPITAL LETTER D WITH LINE BELOW] +"\u1E0E" => "D" + +# Ḑ [LATIN CAPITAL LETTER D WITH CEDILLA] +"\u1E10" => "D" + +# Ḓ [LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW] +"\u1E12" => "D" + +# Ⓓ [CIRCLED LATIN CAPITAL LETTER D] +"\u24B9" => "D" + +# Ꝺ [LATIN CAPITAL LETTER INSULAR D] +"\uA779" => "D" + +# D [FULLWIDTH LATIN CAPITAL LETTER D] +"\uFF24" => "D" + +# ð [LATIN SMALL LETTER ETH] +"\u00F0" => "d" + +# ď [LATIN SMALL LETTER D WITH CARON] +"\u010F" => "d" + +# đ [LATIN SMALL LETTER D WITH STROKE] +"\u0111" => "d" + +# ƌ [LATIN SMALL LETTER D WITH TOPBAR] +"\u018C" => "d" + +# ȡ [LATIN SMALL LETTER D WITH CURL] +"\u0221" => "d" + +# ɖ [LATIN SMALL LETTER D WITH TAIL] +"\u0256" => "d" + +# ɗ [LATIN SMALL LETTER D WITH HOOK] +"\u0257" => "d" + +# ᵭ [LATIN SMALL LETTER D WITH MIDDLE TILDE] +"\u1D6D" => "d" + +# ᶁ [LATIN SMALL LETTER D WITH PALATAL HOOK] +"\u1D81" => "d" + +# ᶑ [LATIN SMALL LETTER D WITH HOOK AND TAIL] +"\u1D91" => "d" + +# ḋ [LATIN SMALL LETTER D WITH DOT ABOVE] +"\u1E0B" => "d" + +# ḍ [LATIN SMALL LETTER D WITH DOT BELOW] +"\u1E0D" => "d" + +# ḏ [LATIN SMALL LETTER D WITH LINE BELOW] +"\u1E0F" => "d" + +# ḑ [LATIN SMALL LETTER D WITH CEDILLA] +"\u1E11" => "d" + +# ḓ [LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW] +"\u1E13" => "d" + +# ⓓ [CIRCLED LATIN SMALL LETTER D] +"\u24D3" => "d" + +# ꝺ [LATIN SMALL LETTER INSULAR D] +"\uA77A" => "d" + +# d [FULLWIDTH LATIN SMALL LETTER D] +"\uFF44" => "d" + +# DŽ [LATIN CAPITAL LETTER DZ WITH CARON] +"\u01C4" => "DZ" + +# DZ [LATIN CAPITAL LETTER DZ] +"\u01F1" => "DZ" + +# Dž [LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON] +"\u01C5" => "Dz" + +# Dz [LATIN CAPITAL LETTER D WITH SMALL LETTER Z] +"\u01F2" => "Dz" + +# ⒟ [PARENTHESIZED LATIN SMALL LETTER D] +"\u249F" => "(d)" + +# ȸ [LATIN SMALL LETTER DB DIGRAPH] +"\u0238" => "db" + +# dž [LATIN SMALL LETTER DZ WITH CARON] +"\u01C6" => "dz" + +# dz [LATIN SMALL LETTER DZ] +"\u01F3" => "dz" + +# ʣ [LATIN SMALL LETTER DZ DIGRAPH] +"\u02A3" => "dz" + +# ʥ [LATIN SMALL LETTER DZ DIGRAPH WITH CURL] +"\u02A5" => "dz" + +# È [LATIN CAPITAL LETTER E WITH GRAVE] +"\u00C8" => "E" + +# É [LATIN CAPITAL LETTER E WITH ACUTE] +"\u00C9" => "E" + +# Ê [LATIN CAPITAL LETTER E WITH CIRCUMFLEX] +"\u00CA" => "E" + +# Ë [LATIN CAPITAL LETTER E WITH DIAERESIS] +"\u00CB" => "E" + +# Ē [LATIN CAPITAL LETTER E WITH MACRON] +"\u0112" => "E" + +# Ĕ [LATIN CAPITAL LETTER E WITH BREVE] +"\u0114" => "E" + +# Ė [LATIN CAPITAL LETTER E WITH DOT ABOVE] +"\u0116" => "E" + +# Ę [LATIN CAPITAL LETTER E WITH OGONEK] +"\u0118" => "E" + +# Ě [LATIN CAPITAL LETTER E WITH CARON] +"\u011A" => "E" + +# Ǝ [LATIN CAPITAL LETTER REVERSED E] +"\u018E" => "E" + +# Ɛ [LATIN CAPITAL LETTER OPEN E] +"\u0190" => "E" + +# Ȅ [LATIN CAPITAL LETTER E WITH DOUBLE GRAVE] +"\u0204" => "E" + +# Ȇ [LATIN CAPITAL LETTER E WITH INVERTED BREVE] +"\u0206" => "E" + +# Ȩ [LATIN CAPITAL LETTER E WITH CEDILLA] +"\u0228" => "E" + +# Ɇ [LATIN CAPITAL LETTER E WITH STROKE] +"\u0246" => "E" + +# ᴇ [LATIN LETTER SMALL CAPITAL E] +"\u1D07" => "E" + +# Ḕ [LATIN CAPITAL LETTER E WITH MACRON AND GRAVE] +"\u1E14" => "E" + +# Ḗ [LATIN CAPITAL LETTER E WITH MACRON AND ACUTE] +"\u1E16" => "E" + +# Ḙ [LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW] +"\u1E18" => "E" + +# Ḛ [LATIN CAPITAL LETTER E WITH TILDE BELOW] +"\u1E1A" => "E" + +# Ḝ [LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE] +"\u1E1C" => "E" + +# Ẹ [LATIN CAPITAL LETTER E WITH DOT BELOW] +"\u1EB8" => "E" + +# Ẻ [LATIN CAPITAL LETTER E WITH HOOK ABOVE] +"\u1EBA" => "E" + +# Ẽ [LATIN CAPITAL LETTER E WITH TILDE] +"\u1EBC" => "E" + +# Ế [LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE] +"\u1EBE" => "E" + +# Ề [LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE] +"\u1EC0" => "E" + +# Ể [LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE] +"\u1EC2" => "E" + +# Ễ [LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE] +"\u1EC4" => "E" + +# Ệ [LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW] +"\u1EC6" => "E" + +# Ⓔ [CIRCLED LATIN CAPITAL LETTER E] +"\u24BA" => "E" + +# ⱻ [LATIN LETTER SMALL CAPITAL TURNED E] +"\u2C7B" => "E" + +# E [FULLWIDTH LATIN CAPITAL LETTER E] +"\uFF25" => "E" + +# è [LATIN SMALL LETTER E WITH GRAVE] +"\u00E8" => "e" + +# é [LATIN SMALL LETTER E WITH ACUTE] +"\u00E9" => "e" + +# ê [LATIN SMALL LETTER E WITH CIRCUMFLEX] +"\u00EA" => "e" + +# ë [LATIN SMALL LETTER E WITH DIAERESIS] +"\u00EB" => "e" + +# ē [LATIN SMALL LETTER E WITH MACRON] +"\u0113" => "e" + +# ĕ [LATIN SMALL LETTER E WITH BREVE] +"\u0115" => "e" + +# ė [LATIN SMALL LETTER E WITH DOT ABOVE] +"\u0117" => "e" + +# ę [LATIN SMALL LETTER E WITH OGONEK] +"\u0119" => "e" + +# ě [LATIN SMALL LETTER E WITH CARON] +"\u011B" => "e" + +# ǝ [LATIN SMALL LETTER TURNED E] +"\u01DD" => "e" + +# ȅ [LATIN SMALL LETTER E WITH DOUBLE GRAVE] +"\u0205" => "e" + +# ȇ [LATIN SMALL LETTER E WITH INVERTED BREVE] +"\u0207" => "e" + +# ȩ [LATIN SMALL LETTER E WITH CEDILLA] +"\u0229" => "e" + +# ɇ [LATIN SMALL LETTER E WITH STROKE] +"\u0247" => "e" + +# ɘ [LATIN SMALL LETTER REVERSED E] +"\u0258" => "e" + +# ɛ [LATIN SMALL LETTER OPEN E] +"\u025B" => "e" + +# ɜ [LATIN SMALL LETTER REVERSED OPEN E] +"\u025C" => "e" + +# ɝ [LATIN SMALL LETTER REVERSED OPEN E WITH HOOK] +"\u025D" => "e" + +# ɞ [LATIN SMALL LETTER CLOSED REVERSED OPEN E] +"\u025E" => "e" + +# ʚ [LATIN SMALL LETTER CLOSED OPEN E] +"\u029A" => "e" + +# ᴈ [LATIN SMALL LETTER TURNED OPEN E] +"\u1D08" => "e" + +# ᶒ [LATIN SMALL LETTER E WITH RETROFLEX HOOK] +"\u1D92" => "e" + +# ᶓ [LATIN SMALL LETTER OPEN E WITH RETROFLEX HOOK] +"\u1D93" => "e" + +# ᶔ [LATIN SMALL LETTER REVERSED OPEN E WITH RETROFLEX HOOK] +"\u1D94" => "e" + +# ḕ [LATIN SMALL LETTER E WITH MACRON AND GRAVE] +"\u1E15" => "e" + +# ḗ [LATIN SMALL LETTER E WITH MACRON AND ACUTE] +"\u1E17" => "e" + +# ḙ [LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW] +"\u1E19" => "e" + +# ḛ [LATIN SMALL LETTER E WITH TILDE BELOW] +"\u1E1B" => "e" + +# ḝ [LATIN SMALL LETTER E WITH CEDILLA AND BREVE] +"\u1E1D" => "e" + +# ẹ [LATIN SMALL LETTER E WITH DOT BELOW] +"\u1EB9" => "e" + +# ẻ [LATIN SMALL LETTER E WITH HOOK ABOVE] +"\u1EBB" => "e" + +# ẽ [LATIN SMALL LETTER E WITH TILDE] +"\u1EBD" => "e" + +# ế [LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE] +"\u1EBF" => "e" + +# ề [LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE] +"\u1EC1" => "e" + +# ể [LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE] +"\u1EC3" => "e" + +# ễ [LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE] +"\u1EC5" => "e" + +# ệ [LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW] +"\u1EC7" => "e" + +# ₑ [LATIN SUBSCRIPT SMALL LETTER E] +"\u2091" => "e" + +# ⓔ [CIRCLED LATIN SMALL LETTER E] +"\u24D4" => "e" + +# ⱸ [LATIN SMALL LETTER E WITH NOTCH] +"\u2C78" => "e" + +# e [FULLWIDTH LATIN SMALL LETTER E] +"\uFF45" => "e" + +# ⒠ [PARENTHESIZED LATIN SMALL LETTER E] +"\u24A0" => "(e)" + +# Ƒ [LATIN CAPITAL LETTER F WITH HOOK] +"\u0191" => "F" + +# Ḟ [LATIN CAPITAL LETTER F WITH DOT ABOVE] +"\u1E1E" => "F" + +# Ⓕ [CIRCLED LATIN CAPITAL LETTER F] +"\u24BB" => "F" + +# ꜰ [LATIN LETTER SMALL CAPITAL F] +"\uA730" => "F" + +# Ꝼ [LATIN CAPITAL LETTER INSULAR F] +"\uA77B" => "F" + +# ꟻ [LATIN EPIGRAPHIC LETTER REVERSED F] +"\uA7FB" => "F" + +# F [FULLWIDTH LATIN CAPITAL LETTER F] +"\uFF26" => "F" + +# ƒ [LATIN SMALL LETTER F WITH HOOK] +"\u0192" => "f" + +# ᵮ [LATIN SMALL LETTER F WITH MIDDLE TILDE] +"\u1D6E" => "f" + +# ᶂ [LATIN SMALL LETTER F WITH PALATAL HOOK] +"\u1D82" => "f" + +# ḟ [LATIN SMALL LETTER F WITH DOT ABOVE] +"\u1E1F" => "f" + +# ẛ [LATIN SMALL LETTER LONG S WITH DOT ABOVE] +"\u1E9B" => "f" + +# ⓕ [CIRCLED LATIN SMALL LETTER F] +"\u24D5" => "f" + +# ꝼ [LATIN SMALL LETTER INSULAR F] +"\uA77C" => "f" + +# f [FULLWIDTH LATIN SMALL LETTER F] +"\uFF46" => "f" + +# ⒡ [PARENTHESIZED LATIN SMALL LETTER F] +"\u24A1" => "(f)" + +# ff [LATIN SMALL LIGATURE FF] +"\uFB00" => "ff" + +# ffi [LATIN SMALL LIGATURE FFI] +"\uFB03" => "ffi" + +# ffl [LATIN SMALL LIGATURE FFL] +"\uFB04" => "ffl" + +# fi [LATIN SMALL LIGATURE FI] +"\uFB01" => "fi" + +# fl [LATIN SMALL LIGATURE FL] +"\uFB02" => "fl" + +# Ĝ [LATIN CAPITAL LETTER G WITH CIRCUMFLEX] +"\u011C" => "G" + +# Ğ [LATIN CAPITAL LETTER G WITH BREVE] +"\u011E" => "G" + +# Ġ [LATIN CAPITAL LETTER G WITH DOT ABOVE] +"\u0120" => "G" + +# Ģ [LATIN CAPITAL LETTER G WITH CEDILLA] +"\u0122" => "G" + +# Ɠ [LATIN CAPITAL LETTER G WITH HOOK] +"\u0193" => "G" + +# Ǥ [LATIN CAPITAL LETTER G WITH STROKE] +"\u01E4" => "G" + +# ǥ [LATIN SMALL LETTER G WITH STROKE] +"\u01E5" => "G" + +# Ǧ [LATIN CAPITAL LETTER G WITH CARON] +"\u01E6" => "G" + +# ǧ [LATIN SMALL LETTER G WITH CARON] +"\u01E7" => "G" + +# Ǵ [LATIN CAPITAL LETTER G WITH ACUTE] +"\u01F4" => "G" + +# ɢ [LATIN LETTER SMALL CAPITAL G] +"\u0262" => "G" + +# ʛ [LATIN LETTER SMALL CAPITAL G WITH HOOK] +"\u029B" => "G" + +# Ḡ [LATIN CAPITAL LETTER G WITH MACRON] +"\u1E20" => "G" + +# Ⓖ [CIRCLED LATIN CAPITAL LETTER G] +"\u24BC" => "G" + +# Ᵹ [LATIN CAPITAL LETTER INSULAR G] +"\uA77D" => "G" + +# Ꝿ [LATIN CAPITAL LETTER TURNED INSULAR G] +"\uA77E" => "G" + +# G [FULLWIDTH LATIN CAPITAL LETTER G] +"\uFF27" => "G" + +# ĝ [LATIN SMALL LETTER G WITH CIRCUMFLEX] +"\u011D" => "g" + +# ğ [LATIN SMALL LETTER G WITH BREVE] +"\u011F" => "g" + +# ġ [LATIN SMALL LETTER G WITH DOT ABOVE] +"\u0121" => "g" + +# ģ [LATIN SMALL LETTER G WITH CEDILLA] +"\u0123" => "g" + +# ǵ [LATIN SMALL LETTER G WITH ACUTE] +"\u01F5" => "g" + +# ɠ [LATIN SMALL LETTER G WITH HOOK] +"\u0260" => "g" + +# ɡ [LATIN SMALL LETTER SCRIPT G] +"\u0261" => "g" + +# ᵷ [LATIN SMALL LETTER TURNED G] +"\u1D77" => "g" + +# ᵹ [LATIN SMALL LETTER INSULAR G] +"\u1D79" => "g" + +# ᶃ [LATIN SMALL LETTER G WITH PALATAL HOOK] +"\u1D83" => "g" + +# ḡ [LATIN SMALL LETTER G WITH MACRON] +"\u1E21" => "g" + +# ⓖ [CIRCLED LATIN SMALL LETTER G] +"\u24D6" => "g" + +# ꝿ [LATIN SMALL LETTER TURNED INSULAR G] +"\uA77F" => "g" + +# g [FULLWIDTH LATIN SMALL LETTER G] +"\uFF47" => "g" + +# ⒢ [PARENTHESIZED LATIN SMALL LETTER G] +"\u24A2" => "(g)" + +# Ĥ [LATIN CAPITAL LETTER H WITH CIRCUMFLEX] +"\u0124" => "H" + +# Ħ [LATIN CAPITAL LETTER H WITH STROKE] +"\u0126" => "H" + +# Ȟ [LATIN CAPITAL LETTER H WITH CARON] +"\u021E" => "H" + +# ʜ [LATIN LETTER SMALL CAPITAL H] +"\u029C" => "H" + +# Ḣ [LATIN CAPITAL LETTER H WITH DOT ABOVE] +"\u1E22" => "H" + +# Ḥ [LATIN CAPITAL LETTER H WITH DOT BELOW] +"\u1E24" => "H" + +# Ḧ [LATIN CAPITAL LETTER H WITH DIAERESIS] +"\u1E26" => "H" + +# Ḩ [LATIN CAPITAL LETTER H WITH CEDILLA] +"\u1E28" => "H" + +# Ḫ [LATIN CAPITAL LETTER H WITH BREVE BELOW] +"\u1E2A" => "H" + +# Ⓗ [CIRCLED LATIN CAPITAL LETTER H] +"\u24BD" => "H" + +# Ⱨ [LATIN CAPITAL LETTER H WITH DESCENDER] +"\u2C67" => "H" + +# Ⱶ [LATIN CAPITAL LETTER HALF H] +"\u2C75" => "H" + +# H [FULLWIDTH LATIN CAPITAL LETTER H] +"\uFF28" => "H" + +# ĥ [LATIN SMALL LETTER H WITH CIRCUMFLEX] +"\u0125" => "h" + +# ħ [LATIN SMALL LETTER H WITH STROKE] +"\u0127" => "h" + +# ȟ [LATIN SMALL LETTER H WITH CARON] +"\u021F" => "h" + +# ɥ [LATIN SMALL LETTER TURNED H] +"\u0265" => "h" + +# ɦ [LATIN SMALL LETTER H WITH HOOK] +"\u0266" => "h" + +# ʮ [LATIN SMALL LETTER TURNED H WITH FISHHOOK] +"\u02AE" => "h" + +# ʯ [LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL] +"\u02AF" => "h" + +# ḣ [LATIN SMALL LETTER H WITH DOT ABOVE] +"\u1E23" => "h" + +# ḥ [LATIN SMALL LETTER H WITH DOT BELOW] +"\u1E25" => "h" + +# ḧ [LATIN SMALL LETTER H WITH DIAERESIS] +"\u1E27" => "h" + +# ḩ [LATIN SMALL LETTER H WITH CEDILLA] +"\u1E29" => "h" + +# ḫ [LATIN SMALL LETTER H WITH BREVE BELOW] +"\u1E2B" => "h" + +# ẖ [LATIN SMALL LETTER H WITH LINE BELOW] +"\u1E96" => "h" + +# ⓗ [CIRCLED LATIN SMALL LETTER H] +"\u24D7" => "h" + +# ⱨ [LATIN SMALL LETTER H WITH DESCENDER] +"\u2C68" => "h" + +# ⱶ [LATIN SMALL LETTER HALF H] +"\u2C76" => "h" + +# h [FULLWIDTH LATIN SMALL LETTER H] +"\uFF48" => "h" + +# Ƕ http://en.wikipedia.org/wiki/Hwair [LATIN CAPITAL LETTER HWAIR] +"\u01F6" => "HV" + +# ⒣ [PARENTHESIZED LATIN SMALL LETTER H] +"\u24A3" => "(h)" + +# ƕ [LATIN SMALL LETTER HV] +"\u0195" => "hv" + +# Ì [LATIN CAPITAL LETTER I WITH GRAVE] +"\u00CC" => "I" + +# Í [LATIN CAPITAL LETTER I WITH ACUTE] +"\u00CD" => "I" + +# Î [LATIN CAPITAL LETTER I WITH CIRCUMFLEX] +"\u00CE" => "I" + +# Ï [LATIN CAPITAL LETTER I WITH DIAERESIS] +"\u00CF" => "I" + +# Ĩ [LATIN CAPITAL LETTER I WITH TILDE] +"\u0128" => "I" + +# Ī [LATIN CAPITAL LETTER I WITH MACRON] +"\u012A" => "I" + +# Ĭ [LATIN CAPITAL LETTER I WITH BREVE] +"\u012C" => "I" + +# Į [LATIN CAPITAL LETTER I WITH OGONEK] +"\u012E" => "I" + +# İ [LATIN CAPITAL LETTER I WITH DOT ABOVE] +"\u0130" => "I" + +# Ɩ [LATIN CAPITAL LETTER IOTA] +"\u0196" => "I" + +# Ɨ [LATIN CAPITAL LETTER I WITH STROKE] +"\u0197" => "I" + +# Ǐ [LATIN CAPITAL LETTER I WITH CARON] +"\u01CF" => "I" + +# Ȉ [LATIN CAPITAL LETTER I WITH DOUBLE GRAVE] +"\u0208" => "I" + +# Ȋ [LATIN CAPITAL LETTER I WITH INVERTED BREVE] +"\u020A" => "I" + +# ɪ [LATIN LETTER SMALL CAPITAL I] +"\u026A" => "I" + +# ᵻ [LATIN SMALL CAPITAL LETTER I WITH STROKE] +"\u1D7B" => "I" + +# Ḭ [LATIN CAPITAL LETTER I WITH TILDE BELOW] +"\u1E2C" => "I" + +# Ḯ [LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE] +"\u1E2E" => "I" + +# Ỉ [LATIN CAPITAL LETTER I WITH HOOK ABOVE] +"\u1EC8" => "I" + +# Ị [LATIN CAPITAL LETTER I WITH DOT BELOW] +"\u1ECA" => "I" + +# Ⓘ [CIRCLED LATIN CAPITAL LETTER I] +"\u24BE" => "I" + +# ꟾ [LATIN EPIGRAPHIC LETTER I LONGA] +"\uA7FE" => "I" + +# I [FULLWIDTH LATIN CAPITAL LETTER I] +"\uFF29" => "I" + +# ì [LATIN SMALL LETTER I WITH GRAVE] +"\u00EC" => "i" + +# í [LATIN SMALL LETTER I WITH ACUTE] +"\u00ED" => "i" + +# î [LATIN SMALL LETTER I WITH CIRCUMFLEX] +"\u00EE" => "i" + +# ï [LATIN SMALL LETTER I WITH DIAERESIS] +"\u00EF" => "i" + +# ĩ [LATIN SMALL LETTER I WITH TILDE] +"\u0129" => "i" + +# ī [LATIN SMALL LETTER I WITH MACRON] +"\u012B" => "i" + +# ĭ [LATIN SMALL LETTER I WITH BREVE] +"\u012D" => "i" + +# į [LATIN SMALL LETTER I WITH OGONEK] +"\u012F" => "i" + +# ı [LATIN SMALL LETTER DOTLESS I] +"\u0131" => "i" + +# ǐ [LATIN SMALL LETTER I WITH CARON] +"\u01D0" => "i" + +# ȉ [LATIN SMALL LETTER I WITH DOUBLE GRAVE] +"\u0209" => "i" + +# ȋ [LATIN SMALL LETTER I WITH INVERTED BREVE] +"\u020B" => "i" + +# ɨ [LATIN SMALL LETTER I WITH STROKE] +"\u0268" => "i" + +# ᴉ [LATIN SMALL LETTER TURNED I] +"\u1D09" => "i" + +# ᵢ [LATIN SUBSCRIPT SMALL LETTER I] +"\u1D62" => "i" + +# ᵼ [LATIN SMALL LETTER IOTA WITH STROKE] +"\u1D7C" => "i" + +# ᶖ [LATIN SMALL LETTER I WITH RETROFLEX HOOK] +"\u1D96" => "i" + +# ḭ [LATIN SMALL LETTER I WITH TILDE BELOW] +"\u1E2D" => "i" + +# ḯ [LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE] +"\u1E2F" => "i" + +# ỉ [LATIN SMALL LETTER I WITH HOOK ABOVE] +"\u1EC9" => "i" + +# ị [LATIN SMALL LETTER I WITH DOT BELOW] +"\u1ECB" => "i" + +# ⁱ [SUPERSCRIPT LATIN SMALL LETTER I] +"\u2071" => "i" + +# ⓘ [CIRCLED LATIN SMALL LETTER I] +"\u24D8" => "i" + +# i [FULLWIDTH LATIN SMALL LETTER I] +"\uFF49" => "i" + +# IJ [LATIN CAPITAL LIGATURE IJ] +"\u0132" => "IJ" + +# ⒤ [PARENTHESIZED LATIN SMALL LETTER I] +"\u24A4" => "(i)" + +# ij [LATIN SMALL LIGATURE IJ] +"\u0133" => "ij" + +# Ĵ [LATIN CAPITAL LETTER J WITH CIRCUMFLEX] +"\u0134" => "J" + +# Ɉ [LATIN CAPITAL LETTER J WITH STROKE] +"\u0248" => "J" + +# ᴊ [LATIN LETTER SMALL CAPITAL J] +"\u1D0A" => "J" + +# Ⓙ [CIRCLED LATIN CAPITAL LETTER J] +"\u24BF" => "J" + +# J [FULLWIDTH LATIN CAPITAL LETTER J] +"\uFF2A" => "J" + +# ĵ [LATIN SMALL LETTER J WITH CIRCUMFLEX] +"\u0135" => "j" + +# ǰ [LATIN SMALL LETTER J WITH CARON] +"\u01F0" => "j" + +# ȷ [LATIN SMALL LETTER DOTLESS J] +"\u0237" => "j" + +# ɉ [LATIN SMALL LETTER J WITH STROKE] +"\u0249" => "j" + +# ɟ [LATIN SMALL LETTER DOTLESS J WITH STROKE] +"\u025F" => "j" + +# ʄ [LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK] +"\u0284" => "j" + +# ʝ [LATIN SMALL LETTER J WITH CROSSED-TAIL] +"\u029D" => "j" + +# ⓙ [CIRCLED LATIN SMALL LETTER J] +"\u24D9" => "j" + +# ⱼ [LATIN SUBSCRIPT SMALL LETTER J] +"\u2C7C" => "j" + +# j [FULLWIDTH LATIN SMALL LETTER J] +"\uFF4A" => "j" + +# ⒥ [PARENTHESIZED LATIN SMALL LETTER J] +"\u24A5" => "(j)" + +# Ķ [LATIN CAPITAL LETTER K WITH CEDILLA] +"\u0136" => "K" + +# Ƙ [LATIN CAPITAL LETTER K WITH HOOK] +"\u0198" => "K" + +# Ǩ [LATIN CAPITAL LETTER K WITH CARON] +"\u01E8" => "K" + +# ᴋ [LATIN LETTER SMALL CAPITAL K] +"\u1D0B" => "K" + +# Ḱ [LATIN CAPITAL LETTER K WITH ACUTE] +"\u1E30" => "K" + +# Ḳ [LATIN CAPITAL LETTER K WITH DOT BELOW] +"\u1E32" => "K" + +# Ḵ [LATIN CAPITAL LETTER K WITH LINE BELOW] +"\u1E34" => "K" + +# Ⓚ [CIRCLED LATIN CAPITAL LETTER K] +"\u24C0" => "K" + +# Ⱪ [LATIN CAPITAL LETTER K WITH DESCENDER] +"\u2C69" => "K" + +# Ꝁ [LATIN CAPITAL LETTER K WITH STROKE] +"\uA740" => "K" + +# Ꝃ [LATIN CAPITAL LETTER K WITH DIAGONAL STROKE] +"\uA742" => "K" + +# Ꝅ [LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE] +"\uA744" => "K" + +# K [FULLWIDTH LATIN CAPITAL LETTER K] +"\uFF2B" => "K" + +# ķ [LATIN SMALL LETTER K WITH CEDILLA] +"\u0137" => "k" + +# ƙ [LATIN SMALL LETTER K WITH HOOK] +"\u0199" => "k" + +# ǩ [LATIN SMALL LETTER K WITH CARON] +"\u01E9" => "k" + +# ʞ [LATIN SMALL LETTER TURNED K] +"\u029E" => "k" + +# ᶄ [LATIN SMALL LETTER K WITH PALATAL HOOK] +"\u1D84" => "k" + +# ḱ [LATIN SMALL LETTER K WITH ACUTE] +"\u1E31" => "k" + +# ḳ [LATIN SMALL LETTER K WITH DOT BELOW] +"\u1E33" => "k" + +# ḵ [LATIN SMALL LETTER K WITH LINE BELOW] +"\u1E35" => "k" + +# ⓚ [CIRCLED LATIN SMALL LETTER K] +"\u24DA" => "k" + +# ⱪ [LATIN SMALL LETTER K WITH DESCENDER] +"\u2C6A" => "k" + +# ꝁ [LATIN SMALL LETTER K WITH STROKE] +"\uA741" => "k" + +# ꝃ [LATIN SMALL LETTER K WITH DIAGONAL STROKE] +"\uA743" => "k" + +# ꝅ [LATIN SMALL LETTER K WITH STROKE AND DIAGONAL STROKE] +"\uA745" => "k" + +# k [FULLWIDTH LATIN SMALL LETTER K] +"\uFF4B" => "k" + +# ⒦ [PARENTHESIZED LATIN SMALL LETTER K] +"\u24A6" => "(k)" + +# Ĺ [LATIN CAPITAL LETTER L WITH ACUTE] +"\u0139" => "L" + +# Ļ [LATIN CAPITAL LETTER L WITH CEDILLA] +"\u013B" => "L" + +# Ľ [LATIN CAPITAL LETTER L WITH CARON] +"\u013D" => "L" + +# Ŀ [LATIN CAPITAL LETTER L WITH MIDDLE DOT] +"\u013F" => "L" + +# Ł [LATIN CAPITAL LETTER L WITH STROKE] +"\u0141" => "L" + +# Ƚ [LATIN CAPITAL LETTER L WITH BAR] +"\u023D" => "L" + +# ʟ [LATIN LETTER SMALL CAPITAL L] +"\u029F" => "L" + +# ᴌ [LATIN LETTER SMALL CAPITAL L WITH STROKE] +"\u1D0C" => "L" + +# Ḷ [LATIN CAPITAL LETTER L WITH DOT BELOW] +"\u1E36" => "L" + +# Ḹ [LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON] +"\u1E38" => "L" + +# Ḻ [LATIN CAPITAL LETTER L WITH LINE BELOW] +"\u1E3A" => "L" + +# Ḽ [LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW] +"\u1E3C" => "L" + +# Ⓛ [CIRCLED LATIN CAPITAL LETTER L] +"\u24C1" => "L" + +# Ⱡ [LATIN CAPITAL LETTER L WITH DOUBLE BAR] +"\u2C60" => "L" + +# Ɫ [LATIN CAPITAL LETTER L WITH MIDDLE TILDE] +"\u2C62" => "L" + +# Ꝇ [LATIN CAPITAL LETTER BROKEN L] +"\uA746" => "L" + +# Ꝉ [LATIN CAPITAL LETTER L WITH HIGH STROKE] +"\uA748" => "L" + +# Ꞁ [LATIN CAPITAL LETTER TURNED L] +"\uA780" => "L" + +# L [FULLWIDTH LATIN CAPITAL LETTER L] +"\uFF2C" => "L" + +# ĺ [LATIN SMALL LETTER L WITH ACUTE] +"\u013A" => "l" + +# ļ [LATIN SMALL LETTER L WITH CEDILLA] +"\u013C" => "l" + +# ľ [LATIN SMALL LETTER L WITH CARON] +"\u013E" => "l" + +# ŀ [LATIN SMALL LETTER L WITH MIDDLE DOT] +"\u0140" => "l" + +# ł [LATIN SMALL LETTER L WITH STROKE] +"\u0142" => "l" + +# ƚ [LATIN SMALL LETTER L WITH BAR] +"\u019A" => "l" + +# ȴ [LATIN SMALL LETTER L WITH CURL] +"\u0234" => "l" + +# ɫ [LATIN SMALL LETTER L WITH MIDDLE TILDE] +"\u026B" => "l" + +# ɬ [LATIN SMALL LETTER L WITH BELT] +"\u026C" => "l" + +# ɭ [LATIN SMALL LETTER L WITH RETROFLEX HOOK] +"\u026D" => "l" + +# ᶅ [LATIN SMALL LETTER L WITH PALATAL HOOK] +"\u1D85" => "l" + +# ḷ [LATIN SMALL LETTER L WITH DOT BELOW] +"\u1E37" => "l" + +# ḹ [LATIN SMALL LETTER L WITH DOT BELOW AND MACRON] +"\u1E39" => "l" + +# ḻ [LATIN SMALL LETTER L WITH LINE BELOW] +"\u1E3B" => "l" + +# ḽ [LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW] +"\u1E3D" => "l" + +# ⓛ [CIRCLED LATIN SMALL LETTER L] +"\u24DB" => "l" + +# ⱡ [LATIN SMALL LETTER L WITH DOUBLE BAR] +"\u2C61" => "l" + +# ꝇ [LATIN SMALL LETTER BROKEN L] +"\uA747" => "l" + +# ꝉ [LATIN SMALL LETTER L WITH HIGH STROKE] +"\uA749" => "l" + +# ꞁ [LATIN SMALL LETTER TURNED L] +"\uA781" => "l" + +# l [FULLWIDTH LATIN SMALL LETTER L] +"\uFF4C" => "l" + +# LJ [LATIN CAPITAL LETTER LJ] +"\u01C7" => "LJ" + +# Ỻ [LATIN CAPITAL LETTER MIDDLE-WELSH LL] +"\u1EFA" => "LL" + +# Lj [LATIN CAPITAL LETTER L WITH SMALL LETTER J] +"\u01C8" => "Lj" + +# ⒧ [PARENTHESIZED LATIN SMALL LETTER L] +"\u24A7" => "(l)" + +# lj [LATIN SMALL LETTER LJ] +"\u01C9" => "lj" + +# ỻ [LATIN SMALL LETTER MIDDLE-WELSH LL] +"\u1EFB" => "ll" + +# ʪ [LATIN SMALL LETTER LS DIGRAPH] +"\u02AA" => "ls" + +# ʫ [LATIN SMALL LETTER LZ DIGRAPH] +"\u02AB" => "lz" + +# Ɯ [LATIN CAPITAL LETTER TURNED M] +"\u019C" => "M" + +# ᴍ [LATIN LETTER SMALL CAPITAL M] +"\u1D0D" => "M" + +# Ḿ [LATIN CAPITAL LETTER M WITH ACUTE] +"\u1E3E" => "M" + +# Ṁ [LATIN CAPITAL LETTER M WITH DOT ABOVE] +"\u1E40" => "M" + +# Ṃ [LATIN CAPITAL LETTER M WITH DOT BELOW] +"\u1E42" => "M" + +# Ⓜ [CIRCLED LATIN CAPITAL LETTER M] +"\u24C2" => "M" + +# Ɱ [LATIN CAPITAL LETTER M WITH HOOK] +"\u2C6E" => "M" + +# ꟽ [LATIN EPIGRAPHIC LETTER INVERTED M] +"\uA7FD" => "M" + +# ꟿ [LATIN EPIGRAPHIC LETTER ARCHAIC M] +"\uA7FF" => "M" + +# M [FULLWIDTH LATIN CAPITAL LETTER M] +"\uFF2D" => "M" + +# ɯ [LATIN SMALL LETTER TURNED M] +"\u026F" => "m" + +# ɰ [LATIN SMALL LETTER TURNED M WITH LONG LEG] +"\u0270" => "m" + +# ɱ [LATIN SMALL LETTER M WITH HOOK] +"\u0271" => "m" + +# ᵯ [LATIN SMALL LETTER M WITH MIDDLE TILDE] +"\u1D6F" => "m" + +# ᶆ [LATIN SMALL LETTER M WITH PALATAL HOOK] +"\u1D86" => "m" + +# ḿ [LATIN SMALL LETTER M WITH ACUTE] +"\u1E3F" => "m" + +# ṁ [LATIN SMALL LETTER M WITH DOT ABOVE] +"\u1E41" => "m" + +# ṃ [LATIN SMALL LETTER M WITH DOT BELOW] +"\u1E43" => "m" + +# ⓜ [CIRCLED LATIN SMALL LETTER M] +"\u24DC" => "m" + +# m [FULLWIDTH LATIN SMALL LETTER M] +"\uFF4D" => "m" + +# ⒨ [PARENTHESIZED LATIN SMALL LETTER M] +"\u24A8" => "(m)" + +# Ñ [LATIN CAPITAL LETTER N WITH TILDE] +"\u00D1" => "N" + +# Ń [LATIN CAPITAL LETTER N WITH ACUTE] +"\u0143" => "N" + +# Ņ [LATIN CAPITAL LETTER N WITH CEDILLA] +"\u0145" => "N" + +# Ň [LATIN CAPITAL LETTER N WITH CARON] +"\u0147" => "N" + +# Ŋ http://en.wikipedia.org/wiki/Eng_(letter) [LATIN CAPITAL LETTER ENG] +"\u014A" => "N" + +# Ɲ [LATIN CAPITAL LETTER N WITH LEFT HOOK] +"\u019D" => "N" + +# Ǹ [LATIN CAPITAL LETTER N WITH GRAVE] +"\u01F8" => "N" + +# Ƞ [LATIN CAPITAL LETTER N WITH LONG RIGHT LEG] +"\u0220" => "N" + +# ɴ [LATIN LETTER SMALL CAPITAL N] +"\u0274" => "N" + +# ᴎ [LATIN LETTER SMALL CAPITAL REVERSED N] +"\u1D0E" => "N" + +# Ṅ [LATIN CAPITAL LETTER N WITH DOT ABOVE] +"\u1E44" => "N" + +# Ṇ [LATIN CAPITAL LETTER N WITH DOT BELOW] +"\u1E46" => "N" + +# Ṉ [LATIN CAPITAL LETTER N WITH LINE BELOW] +"\u1E48" => "N" + +# Ṋ [LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW] +"\u1E4A" => "N" + +# Ⓝ [CIRCLED LATIN CAPITAL LETTER N] +"\u24C3" => "N" + +# N [FULLWIDTH LATIN CAPITAL LETTER N] +"\uFF2E" => "N" + +# ñ [LATIN SMALL LETTER N WITH TILDE] +"\u00F1" => "n" + +# ń [LATIN SMALL LETTER N WITH ACUTE] +"\u0144" => "n" + +# ņ [LATIN SMALL LETTER N WITH CEDILLA] +"\u0146" => "n" + +# ň [LATIN SMALL LETTER N WITH CARON] +"\u0148" => "n" + +# ʼn [LATIN SMALL LETTER N PRECEDED BY APOSTROPHE] +"\u0149" => "n" + +# ŋ http://en.wikipedia.org/wiki/Eng_(letter) [LATIN SMALL LETTER ENG] +"\u014B" => "n" + +# ƞ [LATIN SMALL LETTER N WITH LONG RIGHT LEG] +"\u019E" => "n" + +# ǹ [LATIN SMALL LETTER N WITH GRAVE] +"\u01F9" => "n" + +# ȵ [LATIN SMALL LETTER N WITH CURL] +"\u0235" => "n" + +# ɲ [LATIN SMALL LETTER N WITH LEFT HOOK] +"\u0272" => "n" + +# ɳ [LATIN SMALL LETTER N WITH RETROFLEX HOOK] +"\u0273" => "n" + +# ᵰ [LATIN SMALL LETTER N WITH MIDDLE TILDE] +"\u1D70" => "n" + +# ᶇ [LATIN SMALL LETTER N WITH PALATAL HOOK] +"\u1D87" => "n" + +# ṅ [LATIN SMALL LETTER N WITH DOT ABOVE] +"\u1E45" => "n" + +# ṇ [LATIN SMALL LETTER N WITH DOT BELOW] +"\u1E47" => "n" + +# ṉ [LATIN SMALL LETTER N WITH LINE BELOW] +"\u1E49" => "n" + +# ṋ [LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW] +"\u1E4B" => "n" + +# ⁿ [SUPERSCRIPT LATIN SMALL LETTER N] +"\u207F" => "n" + +# ⓝ [CIRCLED LATIN SMALL LETTER N] +"\u24DD" => "n" + +# n [FULLWIDTH LATIN SMALL LETTER N] +"\uFF4E" => "n" + +# NJ [LATIN CAPITAL LETTER NJ] +"\u01CA" => "NJ" + +# Nj [LATIN CAPITAL LETTER N WITH SMALL LETTER J] +"\u01CB" => "Nj" + +# ⒩ [PARENTHESIZED LATIN SMALL LETTER N] +"\u24A9" => "(n)" + +# nj [LATIN SMALL LETTER NJ] +"\u01CC" => "nj" + +# Ò [LATIN CAPITAL LETTER O WITH GRAVE] +"\u00D2" => "O" + +# Ó [LATIN CAPITAL LETTER O WITH ACUTE] +"\u00D3" => "O" + +# Ô [LATIN CAPITAL LETTER O WITH CIRCUMFLEX] +"\u00D4" => "O" + +# Õ [LATIN CAPITAL LETTER O WITH TILDE] +"\u00D5" => "O" + +# Ö [LATIN CAPITAL LETTER O WITH DIAERESIS] +"\u00D6" => "O" + +# Ø [LATIN CAPITAL LETTER O WITH STROKE] +"\u00D8" => "O" + +# Ō [LATIN CAPITAL LETTER O WITH MACRON] +"\u014C" => "O" + +# Ŏ [LATIN CAPITAL LETTER O WITH BREVE] +"\u014E" => "O" + +# Ő [LATIN CAPITAL LETTER O WITH DOUBLE ACUTE] +"\u0150" => "O" + +# Ɔ [LATIN CAPITAL LETTER OPEN O] +"\u0186" => "O" + +# Ɵ [LATIN CAPITAL LETTER O WITH MIDDLE TILDE] +"\u019F" => "O" + +# Ơ [LATIN CAPITAL LETTER O WITH HORN] +"\u01A0" => "O" + +# Ǒ [LATIN CAPITAL LETTER O WITH CARON] +"\u01D1" => "O" + +# Ǫ [LATIN CAPITAL LETTER O WITH OGONEK] +"\u01EA" => "O" + +# Ǭ [LATIN CAPITAL LETTER O WITH OGONEK AND MACRON] +"\u01EC" => "O" + +# Ǿ [LATIN CAPITAL LETTER O WITH STROKE AND ACUTE] +"\u01FE" => "O" + +# Ȍ [LATIN CAPITAL LETTER O WITH DOUBLE GRAVE] +"\u020C" => "O" + +# Ȏ [LATIN CAPITAL LETTER O WITH INVERTED BREVE] +"\u020E" => "O" + +# Ȫ [LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON] +"\u022A" => "O" + +# Ȭ [LATIN CAPITAL LETTER O WITH TILDE AND MACRON] +"\u022C" => "O" + +# Ȯ [LATIN CAPITAL LETTER O WITH DOT ABOVE] +"\u022E" => "O" + +# Ȱ [LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON] +"\u0230" => "O" + +# ᴏ [LATIN LETTER SMALL CAPITAL O] +"\u1D0F" => "O" + +# ᴐ [LATIN LETTER SMALL CAPITAL OPEN O] +"\u1D10" => "O" + +# Ṍ [LATIN CAPITAL LETTER O WITH TILDE AND ACUTE] +"\u1E4C" => "O" + +# Ṏ [LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS] +"\u1E4E" => "O" + +# Ṑ [LATIN CAPITAL LETTER O WITH MACRON AND GRAVE] +"\u1E50" => "O" + +# Ṓ [LATIN CAPITAL LETTER O WITH MACRON AND ACUTE] +"\u1E52" => "O" + +# Ọ [LATIN CAPITAL LETTER O WITH DOT BELOW] +"\u1ECC" => "O" + +# Ỏ [LATIN CAPITAL LETTER O WITH HOOK ABOVE] +"\u1ECE" => "O" + +# Ố [LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE] +"\u1ED0" => "O" + +# Ồ [LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE] +"\u1ED2" => "O" + +# Ổ [LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE] +"\u1ED4" => "O" + +# Ỗ [LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE] +"\u1ED6" => "O" + +# Ộ [LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW] +"\u1ED8" => "O" + +# Ớ [LATIN CAPITAL LETTER O WITH HORN AND ACUTE] +"\u1EDA" => "O" + +# Ờ [LATIN CAPITAL LETTER O WITH HORN AND GRAVE] +"\u1EDC" => "O" + +# Ở [LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE] +"\u1EDE" => "O" + +# Ỡ [LATIN CAPITAL LETTER O WITH HORN AND TILDE] +"\u1EE0" => "O" + +# Ợ [LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW] +"\u1EE2" => "O" + +# Ⓞ [CIRCLED LATIN CAPITAL LETTER O] +"\u24C4" => "O" + +# Ꝋ [LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY] +"\uA74A" => "O" + +# Ꝍ [LATIN CAPITAL LETTER O WITH LOOP] +"\uA74C" => "O" + +# O [FULLWIDTH LATIN CAPITAL LETTER O] +"\uFF2F" => "O" + +# ò [LATIN SMALL LETTER O WITH GRAVE] +"\u00F2" => "o" + +# ó [LATIN SMALL LETTER O WITH ACUTE] +"\u00F3" => "o" + +# ô [LATIN SMALL LETTER O WITH CIRCUMFLEX] +"\u00F4" => "o" + +# õ [LATIN SMALL LETTER O WITH TILDE] +"\u00F5" => "o" + +# ö [LATIN SMALL LETTER O WITH DIAERESIS] +"\u00F6" => "o" + +# ø [LATIN SMALL LETTER O WITH STROKE] +"\u00F8" => "o" + +# ō [LATIN SMALL LETTER O WITH MACRON] +"\u014D" => "o" + +# ŏ [LATIN SMALL LETTER O WITH BREVE] +"\u014F" => "o" + +# ő [LATIN SMALL LETTER O WITH DOUBLE ACUTE] +"\u0151" => "o" + +# ơ [LATIN SMALL LETTER O WITH HORN] +"\u01A1" => "o" + +# ǒ [LATIN SMALL LETTER O WITH CARON] +"\u01D2" => "o" + +# ǫ [LATIN SMALL LETTER O WITH OGONEK] +"\u01EB" => "o" + +# ǭ [LATIN SMALL LETTER O WITH OGONEK AND MACRON] +"\u01ED" => "o" + +# ǿ [LATIN SMALL LETTER O WITH STROKE AND ACUTE] +"\u01FF" => "o" + +# ȍ [LATIN SMALL LETTER O WITH DOUBLE GRAVE] +"\u020D" => "o" + +# ȏ [LATIN SMALL LETTER O WITH INVERTED BREVE] +"\u020F" => "o" + +# ȫ [LATIN SMALL LETTER O WITH DIAERESIS AND MACRON] +"\u022B" => "o" + +# ȭ [LATIN SMALL LETTER O WITH TILDE AND MACRON] +"\u022D" => "o" + +# ȯ [LATIN SMALL LETTER O WITH DOT ABOVE] +"\u022F" => "o" + +# ȱ [LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON] +"\u0231" => "o" + +# ɔ [LATIN SMALL LETTER OPEN O] +"\u0254" => "o" + +# ɵ [LATIN SMALL LETTER BARRED O] +"\u0275" => "o" + +# ᴖ [LATIN SMALL LETTER TOP HALF O] +"\u1D16" => "o" + +# ᴗ [LATIN SMALL LETTER BOTTOM HALF O] +"\u1D17" => "o" + +# ᶗ [LATIN SMALL LETTER OPEN O WITH RETROFLEX HOOK] +"\u1D97" => "o" + +# ṍ [LATIN SMALL LETTER O WITH TILDE AND ACUTE] +"\u1E4D" => "o" + +# ṏ [LATIN SMALL LETTER O WITH TILDE AND DIAERESIS] +"\u1E4F" => "o" + +# ṑ [LATIN SMALL LETTER O WITH MACRON AND GRAVE] +"\u1E51" => "o" + +# ṓ [LATIN SMALL LETTER O WITH MACRON AND ACUTE] +"\u1E53" => "o" + +# ọ [LATIN SMALL LETTER O WITH DOT BELOW] +"\u1ECD" => "o" + +# ỏ [LATIN SMALL LETTER O WITH HOOK ABOVE] +"\u1ECF" => "o" + +# ố [LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE] +"\u1ED1" => "o" + +# ồ [LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE] +"\u1ED3" => "o" + +# ổ [LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE] +"\u1ED5" => "o" + +# ỗ [LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE] +"\u1ED7" => "o" + +# ộ [LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW] +"\u1ED9" => "o" + +# ớ [LATIN SMALL LETTER O WITH HORN AND ACUTE] +"\u1EDB" => "o" + +# ờ [LATIN SMALL LETTER O WITH HORN AND GRAVE] +"\u1EDD" => "o" + +# ở [LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE] +"\u1EDF" => "o" + +# ỡ [LATIN SMALL LETTER O WITH HORN AND TILDE] +"\u1EE1" => "o" + +# ợ [LATIN SMALL LETTER O WITH HORN AND DOT BELOW] +"\u1EE3" => "o" + +# ₒ [LATIN SUBSCRIPT SMALL LETTER O] +"\u2092" => "o" + +# ⓞ [CIRCLED LATIN SMALL LETTER O] +"\u24DE" => "o" + +# ⱺ [LATIN SMALL LETTER O WITH LOW RING INSIDE] +"\u2C7A" => "o" + +# ꝋ [LATIN SMALL LETTER O WITH LONG STROKE OVERLAY] +"\uA74B" => "o" + +# ꝍ [LATIN SMALL LETTER O WITH LOOP] +"\uA74D" => "o" + +# o [FULLWIDTH LATIN SMALL LETTER O] +"\uFF4F" => "o" + +# Œ [LATIN CAPITAL LIGATURE OE] +"\u0152" => "OE" + +# ɶ [LATIN LETTER SMALL CAPITAL OE] +"\u0276" => "OE" + +# Ꝏ [LATIN CAPITAL LETTER OO] +"\uA74E" => "OO" + +# Ȣ http://en.wikipedia.org/wiki/OU [LATIN CAPITAL LETTER OU] +"\u0222" => "OU" + +# ᴕ [LATIN LETTER SMALL CAPITAL OU] +"\u1D15" => "OU" + +# ⒪ [PARENTHESIZED LATIN SMALL LETTER O] +"\u24AA" => "(o)" + +# œ [LATIN SMALL LIGATURE OE] +"\u0153" => "oe" + +# ᴔ [LATIN SMALL LETTER TURNED OE] +"\u1D14" => "oe" + +# ꝏ [LATIN SMALL LETTER OO] +"\uA74F" => "oo" + +# ȣ http://en.wikipedia.org/wiki/OU [LATIN SMALL LETTER OU] +"\u0223" => "ou" + +# Ƥ [LATIN CAPITAL LETTER P WITH HOOK] +"\u01A4" => "P" + +# ᴘ [LATIN LETTER SMALL CAPITAL P] +"\u1D18" => "P" + +# Ṕ [LATIN CAPITAL LETTER P WITH ACUTE] +"\u1E54" => "P" + +# Ṗ [LATIN CAPITAL LETTER P WITH DOT ABOVE] +"\u1E56" => "P" + +# Ⓟ [CIRCLED LATIN CAPITAL LETTER P] +"\u24C5" => "P" + +# Ᵽ [LATIN CAPITAL LETTER P WITH STROKE] +"\u2C63" => "P" + +# Ꝑ [LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER] +"\uA750" => "P" + +# Ꝓ [LATIN CAPITAL LETTER P WITH FLOURISH] +"\uA752" => "P" + +# Ꝕ [LATIN CAPITAL LETTER P WITH SQUIRREL TAIL] +"\uA754" => "P" + +# P [FULLWIDTH LATIN CAPITAL LETTER P] +"\uFF30" => "P" + +# ƥ [LATIN SMALL LETTER P WITH HOOK] +"\u01A5" => "p" + +# ᵱ [LATIN SMALL LETTER P WITH MIDDLE TILDE] +"\u1D71" => "p" + +# ᵽ [LATIN SMALL LETTER P WITH STROKE] +"\u1D7D" => "p" + +# ᶈ [LATIN SMALL LETTER P WITH PALATAL HOOK] +"\u1D88" => "p" + +# ṕ [LATIN SMALL LETTER P WITH ACUTE] +"\u1E55" => "p" + +# ṗ [LATIN SMALL LETTER P WITH DOT ABOVE] +"\u1E57" => "p" + +# ⓟ [CIRCLED LATIN SMALL LETTER P] +"\u24DF" => "p" + +# ꝑ [LATIN SMALL LETTER P WITH STROKE THROUGH DESCENDER] +"\uA751" => "p" + +# ꝓ [LATIN SMALL LETTER P WITH FLOURISH] +"\uA753" => "p" + +# ꝕ [LATIN SMALL LETTER P WITH SQUIRREL TAIL] +"\uA755" => "p" + +# ꟼ [LATIN EPIGRAPHIC LETTER REVERSED P] +"\uA7FC" => "p" + +# p [FULLWIDTH LATIN SMALL LETTER P] +"\uFF50" => "p" + +# ⒫ [PARENTHESIZED LATIN SMALL LETTER P] +"\u24AB" => "(p)" + +# Ɋ [LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL] +"\u024A" => "Q" + +# Ⓠ [CIRCLED LATIN CAPITAL LETTER Q] +"\u24C6" => "Q" + +# Ꝗ [LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER] +"\uA756" => "Q" + +# Ꝙ [LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE] +"\uA758" => "Q" + +# Q [FULLWIDTH LATIN CAPITAL LETTER Q] +"\uFF31" => "Q" + +# ĸ http://en.wikipedia.org/wiki/Kra_(letter) [LATIN SMALL LETTER KRA] +"\u0138" => "q" + +# ɋ [LATIN SMALL LETTER Q WITH HOOK TAIL] +"\u024B" => "q" + +# ʠ [LATIN SMALL LETTER Q WITH HOOK] +"\u02A0" => "q" + +# ⓠ [CIRCLED LATIN SMALL LETTER Q] +"\u24E0" => "q" + +# ꝗ [LATIN SMALL LETTER Q WITH STROKE THROUGH DESCENDER] +"\uA757" => "q" + +# ꝙ [LATIN SMALL LETTER Q WITH DIAGONAL STROKE] +"\uA759" => "q" + +# q [FULLWIDTH LATIN SMALL LETTER Q] +"\uFF51" => "q" + +# ⒬ [PARENTHESIZED LATIN SMALL LETTER Q] +"\u24AC" => "(q)" + +# ȹ [LATIN SMALL LETTER QP DIGRAPH] +"\u0239" => "qp" + +# Ŕ [LATIN CAPITAL LETTER R WITH ACUTE] +"\u0154" => "R" + +# Ŗ [LATIN CAPITAL LETTER R WITH CEDILLA] +"\u0156" => "R" + +# Ř [LATIN CAPITAL LETTER R WITH CARON] +"\u0158" => "R" + +# Ȓ [LATIN CAPITAL LETTER R WITH DOUBLE GRAVE] +"\u0210" => "R" + +# Ȓ [LATIN CAPITAL LETTER R WITH INVERTED BREVE] +"\u0212" => "R" + +# Ɍ [LATIN CAPITAL LETTER R WITH STROKE] +"\u024C" => "R" + +# ʀ [LATIN LETTER SMALL CAPITAL R] +"\u0280" => "R" + +# ʁ [LATIN LETTER SMALL CAPITAL INVERTED R] +"\u0281" => "R" + +# ᴙ [LATIN LETTER SMALL CAPITAL REVERSED R] +"\u1D19" => "R" + +# ᴚ [LATIN LETTER SMALL CAPITAL TURNED R] +"\u1D1A" => "R" + +# Ṙ [LATIN CAPITAL LETTER R WITH DOT ABOVE] +"\u1E58" => "R" + +# Ṛ [LATIN CAPITAL LETTER R WITH DOT BELOW] +"\u1E5A" => "R" + +# Ṝ [LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON] +"\u1E5C" => "R" + +# Ṟ [LATIN CAPITAL LETTER R WITH LINE BELOW] +"\u1E5E" => "R" + +# Ⓡ [CIRCLED LATIN CAPITAL LETTER R] +"\u24C7" => "R" + +# Ɽ [LATIN CAPITAL LETTER R WITH TAIL] +"\u2C64" => "R" + +# Ꝛ [LATIN CAPITAL LETTER R ROTUNDA] +"\uA75A" => "R" + +# Ꞃ [LATIN CAPITAL LETTER INSULAR R] +"\uA782" => "R" + +# R [FULLWIDTH LATIN CAPITAL LETTER R] +"\uFF32" => "R" + +# ŕ [LATIN SMALL LETTER R WITH ACUTE] +"\u0155" => "r" + +# ŗ [LATIN SMALL LETTER R WITH CEDILLA] +"\u0157" => "r" + +# ř [LATIN SMALL LETTER R WITH CARON] +"\u0159" => "r" + +# ȑ [LATIN SMALL LETTER R WITH DOUBLE GRAVE] +"\u0211" => "r" + +# ȓ [LATIN SMALL LETTER R WITH INVERTED BREVE] +"\u0213" => "r" + +# ɍ [LATIN SMALL LETTER R WITH STROKE] +"\u024D" => "r" + +# ɼ [LATIN SMALL LETTER R WITH LONG LEG] +"\u027C" => "r" + +# ɽ [LATIN SMALL LETTER R WITH TAIL] +"\u027D" => "r" + +# ɾ [LATIN SMALL LETTER R WITH FISHHOOK] +"\u027E" => "r" + +# ɿ [LATIN SMALL LETTER REVERSED R WITH FISHHOOK] +"\u027F" => "r" + +# ᵣ [LATIN SUBSCRIPT SMALL LETTER R] +"\u1D63" => "r" + +# ᵲ [LATIN SMALL LETTER R WITH MIDDLE TILDE] +"\u1D72" => "r" + +# ᵳ [LATIN SMALL LETTER R WITH FISHHOOK AND MIDDLE TILDE] +"\u1D73" => "r" + +# ᶉ [LATIN SMALL LETTER R WITH PALATAL HOOK] +"\u1D89" => "r" + +# ṙ [LATIN SMALL LETTER R WITH DOT ABOVE] +"\u1E59" => "r" + +# ṛ [LATIN SMALL LETTER R WITH DOT BELOW] +"\u1E5B" => "r" + +# ṝ [LATIN SMALL LETTER R WITH DOT BELOW AND MACRON] +"\u1E5D" => "r" + +# ṟ [LATIN SMALL LETTER R WITH LINE BELOW] +"\u1E5F" => "r" + +# ⓡ [CIRCLED LATIN SMALL LETTER R] +"\u24E1" => "r" + +# ꝛ [LATIN SMALL LETTER R ROTUNDA] +"\uA75B" => "r" + +# ꞃ [LATIN SMALL LETTER INSULAR R] +"\uA783" => "r" + +# r [FULLWIDTH LATIN SMALL LETTER R] +"\uFF52" => "r" + +# ⒭ [PARENTHESIZED LATIN SMALL LETTER R] +"\u24AD" => "(r)" + +# Ś [LATIN CAPITAL LETTER S WITH ACUTE] +"\u015A" => "S" + +# Ŝ [LATIN CAPITAL LETTER S WITH CIRCUMFLEX] +"\u015C" => "S" + +# Ş [LATIN CAPITAL LETTER S WITH CEDILLA] +"\u015E" => "S" + +# Š [LATIN CAPITAL LETTER S WITH CARON] +"\u0160" => "S" + +# Ș [LATIN CAPITAL LETTER S WITH COMMA BELOW] +"\u0218" => "S" + +# Ṡ [LATIN CAPITAL LETTER S WITH DOT ABOVE] +"\u1E60" => "S" + +# Ṣ [LATIN CAPITAL LETTER S WITH DOT BELOW] +"\u1E62" => "S" + +# Ṥ [LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE] +"\u1E64" => "S" + +# Ṧ [LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE] +"\u1E66" => "S" + +# Ṩ [LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE] +"\u1E68" => "S" + +# Ⓢ [CIRCLED LATIN CAPITAL LETTER S] +"\u24C8" => "S" + +# ꜱ [LATIN LETTER SMALL CAPITAL S] +"\uA731" => "S" + +# ꞅ [LATIN SMALL LETTER INSULAR S] +"\uA785" => "S" + +# S [FULLWIDTH LATIN CAPITAL LETTER S] +"\uFF33" => "S" + +# ś [LATIN SMALL LETTER S WITH ACUTE] +"\u015B" => "s" + +# ŝ [LATIN SMALL LETTER S WITH CIRCUMFLEX] +"\u015D" => "s" + +# ş [LATIN SMALL LETTER S WITH CEDILLA] +"\u015F" => "s" + +# š [LATIN SMALL LETTER S WITH CARON] +"\u0161" => "s" + +# ſ http://en.wikipedia.org/wiki/Long_S [LATIN SMALL LETTER LONG S] +"\u017F" => "s" + +# ș [LATIN SMALL LETTER S WITH COMMA BELOW] +"\u0219" => "s" + +# ȿ [LATIN SMALL LETTER S WITH SWASH TAIL] +"\u023F" => "s" + +# ʂ [LATIN SMALL LETTER S WITH HOOK] +"\u0282" => "s" + +# ᵴ [LATIN SMALL LETTER S WITH MIDDLE TILDE] +"\u1D74" => "s" + +# ᶊ [LATIN SMALL LETTER S WITH PALATAL HOOK] +"\u1D8A" => "s" + +# ṡ [LATIN SMALL LETTER S WITH DOT ABOVE] +"\u1E61" => "s" + +# ṣ [LATIN SMALL LETTER S WITH DOT BELOW] +"\u1E63" => "s" + +# ṥ [LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE] +"\u1E65" => "s" + +# ṧ [LATIN SMALL LETTER S WITH CARON AND DOT ABOVE] +"\u1E67" => "s" + +# ṩ [LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE] +"\u1E69" => "s" + +# ẜ [LATIN SMALL LETTER LONG S WITH DIAGONAL STROKE] +"\u1E9C" => "s" + +# ẝ [LATIN SMALL LETTER LONG S WITH HIGH STROKE] +"\u1E9D" => "s" + +# ⓢ [CIRCLED LATIN SMALL LETTER S] +"\u24E2" => "s" + +# Ꞅ [LATIN CAPITAL LETTER INSULAR S] +"\uA784" => "s" + +# s [FULLWIDTH LATIN SMALL LETTER S] +"\uFF53" => "s" + +# ẞ [LATIN CAPITAL LETTER SHARP S] +"\u1E9E" => "SS" + +# ⒮ [PARENTHESIZED LATIN SMALL LETTER S] +"\u24AE" => "(s)" + +# ß [LATIN SMALL LETTER SHARP S] +"\u00DF" => "ss" + +# st [LATIN SMALL LIGATURE ST] +"\uFB06" => "st" + +# Ţ [LATIN CAPITAL LETTER T WITH CEDILLA] +"\u0162" => "T" + +# Ť [LATIN CAPITAL LETTER T WITH CARON] +"\u0164" => "T" + +# Ŧ [LATIN CAPITAL LETTER T WITH STROKE] +"\u0166" => "T" + +# Ƭ [LATIN CAPITAL LETTER T WITH HOOK] +"\u01AC" => "T" + +# Ʈ [LATIN CAPITAL LETTER T WITH RETROFLEX HOOK] +"\u01AE" => "T" + +# Ț [LATIN CAPITAL LETTER T WITH COMMA BELOW] +"\u021A" => "T" + +# Ⱦ [LATIN CAPITAL LETTER T WITH DIAGONAL STROKE] +"\u023E" => "T" + +# ᴛ [LATIN LETTER SMALL CAPITAL T] +"\u1D1B" => "T" + +# Ṫ [LATIN CAPITAL LETTER T WITH DOT ABOVE] +"\u1E6A" => "T" + +# Ṭ [LATIN CAPITAL LETTER T WITH DOT BELOW] +"\u1E6C" => "T" + +# Ṯ [LATIN CAPITAL LETTER T WITH LINE BELOW] +"\u1E6E" => "T" + +# Ṱ [LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW] +"\u1E70" => "T" + +# Ⓣ [CIRCLED LATIN CAPITAL LETTER T] +"\u24C9" => "T" + +# Ꞇ [LATIN CAPITAL LETTER INSULAR T] +"\uA786" => "T" + +# T [FULLWIDTH LATIN CAPITAL LETTER T] +"\uFF34" => "T" + +# ţ [LATIN SMALL LETTER T WITH CEDILLA] +"\u0163" => "t" + +# ť [LATIN SMALL LETTER T WITH CARON] +"\u0165" => "t" + +# ŧ [LATIN SMALL LETTER T WITH STROKE] +"\u0167" => "t" + +# ƫ [LATIN SMALL LETTER T WITH PALATAL HOOK] +"\u01AB" => "t" + +# ƭ [LATIN SMALL LETTER T WITH HOOK] +"\u01AD" => "t" + +# ț [LATIN SMALL LETTER T WITH COMMA BELOW] +"\u021B" => "t" + +# ȶ [LATIN SMALL LETTER T WITH CURL] +"\u0236" => "t" + +# ʇ [LATIN SMALL LETTER TURNED T] +"\u0287" => "t" + +# ʈ [LATIN SMALL LETTER T WITH RETROFLEX HOOK] +"\u0288" => "t" + +# ᵵ [LATIN SMALL LETTER T WITH MIDDLE TILDE] +"\u1D75" => "t" + +# ṫ [LATIN SMALL LETTER T WITH DOT ABOVE] +"\u1E6B" => "t" + +# ṭ [LATIN SMALL LETTER T WITH DOT BELOW] +"\u1E6D" => "t" + +# ṯ [LATIN SMALL LETTER T WITH LINE BELOW] +"\u1E6F" => "t" + +# ṱ [LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW] +"\u1E71" => "t" + +# ẗ [LATIN SMALL LETTER T WITH DIAERESIS] +"\u1E97" => "t" + +# ⓣ [CIRCLED LATIN SMALL LETTER T] +"\u24E3" => "t" + +# ⱦ [LATIN SMALL LETTER T WITH DIAGONAL STROKE] +"\u2C66" => "t" + +# t [FULLWIDTH LATIN SMALL LETTER T] +"\uFF54" => "t" + +# Þ [LATIN CAPITAL LETTER THORN] +"\u00DE" => "TH" + +# Ꝧ [LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER] +"\uA766" => "TH" + +# Ꜩ [LATIN CAPITAL LETTER TZ] +"\uA728" => "TZ" + +# ⒯ [PARENTHESIZED LATIN SMALL LETTER T] +"\u24AF" => "(t)" + +# ʨ [LATIN SMALL LETTER TC DIGRAPH WITH CURL] +"\u02A8" => "tc" + +# þ [LATIN SMALL LETTER THORN] +"\u00FE" => "th" + +# ᵺ [LATIN SMALL LETTER TH WITH STRIKETHROUGH] +"\u1D7A" => "th" + +# ꝧ [LATIN SMALL LETTER THORN WITH STROKE THROUGH DESCENDER] +"\uA767" => "th" + +# ʦ [LATIN SMALL LETTER TS DIGRAPH] +"\u02A6" => "ts" + +# ꜩ [LATIN SMALL LETTER TZ] +"\uA729" => "tz" + +# Ù [LATIN CAPITAL LETTER U WITH GRAVE] +"\u00D9" => "U" + +# Ú [LATIN CAPITAL LETTER U WITH ACUTE] +"\u00DA" => "U" + +# Û [LATIN CAPITAL LETTER U WITH CIRCUMFLEX] +"\u00DB" => "U" + +# Ü [LATIN CAPITAL LETTER U WITH DIAERESIS] +"\u00DC" => "U" + +# Ũ [LATIN CAPITAL LETTER U WITH TILDE] +"\u0168" => "U" + +# Ū [LATIN CAPITAL LETTER U WITH MACRON] +"\u016A" => "U" + +# Ŭ [LATIN CAPITAL LETTER U WITH BREVE] +"\u016C" => "U" + +# Ů [LATIN CAPITAL LETTER U WITH RING ABOVE] +"\u016E" => "U" + +# Ű [LATIN CAPITAL LETTER U WITH DOUBLE ACUTE] +"\u0170" => "U" + +# Ų [LATIN CAPITAL LETTER U WITH OGONEK] +"\u0172" => "U" + +# Ư [LATIN CAPITAL LETTER U WITH HORN] +"\u01AF" => "U" + +# Ǔ [LATIN CAPITAL LETTER U WITH CARON] +"\u01D3" => "U" + +# Ǖ [LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON] +"\u01D5" => "U" + +# Ǘ [LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE] +"\u01D7" => "U" + +# Ǚ [LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON] +"\u01D9" => "U" + +# Ǜ [LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE] +"\u01DB" => "U" + +# Ȕ [LATIN CAPITAL LETTER U WITH DOUBLE GRAVE] +"\u0214" => "U" + +# Ȗ [LATIN CAPITAL LETTER U WITH INVERTED BREVE] +"\u0216" => "U" + +# Ʉ [LATIN CAPITAL LETTER U BAR] +"\u0244" => "U" + +# ᴜ [LATIN LETTER SMALL CAPITAL U] +"\u1D1C" => "U" + +# ᵾ [LATIN SMALL CAPITAL LETTER U WITH STROKE] +"\u1D7E" => "U" + +# Ṳ [LATIN CAPITAL LETTER U WITH DIAERESIS BELOW] +"\u1E72" => "U" + +# Ṵ [LATIN CAPITAL LETTER U WITH TILDE BELOW] +"\u1E74" => "U" + +# Ṷ [LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW] +"\u1E76" => "U" + +# Ṹ [LATIN CAPITAL LETTER U WITH TILDE AND ACUTE] +"\u1E78" => "U" + +# Ṻ [LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS] +"\u1E7A" => "U" + +# Ụ [LATIN CAPITAL LETTER U WITH DOT BELOW] +"\u1EE4" => "U" + +# Ủ [LATIN CAPITAL LETTER U WITH HOOK ABOVE] +"\u1EE6" => "U" + +# Ứ [LATIN CAPITAL LETTER U WITH HORN AND ACUTE] +"\u1EE8" => "U" + +# Ừ [LATIN CAPITAL LETTER U WITH HORN AND GRAVE] +"\u1EEA" => "U" + +# Ử [LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE] +"\u1EEC" => "U" + +# Ữ [LATIN CAPITAL LETTER U WITH HORN AND TILDE] +"\u1EEE" => "U" + +# Ự [LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW] +"\u1EF0" => "U" + +# Ⓤ [CIRCLED LATIN CAPITAL LETTER U] +"\u24CA" => "U" + +# U [FULLWIDTH LATIN CAPITAL LETTER U] +"\uFF35" => "U" + +# ù [LATIN SMALL LETTER U WITH GRAVE] +"\u00F9" => "u" + +# ú [LATIN SMALL LETTER U WITH ACUTE] +"\u00FA" => "u" + +# û [LATIN SMALL LETTER U WITH CIRCUMFLEX] +"\u00FB" => "u" + +# ü [LATIN SMALL LETTER U WITH DIAERESIS] +"\u00FC" => "u" + +# ũ [LATIN SMALL LETTER U WITH TILDE] +"\u0169" => "u" + +# ū [LATIN SMALL LETTER U WITH MACRON] +"\u016B" => "u" + +# ŭ [LATIN SMALL LETTER U WITH BREVE] +"\u016D" => "u" + +# ů [LATIN SMALL LETTER U WITH RING ABOVE] +"\u016F" => "u" + +# ű [LATIN SMALL LETTER U WITH DOUBLE ACUTE] +"\u0171" => "u" + +# ų [LATIN SMALL LETTER U WITH OGONEK] +"\u0173" => "u" + +# ư [LATIN SMALL LETTER U WITH HORN] +"\u01B0" => "u" + +# ǔ [LATIN SMALL LETTER U WITH CARON] +"\u01D4" => "u" + +# ǖ [LATIN SMALL LETTER U WITH DIAERESIS AND MACRON] +"\u01D6" => "u" + +# ǘ [LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE] +"\u01D8" => "u" + +# ǚ [LATIN SMALL LETTER U WITH DIAERESIS AND CARON] +"\u01DA" => "u" + +# ǜ [LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE] +"\u01DC" => "u" + +# ȕ [LATIN SMALL LETTER U WITH DOUBLE GRAVE] +"\u0215" => "u" + +# ȗ [LATIN SMALL LETTER U WITH INVERTED BREVE] +"\u0217" => "u" + +# ʉ [LATIN SMALL LETTER U BAR] +"\u0289" => "u" + +# ᵤ [LATIN SUBSCRIPT SMALL LETTER U] +"\u1D64" => "u" + +# ᶙ [LATIN SMALL LETTER U WITH RETROFLEX HOOK] +"\u1D99" => "u" + +# ṳ [LATIN SMALL LETTER U WITH DIAERESIS BELOW] +"\u1E73" => "u" + +# ṵ [LATIN SMALL LETTER U WITH TILDE BELOW] +"\u1E75" => "u" + +# ṷ [LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW] +"\u1E77" => "u" + +# ṹ [LATIN SMALL LETTER U WITH TILDE AND ACUTE] +"\u1E79" => "u" + +# ṻ [LATIN SMALL LETTER U WITH MACRON AND DIAERESIS] +"\u1E7B" => "u" + +# ụ [LATIN SMALL LETTER U WITH DOT BELOW] +"\u1EE5" => "u" + +# ủ [LATIN SMALL LETTER U WITH HOOK ABOVE] +"\u1EE7" => "u" + +# ứ [LATIN SMALL LETTER U WITH HORN AND ACUTE] +"\u1EE9" => "u" + +# ừ [LATIN SMALL LETTER U WITH HORN AND GRAVE] +"\u1EEB" => "u" + +# ử [LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE] +"\u1EED" => "u" + +# ữ [LATIN SMALL LETTER U WITH HORN AND TILDE] +"\u1EEF" => "u" + +# ự [LATIN SMALL LETTER U WITH HORN AND DOT BELOW] +"\u1EF1" => "u" + +# ⓤ [CIRCLED LATIN SMALL LETTER U] +"\u24E4" => "u" + +# u [FULLWIDTH LATIN SMALL LETTER U] +"\uFF55" => "u" + +# ⒰ [PARENTHESIZED LATIN SMALL LETTER U] +"\u24B0" => "(u)" + +# ᵫ [LATIN SMALL LETTER UE] +"\u1D6B" => "ue" + +# Ʋ [LATIN CAPITAL LETTER V WITH HOOK] +"\u01B2" => "V" + +# Ʌ [LATIN CAPITAL LETTER TURNED V] +"\u0245" => "V" + +# ᴠ [LATIN LETTER SMALL CAPITAL V] +"\u1D20" => "V" + +# Ṽ [LATIN CAPITAL LETTER V WITH TILDE] +"\u1E7C" => "V" + +# Ṿ [LATIN CAPITAL LETTER V WITH DOT BELOW] +"\u1E7E" => "V" + +# Ỽ [LATIN CAPITAL LETTER MIDDLE-WELSH V] +"\u1EFC" => "V" + +# Ⓥ [CIRCLED LATIN CAPITAL LETTER V] +"\u24CB" => "V" + +# Ꝟ [LATIN CAPITAL LETTER V WITH DIAGONAL STROKE] +"\uA75E" => "V" + +# Ꝩ [LATIN CAPITAL LETTER VEND] +"\uA768" => "V" + +# V [FULLWIDTH LATIN CAPITAL LETTER V] +"\uFF36" => "V" + +# ʋ [LATIN SMALL LETTER V WITH HOOK] +"\u028B" => "v" + +# ʌ [LATIN SMALL LETTER TURNED V] +"\u028C" => "v" + +# ᵥ [LATIN SUBSCRIPT SMALL LETTER V] +"\u1D65" => "v" + +# ᶌ [LATIN SMALL LETTER V WITH PALATAL HOOK] +"\u1D8C" => "v" + +# ṽ [LATIN SMALL LETTER V WITH TILDE] +"\u1E7D" => "v" + +# ṿ [LATIN SMALL LETTER V WITH DOT BELOW] +"\u1E7F" => "v" + +# ⓥ [CIRCLED LATIN SMALL LETTER V] +"\u24E5" => "v" + +# ⱱ [LATIN SMALL LETTER V WITH RIGHT HOOK] +"\u2C71" => "v" + +# ⱴ [LATIN SMALL LETTER V WITH CURL] +"\u2C74" => "v" + +# ꝟ [LATIN SMALL LETTER V WITH DIAGONAL STROKE] +"\uA75F" => "v" + +# v [FULLWIDTH LATIN SMALL LETTER V] +"\uFF56" => "v" + +# Ꝡ [LATIN CAPITAL LETTER VY] +"\uA760" => "VY" + +# ⒱ [PARENTHESIZED LATIN SMALL LETTER V] +"\u24B1" => "(v)" + +# ꝡ [LATIN SMALL LETTER VY] +"\uA761" => "vy" + +# Ŵ [LATIN CAPITAL LETTER W WITH CIRCUMFLEX] +"\u0174" => "W" + +# Ƿ http://en.wikipedia.org/wiki/Wynn [LATIN CAPITAL LETTER WYNN] +"\u01F7" => "W" + +# ᴡ [LATIN LETTER SMALL CAPITAL W] +"\u1D21" => "W" + +# Ẁ [LATIN CAPITAL LETTER W WITH GRAVE] +"\u1E80" => "W" + +# Ẃ [LATIN CAPITAL LETTER W WITH ACUTE] +"\u1E82" => "W" + +# Ẅ [LATIN CAPITAL LETTER W WITH DIAERESIS] +"\u1E84" => "W" + +# Ẇ [LATIN CAPITAL LETTER W WITH DOT ABOVE] +"\u1E86" => "W" + +# Ẉ [LATIN CAPITAL LETTER W WITH DOT BELOW] +"\u1E88" => "W" + +# Ⓦ [CIRCLED LATIN CAPITAL LETTER W] +"\u24CC" => "W" + +# Ⱳ [LATIN CAPITAL LETTER W WITH HOOK] +"\u2C72" => "W" + +# W [FULLWIDTH LATIN CAPITAL LETTER W] +"\uFF37" => "W" + +# ŵ [LATIN SMALL LETTER W WITH CIRCUMFLEX] +"\u0175" => "w" + +# ƿ http://en.wikipedia.org/wiki/Wynn [LATIN LETTER WYNN] +"\u01BF" => "w" + +# ʍ [LATIN SMALL LETTER TURNED W] +"\u028D" => "w" + +# ẁ [LATIN SMALL LETTER W WITH GRAVE] +"\u1E81" => "w" + +# ẃ [LATIN SMALL LETTER W WITH ACUTE] +"\u1E83" => "w" + +# ẅ [LATIN SMALL LETTER W WITH DIAERESIS] +"\u1E85" => "w" + +# ẇ [LATIN SMALL LETTER W WITH DOT ABOVE] +"\u1E87" => "w" + +# ẉ [LATIN SMALL LETTER W WITH DOT BELOW] +"\u1E89" => "w" + +# ẘ [LATIN SMALL LETTER W WITH RING ABOVE] +"\u1E98" => "w" + +# ⓦ [CIRCLED LATIN SMALL LETTER W] +"\u24E6" => "w" + +# ⱳ [LATIN SMALL LETTER W WITH HOOK] +"\u2C73" => "w" + +# w [FULLWIDTH LATIN SMALL LETTER W] +"\uFF57" => "w" + +# ⒲ [PARENTHESIZED LATIN SMALL LETTER W] +"\u24B2" => "(w)" + +# Ẋ [LATIN CAPITAL LETTER X WITH DOT ABOVE] +"\u1E8A" => "X" + +# Ẍ [LATIN CAPITAL LETTER X WITH DIAERESIS] +"\u1E8C" => "X" + +# Ⓧ [CIRCLED LATIN CAPITAL LETTER X] +"\u24CD" => "X" + +# X [FULLWIDTH LATIN CAPITAL LETTER X] +"\uFF38" => "X" + +# ᶍ [LATIN SMALL LETTER X WITH PALATAL HOOK] +"\u1D8D" => "x" + +# ẋ [LATIN SMALL LETTER X WITH DOT ABOVE] +"\u1E8B" => "x" + +# ẍ [LATIN SMALL LETTER X WITH DIAERESIS] +"\u1E8D" => "x" + +# ₓ [LATIN SUBSCRIPT SMALL LETTER X] +"\u2093" => "x" + +# ⓧ [CIRCLED LATIN SMALL LETTER X] +"\u24E7" => "x" + +# x [FULLWIDTH LATIN SMALL LETTER X] +"\uFF58" => "x" + +# ⒳ [PARENTHESIZED LATIN SMALL LETTER X] +"\u24B3" => "(x)" + +# Ý [LATIN CAPITAL LETTER Y WITH ACUTE] +"\u00DD" => "Y" + +# Ŷ [LATIN CAPITAL LETTER Y WITH CIRCUMFLEX] +"\u0176" => "Y" + +# Ÿ [LATIN CAPITAL LETTER Y WITH DIAERESIS] +"\u0178" => "Y" + +# Ƴ [LATIN CAPITAL LETTER Y WITH HOOK] +"\u01B3" => "Y" + +# Ȳ [LATIN CAPITAL LETTER Y WITH MACRON] +"\u0232" => "Y" + +# Ɏ [LATIN CAPITAL LETTER Y WITH STROKE] +"\u024E" => "Y" + +# ʏ [LATIN LETTER SMALL CAPITAL Y] +"\u028F" => "Y" + +# Ẏ [LATIN CAPITAL LETTER Y WITH DOT ABOVE] +"\u1E8E" => "Y" + +# Ỳ [LATIN CAPITAL LETTER Y WITH GRAVE] +"\u1EF2" => "Y" + +# Ỵ [LATIN CAPITAL LETTER Y WITH DOT BELOW] +"\u1EF4" => "Y" + +# Ỷ [LATIN CAPITAL LETTER Y WITH HOOK ABOVE] +"\u1EF6" => "Y" + +# Ỹ [LATIN CAPITAL LETTER Y WITH TILDE] +"\u1EF8" => "Y" + +# Ỿ [LATIN CAPITAL LETTER Y WITH LOOP] +"\u1EFE" => "Y" + +# Ⓨ [CIRCLED LATIN CAPITAL LETTER Y] +"\u24CE" => "Y" + +# Y [FULLWIDTH LATIN CAPITAL LETTER Y] +"\uFF39" => "Y" + +# ý [LATIN SMALL LETTER Y WITH ACUTE] +"\u00FD" => "y" + +# ÿ [LATIN SMALL LETTER Y WITH DIAERESIS] +"\u00FF" => "y" + +# ŷ [LATIN SMALL LETTER Y WITH CIRCUMFLEX] +"\u0177" => "y" + +# ƴ [LATIN SMALL LETTER Y WITH HOOK] +"\u01B4" => "y" + +# ȳ [LATIN SMALL LETTER Y WITH MACRON] +"\u0233" => "y" + +# ɏ [LATIN SMALL LETTER Y WITH STROKE] +"\u024F" => "y" + +# ʎ [LATIN SMALL LETTER TURNED Y] +"\u028E" => "y" + +# ẏ [LATIN SMALL LETTER Y WITH DOT ABOVE] +"\u1E8F" => "y" + +# ẙ [LATIN SMALL LETTER Y WITH RING ABOVE] +"\u1E99" => "y" + +# ỳ [LATIN SMALL LETTER Y WITH GRAVE] +"\u1EF3" => "y" + +# ỵ [LATIN SMALL LETTER Y WITH DOT BELOW] +"\u1EF5" => "y" + +# ỷ [LATIN SMALL LETTER Y WITH HOOK ABOVE] +"\u1EF7" => "y" + +# ỹ [LATIN SMALL LETTER Y WITH TILDE] +"\u1EF9" => "y" + +# ỿ [LATIN SMALL LETTER Y WITH LOOP] +"\u1EFF" => "y" + +# ⓨ [CIRCLED LATIN SMALL LETTER Y] +"\u24E8" => "y" + +# y [FULLWIDTH LATIN SMALL LETTER Y] +"\uFF59" => "y" + +# ⒴ [PARENTHESIZED LATIN SMALL LETTER Y] +"\u24B4" => "(y)" + +# Ź [LATIN CAPITAL LETTER Z WITH ACUTE] +"\u0179" => "Z" + +# Ż [LATIN CAPITAL LETTER Z WITH DOT ABOVE] +"\u017B" => "Z" + +# Ž [LATIN CAPITAL LETTER Z WITH CARON] +"\u017D" => "Z" + +# Ƶ [LATIN CAPITAL LETTER Z WITH STROKE] +"\u01B5" => "Z" + +# Ȝ http://en.wikipedia.org/wiki/Yogh [LATIN CAPITAL LETTER YOGH] +"\u021C" => "Z" + +# Ȥ [LATIN CAPITAL LETTER Z WITH HOOK] +"\u0224" => "Z" + +# ᴢ [LATIN LETTER SMALL CAPITAL Z] +"\u1D22" => "Z" + +# Ẑ [LATIN CAPITAL LETTER Z WITH CIRCUMFLEX] +"\u1E90" => "Z" + +# Ẓ [LATIN CAPITAL LETTER Z WITH DOT BELOW] +"\u1E92" => "Z" + +# Ẕ [LATIN CAPITAL LETTER Z WITH LINE BELOW] +"\u1E94" => "Z" + +# Ⓩ [CIRCLED LATIN CAPITAL LETTER Z] +"\u24CF" => "Z" + +# Ⱬ [LATIN CAPITAL LETTER Z WITH DESCENDER] +"\u2C6B" => "Z" + +# Ꝣ [LATIN CAPITAL LETTER VISIGOTHIC Z] +"\uA762" => "Z" + +# Z [FULLWIDTH LATIN CAPITAL LETTER Z] +"\uFF3A" => "Z" + +# ź [LATIN SMALL LETTER Z WITH ACUTE] +"\u017A" => "z" + +# ż [LATIN SMALL LETTER Z WITH DOT ABOVE] +"\u017C" => "z" + +# ž [LATIN SMALL LETTER Z WITH CARON] +"\u017E" => "z" + +# ƶ [LATIN SMALL LETTER Z WITH STROKE] +"\u01B6" => "z" + +# ȝ http://en.wikipedia.org/wiki/Yogh [LATIN SMALL LETTER YOGH] +"\u021D" => "z" + +# ȥ [LATIN SMALL LETTER Z WITH HOOK] +"\u0225" => "z" + +# ɀ [LATIN SMALL LETTER Z WITH SWASH TAIL] +"\u0240" => "z" + +# ʐ [LATIN SMALL LETTER Z WITH RETROFLEX HOOK] +"\u0290" => "z" + +# ʑ [LATIN SMALL LETTER Z WITH CURL] +"\u0291" => "z" + +# ᵶ [LATIN SMALL LETTER Z WITH MIDDLE TILDE] +"\u1D76" => "z" + +# ᶎ [LATIN SMALL LETTER Z WITH PALATAL HOOK] +"\u1D8E" => "z" + +# ẑ [LATIN SMALL LETTER Z WITH CIRCUMFLEX] +"\u1E91" => "z" + +# ẓ [LATIN SMALL LETTER Z WITH DOT BELOW] +"\u1E93" => "z" + +# ẕ [LATIN SMALL LETTER Z WITH LINE BELOW] +"\u1E95" => "z" + +# ⓩ [CIRCLED LATIN SMALL LETTER Z] +"\u24E9" => "z" + +# ⱬ [LATIN SMALL LETTER Z WITH DESCENDER] +"\u2C6C" => "z" + +# ꝣ [LATIN SMALL LETTER VISIGOTHIC Z] +"\uA763" => "z" + +# z [FULLWIDTH LATIN SMALL LETTER Z] +"\uFF5A" => "z" + +# ⒵ [PARENTHESIZED LATIN SMALL LETTER Z] +"\u24B5" => "(z)" + +# ⁰ [SUPERSCRIPT ZERO] +"\u2070" => "0" + +# ₀ [SUBSCRIPT ZERO] +"\u2080" => "0" + +# ⓪ [CIRCLED DIGIT ZERO] +"\u24EA" => "0" + +# ⓿ [NEGATIVE CIRCLED DIGIT ZERO] +"\u24FF" => "0" + +# 0 [FULLWIDTH DIGIT ZERO] +"\uFF10" => "0" + +# ¹ [SUPERSCRIPT ONE] +"\u00B9" => "1" + +# ₁ [SUBSCRIPT ONE] +"\u2081" => "1" + +# ① [CIRCLED DIGIT ONE] +"\u2460" => "1" + +# ⓵ [DOUBLE CIRCLED DIGIT ONE] +"\u24F5" => "1" + +# ❶ [DINGBAT NEGATIVE CIRCLED DIGIT ONE] +"\u2776" => "1" + +# ➀ [DINGBAT CIRCLED SANS-SERIF DIGIT ONE] +"\u2780" => "1" + +# ➊ [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE] +"\u278A" => "1" + +# 1 [FULLWIDTH DIGIT ONE] +"\uFF11" => "1" + +# ⒈ [DIGIT ONE FULL STOP] +"\u2488" => "1." + +# ⑴ [PARENTHESIZED DIGIT ONE] +"\u2474" => "(1)" + +# ² [SUPERSCRIPT TWO] +"\u00B2" => "2" + +# ₂ [SUBSCRIPT TWO] +"\u2082" => "2" + +# ② [CIRCLED DIGIT TWO] +"\u2461" => "2" + +# ⓶ [DOUBLE CIRCLED DIGIT TWO] +"\u24F6" => "2" + +# ❷ [DINGBAT NEGATIVE CIRCLED DIGIT TWO] +"\u2777" => "2" + +# ➁ [DINGBAT CIRCLED SANS-SERIF DIGIT TWO] +"\u2781" => "2" + +# ➋ [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO] +"\u278B" => "2" + +# 2 [FULLWIDTH DIGIT TWO] +"\uFF12" => "2" + +# ⒉ [DIGIT TWO FULL STOP] +"\u2489" => "2." + +# ⑵ [PARENTHESIZED DIGIT TWO] +"\u2475" => "(2)" + +# ³ [SUPERSCRIPT THREE] +"\u00B3" => "3" + +# ₃ [SUBSCRIPT THREE] +"\u2083" => "3" + +# ③ [CIRCLED DIGIT THREE] +"\u2462" => "3" + +# ⓷ [DOUBLE CIRCLED DIGIT THREE] +"\u24F7" => "3" + +# ❸ [DINGBAT NEGATIVE CIRCLED DIGIT THREE] +"\u2778" => "3" + +# ➂ [DINGBAT CIRCLED SANS-SERIF DIGIT THREE] +"\u2782" => "3" + +# ➌ [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE] +"\u278C" => "3" + +# 3 [FULLWIDTH DIGIT THREE] +"\uFF13" => "3" + +# ⒊ [DIGIT THREE FULL STOP] +"\u248A" => "3." + +# ⑶ [PARENTHESIZED DIGIT THREE] +"\u2476" => "(3)" + +# ⁴ [SUPERSCRIPT FOUR] +"\u2074" => "4" + +# ₄ [SUBSCRIPT FOUR] +"\u2084" => "4" + +# ④ [CIRCLED DIGIT FOUR] +"\u2463" => "4" + +# ⓸ [DOUBLE CIRCLED DIGIT FOUR] +"\u24F8" => "4" + +# ❹ [DINGBAT NEGATIVE CIRCLED DIGIT FOUR] +"\u2779" => "4" + +# ➃ [DINGBAT CIRCLED SANS-SERIF DIGIT FOUR] +"\u2783" => "4" + +# ➍ [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR] +"\u278D" => "4" + +# 4 [FULLWIDTH DIGIT FOUR] +"\uFF14" => "4" + +# ⒋ [DIGIT FOUR FULL STOP] +"\u248B" => "4." + +# ⑷ [PARENTHESIZED DIGIT FOUR] +"\u2477" => "(4)" + +# ⁵ [SUPERSCRIPT FIVE] +"\u2075" => "5" + +# ₅ [SUBSCRIPT FIVE] +"\u2085" => "5" + +# ⑤ [CIRCLED DIGIT FIVE] +"\u2464" => "5" + +# ⓹ [DOUBLE CIRCLED DIGIT FIVE] +"\u24F9" => "5" + +# ❺ [DINGBAT NEGATIVE CIRCLED DIGIT FIVE] +"\u277A" => "5" + +# ➄ [DINGBAT CIRCLED SANS-SERIF DIGIT FIVE] +"\u2784" => "5" + +# ➎ [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE] +"\u278E" => "5" + +# 5 [FULLWIDTH DIGIT FIVE] +"\uFF15" => "5" + +# ⒌ [DIGIT FIVE FULL STOP] +"\u248C" => "5." + +# ⑸ [PARENTHESIZED DIGIT FIVE] +"\u2478" => "(5)" + +# ⁶ [SUPERSCRIPT SIX] +"\u2076" => "6" + +# ₆ [SUBSCRIPT SIX] +"\u2086" => "6" + +# ⑥ [CIRCLED DIGIT SIX] +"\u2465" => "6" + +# ⓺ [DOUBLE CIRCLED DIGIT SIX] +"\u24FA" => "6" + +# ❻ [DINGBAT NEGATIVE CIRCLED DIGIT SIX] +"\u277B" => "6" + +# ➅ [DINGBAT CIRCLED SANS-SERIF DIGIT SIX] +"\u2785" => "6" + +# ➏ [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX] +"\u278F" => "6" + +# 6 [FULLWIDTH DIGIT SIX] +"\uFF16" => "6" + +# ⒍ [DIGIT SIX FULL STOP] +"\u248D" => "6." + +# ⑹ [PARENTHESIZED DIGIT SIX] +"\u2479" => "(6)" + +# ⁷ [SUPERSCRIPT SEVEN] +"\u2077" => "7" + +# ₇ [SUBSCRIPT SEVEN] +"\u2087" => "7" + +# ⑦ [CIRCLED DIGIT SEVEN] +"\u2466" => "7" + +# ⓻ [DOUBLE CIRCLED DIGIT SEVEN] +"\u24FB" => "7" + +# ❼ [DINGBAT NEGATIVE CIRCLED DIGIT SEVEN] +"\u277C" => "7" + +# ➆ [DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN] +"\u2786" => "7" + +# ➐ [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN] +"\u2790" => "7" + +# 7 [FULLWIDTH DIGIT SEVEN] +"\uFF17" => "7" + +# ⒎ [DIGIT SEVEN FULL STOP] +"\u248E" => "7." + +# ⑺ [PARENTHESIZED DIGIT SEVEN] +"\u247A" => "(7)" + +# ⁸ [SUPERSCRIPT EIGHT] +"\u2078" => "8" + +# ₈ [SUBSCRIPT EIGHT] +"\u2088" => "8" + +# ⑧ [CIRCLED DIGIT EIGHT] +"\u2467" => "8" + +# ⓼ [DOUBLE CIRCLED DIGIT EIGHT] +"\u24FC" => "8" + +# ❽ [DINGBAT NEGATIVE CIRCLED DIGIT EIGHT] +"\u277D" => "8" + +# ➇ [DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT] +"\u2787" => "8" + +# ➑ [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT] +"\u2791" => "8" + +# 8 [FULLWIDTH DIGIT EIGHT] +"\uFF18" => "8" + +# ⒏ [DIGIT EIGHT FULL STOP] +"\u248F" => "8." + +# ⑻ [PARENTHESIZED DIGIT EIGHT] +"\u247B" => "(8)" + +# ⁹ [SUPERSCRIPT NINE] +"\u2079" => "9" + +# ₉ [SUBSCRIPT NINE] +"\u2089" => "9" + +# ⑨ [CIRCLED DIGIT NINE] +"\u2468" => "9" + +# ⓽ [DOUBLE CIRCLED DIGIT NINE] +"\u24FD" => "9" + +# ❾ [DINGBAT NEGATIVE CIRCLED DIGIT NINE] +"\u277E" => "9" + +# ➈ [DINGBAT CIRCLED SANS-SERIF DIGIT NINE] +"\u2788" => "9" + +# ➒ [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE] +"\u2792" => "9" + +# 9 [FULLWIDTH DIGIT NINE] +"\uFF19" => "9" + +# ⒐ [DIGIT NINE FULL STOP] +"\u2490" => "9." + +# ⑼ [PARENTHESIZED DIGIT NINE] +"\u247C" => "(9)" + +# ⑩ [CIRCLED NUMBER TEN] +"\u2469" => "10" + +# ⓾ [DOUBLE CIRCLED NUMBER TEN] +"\u24FE" => "10" + +# ❿ [DINGBAT NEGATIVE CIRCLED NUMBER TEN] +"\u277F" => "10" + +# ➉ [DINGBAT CIRCLED SANS-SERIF NUMBER TEN] +"\u2789" => "10" + +# ➓ [DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN] +"\u2793" => "10" + +# ⒑ [NUMBER TEN FULL STOP] +"\u2491" => "10." + +# ⑽ [PARENTHESIZED NUMBER TEN] +"\u247D" => "(10)" + +# ⑪ [CIRCLED NUMBER ELEVEN] +"\u246A" => "11" + +# ⓫ [NEGATIVE CIRCLED NUMBER ELEVEN] +"\u24EB" => "11" + +# ⒒ [NUMBER ELEVEN FULL STOP] +"\u2492" => "11." + +# ⑾ [PARENTHESIZED NUMBER ELEVEN] +"\u247E" => "(11)" + +# ⑫ [CIRCLED NUMBER TWELVE] +"\u246B" => "12" + +# ⓬ [NEGATIVE CIRCLED NUMBER TWELVE] +"\u24EC" => "12" + +# ⒓ [NUMBER TWELVE FULL STOP] +"\u2493" => "12." + +# ⑿ [PARENTHESIZED NUMBER TWELVE] +"\u247F" => "(12)" + +# ⑬ [CIRCLED NUMBER THIRTEEN] +"\u246C" => "13" + +# ⓭ [NEGATIVE CIRCLED NUMBER THIRTEEN] +"\u24ED" => "13" + +# ⒔ [NUMBER THIRTEEN FULL STOP] +"\u2494" => "13." + +# ⒀ [PARENTHESIZED NUMBER THIRTEEN] +"\u2480" => "(13)" + +# ⑭ [CIRCLED NUMBER FOURTEEN] +"\u246D" => "14" + +# ⓮ [NEGATIVE CIRCLED NUMBER FOURTEEN] +"\u24EE" => "14" + +# ⒕ [NUMBER FOURTEEN FULL STOP] +"\u2495" => "14." + +# ⒁ [PARENTHESIZED NUMBER FOURTEEN] +"\u2481" => "(14)" + +# ⑮ [CIRCLED NUMBER FIFTEEN] +"\u246E" => "15" + +# ⓯ [NEGATIVE CIRCLED NUMBER FIFTEEN] +"\u24EF" => "15" + +# ⒖ [NUMBER FIFTEEN FULL STOP] +"\u2496" => "15." + +# ⒂ [PARENTHESIZED NUMBER FIFTEEN] +"\u2482" => "(15)" + +# ⑯ [CIRCLED NUMBER SIXTEEN] +"\u246F" => "16" + +# ⓰ [NEGATIVE CIRCLED NUMBER SIXTEEN] +"\u24F0" => "16" + +# ⒗ [NUMBER SIXTEEN FULL STOP] +"\u2497" => "16." + +# ⒃ [PARENTHESIZED NUMBER SIXTEEN] +"\u2483" => "(16)" + +# ⑰ [CIRCLED NUMBER SEVENTEEN] +"\u2470" => "17" + +# ⓱ [NEGATIVE CIRCLED NUMBER SEVENTEEN] +"\u24F1" => "17" + +# ⒘ [NUMBER SEVENTEEN FULL STOP] +"\u2498" => "17." + +# ⒄ [PARENTHESIZED NUMBER SEVENTEEN] +"\u2484" => "(17)" + +# ⑱ [CIRCLED NUMBER EIGHTEEN] +"\u2471" => "18" + +# ⓲ [NEGATIVE CIRCLED NUMBER EIGHTEEN] +"\u24F2" => "18" + +# ⒙ [NUMBER EIGHTEEN FULL STOP] +"\u2499" => "18." + +# ⒅ [PARENTHESIZED NUMBER EIGHTEEN] +"\u2485" => "(18)" + +# ⑲ [CIRCLED NUMBER NINETEEN] +"\u2472" => "19" + +# ⓳ [NEGATIVE CIRCLED NUMBER NINETEEN] +"\u24F3" => "19" + +# ⒚ [NUMBER NINETEEN FULL STOP] +"\u249A" => "19." + +# ⒆ [PARENTHESIZED NUMBER NINETEEN] +"\u2486" => "(19)" + +# ⑳ [CIRCLED NUMBER TWENTY] +"\u2473" => "20" + +# ⓴ [NEGATIVE CIRCLED NUMBER TWENTY] +"\u24F4" => "20" + +# ⒛ [NUMBER TWENTY FULL STOP] +"\u249B" => "20." + +# ⒇ [PARENTHESIZED NUMBER TWENTY] +"\u2487" => "(20)" + +# « [LEFT-POINTING DOUBLE ANGLE QUOTATION MARK] +"\u00AB" => "\"" + +# » [RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK] +"\u00BB" => "\"" + +# “ [LEFT DOUBLE QUOTATION MARK] +"\u201C" => "\"" + +# ” [RIGHT DOUBLE QUOTATION MARK] +"\u201D" => "\"" + +# „ [DOUBLE LOW-9 QUOTATION MARK] +"\u201E" => "\"" + +# ″ [DOUBLE PRIME] +"\u2033" => "\"" + +# ‶ [REVERSED DOUBLE PRIME] +"\u2036" => "\"" + +# ❝ [HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT] +"\u275D" => "\"" + +# ❞ [HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT] +"\u275E" => "\"" + +# ❮ [HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT] +"\u276E" => "\"" + +# ❯ [HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT] +"\u276F" => "\"" + +# " [FULLWIDTH QUOTATION MARK] +"\uFF02" => "\"" + +# ‘ [LEFT SINGLE QUOTATION MARK] +"\u2018" => "\'" + +# ’ [RIGHT SINGLE QUOTATION MARK] +"\u2019" => "\'" + +# ‚ [SINGLE LOW-9 QUOTATION MARK] +"\u201A" => "\'" + +# ‛ [SINGLE HIGH-REVERSED-9 QUOTATION MARK] +"\u201B" => "\'" + +# ′ [PRIME] +"\u2032" => "\'" + +# ‵ [REVERSED PRIME] +"\u2035" => "\'" + +# ‹ [SINGLE LEFT-POINTING ANGLE QUOTATION MARK] +"\u2039" => "\'" + +# › [SINGLE RIGHT-POINTING ANGLE QUOTATION MARK] +"\u203A" => "\'" + +# ❛ [HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT] +"\u275B" => "\'" + +# ❜ [HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT] +"\u275C" => "\'" + +# ' [FULLWIDTH APOSTROPHE] +"\uFF07" => "\'" + +# ‐ [HYPHEN] +"\u2010" => "-" + +# ‑ [NON-BREAKING HYPHEN] +"\u2011" => "-" + +# ‒ [FIGURE DASH] +"\u2012" => "-" + +# – [EN DASH] +"\u2013" => "-" + +# — [EM DASH] +"\u2014" => "-" + +# ⁻ [SUPERSCRIPT MINUS] +"\u207B" => "-" + +# ₋ [SUBSCRIPT MINUS] +"\u208B" => "-" + +# - [FULLWIDTH HYPHEN-MINUS] +"\uFF0D" => "-" + +# ⁅ [LEFT SQUARE BRACKET WITH QUILL] +"\u2045" => "[" + +# ❲ [LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT] +"\u2772" => "[" + +# [ [FULLWIDTH LEFT SQUARE BRACKET] +"\uFF3B" => "[" + +# ⁆ [RIGHT SQUARE BRACKET WITH QUILL] +"\u2046" => "]" + +# ❳ [LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT] +"\u2773" => "]" + +# ] [FULLWIDTH RIGHT SQUARE BRACKET] +"\uFF3D" => "]" + +# ⁽ [SUPERSCRIPT LEFT PARENTHESIS] +"\u207D" => "(" + +# ₍ [SUBSCRIPT LEFT PARENTHESIS] +"\u208D" => "(" + +# ❨ [MEDIUM LEFT PARENTHESIS ORNAMENT] +"\u2768" => "(" + +# ❪ [MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT] +"\u276A" => "(" + +# ( [FULLWIDTH LEFT PARENTHESIS] +"\uFF08" => "(" + +# ⸨ [LEFT DOUBLE PARENTHESIS] +"\u2E28" => "((" + +# ⁾ [SUPERSCRIPT RIGHT PARENTHESIS] +"\u207E" => ")" + +# ₎ [SUBSCRIPT RIGHT PARENTHESIS] +"\u208E" => ")" + +# ❩ [MEDIUM RIGHT PARENTHESIS ORNAMENT] +"\u2769" => ")" + +# ❫ [MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT] +"\u276B" => ")" + +# ) [FULLWIDTH RIGHT PARENTHESIS] +"\uFF09" => ")" + +# ⸩ [RIGHT DOUBLE PARENTHESIS] +"\u2E29" => "))" + +# ❬ [MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT] +"\u276C" => "<" + +# ❰ [HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT] +"\u2770" => "<" + +# < [FULLWIDTH LESS-THAN SIGN] +"\uFF1C" => "<" + +# ❭ [MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT] +"\u276D" => ">" + +# ❱ [HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT] +"\u2771" => ">" + +# > [FULLWIDTH GREATER-THAN SIGN] +"\uFF1E" => ">" + +# ❴ [MEDIUM LEFT CURLY BRACKET ORNAMENT] +"\u2774" => "{" + +# { [FULLWIDTH LEFT CURLY BRACKET] +"\uFF5B" => "{" + +# ❵ [MEDIUM RIGHT CURLY BRACKET ORNAMENT] +"\u2775" => "}" + +# } [FULLWIDTH RIGHT CURLY BRACKET] +"\uFF5D" => "}" + +# ⁺ [SUPERSCRIPT PLUS SIGN] +"\u207A" => "+" + +# ₊ [SUBSCRIPT PLUS SIGN] +"\u208A" => "+" + +# + [FULLWIDTH PLUS SIGN] +"\uFF0B" => "+" + +# ⁼ [SUPERSCRIPT EQUALS SIGN] +"\u207C" => "=" + +# ₌ [SUBSCRIPT EQUALS SIGN] +"\u208C" => "=" + +# = [FULLWIDTH EQUALS SIGN] +"\uFF1D" => "=" + +# ! [FULLWIDTH EXCLAMATION MARK] +"\uFF01" => "!" + +# ‼ [DOUBLE EXCLAMATION MARK] +"\u203C" => "!!" + +# ⁉ [EXCLAMATION QUESTION MARK] +"\u2049" => "!?" + +# # [FULLWIDTH NUMBER SIGN] +"\uFF03" => "#" + +# $ [FULLWIDTH DOLLAR SIGN] +"\uFF04" => "$" + +# ⁒ [COMMERCIAL MINUS SIGN] +"\u2052" => "%" + +# % [FULLWIDTH PERCENT SIGN] +"\uFF05" => "%" + +# & [FULLWIDTH AMPERSAND] +"\uFF06" => "&" + +# ⁎ [LOW ASTERISK] +"\u204E" => "*" + +# * [FULLWIDTH ASTERISK] +"\uFF0A" => "*" + +# , [FULLWIDTH COMMA] +"\uFF0C" => "," + +# . [FULLWIDTH FULL STOP] +"\uFF0E" => "." + +# ⁄ [FRACTION SLASH] +"\u2044" => "/" + +# / [FULLWIDTH SOLIDUS] +"\uFF0F" => "/" + +# : [FULLWIDTH COLON] +"\uFF1A" => ":" + +# ⁏ [REVERSED SEMICOLON] +"\u204F" => ";" + +# ; [FULLWIDTH SEMICOLON] +"\uFF1B" => ";" + +# ? [FULLWIDTH QUESTION MARK] +"\uFF1F" => "?" + +# ⁇ [DOUBLE QUESTION MARK] +"\u2047" => "??" + +# ⁈ [QUESTION EXCLAMATION MARK] +"\u2048" => "?!" + +# @ [FULLWIDTH COMMERCIAL AT] +"\uFF20" => "@" + +# \ [FULLWIDTH REVERSE SOLIDUS] +"\uFF3C" => "\\" + +# ‸ [CARET] +"\u2038" => "^" + +# ^ [FULLWIDTH CIRCUMFLEX ACCENT] +"\uFF3E" => "^" + +# _ [FULLWIDTH LOW LINE] +"\uFF3F" => "_" + +# ⁓ [SWUNG DASH] +"\u2053" => "~" + +# ~ [FULLWIDTH TILDE] +"\uFF5E" => "~" + +################################################################ +# Below is the Perl script used to generate the above mappings # +# from ASCIIFoldingFilter.java: # +################################################################ +# +# #!/usr/bin/perl +# +# use warnings; +# use strict; +# +# my @source_chars = (); +# my @source_char_descriptions = (); +# my $target = ''; +# +# while (<>) { +# if (/case\s+'(\\u[A-F0-9]+)':\s*\/\/\s*(.*)/i) { +# push @source_chars, $1; +# push @source_char_descriptions, $2; +# next; +# } +# if (/output\[[^\]]+\]\s*=\s*'(\\'|\\\\|.)'/) { +# $target .= $1; +# next; +# } +# if (/break;/) { +# $target = "\\\"" if ($target eq '"'); +# for my $source_char_num (0..$#source_chars) { +# print "# $source_char_descriptions[$source_char_num]\n"; +# print "\"$source_chars[$source_char_num]\" => \"$target\"\n\n"; +# } +# @source_chars = (); +# @source_char_descriptions = (); +# $target = ''; +# } +# } diff --git a/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/mapping-ISOLatin1Accent.txt b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/mapping-ISOLatin1Accent.txt new file mode 100755 index 0000000000..ede7742581 --- /dev/null +++ b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/mapping-ISOLatin1Accent.txt @@ -0,0 +1,246 @@ +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Syntax: +# "source" => "target" +# "source".length() > 0 (source cannot be empty.) +# "target".length() >= 0 (target can be empty.) + +# example: +# "À" => "A" +# "\u00C0" => "A" +# "\u00C0" => "\u0041" +# "ß" => "ss" +# "\t" => " " +# "\n" => "" + +# À => A +"\u00C0" => "A" + +# Á => A +"\u00C1" => "A" + +#  => A +"\u00C2" => "A" + +# à => A +"\u00C3" => "A" + +# Ä => A +"\u00C4" => "A" + +# Å => A +"\u00C5" => "A" + +# Æ => AE +"\u00C6" => "AE" + +# Ç => C +"\u00C7" => "C" + +# È => E +"\u00C8" => "E" + +# É => E +"\u00C9" => "E" + +# Ê => E +"\u00CA" => "E" + +# Ë => E +"\u00CB" => "E" + +# Ì => I +"\u00CC" => "I" + +# Í => I +"\u00CD" => "I" + +# Î => I +"\u00CE" => "I" + +# Ï => I +"\u00CF" => "I" + +# IJ => IJ +"\u0132" => "IJ" + +# Ð => D +"\u00D0" => "D" + +# Ñ => N +"\u00D1" => "N" + +# Ò => O +"\u00D2" => "O" + +# Ó => O +"\u00D3" => "O" + +# Ô => O +"\u00D4" => "O" + +# Õ => O +"\u00D5" => "O" + +# Ö => O +"\u00D6" => "O" + +# Ø => O +"\u00D8" => "O" + +# Œ => OE +"\u0152" => "OE" + +# Þ +"\u00DE" => "TH" + +# Ù => U +"\u00D9" => "U" + +# Ú => U +"\u00DA" => "U" + +# Û => U +"\u00DB" => "U" + +# Ü => U +"\u00DC" => "U" + +# Ý => Y +"\u00DD" => "Y" + +# Ÿ => Y +"\u0178" => "Y" + +# à => a +"\u00E0" => "a" + +# á => a +"\u00E1" => "a" + +# â => a +"\u00E2" => "a" + +# ã => a +"\u00E3" => "a" + +# ä => a +"\u00E4" => "a" + +# å => a +"\u00E5" => "a" + +# æ => ae +"\u00E6" => "ae" + +# ç => c +"\u00E7" => "c" + +# è => e +"\u00E8" => "e" + +# é => e +"\u00E9" => "e" + +# ê => e +"\u00EA" => "e" + +# ë => e +"\u00EB" => "e" + +# ì => i +"\u00EC" => "i" + +# í => i +"\u00ED" => "i" + +# î => i +"\u00EE" => "i" + +# ï => i +"\u00EF" => "i" + +# ij => ij +"\u0133" => "ij" + +# ð => d +"\u00F0" => "d" + +# ñ => n +"\u00F1" => "n" + +# ò => o +"\u00F2" => "o" + +# ó => o +"\u00F3" => "o" + +# ô => o +"\u00F4" => "o" + +# õ => o +"\u00F5" => "o" + +# ö => o +"\u00F6" => "o" + +# ø => o +"\u00F8" => "o" + +# œ => oe +"\u0153" => "oe" + +# ß => ss +"\u00DF" => "ss" + +# þ => th +"\u00FE" => "th" + +# ù => u +"\u00F9" => "u" + +# ú => u +"\u00FA" => "u" + +# û => u +"\u00FB" => "u" + +# ü => u +"\u00FC" => "u" + +# ý => y +"\u00FD" => "y" + +# ÿ => y +"\u00FF" => "y" + +# ff => ff +"\uFB00" => "ff" + +# fi => fi +"\uFB01" => "fi" + +# fl => fl +"\uFB02" => "fl" + +# ffi => ffi +"\uFB03" => "ffi" + +# ffl => ffl +"\uFB04" => "ffl" + +# ſt => ft +"\uFB05" => "ft" + +# st => st +"\uFB06" => "st" diff --git a/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/protwords.txt b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/protwords.txt new file mode 100755 index 0000000000..1dfc0abecb --- /dev/null +++ b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/protwords.txt @@ -0,0 +1,21 @@ +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#----------------------------------------------------------------------- +# Use a protected word file to protect against the stemmer reducing two +# unrelated words to the same base word. + +# Some non-words that normally won't be encountered, +# just to test that they won't be stemmed. +dontstems +zwhacky + diff --git a/KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/schema.xml b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/schema.xml old mode 100644 new mode 100755 similarity index 100% rename from KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/schema.xml rename to KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/schema.xml diff --git a/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/scripts.conf b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/scripts.conf new file mode 100755 index 0000000000..7be01a6bee --- /dev/null +++ b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/scripts.conf @@ -0,0 +1,24 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +user= +solr_hostname=localhost +solr_port=9293 +rsyncd_port=19293 +data_dir= +webapp_name=solr +master_host= +master_data_dir= +master_status_dir= diff --git a/KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/solrconfig.xml b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/solrconfig.xml old mode 100644 new mode 100755 similarity index 100% rename from KeywordSearch/solr/solr/configsets/AutopsyConfig/conf/solrconfig.xml rename to KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/solrconfig.xml diff --git a/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/spellings.txt b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/spellings.txt new file mode 100755 index 0000000000..162a044d56 --- /dev/null +++ b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/spellings.txt @@ -0,0 +1,2 @@ +pizza +history diff --git a/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/stopwords.txt b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/stopwords.txt new file mode 100755 index 0000000000..ae1e83eeb3 --- /dev/null +++ b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/stopwords.txt @@ -0,0 +1,14 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/stopwords_en.txt b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/stopwords_en.txt new file mode 100755 index 0000000000..2c164c0b2a --- /dev/null +++ b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/stopwords_en.txt @@ -0,0 +1,54 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# a couple of test stopwords to test that the words are really being +# configured from this file: +stopworda +stopwordb + +# Standard english stop words taken from Lucene's StopAnalyzer +a +an +and +are +as +at +be +but +by +for +if +in +into +is +it +no +not +of +on +or +such +that +the +their +then +there +these +they +this +to +was +will +with diff --git a/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/synonyms.txt b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/synonyms.txt new file mode 100755 index 0000000000..5c3b95fb6a --- /dev/null +++ b/KeywordSearch/solr4/solr/configsets/AutopsyConfig/conf/synonyms.txt @@ -0,0 +1,31 @@ +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#----------------------------------------------------------------------- +#some test synonym mappings unlikely to appear in real input text +aaafoo => aaabar +bbbfoo => bbbfoo bbbbar +cccfoo => cccbar cccbaz +fooaaa,baraaa,bazaaa + +# Some synonym groups specific to this example +GB,gib,gigabyte,gigabytes +MB,mib,megabyte,megabytes +Television, Televisions, TV, TVs +#notice we use "gib" instead of "GiB" so any WordDelimiterFilter coming +#after us won't split it into two words. + +# Synonym mappings can be used for spelling correction too +pixima => pixma + +a\,a => b\,b + diff --git a/KeywordSearch/solr/solr/solr.xml b/KeywordSearch/solr4/solr/solr.xml old mode 100644 new mode 100755 similarity index 100% rename from KeywordSearch/solr/solr/solr.xml rename to KeywordSearch/solr4/solr/solr.xml diff --git a/KeywordSearch/solr/solr/zoo.cfg b/KeywordSearch/solr4/solr/zoo.cfg old mode 100644 new mode 100755 similarity index 100% rename from KeywordSearch/solr/solr/zoo.cfg rename to KeywordSearch/solr4/solr/zoo.cfg diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties index 84c71a9bf5..22df9fae94 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties @@ -193,7 +193,12 @@ Server.openCore.exception.noIndexDir.msg=Index directory could not be created or Server.request.exception.exception.msg=Could not issue Solr request Server.commit.exception.msg=Could not commit index Server.addDoc.exception.msg=Could not add document to index via update handler: {0} +Server.addDoc.exception.msg2=Could not add document to index via update handler: {0} +Server.addDocBatch.exception.msg=Could not add batched documents to index Server.close.exception.msg=Cannot close Core +Server.connect.exception.msg=Unable to connect to Solr server {0} +Server.serverList.exception.msg=Unable to get the list of Solr servers from server {0} +Server.connectionInfoMissing.exception.msg=Solr version {0} multi-user connection info is not configured Server.solrServerNoPortException.msg=Indexing server could not bind to port {0}, port is not available, consider change the default {1} port. KeywordSearchJobSettingsPanel.keywordSearchEncodings.text=- KeywordSearchJobSettingsPanel.languagesValLabel.toolTipText= @@ -286,8 +291,6 @@ GlobalListsManagementPanel.copyListButton.text=Copy List GlobalListsManagementPanel.renameListButton.text=Edit List Name GlobalEditListPanel.editWordButton.text=Edit Keyword SolrSearchService.ServiceName=Solr Keyword Search Service -SolrSearchService.IndexReadOnlyDialog.title=Text Index Is Read-Only -SolrSearchService.IndexReadOnlyDialog.msg=The text index for this case is read-only.
    You will be able to see existing keyword search results and perform exact match and substring match keyword searches,
    but you will not be able to add new text to the index or perform regex searches. You may instead open the case
    with your previous version of this application. SolrSearchService.DeleteDataSource.msg=Error Deleting Solr data for data source id {0} DropdownSingleTermSearchPanel.dataSourceCheckBox.text=Restrict search to the selected data sources: DropdownListSearchPanel.dataSourceCheckBox.text=Restrict search to the selected data sources: diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED index 95066b41d1..7c80796861 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED @@ -36,7 +36,7 @@ KeywordSearchResultFactory.createNodeForKey.noResultsFound.text=No results found KeywordSearchResultFactory.query.exception.msg=Could not perform the query OpenIDE-Module-Display-Category=Ingest Module -OpenIDE-Module-Long-Description=Keyword Search ingest module.\n\nThe module indexes files found in the disk image at ingest time.\nIt then periodically runs the search on the indexed files using one or more keyword lists (containing pure words and/or regular expressions) and posts results.\n\nThe module also contains additional tools integrated in the main GUI, such as keyword list configuration, keyword search bar in the top-right corner, extracted text viewer and search results viewer showing highlighted keywords found. +OpenIDE-Module-Long-Description=Keyword Search ingest module.\n\nThe module indexes files found in the disk image at ingest time.\nIt then periodically runs the search on the indexed files using one or more keyword lists (containing pure words and/or regular expressions) and posts results.\n\n\The module also contains additional tools integrated in the main GUI, such as keyword list configuration, keyword search bar in the top-right corner, extracted text viewer and search results viewer showing highlighted keywords found. OpenIDE-Module-Name=KeywordSearch OptionsCategory_Name_KeywordSearchOptions=Keyword Search OptionsCategory_Keywords_KeywordSearchOptions=Keyword Search @@ -212,8 +212,11 @@ KeywordSearchSettings.propertiesNSRL.text={0}_NSRL KeywordSearchSettings.propertiesScripts.text={0}_Scripts NoOpenCoreException.err.noOpenSorlCore.msg=No currently open Solr core. SearchRunner.query.exception.msg=Error performing query: -# {0} - core name -Server.deleteCore.exception.msg=Failed to delete Solr core {0} +# {0} - colelction name +Server.deleteCore.exception.msg=Failed to delete Solr colelction {0} +Server.exceptionMessage.unableToBackupCollection=Unable to backup Solr collection +Server.exceptionMessage.unableToCreateCollection=Unable to create Solr collection +Server.exceptionMessage.unableToRestoreCollection=Unable to restore Solr collection Server.start.exception.cantStartSolr.msg=Could not start Solr server process Server.start.exception.cantStartSolr.msg2=Could not start Solr server process Server.isRunning.exception.errCheckSolrRunning.msg=Error checking if Solr server is running @@ -234,7 +237,12 @@ Server.openCore.exception.noIndexDir.msg=Index directory could not be created or Server.request.exception.exception.msg=Could not issue Solr request Server.commit.exception.msg=Could not commit index Server.addDoc.exception.msg=Could not add document to index via update handler: {0} +Server.addDoc.exception.msg2=Could not add document to index via update handler: {0} +Server.addDocBatch.exception.msg=Could not add batched documents to index Server.close.exception.msg=Cannot close Core +Server.connect.exception.msg=Unable to connect to Solr server {0} +Server.serverList.exception.msg=Unable to get the list of Solr servers from server {0} +Server.connectionInfoMissing.exception.msg=Solr version {0} multi-user connection info is not configured Server.solrServerNoPortException.msg=Indexing server could not bind to port {0}, port is not available, consider change the default {1} port. KeywordSearchJobSettingsPanel.keywordSearchEncodings.text=- KeywordSearchJobSettingsPanel.languagesValLabel.toolTipText= @@ -334,19 +342,17 @@ SolrSearch.creatingNewIndex.msg=Creating new text index SolrSearch.findingIndexes.msg=Looking for existing text index directories SolrSearch.indentifyingIndex.msg=Identifying text index to use SolrSearch.lookingForMetadata.msg=Looking for text index metadata file -SolrSearch.openCore.msg=Opening text index -SolrSearch.openGiantCore.msg=Opening text index. Text index for this case is very large and may take long time to load. -SolrSearch.openLargeCore.msg=Opening text index. This may take several minutes. +SolrSearch.openCore.msg=Opening text index. For large cases this may take several minutes. SolrSearch.readingIndexes.msg=Reading text index metadata file # {0} - index folder path SolrSearchService.exceptionMessage.failedToDeleteIndexFiles=Failed to delete text index files at {0} SolrSearchService.exceptionMessage.noCurrentSolrCore=IndexMetadata did not contain a current Solr core so could not delete the case # {0} - case directory SolrSearchService.exceptionMessage.noIndexMetadata=Unable to create IndexMetaData from case directory: {0} +# {0} - collection name +SolrSearchService.exceptionMessage.unableToDeleteCollection=Unable to delete collection {0} SolrSearchService.indexingError=Unable to index blackboard artifact. SolrSearchService.ServiceName=Solr Keyword Search Service -SolrSearchService.IndexReadOnlyDialog.title=Text Index Is Read-Only -SolrSearchService.IndexReadOnlyDialog.msg=The text index for this case is read-only.
    You will be able to see existing keyword search results and perform exact match and substring match keyword searches,
    but you will not be able to add new text to the index or perform regex searches. You may instead open the case
    with your previous version of this application. SolrSearchService.DeleteDataSource.msg=Error Deleting Solr data for data source id {0} DropdownSingleTermSearchPanel.dataSourceCheckBox.text=Restrict search to the selected data sources: DropdownListSearchPanel.dataSourceCheckBox.text=Restrict search to the selected data sources: diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle_ja.properties b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle_ja.properties index 6f7def55a8..58eab4b35a 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle_ja.properties +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle_ja.properties @@ -368,5 +368,35 @@ SolrSearchService.IndexReadOnlyDialog.title=\u30c6\u30ad\u30b9\u30c8\u7d22\u5f15 SolrSearchService.ServiceName=Solr\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u30b5\u30fc\u30d3\u30b9 SolrSearchService.exceptionMessage.failedToDeleteIndexFiles={0} \u306e\u30c6\u30ad\u30b9\u30c8\u7d22\u5f15\u30d5\u30a1\u30a4\u30eb\u3092\u524a\u9664\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f SolrSearchService.exceptionMessage.noCurrentSolrCore=IndexMetadata\u306b\u306f\u73fe\u5728\u306eSolr\u306e\u30b3\u30a2\u304c\u542b\u307e\u308c\u3066\u3044\u306a\u304b\u3063\u305f\u305f\u3081\u3001\u30b1\u30fc\u30b9\u3092\u524a\u9664\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f -SolrSearchService.exceptionMessage.noIndexMetadata=\u30b1\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u304b\u3089\u6b21\u306eIndexMetaData\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\: {0} +# {0} - \u30b1\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc +SolrSearchService.exceptionMessage.noIndexMetadata=\u30b1\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u304b\u3089\u6b21\u306eIndexMetaData\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f: {0} +SolrSearchService.ServiceName=Solr\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u30b5\u30fc\u30d3\u30b9 +DropdownSingleTermSearchPanel.dataSourceCheckBox.text=\u9078\u629e\u3057\u305f\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306b\u691c\u7d22\u3092\u5236\u9650: +DropdownListSearchPanel.dataSourceCheckBox.text=\u9078\u629e\u3057\u305f\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306b\u691c\u7d22\u3092\u5236\u9650: +DropdownSingleTermSearchPanel.ingestIndexLabel.text=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb: +DropdownSingleTermSearchPanel.jSaveSearchResults.toolTipText=\u30ad\u30fc\u30ef\u30fc\u30c9\u30d2\u30c3\u30c8\u306b\u3088\u308b\u904e\u53bb\u306e\u691c\u7d22\u7d50\u679c\u306e\u5f62\u3067\u7d50\u679c\u3092\u4fdd\u5b58\u305b\u305a\u306b\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u3092\u5b9f\u884c +DropdownSingleTermSearchPanel.jSaveSearchResults.text=\u691c\u7d22\u7d50\u679c\u3092\u4fdd\u5b58 +DropdownListSearchPanel.jSaveSearchResults.toolTipText=\u30ad\u30fc\u30ef\u30fc\u30c9\u30d2\u30c3\u30c8\u306b\u3088\u308b\u904e\u53bb\u306e\u691c\u7d22\u7d50\u679c\u306e\u5f62\u3067\u7d50\u679c\u3092\u4fdd\u5b58\u305b\u305a\u306b\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u3092\u5b9f\u884c +DropdownListSearchPanel.jSaveSearchResults.text=\u691c\u7d22\u7d50\u679c\u3092\u4fdd\u5b58 +GlobalEditListPanel.ingestWarningLabel.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u9032\u884c\u4e2d\u3067\u3059\u3002\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u5b8c\u4e86\u3059\u308b\u307e\u3067\u4e00\u90e8\u306e\u8a2d\u5b9a\u3092\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002 +KeywordSearchGlobalLanguageSettingsPanel.ingestWarningLabel.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u9032\u884c\u4e2d\u3067\u3059\u3002\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u5b8c\u4e86\u3059\u308b\u307e\u3067\u4e00\u90e8\u306e\u8a2d\u5b9a\u3092\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002 +KeywordSearchGlobalSearchSettingsPanel.ingestWarningLabel.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u9032\u884c\u4e2d\u3067\u3059\u3002\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u5b8c\u4e86\u3059\u308b\u307e\u3067\u4e00\u90e8\u306e\u8a2d\u5b9a\u3092\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002 +ExtractedContentPanel.jLabel1.text=\u30c6\u30ad\u30b9\u30c8\u30bd\u30fc\u30b9: +ExtractedContentPanel.hitNextButton.text= +ExtractedContentPanel.hitPreviousButton.text= +ExtractedContentPanel.hitButtonsLabel.text=\u4e00\u81f4\u3059\u308b\u7d50\u679c +ExtractedContentPanel.hitTotalLabel.text=- +ExtractedContentPanel.hitOfLabel.text=/ +ExtractedContentPanel.hitCountLabel.text=- +ExtractedContentPanel.hitLabel.toolTipText= +ExtractedContentPanel.hitLabel.text=\u30da\u30fc\u30b8\u4e0a\u306e\u4e00\u81f4\u3059\u308b\u7d50\u679c: +ExtractedContentPanel.pageNextButton.text= +ExtractedContentPanel.pagePreviousButton.actionCommand=pagePreviousButton +ExtractedContentPanel.pagePreviousButton.text= +ExtractedContentPanel.pageButtonsLabel.text=\u30da\u30fc\u30b8 +ExtractedContentPanel.pageTotalLabel.text=- +ExtractedContentPanel.pageOfLabel.text=/ +ExtractedContentPanel.pageCurLabel.text=- +ExtractedContentPanel.pagesLabel.text=\u30da\u30fc\u30b8: TextZoomPanel.zoomResetButton.text=\u30ea\u30bb\u30c3\u30c8 + diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownToolbar.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownToolbar.java index 7c456039b3..3f5669dde6 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownToolbar.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/DropdownToolbar.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2018 Basis Technology Corp. + * Copyright 2011-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -183,23 +183,17 @@ class DropdownToolbar extends javax.swing.JPanel { } else { Index indexInfo = server.getIndexInfo(); - if (IndexFinder.getCurrentSolrVersion().equals(indexInfo.getSolrVersion())) { - /* - * Solr version is current, so check the Solr - * schema version and selectively enable the ad - * hoc search UI components. - */ - boolean schemaIsCompatible = indexInfo.isCompatible(IndexFinder.getCurrentSchemaVersion()); - listsButton.setEnabled(schemaIsCompatible); - searchDropButton.setEnabled(true); - dropPanel.setRegexSearchEnabled(schemaIsCompatible); - active = true; - } else { - /* - * Unsupported Solr version, disable the ad hoc - * search UI components. - */ + + // Check the Solr schema version and enable ad-hoc search UI components. + boolean schemaIsCompatible = indexInfo.isCompatible(IndexFinder.getCurrentSchemaVersion()); + if (!schemaIsCompatible) { + logger.log(Level.WARNING, "Text index schema version {0} is not compatible with current schema", indexInfo.getSchemaVersion()); //NON-NLS disableSearch = true; + } else { + listsButton.setEnabled(true); + searchDropButton.setEnabled(true); + dropPanel.setRegexSearchEnabled(true); + active = true; } } } catch (NoOpenCoreException ex) { diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Index.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Index.java index 20c62ccab2..85afdbff07 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Index.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Index.java @@ -49,7 +49,7 @@ final class Index { Index(String indexPath, String solrVersion, String schemaVersion, String coreName, String caseName) { this.indexPath = uncPathUtilities.convertPathToUNC(indexPath); this.solrVersion = solrVersion; - this.schemaVersion = schemaVersion; + this.schemaVersion = schemaVersion; if (coreName == null || coreName.isEmpty()) { // come up with a new core name coreName = createCoreName(caseName); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IndexFinder.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IndexFinder.java index e2abde6eb0..9219a80b74 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IndexFinder.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IndexFinder.java @@ -20,10 +20,8 @@ package org.sleuthkit.autopsy.keywordsearch; import java.io.File; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.List; +import java.util.logging.Level; import org.apache.commons.lang.math.NumberUtils; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; @@ -38,8 +36,8 @@ class IndexFinder { private static final String KWS_OUTPUT_FOLDER_NAME = "keywordsearch"; private static final String KWS_DATA_FOLDER_NAME = "data"; private static final String INDEX_FOLDER_NAME = "index"; - private static final String CURRENT_SOLR_VERSION = "4"; - private static final String CURRENT_SOLR_SCHEMA_VERSION = "2.2"; + private static final String CURRENT_SOLR_VERSION = "8"; + private static final String CURRENT_SOLR_SCHEMA_VERSION = "2.3"; static String getCurrentSolrVersion() { return CURRENT_SOLR_VERSION; @@ -63,6 +61,7 @@ class IndexFinder { // new index should be stored in "\ModuleOutput\keywordsearch\data\solrX_schemaY\index" File targetDirPath = Paths.get(theCase.getModuleDirectory(), KWS_OUTPUT_FOLDER_NAME, KWS_DATA_FOLDER_NAME, indexFolderName, INDEX_FOLDER_NAME).toFile(); //NON-NLS if (!targetDirPath.mkdirs()) { + logger.log(Level.SEVERE, "Unable to create index directory: {0}", targetDirPath.toString()); throw new AutopsyService.AutopsyServiceException("Unable to create text index directory " + targetDirPath.getAbsolutePath()); } return new Index(targetDirPath.getAbsolutePath(), CURRENT_SOLR_VERSION, CURRENT_SOLR_SCHEMA_VERSION, "", theCase.getName()); @@ -93,84 +92,4 @@ class IndexFinder { } return bestCandidateIndex; } - - /** - * Find existing Solr 4 Schema 1.8 index directory location for the case. - * This is done via subdirectory search of all existing - * "ModuleOutput/node_name/keywordsearch/data/" folders. - * - * @param theCase the case to get index dir for - * - * @return List of Index objects for each found index directory - */ - static Index findOldIndexDir(Case theCase) { - // first find all existing "/ModuleOutput/keywordsearch/data/" folders - if (theCase.getCaseType() == Case.CaseType.MULTI_USER_CASE) { - // multi user cases contain a subfolder for each node that participated in case ingest or review. - // Any one (but only one!) of those subfolders may contain the actual index. - /* - * NOTE: the following path is an example of valid Solr 4 Schema 1.8 - * multi-user index path: - * X:\Case\ingest1\ModuleOutput\keywordsearch\data\index - */ - - // get a list of all folder's contents - List contents = getAllContentsInFolder(theCase.getCaseDirectory()); - if (!contents.isEmpty()) { - // decipher "ModuleOutput" directory name from module output path - // (e.g. X:\Case\ingest4\ModuleOutput\) because there is no other way to get it... - String moduleOutDirName = new File(theCase.getModuleDirectory()).getName(); - - // scan all topLevelOutputDir subfolders for presence of non-empty "/ModuleOutput/keywordsearch/data/" folder - for (File item : contents) { - File path = Paths.get(item.getAbsolutePath(), moduleOutDirName, KWS_OUTPUT_FOLDER_NAME, KWS_DATA_FOLDER_NAME, INDEX_FOLDER_NAME).toFile(); //NON-NLS - // must be a non-empty index directory - if (isNonEmptyIndexFolder(path)) { - return new Index(path.toString(), "4", "1.8", theCase.getTextIndexName(), theCase.getName()); - } - } - } - } else { - // single user case - /* - * NOTE: the following path is valid single user Solr 4 Schema 1.8 - * index path: X:\Case\ModuleOutput\keywordsearch\data\index - */ - File path = Paths.get(theCase.getModuleDirectory(), KWS_OUTPUT_FOLDER_NAME, KWS_DATA_FOLDER_NAME, INDEX_FOLDER_NAME).toFile(); //NON-NLS - // must be a non-empty index directory - if (isNonEmptyIndexFolder(path)) { - return new Index(path.toString(), "4", "1.8", theCase.getTextIndexName(), theCase.getName()); - } - } - return null; - } - - /** - * Returns a list of all contents in the folder of interest. - * - * @param path Absolute targetDirPath of the folder of interest - * - * @return List of all contents in the folder of interest - */ - private static List getAllContentsInFolder(String path) { - File directory = new File(path); - File[] contents = directory.listFiles(); - if (contents == null) { - // the directory file is not really a directory.. - return Collections.emptyList(); - } else if (contents.length == 0) { - // Folder is empty - return Collections.emptyList(); - } else { - // Folder has contents - return new ArrayList<>(Arrays.asList(contents)); - } - } - - private static boolean isNonEmptyIndexFolder(File path) { - if (path.exists() && path.isDirectory() && path.getName().equals(INDEX_FOLDER_NAME) && path.listFiles().length > 0) { - return true; - } - return false; - } } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Installer.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Installer.java index 8119015320..04bcbf6940 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Installer.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Installer.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.keywordsearch; import java.util.logging.Level; +import org.apache.solr.client.solrj.SolrServerException; import org.openide.modules.ModuleInstall; import org.openide.util.NbBundle; import org.openide.windows.WindowManager; @@ -49,12 +50,12 @@ class Installer extends ModuleInstall { server.start(); } catch (SolrServerNoPortException ex) { logger.log(Level.SEVERE, "Failed to start Keyword Search server: ", ex); //NON-NLS - if (ex.getPortNumber() == server.getCurrentSolrServerPort()) { + if (ex.getPortNumber() == server.getLocalSolrServerPort()) { reportPortError(ex.getPortNumber()); } else { reportStopPortError(ex.getPortNumber()); } - } catch (KeywordSearchModuleException ex) { + } catch (KeywordSearchModuleException | SolrServerException ex) { logger.log(Level.SEVERE, "Failed to start Keyword Search server: ", ex); //NON-NLS reportInitError(ex.getMessage()); } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java index d26290d112..00b0eb3431 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java @@ -248,9 +248,6 @@ public final class KeywordSearchIngestModule implements FileIngestModule { try { Index indexInfo = server.getIndexInfo(); - if (!IndexFinder.getCurrentSolrVersion().equals(indexInfo.getSolrVersion())) { - throw new IngestModuleException(Bundle.KeywordSearchIngestModule_startupException_indexSolrVersionNotSupported(indexInfo.getSolrVersion())); - } if (!indexInfo.isCompatible(IndexFinder.getCurrentSchemaVersion())) { throw new IngestModuleException(Bundle.KeywordSearchIngestModule_startupException_indexSchemaNotSupported(indexInfo.getSchemaVersion())); } @@ -295,7 +292,7 @@ public final class KeywordSearchIngestModule implements FileIngestModule { } else { // for single-user cases need to verify connection to local SOLR service try { - if (!server.isRunning()) { + if (!server.isLocalSolrRunning()) { throw new IngestModuleException(Bundle.KeywordSearchIngestModule_init_tryStopSolrMsg(Bundle.KeywordSearchIngestModule_init_badInitMsg())); } } catch (KeywordSearchModuleException ex) { diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/QueryTermHelper.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/QueryTermHelper.java index 39a050c47f..b12f48e4f4 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/QueryTermHelper.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/QueryTermHelper.java @@ -28,6 +28,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import org.apache.solr.client.solrj.impl.BaseHttpSolrClient; /** * Get terms from query using Solr. @@ -70,7 +71,7 @@ final class QueryTermHelper { FieldAnalysisResponse response = new FieldAnalysisResponse(); try { response.setResponse(server.request(request)); - } catch (SolrServerException e) { + } catch (SolrServerException | BaseHttpSolrClient.RemoteSolrException e) { throw new KeywordSearchModuleException(e); } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java index 88c8a774f1..8972d0182f 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2019 Basis Technology Corp. + * Copyright 2011-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,11 +35,12 @@ import java.net.ServerSocket; import java.net.SocketException; import java.nio.charset.Charset; import java.nio.file.Files; +import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Random; @@ -47,22 +48,29 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.logging.Level; -import static java.util.stream.Collectors.toList; import javax.swing.AbstractAction; +import org.apache.commons.io.FileUtils; +import java.util.concurrent.TimeoutException; +import static java.util.stream.Collectors.toList; import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.impl.HttpSolrServer; +import org.apache.solr.client.solrj.SolrClient; +import org.apache.solr.client.solrj.impl.HttpSolrClient; +import org.apache.solr.client.solrj.impl.CloudSolrClient; +import org.apache.solr.client.solrj.impl.ConcurrentUpdateSolrClient; import org.apache.solr.client.solrj.impl.XMLResponseParser; +import org.apache.solr.client.solrj.request.CollectionAdminRequest; +import org.apache.solr.client.solrj.response.CollectionAdminResponse; import org.apache.solr.client.solrj.request.CoreAdminRequest; import org.apache.solr.client.solrj.response.CoreAdminResponse; +import org.apache.solr.client.solrj.impl.BaseHttpSolrClient.RemoteSolrException; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.client.solrj.response.TermsResponse; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrInputDocument; -import org.apache.solr.common.params.CoreAdminParams; import org.apache.solr.common.util.NamedList; import org.openide.modules.InstalledFileLocator; import org.openide.modules.Places; @@ -72,6 +80,7 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case.CaseType; import org.sleuthkit.autopsy.casemodule.CaseMetadata; import org.sleuthkit.autopsy.core.UserPreferences; +import org.sleuthkit.autopsy.coreutils.FileUtil; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.ModuleSettings; @@ -84,7 +93,7 @@ import org.sleuthkit.datamodel.Content; /** * Handles management of a either a local or centralized Solr server and its - * cores. + * collections or cores. */ public class Server { @@ -223,29 +232,34 @@ public class Server { static final String DEFAULT_SOLR_SERVER_HOST = "localhost"; //NON-NLS static final int DEFAULT_SOLR_SERVER_PORT = 23232; static final int DEFAULT_SOLR_STOP_PORT = 34343; - private int currentSolrServerPort = 0; - private int currentSolrStopPort = 0; - private static final boolean DEBUG = false;//(Version.getBuildType() == Version.Type.DEVELOPMENT); + private int localSolrServerPort = 0; + private int localSolrStopPort = 0; + private File localSolrFolder; private static final String SOLR = "solr"; private static final String CORE_PROPERTIES = "core.properties"; + private static final boolean DEBUG = false;//(Version.getBuildType() == Version.Type.DEVELOPMENT); + private static final int NUM_COLLECTION_CREATION_RETRIES = 5; public enum CORE_EVT_STATES { STOPPED, STARTED }; + + private enum SOLR_VERSION { + + SOLR8, SOLR4 + }; // A reference to the locally running Solr instance. - private final HttpSolrServer localSolrServer; + private HttpSolrClient localSolrServer = null; + private SOLR_VERSION localServerVersion = SOLR_VERSION.SOLR8; // start local Solr 8 by default - // A reference to the Solr server we are currently connected to for the Case. - // This could be a local or remote server. - private HttpSolrServer currentSolrServer; + // A reference to the remote/network running Solr instance. + private HttpSolrClient remoteSolrServer; - private Core currentCore; + private Collection currentCollection; private final ReentrantReadWriteLock currentCoreLock; - private final File solrFolder; - private Path solrHome; private final ServerAction serverAction; private InputStreamPrinterThread errorRedirectThread; @@ -256,21 +270,44 @@ public class Server { Server() { initSettings(); - this.localSolrServer = new HttpSolrServer("http://localhost:" + currentSolrServerPort + "/solr"); //NON-NLS serverAction = new ServerAction(); - solrFolder = InstalledFileLocator.getDefault().locate("solr", Server.class.getPackage().getName(), false); //NON-NLS + File solr8Folder = InstalledFileLocator.getDefault().locate("solr", Server.class.getPackage().getName(), false); //NON-NLS + File solr4Folder = InstalledFileLocator.getDefault().locate("solr4", Server.class.getPackage().getName(), false); //NON-NLS + + // Figure out where Java is located. The Java home location + // will be passed as the SOLR_JAVA_HOME environment + // variable to the Solr script but it can be overridden by the user in + // either autopsy-solr.cmd or autopsy-solr-in.cmd. javaPath = PlatformUtil.getJavaPath(); - solrHome = Paths.get(PlatformUtil.getUserDirectory().getAbsolutePath(), "solr"); //NON-NLS - if (!solrHome.toFile().exists()) { - try { - Files.createDirectory(solrHome); - Files.copy(Paths.get(solrFolder.getAbsolutePath(), "solr", "solr.xml"), solrHome.resolve("solr.xml")); //NON-NLS - Files.copy(Paths.get(solrFolder.getAbsolutePath(), "solr", "zoo.cfg"), solrHome.resolve("zoo.cfg")); //NON-NLS - } catch (IOException ex) { - logger.log(Level.SEVERE, "Failed to create Solr home folder:", ex); //NON-NLS + Path solr8Home = Paths.get(PlatformUtil.getUserDirectory().getAbsolutePath(), "solr"); //NON-NLS + try { + // Always copy the config files, as they may have changed. Otherwise potentially stale Solr configuration is being used. + if (!solr8Home.toFile().exists()) { + Files.createDirectory(solr8Home); + } else { + // delete the configsets directory as the Autopsy configset could have changed + FileUtil.deleteDir(solr8Home.resolve("configsets").toFile()); } + Files.copy(Paths.get(solr8Folder.getAbsolutePath(), "server", "solr", "solr.xml"), solr8Home.resolve("solr.xml"), REPLACE_EXISTING); //NON-NLS + Files.copy(Paths.get(solr8Folder.getAbsolutePath(), "server", "solr", "zoo.cfg"), solr8Home.resolve("zoo.cfg"), REPLACE_EXISTING); //NON-NLS + FileUtils.copyDirectory(Paths.get(solr8Folder.getAbsolutePath(), "server", "solr", "configsets").toFile(), solr8Home.resolve("configsets").toFile()); //NON-NLS + } catch (IOException ex) { + logger.log(Level.SEVERE, "Failed to create Solr 8 home folder:", ex); //NON-NLS } + + Path solr4Home = Paths.get(PlatformUtil.getUserDirectory().getAbsolutePath(), "solr4"); //NON-NLS + try { + // Always copy the config files, as they may have changed. Otherwise potentially stale Solr configuration is being used. + if (!solr4Home.toFile().exists()) { + Files.createDirectory(solr4Home); + } + Files.copy(Paths.get(solr4Folder.getAbsolutePath(), "solr", "solr.xml"), solr4Home.resolve("solr.xml"), REPLACE_EXISTING); //NON-NLS + Files.copy(Paths.get(solr4Folder.getAbsolutePath(), "solr", "zoo.cfg"), solr4Home.resolve("zoo.cfg"), REPLACE_EXISTING); //NON-NLS + } catch (IOException ex) { + logger.log(Level.SEVERE, "Failed to create Solr 4 home folder:", ex); //NON-NLS + } + currentCoreLock = new ReentrantReadWriteLock(true); logger.log(Level.INFO, "Created Server instance using Java at {0}", javaPath); //NON-NLS @@ -280,28 +317,76 @@ public class Server { if (ModuleSettings.settingExists(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT)) { try { - currentSolrServerPort = Integer.decode(ModuleSettings.getConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT)); + localSolrServerPort = Integer.decode(ModuleSettings.getConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT)); } catch (NumberFormatException nfe) { logger.log(Level.WARNING, "Could not decode indexing server port, value was not a valid port number, using the default. ", nfe); //NON-NLS - currentSolrServerPort = DEFAULT_SOLR_SERVER_PORT; + localSolrServerPort = DEFAULT_SOLR_SERVER_PORT; } } else { - currentSolrServerPort = DEFAULT_SOLR_SERVER_PORT; - ModuleSettings.setConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT, String.valueOf(currentSolrServerPort)); + localSolrServerPort = DEFAULT_SOLR_SERVER_PORT; + ModuleSettings.setConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT, String.valueOf(localSolrServerPort)); } if (ModuleSettings.settingExists(PROPERTIES_FILE, PROPERTIES_CURRENT_STOP_PORT)) { try { - currentSolrStopPort = Integer.decode(ModuleSettings.getConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_STOP_PORT)); + localSolrStopPort = Integer.decode(ModuleSettings.getConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_STOP_PORT)); } catch (NumberFormatException nfe) { logger.log(Level.WARNING, "Could not decode indexing server stop port, value was not a valid port number, using default", nfe); //NON-NLS - currentSolrStopPort = DEFAULT_SOLR_STOP_PORT; + localSolrStopPort = DEFAULT_SOLR_STOP_PORT; } } else { - currentSolrStopPort = DEFAULT_SOLR_STOP_PORT; - ModuleSettings.setConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_STOP_PORT, String.valueOf(currentSolrStopPort)); + localSolrStopPort = DEFAULT_SOLR_STOP_PORT; + ModuleSettings.setConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_STOP_PORT, String.valueOf(localSolrStopPort)); } } + + private HttpSolrClient getSolrClient(String solrUrl) { + int connectionTimeoutMs = org.sleuthkit.autopsy.keywordsearch.UserPreferences.getConnectionTimeout(); + return new HttpSolrClient.Builder(solrUrl) + .withSocketTimeout(connectionTimeoutMs) + .withConnectionTimeout(connectionTimeoutMs) + .withResponseParser(new XMLResponseParser()) + .build(); + } + + private ConcurrentUpdateSolrClient getConcurrentClient(String solrUrl) { + int numThreads = org.sleuthkit.autopsy.keywordsearch.UserPreferences.getNumThreads(); + int numDocs = org.sleuthkit.autopsy.keywordsearch.UserPreferences.getDocumentsQueueSize(); + int connectionTimeoutMs = org.sleuthkit.autopsy.keywordsearch.UserPreferences.getConnectionTimeout(); + logger.log(Level.INFO, "Creating new ConcurrentUpdateSolrClient: {0}", solrUrl); //NON-NLS + logger.log(Level.INFO, "Queue size = {0}, Number of threads = {1}, Connection Timeout (ms) = {2}", new Object[]{numDocs, numThreads, connectionTimeoutMs}); //NON-NLS + ConcurrentUpdateSolrClient client = new ConcurrentUpdateSolrClient.Builder(solrUrl) + .withQueueSize(numDocs) + .withThreadCount(numThreads) + .withSocketTimeout(connectionTimeoutMs) + .withConnectionTimeout(connectionTimeoutMs) + .withResponseParser(new XMLResponseParser()) + .build(); + + return client; + } + + private CloudSolrClient getCloudSolrClient(String host, String port, String defaultCollectionName) throws KeywordSearchModuleException { + List solrServerList = getSolrServerList(host, port); + List solrUrls = new ArrayList<>(); + for (String server : solrServerList) { + solrUrls.add("http://" + server + "/solr"); + logger.log(Level.INFO, "Using Solr server: {0}", server); + } + + logger.log(Level.INFO, "Creating new CloudSolrClient"); //NON-NLS + int connectionTimeoutMs = org.sleuthkit.autopsy.keywordsearch.UserPreferences.getConnectionTimeout(); + CloudSolrClient client = new CloudSolrClient.Builder(solrUrls) + .withConnectionTimeout(connectionTimeoutMs) + .withSocketTimeout(connectionTimeoutMs) + .withResponseParser(new XMLResponseParser()) + .build(); + if (!defaultCollectionName.isEmpty()) { + client.setDefaultCollection(defaultCollectionName); + } + client.connect(); + return client; + } @Override public void finalize() throws java.lang.Throwable { @@ -313,12 +398,12 @@ public class Server { serverAction.addPropertyChangeListener(l); } - int getCurrentSolrServerPort() { - return currentSolrServerPort; + int getLocalSolrServerPort() { + return localSolrServerPort; } - int getCurrentSolrStopPort() { - return currentSolrStopPort; + int getLocalSolrStopPort() { + return localSolrStopPort; } /** @@ -394,14 +479,60 @@ public class Server { * * @throws IOException */ - private Process runSolrCommand(List solrArguments) throws IOException { + private Process runLocalSolr8ControlCommand(List solrArguments) throws IOException { final String MAX_SOLR_MEM_MB_PAR = "-Xmx" + UserPreferences.getMaxSolrVMSize() + "m"; //NON-NLS + + // This is our customized version of the Solr batch script to start/stop Solr. + File solr8Folder = InstalledFileLocator.getDefault().locate("solr", Server.class.getPackage().getName(), false); //NON-NLS + Path solr8CmdPath = Paths.get(solr8Folder.getAbsolutePath(), "bin", "autopsy-solr.cmd"); //NON-NLS + Path solr8Home = Paths.get(PlatformUtil.getUserDirectory().getAbsolutePath(), "solr"); //NON-NLS + + List commandLine = new ArrayList<>(); + commandLine.add(solr8CmdPath.toString()); + commandLine.addAll(solrArguments); + + ProcessBuilder solrProcessBuilder = new ProcessBuilder(commandLine); + solrProcessBuilder.directory(solr8Folder); + + // Redirect stdout and stderr to files to prevent blocking. + Path solrStdoutPath = Paths.get(Places.getUserDirectory().getAbsolutePath(), "var", "log", "solr.log.stdout"); //NON-NLS + solrProcessBuilder.redirectOutput(solrStdoutPath.toFile()); + + Path solrStderrPath = Paths.get(Places.getUserDirectory().getAbsolutePath(), "var", "log", "solr.log.stderr"); //NON-NLS + solrProcessBuilder.redirectError(solrStderrPath.toFile()); + + // get the path to the JRE folder. That's what Solr needs as SOLR_JAVA_HOME + String jreFolderPath = new File(javaPath).getParentFile().getParentFile().getAbsolutePath(); + + solrProcessBuilder.environment().put("SOLR_JAVA_HOME", jreFolderPath); // NON-NLS + solrProcessBuilder.environment().put("SOLR_HOME", solr8Home.toString()); // NON-NLS + solrProcessBuilder.environment().put("STOP_KEY", KEY); // NON-NLS + solrProcessBuilder.environment().put("SOLR_JAVA_MEM", MAX_SOLR_MEM_MB_PAR); // NON-NLS + logger.log(Level.INFO, "Setting Solr 8 directory: {0}", solr8Folder.toString()); //NON-NLS + logger.log(Level.INFO, "Running Solr 8 command: {0} from {1}", new Object[]{solrProcessBuilder.command(), solr8Folder.toString()}); //NON-NLS + Process process = solrProcessBuilder.start(); + logger.log(Level.INFO, "Finished running Solr 8 command"); //NON-NLS + return process; + } + + /** + * Run a Solr command with the given arguments. + * + * @param solrArguments Command line arguments to pass to the Solr command. + * + * @return + * + * @throws IOException + */ + private Process runLocalSolr4ControlCommand(List solrArguments) throws IOException { + final String MAX_SOLR_MEM_MB_PAR = "-Xmx" + UserPreferences.getMaxSolrVMSize() + "m"; //NON-NLS + File solr4Folder = InstalledFileLocator.getDefault().locate("solr4", Server.class.getPackage().getName(), false); //NON-NLS List commandLine = new ArrayList<>(); commandLine.add(javaPath); commandLine.add(MAX_SOLR_MEM_MB_PAR); - commandLine.add("-DSTOP.PORT=" + currentSolrStopPort); //NON-NLS - commandLine.add("-Djetty.port=" + currentSolrServerPort); //NON-NLS + commandLine.add("-DSTOP.PORT=" + localSolrStopPort); //NON-NLS + commandLine.add("-Djetty.port=" + localSolrServerPort); //NON-NLS commandLine.add("-DSTOP.KEY=" + KEY); //NON-NLS commandLine.add("-jar"); //NON-NLS commandLine.add("start.jar"); //NON-NLS @@ -409,7 +540,7 @@ public class Server { commandLine.addAll(solrArguments); ProcessBuilder solrProcessBuilder = new ProcessBuilder(commandLine); - solrProcessBuilder.directory(solrFolder); + solrProcessBuilder.directory(solr4Folder); // Redirect stdout and stderr to files to prevent blocking. Path solrStdoutPath = Paths.get(Places.getUserDirectory().getAbsolutePath(), "var", "log", "solr.log.stdout"); //NON-NLS @@ -418,11 +549,11 @@ public class Server { Path solrStderrPath = Paths.get(Places.getUserDirectory().getAbsolutePath(), "var", "log", "solr.log.stderr"); //NON-NLS solrProcessBuilder.redirectError(solrStderrPath.toFile()); - logger.log(Level.INFO, "Running Solr command: {0}", solrProcessBuilder.command()); //NON-NLS + logger.log(Level.INFO, "Running Solr 4 command: {0}", solrProcessBuilder.command()); //NON-NLS Process process = solrProcessBuilder.start(); - logger.log(Level.INFO, "Finished running Solr command"); //NON-NLS + logger.log(Level.INFO, "Finished running Solr 4 command"); //NON-NLS return process; - } + } /** * Get list of PIDs of currently running Solr processes @@ -456,6 +587,70 @@ public class Server { PlatformUtil.killProcess(pid); } } + + void start() throws KeywordSearchModuleException, SolrServerNoPortException, SolrServerException { + startLocalSolr(SOLR_VERSION.SOLR8); + } + + private void configureSolrConnection(Case theCase, Index index) throws KeywordSearchModuleException, SolrServerNoPortException { + + try { + if (theCase.getCaseType() == CaseType.SINGLE_USER_CASE) { + + // makes sure the proper local Solr server is running + if (IndexFinder.getCurrentSolrVersion().equals(index.getSolrVersion())) { + startLocalSolr(SOLR_VERSION.SOLR8); + } else { + startLocalSolr(SOLR_VERSION.SOLR4); + } + + // check if the local Solr server is running + if (!this.isLocalSolrRunning()) { + logger.log(Level.SEVERE, "Local Solr server is not running"); //NON-NLS + throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.msg")); + } + } else { + // create SolrJ client to connect to remore Solr server + remoteSolrServer = configureMultiUserConnection(theCase, index, ""); + + // test the connection + connectToSolrServer(remoteSolrServer); + } + } catch (SolrServerException | IOException ex) { + throw new KeywordSearchModuleException(NbBundle.getMessage(Server.class, "Server.connect.exception.msg", ex.getLocalizedMessage()), ex); + } + } + + /** + * Returns a fully configured Solr client to be used for the current case. + * Checks the version of Solr index for the current case (Solr 4 or 8), gets + * connection info for the appropriate Solr server, and configures the Solr + * client. + * + * @param theCase Current case + * @param index Index object for the current case + * @param name Name of the Solr collection + * + * @return Fully configured Solr client. + * + * @throws KeywordSearchModuleException + */ + private HttpSolrClient configureMultiUserConnection(Case theCase, Index index, String name) throws KeywordSearchModuleException { + + // read Solr connection info from user preferences, unless "solrserver.txt" is present + IndexingServerProperties properties = getMultiUserServerProperties(theCase.getCaseDirectory()); + if (properties.host.isEmpty() || properties.port.isEmpty()) { + throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.connectionInfoMissing.exception.msg", index.getSolrVersion())); + } + String solrUrl = "http://" + properties.host + ":" + properties.port + "/solr"; + + if (!name.isEmpty()) { + solrUrl = solrUrl + "/" + name; + } + + // create SolrJ client to connect to remore Solr server + return getSolrClient(solrUrl); + } /** * Tries to start a local Solr instance in a separate process. Returns @@ -464,13 +659,22 @@ public class Server { */ @NbBundle.Messages({ "Server.status.failed.msg=Local Solr server did not respond to status request. This may be because the server failed to start or is taking too long to initialize.",}) - void start() throws KeywordSearchModuleException, SolrServerNoPortException { - if (isRunning()) { - // If a Solr server is running we stop it. - stop(); + void startLocalSolr(SOLR_VERSION version) throws KeywordSearchModuleException, SolrServerNoPortException, SolrServerException { + + if (isLocalSolrRunning()) { + if (localServerVersion.equals(version)) { + // this version of local server is already running + return; + } else { + // wrong version of local server is running, stop it + stop(); + } } + + // set which version of local server is currently running + localServerVersion = version; - if (!isPortAvailable(currentSolrServerPort)) { + if (!isPortAvailable(localSolrServerPort)) { // There is something already listening on our port. Let's see if // this is from an earlier run that didn't successfully shut down // and if so kill it. @@ -479,7 +683,7 @@ public class Server { // If the culprit listening on the port is not a Solr process // we refuse to start. if (pids.isEmpty()) { - throw new SolrServerNoPortException(currentSolrServerPort); + throw new SolrServerNoPortException(localSolrServerPort); } // Ok, we've tried to stop it above but there still appears to be @@ -488,26 +692,35 @@ public class Server { // If either of the ports are still in use after our attempt to kill // previously running processes we give up and throw an exception. - if (!isPortAvailable(currentSolrServerPort)) { - throw new SolrServerNoPortException(currentSolrServerPort); + if (!isPortAvailable(localSolrServerPort)) { + throw new SolrServerNoPortException(localSolrServerPort); } - if (!isPortAvailable(currentSolrStopPort)) { - throw new SolrServerNoPortException(currentSolrStopPort); + if (!isPortAvailable(localSolrStopPort)) { + throw new SolrServerNoPortException(localSolrStopPort); } - } + } - logger.log(Level.INFO, "Starting Solr server from: {0}", solrFolder.getAbsolutePath()); //NON-NLS - - if (isPortAvailable(currentSolrServerPort)) { - logger.log(Level.INFO, "Port [{0}] available, starting Solr", currentSolrServerPort); //NON-NLS + if (isPortAvailable(localSolrServerPort)) { + logger.log(Level.INFO, "Port [{0}] available, starting Solr", localSolrServerPort); //NON-NLS try { - curSolrProcess = runSolrCommand(new ArrayList<>( + if (version == SOLR_VERSION.SOLR8) { + logger.log(Level.INFO, "Starting Solr 8 server"); //NON-NLS + localSolrFolder = InstalledFileLocator.getDefault().locate("solr", Server.class.getPackage().getName(), false); //NON-NLS + curSolrProcess = runLocalSolr8ControlCommand(new ArrayList<>(Arrays.asList("start", "-p", //NON-NLS + Integer.toString(localSolrServerPort)))); //NON-NLS + } else { + // solr4 + localSolrFolder = InstalledFileLocator.getDefault().locate("solr4", Server.class.getPackage().getName(), false); //NON-NLS + logger.log(Level.INFO, "Starting Solr 4 server"); //NON-NLS + curSolrProcess = runLocalSolr4ControlCommand(new ArrayList<>( Arrays.asList("-Dbootstrap_confdir=../solr/configsets/AutopsyConfig/conf", //NON-NLS "-Dcollection.configName=AutopsyConfig"))); //NON-NLS + } - // Wait for the Solr server to start and respond to a status request. + // Wait for the Solr server to start and respond to a statusRequest request. for (int numRetries = 0; numRetries < 6; numRetries++) { - if (isRunning()) { + if (isLocalSolrRunning()) { + localSolrServer = getSolrClient("http://localhost:" + localSolrServerPort + "/solr"); final List pids = this.getSolrPIDs(); logger.log(Level.INFO, "New Solr process PID: {0}", pids); //NON-NLS return; @@ -534,11 +747,9 @@ public class Server { } }); } catch (SecurityException ex) { - logger.log(Level.SEVERE, "Could not start Solr process!", ex); //NON-NLS throw new KeywordSearchModuleException( NbBundle.getMessage(this.getClass(), "Server.start.exception.cantStartSolr.msg"), ex); } catch (IOException ex) { - logger.log(Level.SEVERE, "Could not start Solr server process!", ex); //NON-NLS throw new KeywordSearchModuleException( NbBundle.getMessage(this.getClass(), "Server.start.exception.cantStartSolr.msg2"), ex); } @@ -582,7 +793,7 @@ public class Server { * @param port Port to change to */ void changeSolrServerPort(int port) { - currentSolrServerPort = port; + localSolrServerPort = port; ModuleSettings.setConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT, String.valueOf(port)); } @@ -592,12 +803,12 @@ public class Server { * @param port Port to change to */ void changeSolrStopPort(int port) { - currentSolrStopPort = port; + localSolrStopPort = port; ModuleSettings.setConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_STOP_PORT, String.valueOf(port)); } /** - * Tries to stop the local Solr instance. + * Closes current collection and tries to stop the local Solr instance. * * Waits for the stop command to finish before returning. */ @@ -609,12 +820,25 @@ public class Server { } catch (KeywordSearchModuleException e) { logger.log(Level.WARNING, "Failed to close core: ", e); //NON-NLS } - + + stopLocalSolr(); + } + + /** + * Stops local Solr server instance. + */ + private void stopLocalSolr() { try { - logger.log(Level.INFO, "Stopping Solr server from: {0}", solrFolder.getAbsolutePath()); //NON-NLS - //try graceful shutdown - Process process = runSolrCommand(new ArrayList<>(Arrays.asList("--stop"))); //NON-NLS + Process process; + if (localServerVersion == SOLR_VERSION.SOLR8) { + logger.log(Level.INFO, "Stopping Solr 8 server"); //NON-NLS + process = runLocalSolr8ControlCommand(new ArrayList<>(Arrays.asList("stop", "-k", KEY, "-p", Integer.toString(localSolrServerPort)))); //NON-NLS + } else { + // solr 4 + logger.log(Level.INFO, "Stopping Solr 4 server"); //NON-NLS + process = runLocalSolr4ControlCommand(new ArrayList<>(Arrays.asList("--stop"))); //NON-NLS + } logger.log(Level.INFO, "Waiting for Solr server to stop"); //NON-NLS process.waitFor(); @@ -644,23 +868,23 @@ public class Server { } /** - * Tests if there's a local Solr server running by sending it a core-status - * request. + * Tests if there's a local Solr server running by sending it a core-statusRequest + request. * * @return false if the request failed with a connection error, otherwise - * true + * true */ - synchronized boolean isRunning() throws KeywordSearchModuleException { + synchronized boolean isLocalSolrRunning() throws KeywordSearchModuleException { try { - if (isPortAvailable(currentSolrServerPort)) { + if (isPortAvailable(localSolrServerPort)) { return false; } - // making a status request here instead of just doing solrServer.ping(), because + // making a statusRequest request here instead of just doing solrServer.ping(), because // that doesn't work when there are no cores //TODO handle timeout in cases when some other type of server on that port - connectToSolrServer(localSolrServer); + connectToEbmeddedSolrServer(); logger.log(Level.INFO, "Solr server is running"); //NON-NLS } catch (SolrServerException ex) { @@ -696,15 +920,15 @@ public class Server { * Creates/opens a Solr core (index) for a case. * * @param theCase The case for which the core is to be created/opened. - * @param index The text index that the Solr core should be using. + * @param index The text index that the Solr core should be using. * * @throws KeywordSearchModuleException If an error occurs while - * creating/opening the core. + * creating/opening the core. */ void openCoreForCase(Case theCase, Index index) throws KeywordSearchModuleException { currentCoreLock.writeLock().lock(); try { - currentCore = openCore(theCase, index); + currentCollection = openCore(theCase, index); try { // execute a test query. if it fails, an exception will be thrown @@ -727,7 +951,7 @@ public class Server { boolean coreIsOpen() { currentCoreLock.readLock().lock(); try { - return (null != currentCore); + return (null != currentCollection); } finally { currentCoreLock.readLock().unlock(); } @@ -736,10 +960,10 @@ public class Server { Index getIndexInfo() throws NoOpenCoreException { currentCoreLock.readLock().lock(); try { - if (null == currentCore) { + if (null == currentCollection) { throw new NoOpenCoreException(); } - return currentCore.getIndexInfo(); + return currentCollection.getIndexInfo(); } finally { currentCoreLock.readLock().unlock(); } @@ -748,12 +972,12 @@ public class Server { void closeCore() throws KeywordSearchModuleException { currentCoreLock.writeLock().lock(); try { - if (null != currentCore) { - currentCore.close(); - currentCore = null; + if (null != currentCollection) { + currentCollection.close(); serverAction.putValue(CORE_EVT, CORE_EVT_STATES.STOPPED); } } finally { + currentCollection = null; currentCoreLock.writeLock().unlock(); } } @@ -761,11 +985,11 @@ public class Server { void addDocument(SolrInputDocument doc) throws KeywordSearchModuleException, NoOpenCoreException { currentCoreLock.readLock().lock(); try { - if (null == currentCore) { + if (null == currentCollection) { throw new NoOpenCoreException(); } TimingMetric metric = HealthMonitor.getTimingMetric("Solr: Index chunk"); - currentCore.addDocument(doc); + currentCollection.addDocument(doc); HealthMonitor.submitTimingMetric(metric); } finally { currentCoreLock.readLock().unlock(); @@ -776,37 +1000,26 @@ public class Server { * ** end single-case specific methods *** */ /** - * Deletes the keyword search core for a case. + * Deletes the keyword search collection for a case. * * @param coreName The core name. */ @NbBundle.Messages({ - "# {0} - core name", "Server.deleteCore.exception.msg=Failed to delete Solr core {0}",}) - void deleteCore(String coreName, CaseMetadata metadata) throws KeywordSearchServiceException { + "# {0} - colelction name", "Server.deleteCore.exception.msg=Failed to delete Solr colelction {0}",}) + void deleteCollection(String coreName, CaseMetadata metadata) throws KeywordSearchServiceException, KeywordSearchModuleException { try { - HttpSolrServer solrServer; - if (metadata.getCaseType() == CaseType.SINGLE_USER_CASE) { - Integer localSolrServerPort = Integer.decode(ModuleSettings.getConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT)); - solrServer = new HttpSolrServer("http://localhost:" + localSolrServerPort + "/solr"); //NON-NLS - } else { - IndexingServerProperties properties = getMultiUserServerProperties(metadata.getCaseDirectory()); - solrServer = new HttpSolrServer("http://" + properties.getHost() + ":" + properties.getPort() + "/solr"); //NON-NLS - } + IndexingServerProperties properties = getMultiUserServerProperties(metadata.getCaseDirectory()); + HttpSolrClient solrServer = getSolrClient("http://" + properties.getHost() + ":" + properties.getPort() + "/solr"); connectToSolrServer(solrServer); - CoreAdminResponse response = CoreAdminRequest.getStatus(coreName, solrServer); - if (null != response.getCoreStatus(coreName).get("instanceDir")) { //NON-NLS - /* - * Send a core unload request to the Solr server, with the - * parameter set that request deleting the index and the - * instance directory (deleteInstanceDir = true). Note that this - * removes everything related to the core on the server (the - * index directory, the configuration files, etc.), but does not - * delete the actual Solr text index because it is currently - * stored in the case directory. - */ - org.apache.solr.client.solrj.request.CoreAdminRequest.unloadCore(coreName, true, true, solrServer); + + CollectionAdminRequest.Delete deleteCollectionRequest = CollectionAdminRequest.deleteCollection(coreName); + CollectionAdminResponse response = deleteCollectionRequest.process(solrServer); + if (response.isSuccess()) { + logger.log(Level.INFO, "Deleted collection {0}", coreName); //NON-NLS + } else { + logger.log(Level.WARNING, "Unable to delete collection {0}", coreName); //NON-NLS } - } catch (SolrServerException | HttpSolrServer.RemoteSolrException | IOException ex) { + } catch (SolrServerException | IOException ex) { // We will get a RemoteSolrException with cause == null and detailsMessage // == "Already closed" if the core is not loaded. This is not an error in this scenario. if (!ex.getMessage().equals("Already closed")) { // NON-NLS @@ -819,120 +1032,350 @@ public class Server { * Creates/opens a Solr core (index) for a case. * * @param theCase The case for which the core is to be created/opened. - * @param index The text index that the Solr core should be using. + * @param index The text index that the Solr core should be using. * * @return An object representing the created/opened core. * * @throws KeywordSearchModuleException If an error occurs while - * creating/opening the core. + * creating/opening the core. */ - private Core openCore(Case theCase, Index index) throws KeywordSearchModuleException { + @NbBundle.Messages({ + "Server.exceptionMessage.unableToCreateCollection=Unable to create Solr collection", + "Server.exceptionMessage.unableToBackupCollection=Unable to backup Solr collection", + "Server.exceptionMessage.unableToRestoreCollection=Unable to restore Solr collection", + }) + private Collection openCore(Case theCase, Index index) throws KeywordSearchModuleException { + int numShardsToUse = 1; try { - if (theCase.getCaseType() == CaseType.SINGLE_USER_CASE) { - currentSolrServer = this.localSolrServer; - } else { - IndexingServerProperties properties = getMultiUserServerProperties(theCase.getCaseDirectory()); - currentSolrServer = new HttpSolrServer("http://" + properties.getHost() + ":" + properties.getPort() + "/solr"); //NON-NLS - } - TimingMetric metric = HealthMonitor.getTimingMetric("Solr: Connectivity check"); - connectToSolrServer(currentSolrServer); - HealthMonitor.submitTimingMetric(metric); + // connect to proper Solr server + configureSolrConnection(theCase, index); + if (theCase.getCaseType() == CaseType.MULTI_USER_CASE) { + // select number of shards to use + numShardsToUse = getNumShardsToUse(); + } } catch (Exception ex) { // intentional "catch all" as Solr is known to throw all kinds of Runtime exceptions throw new KeywordSearchModuleException(NbBundle.getMessage(Server.class, "Server.connect.exception.msg", ex.getLocalizedMessage()), ex); } try { - File dataDir = new File(new File(index.getIndexPath()).getParent()); // "data dir" is the parent of the index directory - if (!dataDir.exists()) { - dataDir.mkdirs(); - } - - if (!this.isRunning()) { - logger.log(Level.SEVERE, "Core create/open requested, but server not yet running"); //NON-NLS - throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.msg")); - } - - String coreName = index.getIndexName(); - if (!coreIsLoaded(coreName)) { - /* - * The core either does not exist or it is not loaded. Make a - * request that will cause the core to be created if it does not - * exist or loaded if it already exists. - */ - - // In single user mode, if there is a core.properties file already, - // we've hit a solr bug. Compensate by deleting it. - if (theCase.getCaseType() == CaseType.SINGLE_USER_CASE) { - Path corePropertiesFile = Paths.get(solrFolder.toString(), SOLR, coreName, CORE_PROPERTIES); - if (corePropertiesFile.toFile().exists()) { + String collectionName = index.getIndexName(); + + if (theCase.getCaseType() == CaseType.MULTI_USER_CASE) { + if (!collectionExists(collectionName)) { + /* + * The collection does not exist. Make a request that will cause the colelction to be created. + */ + boolean doRetry = false; + for (int reTryAttempt = 0; reTryAttempt < NUM_COLLECTION_CREATION_RETRIES; reTryAttempt++) { try { - corePropertiesFile.toFile().delete(); + doRetry = false; + createMultiUserCollection(collectionName, numShardsToUse); } catch (Exception ex) { - logger.log(Level.INFO, "Could not delete pre-existing core.properties prior to opening the core."); //NON-NLS + if (reTryAttempt >= NUM_COLLECTION_CREATION_RETRIES) { + logger.log(Level.SEVERE, "Unable to create Solr collection " + collectionName, ex); //NON-NLS + throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.cantOpen.msg"), ex); + } else { + logger.log(Level.SEVERE, "Unable to create Solr collection " + collectionName + ". Re-trying...", ex); //NON-NLS + Thread.sleep(1000L); + doRetry = true; + } + } + if (!doRetry) { + break; } } } + } else { + if (!coreIsLoaded(collectionName)) { + // In single user mode, the index is stored in case output directory + File dataDir = new File(new File(index.getIndexPath()).getParent()); // "data dir" is the parent of the index directory + if (!dataDir.exists()) { + dataDir.mkdirs(); + } + + // In single user mode, if there is a core.properties file already, + // we've hit a solr bug. Compensate by deleting it. + if (theCase.getCaseType() == CaseType.SINGLE_USER_CASE) { + Path corePropertiesFile = Paths.get(localSolrFolder.toString(), SOLR, collectionName, CORE_PROPERTIES); + if (corePropertiesFile.toFile().exists()) { + try { + corePropertiesFile.toFile().delete(); + } catch (Exception ex) { + logger.log(Level.INFO, "Could not delete pre-existing core.properties prior to opening the core."); //NON-NLS + } + } + } - CoreAdminRequest.Create createCoreRequest = new CoreAdminRequest.Create(); - createCoreRequest.setDataDir(dataDir.getAbsolutePath()); - createCoreRequest.setCoreName(coreName); - createCoreRequest.setConfigSet("AutopsyConfig"); //NON-NLS - createCoreRequest.setIsLoadOnStartup(false); - createCoreRequest.setIsTransient(true); - currentSolrServer.request(createCoreRequest); + // for single user cases, we unload the core when we close the case. So we have to load the core again. + CoreAdminRequest.Create createCoreRequest = new CoreAdminRequest.Create(); + createCoreRequest.setDataDir(dataDir.getAbsolutePath()); + createCoreRequest.setCoreName(collectionName); + createCoreRequest.setConfigSet("AutopsyConfig"); //NON-NLS + createCoreRequest.setIsLoadOnStartup(false); + createCoreRequest.setIsTransient(true); + localSolrServer.request(createCoreRequest); + + if (!coreIndexFolderExists(collectionName)) { + throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.noIndexDir.msg")); + } + } } - if (!coreIndexFolderExists(coreName)) { - throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.noIndexDir.msg")); - } - - return new Core(coreName, theCase.getCaseType(), index); + return new Collection(collectionName, theCase, index); } catch (Exception ex) { + logger.log(Level.SEVERE, "Exception during Solr collection creation.", ex); //NON-NLS throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.cantOpen.msg"), ex); } } + + private int getNumShardsToUse() throws KeywordSearchModuleException { + + // if we want to use a specific sharding strategy, use that + if (org.sleuthkit.autopsy.keywordsearch.UserPreferences.getMaxNumShards() > 0) { + return org.sleuthkit.autopsy.keywordsearch.UserPreferences.getMaxNumShards(); + } + + // otherwise get list of all live Solr servers in the cluster + List solrServerList = getSolrServerList(remoteSolrServer); + // shard across all available servers + return solrServerList.size(); + } + + /* + * Poll the remote Solr server for list of existing collections, and check if + * the collection of interest exists. + * + * @param collectionName The name of the collection. + * + * @return True if the collection exists, false otherwise. + * + * @throws SolrServerException If there is a problem communicating with the + * Solr server. + * @throws IOException If there is a problem communicating with the Solr + * server. + */ + private boolean collectionExists(String collectionName) throws SolrServerException, IOException { + CollectionAdminRequest.List req = new CollectionAdminRequest.List(); + CollectionAdminResponse response = req.process(remoteSolrServer); + List existingCollections = (List) response.getResponse().get("collections"); + if (existingCollections == null) { + existingCollections = new ArrayList<>(); + } + return existingCollections.contains(collectionName); + } + + /* NOTE: Keeping this code for reference, since it works. + private boolean collectionExists(String collectionName) throws SolrServerException, IOException { + + // TODO we could potentially use this API. Currently set exception "Solr instance is not running in SolrCloud mode" + // List list = CollectionAdminRequest.listCollections(localSolrServer); + + CollectionAdminRequest.ClusterStatus statusRequest = CollectionAdminRequest.getClusterStatus().setCollectionName(collectionName); + CollectionAdminResponse statusResponse; + try { + statusResponse = statusRequest.process(remoteSolrServer); + } catch (RemoteSolrException ex) { + // collection doesn't exist + return false; + } + + if (statusResponse == null) { + return false; + } + + NamedList error = (NamedList) statusResponse.getResponse().get("error"); + if (error != null) { + return false; + } + + // For some reason this returns info about all collections even though it's supposed to only return about the one we are requesting + NamedList cluster = (NamedList) statusResponse.getResponse().get("cluster"); + NamedList collections = (NamedList) cluster.get("collections"); + if (collections != null) { + Object collection = collections.get(collectionName); + return (collection != null); + } else { + return false; + } + }*/ + + private void createMultiUserCollection(String collectionName, int numShardsToUse) throws KeywordSearchModuleException, SolrServerException, IOException { + /* + * The core either does not exist or it is not loaded. Make a + * request that will cause the core to be created if it does not + * exist or loaded if it already exists. + */ + + Integer numShards = numShardsToUse; + logger.log(Level.INFO, "numShardsToUse: {0}", numShardsToUse); + Integer numNrtReplicas = 1; + Integer numTlogReplicas = 0; + Integer numPullReplicas = 0; + CollectionAdminRequest.Create createCollectionRequest = CollectionAdminRequest.createCollection(collectionName, "AutopsyConfig", numShards, numNrtReplicas, numTlogReplicas, numPullReplicas); + + CollectionAdminResponse createResponse = createCollectionRequest.process(remoteSolrServer); + if (createResponse.isSuccess()) { + logger.log(Level.INFO, "Collection {0} successfully created.", collectionName); + } else { + logger.log(Level.SEVERE, "Unable to create Solr collection {0}", collectionName); //NON-NLS + throw new KeywordSearchModuleException(Bundle.Server_exceptionMessage_unableToCreateCollection()); + } + + /* If we need core name: + Map> status = createResponse.getCollectionCoresStatus(); + existingCoreName = status.keySet().iterator().next();*/ + if (!collectionExists(collectionName)) { + throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.noIndexDir.msg")); + } + } + + private void backupCollection(String collectionName, String backupName, String pathToBackupLocation) throws SolrServerException, IOException, KeywordSearchModuleException { + CollectionAdminRequest.Backup backup = CollectionAdminRequest.backupCollection(collectionName, backupName) + .setLocation(pathToBackupLocation); + + CollectionAdminResponse backupResponse = backup.process(remoteSolrServer); + if (backupResponse.isSuccess()) { + logger.log(Level.INFO, "Collection {0} successfully backep up.", collectionName); + } else { + logger.log(Level.SEVERE, "Unable to back up Solr collection {0}", collectionName); //NON-NLS + throw new KeywordSearchModuleException(Bundle.Server_exceptionMessage_unableToBackupCollection()); + } + } + + private void restoreCollection(String backupName, String restoreCollectionName, String pathToBackupLocation) throws SolrServerException, IOException, KeywordSearchModuleException { + + CollectionAdminRequest.Restore restore = CollectionAdminRequest.restoreCollection(restoreCollectionName, backupName) + .setLocation(pathToBackupLocation); + + CollectionAdminResponse restoreResponse = restore.process(remoteSolrServer); + if (restoreResponse.isSuccess()) { + logger.log(Level.INFO, "Collection {0} successfully resored.", restoreCollectionName); + } else { + logger.log(Level.SEVERE, "Unable to restore Solr collection {0}", restoreCollectionName); //NON-NLS + throw new KeywordSearchModuleException(Bundle.Server_exceptionMessage_unableToRestoreCollection()); + } + } + + /** + * Determines whether or not a particular Solr core exists and is loaded. + * This is used only with embedded Solr server running in non-cloud mode. + * + * @param coreName The name of the core. + * + * @return True if the core exists and is loaded, false if the core does not + * exist or is not loaded + * + * @throws SolrServerException If there is a problem communicating with the + * Solr server. + * @throws IOException If there is a problem communicating with the Solr + * server. + */ + private boolean coreIsLoaded(String coreName) throws SolrServerException, IOException { + CoreAdminResponse response = CoreAdminRequest.getStatus(coreName, localSolrServer); + return response.getCoreStatus(coreName).get("instanceDir") != null; //NON-NLS + } + + /** + * Determines whether or not the index files folder for a Solr core + * exists. This is used only with embedded Solr server running in non-cloud + * mode. + * + * @param coreName the name of the core. + * + * @return true or false + * + * @throws SolrServerException + * @throws IOException + */ + private boolean coreIndexFolderExists(String coreName) throws SolrServerException, IOException { + CoreAdminResponse response = CoreAdminRequest.getStatus(coreName, localSolrServer); + Object dataDirPath = response.getCoreStatus(coreName).get("dataDir"); //NON-NLS + if (null != dataDirPath) { + File indexDir = Paths.get((String) dataDirPath, "index").toFile(); //NON-NLS + return indexDir.exists(); + } else { + return false; + } + } /** - * Get the host and port for a multiuser case. If the file solrserver.txt + * Get the host and port for a multi-user case. If the file solrserver.txt * exists, then use the values from that file. Otherwise use the settings - * from the properties file. + * from the properties file, depending on which version of Solr was used to + * create the current index. Defaults to using latest Solr version info if + * an error occurred. * * @param caseDirectory Current case directory - * * @return IndexingServerProperties containing the solr host/port for this - * case + * case */ public static IndexingServerProperties getMultiUserServerProperties(String caseDirectory) { - Path serverFilePath = Paths.get(caseDirectory, "solrserver.txt"); + // if "solrserver.txt" is present, use those connection settings + Path serverFilePath = Paths.get(caseDirectory, "solrserver.txt"); //NON-NLS if (serverFilePath.toFile().exists()) { try { List lines = Files.readAllLines(serverFilePath); if (lines.isEmpty()) { - logger.log(Level.SEVERE, "solrserver.txt file does not contain any data"); + logger.log(Level.SEVERE, "solrserver.txt file does not contain any data"); //NON-NLS } else if (!lines.get(0).contains(",")) { - logger.log(Level.SEVERE, "solrserver.txt file is corrupt - could not read host/port from " + lines.get(0)); + logger.log(Level.SEVERE, "solrserver.txt file is corrupt - could not read host/port from " + lines.get(0)); //NON-NLS } else { String[] parts = lines.get(0).split(","); if (parts.length != 2) { - logger.log(Level.SEVERE, "solrserver.txt file is corrupt - could not read host/port from " + lines.get(0)); + logger.log(Level.SEVERE, "solrserver.txt file is corrupt - could not read host/port from " + lines.get(0)); //NON-NLS } else { return new IndexingServerProperties(parts[0], parts[1]); } } } catch (IOException ex) { - logger.log(Level.SEVERE, "solrserver.txt file could not be read", ex); + logger.log(Level.SEVERE, "solrserver.txt file could not be read", ex); //NON-NLS } } + + // otherwise (or if an error occurred) determine Solr version of the current case + List indexes = new ArrayList<>(); + try { + IndexMetadata indexMetadata = new IndexMetadata(caseDirectory); + indexes = indexMetadata.getIndexes(); + } catch (IndexMetadata.TextIndexMetadataException ex) { + logger.log(Level.SEVERE, "Unable to read text index metadata file: " + caseDirectory, ex); + + // default to using the latest Solr version settings + String host = UserPreferences.getIndexingServerHost(); + String port = UserPreferences.getIndexingServerPort(); + return new IndexingServerProperties(host, port); + } - // Default back to the user preferences if the solrserver.txt file was not found or if an error occurred - String host = UserPreferences.getIndexingServerHost(); - String port = UserPreferences.getIndexingServerPort(); - return new IndexingServerProperties(host, port); + // select which index to use. In practice, all cases always have only one + // index but there is support for having multiple indexes. + Index indexToUse = IndexFinder.identifyIndexToUse(indexes); + if (indexToUse == null) { + // unable to find index that can be used + logger.log(Level.SEVERE, "Unable to find index that can be used for case: {0}", caseDirectory); + + // default to using the latest Solr version settings + String host = UserPreferences.getIndexingServerHost(); + String port = UserPreferences.getIndexingServerPort(); + return new IndexingServerProperties(host, port); + } + + // return connection info for the Solr version of the current index + if (IndexFinder.getCurrentSolrVersion().equals(indexToUse.getSolrVersion())) { + // Solr 8 + String host = UserPreferences.getIndexingServerHost(); + String port = UserPreferences.getIndexingServerPort(); + return new IndexingServerProperties(host, port); + } else { + // Solr 4 + String host = UserPreferences.getSolr4ServerHost().trim(); + String port = UserPreferences.getSolr4ServerPort().trim(); + return new IndexingServerProperties(host, port); + } } /** @@ -944,12 +1387,11 @@ public class Server { * * @param rootOutputDirectory * @param caseDirectoryPath - * * @throws KeywordSearchModuleException */ public static void selectSolrServerForCase(Path rootOutputDirectory, Path caseDirectoryPath) throws KeywordSearchModuleException { // Look for the solr server list file - String serverListName = "solrServerList.txt"; + String serverListName = "solrServerList.txt"; //NON-NLS Path serverListPath = Paths.get(rootOutputDirectory.toString(), serverListName); if (serverListPath.toFile().exists()) { @@ -958,7 +1400,7 @@ public class Server { try { lines = Files.readAllLines(serverListPath); } catch (IOException ex) { - throw new KeywordSearchModuleException(serverListName + " could not be read", ex); + throw new KeywordSearchModuleException(serverListName + " could not be read", ex); //NON-NLS } // Remove any lines that don't contain a comma (these are likely just whitespace) @@ -970,37 +1412,37 @@ public class Server { } } if (lines.isEmpty()) { - throw new KeywordSearchModuleException(serverListName + " had no valid server information"); + throw new KeywordSearchModuleException(serverListName + " had no valid server information"); //NON-NLS } // Choose which server to use int rnd = new Random().nextInt(lines.size()); String[] parts = lines.get(rnd).split(","); if (parts.length != 2) { - throw new KeywordSearchModuleException("Invalid server data: " + lines.get(rnd)); + throw new KeywordSearchModuleException("Invalid server data: " + lines.get(rnd)); //NON-NLS } // Split it up just to do a sanity check on the data String host = parts[0]; String port = parts[1]; if (host.isEmpty() || port.isEmpty()) { - throw new KeywordSearchModuleException("Invalid server data: " + lines.get(rnd)); + throw new KeywordSearchModuleException("Invalid server data: " + lines.get(rnd)); //NON-NLS } // Write the server data to a file - Path serverFile = Paths.get(caseDirectoryPath.toString(), "solrserver.txt"); + Path serverFile = Paths.get(caseDirectoryPath.toString(), "solrserver.txt"); //NON-NLS try { caseDirectoryPath.toFile().mkdirs(); if (!caseDirectoryPath.toFile().exists()) { - throw new KeywordSearchModuleException("Case directory " + caseDirectoryPath.toString() + " does not exist"); + throw new KeywordSearchModuleException("Case directory " + caseDirectoryPath.toString() + " does not exist"); //NON-NLS } Files.write(serverFile, lines.get(rnd).getBytes()); } catch (IOException ex) { - throw new KeywordSearchModuleException(serverFile.toString() + " could not be written", ex); + throw new KeywordSearchModuleException(serverFile.toString() + " could not be written", ex); //NON-NLS } } } - + /** * Helper class to store the current server properties */ @@ -1041,22 +1483,22 @@ public class Server { void commit() throws SolrServerException, NoOpenCoreException { currentCoreLock.readLock().lock(); try { - if (null == currentCore) { + if (null == currentCollection) { throw new NoOpenCoreException(); } - currentCore.commit(); + currentCollection.commit(); } finally { currentCoreLock.readLock().unlock(); } } - NamedList request(SolrRequest request) throws SolrServerException, NoOpenCoreException { + NamedList request(SolrRequest request) throws SolrServerException, RemoteSolrException, NoOpenCoreException { currentCoreLock.readLock().lock(); try { - if (null == currentCore) { + if (null == currentCollection) { throw new NoOpenCoreException(); } - return currentCore.request(request); + return currentCollection.request(request); } finally { currentCoreLock.readLock().unlock(); } @@ -1075,11 +1517,11 @@ public class Server { public int queryNumIndexedFiles() throws KeywordSearchModuleException, NoOpenCoreException { currentCoreLock.readLock().lock(); try { - if (null == currentCore) { + if (null == currentCollection) { throw new NoOpenCoreException(); } try { - return currentCore.queryNumIndexedFiles(); + return currentCollection.queryNumIndexedFiles(); } catch (Exception ex) { // intentional "catch all" as Solr is known to throw all kinds of Runtime exceptions throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.queryNumIdxFiles.exception.msg"), ex); @@ -1101,11 +1543,11 @@ public class Server { public int queryNumIndexedChunks() throws KeywordSearchModuleException, NoOpenCoreException { currentCoreLock.readLock().lock(); try { - if (null == currentCore) { + if (null == currentCollection) { throw new NoOpenCoreException(); } try { - return currentCore.queryNumIndexedChunks(); + return currentCollection.queryNumIndexedChunks(); } catch (Exception ex) { // intentional "catch all" as Solr is known to throw all kinds of Runtime exceptions throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.queryNumIdxChunks.exception.msg"), ex); @@ -1127,11 +1569,11 @@ public class Server { public int queryNumIndexedDocuments() throws KeywordSearchModuleException, NoOpenCoreException { currentCoreLock.readLock().lock(); try { - if (null == currentCore) { + if (null == currentCollection) { throw new NoOpenCoreException(); } try { - return currentCore.queryNumIndexedDocuments(); + return currentCollection.queryNumIndexedDocuments(); } catch (Exception ex) { // intentional "catch all" as Solr is known to throw all kinds of Runtime exceptions throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.queryNumIdxDocs.exception.msg"), ex); @@ -1154,11 +1596,11 @@ public class Server { public boolean queryIsIndexed(long contentID) throws KeywordSearchModuleException, NoOpenCoreException { currentCoreLock.readLock().lock(); try { - if (null == currentCore) { + if (null == currentCollection) { throw new NoOpenCoreException(); } try { - return currentCore.queryIsIndexed(contentID); + return currentCollection.queryIsIndexed(contentID); } catch (Exception ex) { // intentional "catch all" as Solr is known to throw all kinds of Runtime exceptions throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.queryIsIdxd.exception.msg"), ex); @@ -1175,7 +1617,7 @@ public class Server { * @param fileID file id of the original file broken into chunks and indexed * * @return int representing number of indexed file chunks, 0 if there is no - * chunks + * chunks * * @throws KeywordSearchModuleException * @throws NoOpenCoreException @@ -1183,11 +1625,11 @@ public class Server { public int queryNumFileChunks(long fileID) throws KeywordSearchModuleException, NoOpenCoreException { currentCoreLock.readLock().lock(); try { - if (null == currentCore) { + if (null == currentCollection) { throw new NoOpenCoreException(); } try { - return currentCore.queryNumFileChunks(fileID); + return currentCollection.queryNumFileChunks(fileID); } catch (Exception ex) { // intentional "catch all" as Solr is known to throw all kinds of Runtime exceptions throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.queryNumFileChunks.exception.msg"), ex); @@ -1210,11 +1652,11 @@ public class Server { public QueryResponse query(SolrQuery sq) throws KeywordSearchModuleException, NoOpenCoreException, IOException { currentCoreLock.readLock().lock(); try { - if (null == currentCore) { + if (null == currentCollection) { throw new NoOpenCoreException(); } try { - return currentCore.query(sq); + return currentCollection.query(sq); } catch (Exception ex) { // intentional "catch all" as Solr is known to throw all kinds of Runtime exceptions logger.log(Level.SEVERE, "Solr query failed: " + sq.getQuery(), ex); //NON-NLS @@ -1228,7 +1670,7 @@ public class Server { /** * Execute solr query * - * @param sq the query + * @param sq the query * @param method http method to use * * @return query response @@ -1239,11 +1681,11 @@ public class Server { public QueryResponse query(SolrQuery sq, SolrRequest.METHOD method) throws KeywordSearchModuleException, NoOpenCoreException { currentCoreLock.readLock().lock(); try { - if (null == currentCore) { + if (null == currentCollection) { throw new NoOpenCoreException(); } try { - return currentCore.query(sq, method); + return currentCollection.query(sq, method); } catch (Exception ex) { // intentional "catch all" as Solr is known to throw all kinds of Runtime exceptions logger.log(Level.SEVERE, "Solr query failed: " + sq.getQuery(), ex); //NON-NLS @@ -1267,11 +1709,11 @@ public class Server { public TermsResponse queryTerms(SolrQuery sq) throws KeywordSearchModuleException, NoOpenCoreException { currentCoreLock.readLock().lock(); try { - if (null == currentCore) { + if (null == currentCollection) { throw new NoOpenCoreException(); } try { - return currentCore.queryTerms(sq); + return currentCollection.queryTerms(sq); } catch (Exception ex) { // intentional "catch all" as Solr is known to throw all kinds of Runtime exceptions logger.log(Level.SEVERE, "Solr terms query failed: " + sq.getQuery(), ex); //NON-NLS @@ -1292,11 +1734,11 @@ public class Server { void deleteDataSource(Long dataSourceId) throws IOException, KeywordSearchModuleException, NoOpenCoreException, SolrServerException { try { currentCoreLock.writeLock().lock(); - if (null == currentCore) { + if (null == currentCollection) { throw new NoOpenCoreException(); } - currentCore.deleteDataSource(dataSourceId); - currentCore.commit(); + currentCollection.deleteDataSource(dataSourceId); + currentCollection.commit(); } finally { currentCoreLock.writeLock().unlock(); } @@ -1314,10 +1756,10 @@ public class Server { public String getSolrContent(final Content content) throws NoOpenCoreException { currentCoreLock.readLock().lock(); try { - if (null == currentCore) { + if (null == currentCollection) { throw new NoOpenCoreException(); } - return currentCore.getSolrContent(content.getId(), 0); + return currentCollection.getSolrContent(content.getId(), 0); } finally { currentCoreLock.readLock().unlock(); } @@ -1329,7 +1771,7 @@ public class Server { * * @param content to get the text for * @param chunkID chunk number to query (starting at 1), or 0 if there is no - * chunks for that content + * chunks for that content * * @return content text string or null if error quering * @@ -1338,10 +1780,10 @@ public class Server { public String getSolrContent(final Content content, int chunkID) throws NoOpenCoreException { currentCoreLock.readLock().lock(); try { - if (null == currentCore) { + if (null == currentCollection) { throw new NoOpenCoreException(); } - return currentCore.getSolrContent(content.getId(), chunkID); + return currentCollection.getSolrContent(content.getId(), chunkID); } finally { currentCoreLock.readLock().unlock(); } @@ -1359,10 +1801,10 @@ public class Server { public String getSolrContent(final long objectID) throws NoOpenCoreException { currentCoreLock.readLock().lock(); try { - if (null == currentCore) { + if (null == currentCollection) { throw new NoOpenCoreException(); } - return currentCore.getSolrContent(objectID, 0); + return currentCollection.getSolrContent(objectID, 0); } finally { currentCoreLock.readLock().unlock(); } @@ -1381,10 +1823,10 @@ public class Server { public String getSolrContent(final long objectID, final int chunkID) throws NoOpenCoreException { currentCoreLock.readLock().lock(); try { - if (null == currentCore) { + if (null == currentCollection) { throw new NoOpenCoreException(); } - return currentCore.getSolrContent(objectID, chunkID); + return currentCollection.getSolrContent(objectID, chunkID); } finally { currentCoreLock.readLock().unlock(); } @@ -1395,83 +1837,149 @@ public class Server { * chunk as stored in Solr, e.g. FILEID_CHUNKID * * @param parentID the parent file id (id of the source content) - * @param childID the child chunk id + * @param childID the child chunk id * * @return formatted string id */ public static String getChunkIdString(long parentID, int childID) { return Long.toString(parentID) + Server.CHUNK_ID_SEPARATOR + Integer.toString(childID); } - + /** - * Attempts to connect to the given Solr server. + * Attempts to connect to the local Solr server, which is NOT running in SolrCloud mode. * * @param solrServer * * @throws SolrServerException * @throws IOException */ - void connectToSolrServer(HttpSolrServer solrServer) throws SolrServerException, IOException { + private void connectToEbmeddedSolrServer() throws SolrServerException, IOException { + HttpSolrClient solrServer = getSolrClient("http://localhost:" + localSolrServerPort + "/solr"); TimingMetric metric = HealthMonitor.getTimingMetric("Solr: Connectivity check"); - CoreAdminRequest statusRequest = new CoreAdminRequest(); - statusRequest.setCoreName(null); - statusRequest.setAction(CoreAdminParams.CoreAdminAction.STATUS); - statusRequest.setIndexInfoNeeded(false); - statusRequest.process(solrServer); + CoreAdminRequest.getStatus(null, solrServer); HealthMonitor.submitTimingMetric(metric); } - - /** - * Determines whether or not a particular Solr core exists and is loaded. - * - * @param coreName The name of the core. - * - * @return True if the core exists and is loaded, false if the core does not - * exist or is not loaded - * - * @throws SolrServerException If there is a problem communicating with the - * Solr server. - * @throws IOException If there is a problem communicating with the - * Solr server. - */ - private boolean coreIsLoaded(String coreName) throws SolrServerException, IOException { - CoreAdminResponse response = CoreAdminRequest.getStatus(coreName, currentSolrServer); - return response.getCoreStatus(coreName).get("instanceDir") != null; //NON-NLS + + + void connectToSolrServer(String host, String port) throws SolrServerException, IOException { + try (HttpSolrClient solrServer = getSolrClient("http://" + host + ":" + port + "/solr")) { + connectToSolrServer(solrServer); + } } /** - * Determines whether or not the index files folder for a Solr core exists. + * Attempts to connect to the given Solr server, which is running in SoulrCloud mode. This API does not work + * for the local Solr which is NOT running in SolrCloud mode. * - * @param coreName the name of the core. - * - * @return true or false + * @param solrServer * * @throws SolrServerException * @throws IOException */ - private boolean coreIndexFolderExists(String coreName) throws SolrServerException, IOException { - CoreAdminResponse response = CoreAdminRequest.getStatus(coreName, currentSolrServer); - Object dataDirPath = response.getCoreStatus(coreName).get("dataDir"); //NON-NLS - if (null != dataDirPath) { - File indexDir = Paths.get((String) dataDirPath, "index").toFile(); //NON-NLS - return indexDir.exists(); + private void connectToSolrServer(HttpSolrClient solrServer) throws SolrServerException, IOException { + TimingMetric metric = HealthMonitor.getTimingMetric("Solr: Connectivity check"); + CollectionAdminRequest.ClusterStatus statusRequest = CollectionAdminRequest.getClusterStatus(); + CollectionAdminResponse statusResponse = statusRequest.process(solrServer); + int statusCode = Integer.valueOf(((NamedList) statusResponse.getResponse().get("responseHeader")).get("status").toString()); + if (statusCode != 0) { + logger.log(Level.WARNING, "Could not connect to Solr server "); //NON-NLS } else { - return false; + logger.log(Level.INFO, "Connected to Solr server "); //NON-NLS + } + HealthMonitor.submitTimingMetric(metric); + } + + private List getSolrServerList(String host, String port) throws KeywordSearchModuleException { + HttpSolrClient solrServer = getSolrClient("http://" + host + ":" + port + "/solr"); + return getSolrServerList(solrServer); + } + + private List getSolrServerList(HttpSolrClient solrServer) throws KeywordSearchModuleException { + + try { + CollectionAdminRequest.ClusterStatus statusRequest = CollectionAdminRequest.getClusterStatus(); + CollectionAdminResponse statusResponse; + try { + statusResponse = statusRequest.process(solrServer); + } catch (RemoteSolrException ex) { + // collection doesn't exist + return Collections.emptyList(); + } + + if (statusResponse == null) { + return Collections.emptyList(); + } + + NamedList error = (NamedList) statusResponse.getResponse().get("error"); + if (error != null) { + return Collections.emptyList(); + } + + NamedList cluster = (NamedList) statusResponse.getResponse().get("cluster"); + ArrayList liveNodes = (ArrayList) cluster.get("live_nodes"); + return liveNodes; + } catch (Exception ex) { + // intentional "catch all" as Solr is known to throw all kinds of Runtime exceptions + throw new KeywordSearchModuleException( + NbBundle.getMessage(this.getClass(), "Server.serverList.exception.msg", solrServer.getBaseURL())); } } + + /* ELTODO leaving this for reference, will delete later + private boolean clusterStatusWithCollection(String collectionName) throws IOException, SolrServerException { + ModifiableSolrParams params = new ModifiableSolrParams(); + params.set("action", CollectionParams.CollectionAction.CLUSTERSTATUS.toString()); + params.set("collection", collectionName); + SolrRequest request = new QueryRequest(params); + request.setPath("/admin/collections"); - class Core { + NamedList statusResponse; + try { + statusResponse = currentSolrServer.request(request); + } catch (RemoteSolrException ex) { + // collection doesn't exist + return false; + } + + if (statusResponse == null) { + logger.log(Level.SEVERE, "Collections response should not be null"); //NON-NLS + return false; + } + + NamedList cluster = (NamedList) statusResponse.get("cluster"); + if (cluster == null) { + logger.log(Level.SEVERE, "Cluster should not be null"); //NON-NLS + return false; + } + NamedList collections = (NamedList) cluster.get("collections"); + if (cluster == null) { + logger.log(Level.SEVERE, "Collections should not be null in cluster state"); //NON-NLS + return false; + } + if (collections.size() == 0) { + logger.log(Level.SEVERE, "Collections should not be empty in cluster state"); //NON-NLS + return false; + } - // handle to the core in Solr + Object collection = collections.get(collectionName); + return (collection != null); + }*/ + + class Collection { + + // handle to the collection in Solr private final String name; private final CaseType caseType; private final Index textIndex; - // the server to access a core needs to be built from a URL with the - // core in it, and is only good for core-specific operations - private final HttpSolrServer solrCore; + // We use different Solr clients for different operations. HttpSolrClient is geared towards query performance. + // ConcurrentUpdateSolrClient is geared towards batching solr documents for better indexing throughput. We + // have implemented our own batching algorithm so we will probably not use ConcurrentUpdateSolrClient. + // CloudSolrClient is geared towards SolrCloud deployments. These are only good for collection-specific operations. + private HttpSolrClient queryClient; + private SolrClient indexingClient; private final int maxBufferSize; private final List buffer; @@ -1482,28 +1990,29 @@ public class Server { private static final int NUM_BATCH_UPDATE_RETRIES = 10; private static final long SLEEP_BETWEEN_RETRIES_MS = 10000; // 10 seconds - private final int QUERY_TIMEOUT_MILLISECONDS = 86400000; // 24 Hours = 86,400,000 Milliseconds - - private Core(String name, CaseType caseType, Index index) { + private Collection(String name, Case theCase, Index index) throws TimeoutException, InterruptedException, KeywordSearchModuleException { this.name = name; - this.caseType = caseType; + this.caseType = theCase.getCaseType(); this.textIndex = index; bufferLock = new Object(); - - this.solrCore = new HttpSolrServer(currentSolrServer.getBaseURL() + "/" + name); //NON-NLS - - //TODO test these settings - // socket read timeout, make large enough so can index larger files - solrCore.setSoTimeout(QUERY_TIMEOUT_MILLISECONDS); - //solrCore.setConnectionTimeout(1000); - solrCore.setDefaultMaxConnectionsPerHost(32); - solrCore.setMaxTotalConnections(32); - solrCore.setFollowRedirects(false); // defaults to false - // allowCompression defaults to false. - // Server side must support gzip or deflate for this to have any effect. - solrCore.setAllowCompression(true); - solrCore.setParser(new XMLResponseParser()); // binary parser is used by default - + + if (caseType == CaseType.SINGLE_USER_CASE) { + // get SolrJ client + queryClient = getSolrClient("http://localhost:" + localSolrServerPort + "/solr/" + name); // HttpClient + indexingClient = getSolrClient("http://localhost:" + localSolrServerPort + "/solr/" + name); // HttpClient + } else { + // read Solr connection info from user preferences, unless "solrserver.txt" is present + queryClient = configureMultiUserConnection(theCase, index, name); + + // for MU cases, use CloudSolrClient for indexing. Indexing is only supported for Solr 8. + if (IndexFinder.getCurrentSolrVersion().equals(index.getSolrVersion())) { + IndexingServerProperties properties = getMultiUserServerProperties(theCase.getCaseDirectory()); + indexingClient = getCloudSolrClient(properties.getHost(), properties.getPort(), name); // CloudClient + } else { + indexingClient = configureMultiUserConnection(theCase, index, name); // HttpClient + } + } + // document batching maxBufferSize = org.sleuthkit.autopsy.keywordsearch.UserPreferences.getDocumentsQueueSize(); logger.log(Level.INFO, "Using Solr document queue size = {0}", maxBufferSize); //NON-NLS @@ -1511,7 +2020,7 @@ public class Server { periodicTasksExecutor = new ScheduledThreadPoolExecutor(1, new ThreadFactoryBuilder().setNameFormat("periodic-batched-document-task-%d").build()); //NON-NLS periodicTasksExecutor.scheduleWithFixedDelay(new SendBatchedDocumentsTask(), PERIODIC_BATCH_SEND_INTERVAL_MINUTES, PERIODIC_BATCH_SEND_INTERVAL_MINUTES, TimeUnit.MINUTES); } - + /** * A task that periodically sends batched documents to Solr. Batched documents * get sent automatically as soon as the batching buffer is gets full. However, @@ -1542,12 +2051,12 @@ public class Server { logger.log(Level.SEVERE, "Periodic batched document update failed", ex); //NON-NLS } } - } + } /** - * Get the name of the core + * Get the name of the collection * - * @return the String name of the core + * @return the String name of the collection */ String getName() { return name; @@ -1558,12 +2067,12 @@ public class Server { } private QueryResponse query(SolrQuery sq) throws SolrServerException, IOException { - return solrCore.query(sq); + return queryClient.query(sq); } - private NamedList request(SolrRequest request) throws SolrServerException { + private NamedList request(SolrRequest request) throws SolrServerException, RemoteSolrException { try { - return solrCore.request(request); + return queryClient.request(request); } catch (Exception e) { // intentional "catch all" as Solr is known to throw all kinds of Runtime exceptions logger.log(Level.WARNING, "Could not issue Solr request. ", e); //NON-NLS @@ -1574,11 +2083,11 @@ public class Server { } private QueryResponse query(SolrQuery sq, SolrRequest.METHOD method) throws SolrServerException, IOException { - return solrCore.query(sq, method); + return queryClient.query(sq, method); } private TermsResponse queryTerms(SolrQuery sq) throws SolrServerException, IOException { - QueryResponse qres = solrCore.query(sq); + QueryResponse qres = queryClient.query(sq); return qres.getTermsResponse(); } @@ -1596,10 +2105,10 @@ public class Server { } catch (KeywordSearchModuleException ex) { throw new SolrServerException(NbBundle.getMessage(this.getClass(), "Server.commit.exception.msg"), ex); } - + try { //commit and block - solrCore.commit(true, true); + indexingClient.commit(true, true); } catch (Exception e) { // intentional "catch all" as Solr is known to throw all kinds of Runtime exceptions logger.log(Level.WARNING, "Could not commit index. ", e); //NON-NLS @@ -1611,7 +2120,7 @@ public class Server { String dataSourceId = Long.toString(dsObjId); String deleteQuery = "image_id:" + dataSourceId; - solrCore.deleteByQuery(deleteQuery); + queryClient.deleteByQuery(deleteQuery); } /** @@ -1649,6 +2158,7 @@ public class Server { * * @throws KeywordSearchModuleException */ + // ELTODO DECIDE ON SYNCHRONIZATION private void sendBufferedDocs(List docBuffer) throws KeywordSearchModuleException { if (docBuffer.isEmpty()) { @@ -1660,7 +2170,7 @@ public class Server { for (int reTryAttempt = 0; reTryAttempt < NUM_BATCH_UPDATE_RETRIES; reTryAttempt++) { try { success = true; - solrCore.add(docBuffer); + indexingClient.add(docBuffer); } catch (Exception ex) { success = false; if (reTryAttempt < NUM_BATCH_UPDATE_RETRIES - 1) { @@ -1683,6 +2193,11 @@ public class Server { // if we are here, it means all re-try attempts failed logger.log(Level.SEVERE, "Unable to send document batch to Solr. All re-try attempts failed!"); //NON-NLS throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.addDocBatch.exception.msg")); //NON-NLS + } catch (Exception ex) { + // Solr throws a lot of unexpected exception types + logger.log(Level.SEVERE, "Could not add batched documents to index", ex); //NON-NLS + throw new KeywordSearchModuleException( + NbBundle.getMessage(this.getClass(), "Server.addDocBatch.exception.msg"), ex); //NON-NLS } finally { docBuffer.clear(); } @@ -1692,7 +2207,7 @@ public class Server { * get the text from the content field for the given file * * @param contentID Solr document ID - * @param chunkID Chunk ID of the Solr document + * @param chunkID Chunk ID of the Solr document * * @return Text from matching Solr document (as String). Null if no * matching Solr document found or error while getting content @@ -1709,12 +2224,12 @@ public class Server { q.setFields(Schema.TEXT.toString()); try { // Get the first result. - SolrDocumentList solrDocuments = solrCore.query(q).getResults(); + SolrDocumentList solrDocuments = queryClient.query(q).getResults(); if (!solrDocuments.isEmpty()) { SolrDocument solrDocument = solrDocuments.get(0); if (solrDocument != null) { - Collection fieldValues = solrDocument.getFieldValues(Schema.TEXT.toString()); + java.util.Collection fieldValues = solrDocument.getFieldValues(Schema.TEXT.toString()); if (fieldValues.size() == 1) // The indexed text field for artifacts will only have a single value. { return fieldValues.toArray(new String[0])[0]; @@ -1735,22 +2250,32 @@ public class Server { } synchronized void close() throws KeywordSearchModuleException { - - // stop the periodic batch update task. If the task is already running, - // allow it to finish. - ThreadUtils.shutDownTaskExecutor(periodicTasksExecutor); - - // We only unload cores for "single-user" cases. - if (this.caseType == CaseType.MULTI_USER_CASE) { - return; - } - try { - CoreAdminRequest.unloadCore(this.name, currentSolrServer); + + // stop the periodic batch update task. If the task is already running, + // allow it to finish. + ThreadUtils.shutDownTaskExecutor(periodicTasksExecutor); + + // We only unload cores for "single-user" cases. + if (this.caseType == CaseType.MULTI_USER_CASE) { + return; + } + + CoreAdminRequest.unloadCore(this.name, localSolrServer); } catch (Exception ex) { // intentional "catch all" as Solr is known to throw all kinds of Runtime exceptions throw new KeywordSearchModuleException( NbBundle.getMessage(this.getClass(), "Server.close.exception.msg"), ex); + } finally { + try { + queryClient.close(); + queryClient = null; + indexingClient.close(); + indexingClient = null; + } catch (IOException ex) { + throw new KeywordSearchModuleException( + NbBundle.getMessage(this.getClass(), "Server.close.exception.msg2"), ex); + } } } @@ -1759,7 +2284,7 @@ public class Server { * indexed without actually returning the files * * @return int representing number of indexed files (entire files, not - * chunks) + * chunks) * * @throws SolrServerException */ @@ -1789,7 +2314,7 @@ public class Server { * indexed files as well as chunks, which are treated as documents. * * @return int representing number of indexed documents (entire files - * and chunks) + * and chunks) * * @throws SolrServerException */ @@ -1821,10 +2346,10 @@ public class Server { * Execute query that gets number of indexed file chunks for a file * * @param contentID file id of the original file broken into chunks and - * indexed + * indexed * * @return int representing number of indexed file chunks, 0 if there is - * no chunks + * no chunks * * @throws SolrServerException */ diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java index daaccc91ce..ec82726695 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java @@ -22,26 +22,18 @@ import com.google.common.eventbus.Subscribe; import java.io.File; import java.io.IOException; import java.io.Reader; -import java.lang.reflect.InvocationTargetException; import java.net.InetAddress; import java.util.ArrayList; import java.util.List; import java.util.MissingResourceException; import java.util.logging.Level; -import javax.swing.JDialog; -import javax.swing.JOptionPane; -import javax.swing.SwingUtilities; -import org.apache.commons.io.FileUtils; -import org.apache.commons.lang.math.NumberUtils; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.impl.HttpSolrServer; import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProviders; import org.sleuthkit.autopsy.appservices.AutopsyService; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.CaseMetadata; -import org.sleuthkit.autopsy.core.RuntimeProperties; import org.sleuthkit.autopsy.coreutils.FileUtil; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; @@ -68,8 +60,6 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService { private static final String BAD_IP_ADDRESS_FORMAT = "ioexception occurred when talking to server"; //NON-NLS private static final String SERVER_REFUSED_CONNECTION = "server refused connection"; //NON-NLS private static final int IS_REACHABLE_TIMEOUT_MS = 1000; - private static final int LARGE_INDEX_SIZE_GB = 50; - private static final int GIANT_INDEX_SIZE_GB = 500; private static final Logger logger = Logger.getLogger(SolrSearchService.class.getName()); /** @@ -154,16 +144,16 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService { */ @Override public void tryConnect(String host, int port) throws KeywordSearchServiceException { - HttpSolrServer solrServer = null; if (host == null || host.isEmpty()) { throw new KeywordSearchServiceException(NbBundle.getMessage(SolrSearchService.class, "SolrConnectionCheck.MissingHostname")); //NON-NLS } - try { - solrServer = new HttpSolrServer("http://" + host + ":" + Integer.toString(port) + "/solr"); //NON-NLS - KeywordSearch.getServer().connectToSolrServer(solrServer); + try { + KeywordSearch.getServer().connectToSolrServer(host, Integer.toString(port)); } catch (SolrServerException ex) { - throw new KeywordSearchServiceException(NbBundle.getMessage(SolrSearchService.class, "SolrConnectionCheck.HostnameOrPort")); //NON-NLS + logger.log(Level.SEVERE, "Unable to connect to Solr server. Host: " + host + ", port: " + port, ex); + throw new KeywordSearchServiceException(NbBundle.getMessage(SolrSearchService.class, "SolrConnectionCheck.HostnameOrPort")); //NON-NLS*/ } catch (IOException ex) { + logger.log(Level.SEVERE, "Unable to connect to Solr server. Host: " + host + ", port: " + port, ex); String result = NbBundle.getMessage(SolrSearchService.class, "SolrConnectionCheck.HostnameOrPort"); //NON-NLS String message = ex.getCause().getMessage().toLowerCase(); if (message.startsWith(SERVER_REFUSED_CONNECTION)) { @@ -183,13 +173,11 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService { } throw new KeywordSearchServiceException(result); } catch (NumberFormatException ex) { + logger.log(Level.SEVERE, "Unable to connect to Solr server. Host: " + host + ", port: " + port, ex); throw new KeywordSearchServiceException(Bundle.SolrConnectionCheck_Port()); } catch (IllegalArgumentException ex) { + logger.log(Level.SEVERE, "Unable to connect to Solr server. Host: " + host + ", port: " + port, ex); throw new KeywordSearchServiceException(ex.getMessage()); - } finally { - if (null != solrServer) { - solrServer.shutdown(); - } } } @@ -221,6 +209,7 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService { @NbBundle.Messages({ "# {0} - case directory", "SolrSearchService.exceptionMessage.noIndexMetadata=Unable to create IndexMetaData from case directory: {0}", "SolrSearchService.exceptionMessage.noCurrentSolrCore=IndexMetadata did not contain a current Solr core so could not delete the case", + "# {0} - collection name", "SolrSearchService.exceptionMessage.unableToDeleteCollection=Unable to delete collection {0}", "# {0} - index folder path", "SolrSearchService.exceptionMessage.failedToDeleteIndexFiles=Failed to delete text index files at {0}" }) @Override @@ -233,28 +222,26 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService { logger.log(Level.WARNING, NbBundle.getMessage(SolrSearchService.class, "SolrSearchService.exceptionMessage.noIndexMetadata", caseDirectory), ex); throw new KeywordSearchServiceException(NbBundle.getMessage(SolrSearchService.class, "SolrSearchService.exceptionMessage.noIndexMetadata", caseDirectory), ex); } - //find the index for the current version of solr (the one we are connected to) and delete its core using the index name - String currentSchema = IndexFinder.getCurrentSchemaVersion(); - String currentSolr = IndexFinder.getCurrentSolrVersion(); - for (Index index : indexMetadata.getIndexes()) { - if (index.getSolrVersion().equals(currentSolr) && index.getSchemaVersion().equals(currentSchema)) { - /* - * Unload/delete the core on the server and then delete the text - * index files. - */ - KeywordSearch.getServer().deleteCore(index.getIndexName(), metadata); - if (!FileUtil.deleteDir(new File(index.getIndexPath()).getParentFile())) { - throw new KeywordSearchServiceException(Bundle.SolrSearchService_exceptionMessage_failedToDeleteIndexFiles(index.getIndexPath())); - } - } - return; //only one core exists for each combination of solr and schema version + + if (indexMetadata.getIndexes().isEmpty()) { + logger.log(Level.WARNING, NbBundle.getMessage(SolrSearchService.class, + "SolrSearchService.exceptionMessage.noCurrentSolrCore")); + throw new KeywordSearchServiceException(NbBundle.getMessage(SolrSearchService.class, + "SolrSearchService.exceptionMessage.noCurrentSolrCore")); } - //this code this code will only execute if an index for the current core was not found - logger.log(Level.WARNING, NbBundle.getMessage(SolrSearchService.class, - "SolrSearchService.exceptionMessage.noCurrentSolrCore")); - throw new KeywordSearchServiceException(NbBundle.getMessage(SolrSearchService.class, - "SolrSearchService.exceptionMessage.noCurrentSolrCore")); + // delete index(es) for this case + for (Index index : indexMetadata.getIndexes()) { + try { + // Unload/delete the collection on the server and then delete the text index files. + KeywordSearch.getServer().deleteCollection(index.getIndexName(), metadata); + } catch (KeywordSearchModuleException ex) { + throw new KeywordSearchServiceException(Bundle.SolrSearchService_exceptionMessage_unableToDeleteCollection(index.getIndexName()), ex); + } + if (!FileUtil.deleteDir(new File(index.getIndexPath()).getParentFile())) { + throw new KeywordSearchServiceException(Bundle.SolrSearchService_exceptionMessage_failedToDeleteIndexFiles(index.getIndexPath())); + } + } } @Override @@ -278,9 +265,7 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService { "SolrSearch.creatingNewIndex.msg=Creating new text index", "SolrSearch.checkingForLatestIndex.msg=Looking for text index with latest Solr and schema version", "SolrSearch.indentifyingIndex.msg=Identifying text index to use", - "SolrSearch.openCore.msg=Opening text index", - "SolrSearch.openLargeCore.msg=Opening text index. This may take several minutes.", - "SolrSearch.openGiantCore.msg=Opening text index. Text index for this case is very large and may take long time to load.", + "SolrSearch.openCore.msg=Opening text index. For large cases this may take several minutes.", "SolrSearch.complete.msg=Text index successfully opened"}) public void openCaseResources(CaseContext context) throws AutopsyServiceException { if (context.cancelRequested()) { @@ -306,16 +291,6 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService { logger.log(Level.SEVERE, String.format("Unable to read text index metadata file"), ex); throw new AutopsyServiceException("Unable to read text index metadata file", ex); } - } else { - // metadata file doesn't exist. - // do case subdirectory search to look for Solr 4 Schema 1.8 indexes - progressUnitsCompleted++; - progress.progress(Bundle.SolrSearch_findingIndexes_msg(), progressUnitsCompleted); - Index oldIndex = IndexFinder.findOldIndexDir(theCase); - if (oldIndex != null) { - // add index to the list of indexes that exist for this case - indexes.add(oldIndex); - } } if (context.cancelRequested()) { @@ -350,34 +325,14 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService { return; } - double currentSolrVersion = NumberUtils.toDouble(IndexFinder.getCurrentSolrVersion()); - double indexSolrVersion = NumberUtils.toDouble(indexToUse.getSolrVersion()); - if (indexSolrVersion == currentSolrVersion) { - // latest Solr version but schema not compatible. index should be used in read-only mode - if (!indexToUse.isCompatible(IndexFinder.getCurrentSchemaVersion()) && RuntimeProperties.runningWithGUI()) { - // pop up a message box to indicate the read-only restrictions. - JOptionPane optionPane = new JOptionPane( - NbBundle.getMessage(this.getClass(), "SolrSearchService.IndexReadOnlyDialog.msg"), - JOptionPane.WARNING_MESSAGE, - JOptionPane.DEFAULT_OPTION); - try { - SwingUtilities.invokeAndWait(() -> { - JDialog dialog = optionPane.createDialog(NbBundle.getMessage(this.getClass(), "SolrSearchService.IndexReadOnlyDialog.title")); - dialog.setVisible(true); - }); - } catch (InterruptedException ex) { - // Cancelled - return; - } catch (InvocationTargetException ex) { - throw new AutopsyServiceException("Error displaying limited search features warning dialog", ex); - } - } - // proceed with case open - currentVersionIndex = indexToUse; - } else { - // index needs to be upgraded to latest supported version of Solr - throw new AutopsyServiceException("Unable to find index to use for Case open"); + // check if schema is compatible + if (!indexToUse.isCompatible(IndexFinder.getCurrentSchemaVersion())) { + String msg = "Text index schema version " + indexToUse.getSchemaVersion() + " is not compatible with current schema"; + logger.log(Level.WARNING, msg); + throw new AutopsyServiceException(msg); } + // proceed with case open + currentVersionIndex = indexToUse; } } @@ -392,17 +347,7 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService { // open core try { - // check text index size to gauge estimated time to open/load the index - long indexSizeInBytes = FileUtils.sizeOfDirectory(new File(currentVersionIndex.getIndexPath())); - long sizeInGb = indexSizeInBytes / 1000000000; - if (sizeInGb < LARGE_INDEX_SIZE_GB) { - progress.progress(Bundle.SolrSearch_openCore_msg(), totalNumProgressUnits - 1); - } else if (sizeInGb >= LARGE_INDEX_SIZE_GB && sizeInGb < GIANT_INDEX_SIZE_GB) { - progress.switchToIndeterminate(Bundle.SolrSearch_openLargeCore_msg()); - } else { - progress.switchToIndeterminate(Bundle.SolrSearch_openGiantCore_msg()); - } - + progress.progress(Bundle.SolrSearch_openCore_msg(), totalNumProgressUnits - 1); KeywordSearch.getServer().openCoreForCase(theCase, currentVersionIndex); } catch (KeywordSearchModuleException ex) { throw new AutopsyServiceException(String.format("Failed to open or create core for %s", caseDirPath), ex); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/UserPreferences.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/UserPreferences.java index 11f7654f8c..9b9a29f847 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/UserPreferences.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/UserPreferences.java @@ -30,7 +30,11 @@ import org.openide.util.NbPreferences; final class UserPreferences { private static final Preferences preferences = NbPreferences.forModule(UserPreferences.class); + private static final String INDEXING_MAX_SHARDS = "IndexingMaxShards"; //NON-NLS private static final String INDEXING_DOC_QUEUE_SIZE = "IndexingDocumentQueueSize"; //NON-NLS + private static final String INDEXING_NUM_THREADS = "IndexingNumThreads"; //NON-NLS + private static final String SOLR_CONNECTION_TIMEOUT_MS = "SolrConnectionTimeoutMs"; //NON-NLS + private static final int DEFAULT_CONNECTION_TIMEOUT_MS = 0; // unlimited private static final int DEFAULT_INDEXING_DOC_QUEUE_SIZE = 30; //NON-NLS // Prevent instantiation. @@ -66,11 +70,34 @@ final class UserPreferences { preferences.removePreferenceChangeListener(listener); } - public static void setDocumentsQueueSize(int size) { - preferences.putInt(INDEXING_DOC_QUEUE_SIZE, size); + public static void setMaxNumShards(int maxShards) { + preferences.putInt(INDEXING_MAX_SHARDS, maxShards); } + public static int getMaxNumShards() { + return preferences.getInt(INDEXING_MAX_SHARDS, 0); + } + + public static int getNumThreads() { + return preferences.getInt(INDEXING_NUM_THREADS, 5); + } + + public static void setNumThreads(int maxShards) { + preferences.putInt(INDEXING_NUM_THREADS, maxShards); + } + + public static void setConnectionTimeout(int connectionTimeoutMs) { + preferences.putInt(SOLR_CONNECTION_TIMEOUT_MS, connectionTimeoutMs); + } + + public static int getConnectionTimeout() { + return preferences.getInt(SOLR_CONNECTION_TIMEOUT_MS, DEFAULT_CONNECTION_TIMEOUT_MS); + } + + // reading of this parameter exists so that sys admins can change the batch size without + // having to ask for a new installer. We do not want users to be changing this, hence + // this is not in UI. public static int getDocumentsQueueSize() { return preferences.getInt(INDEXING_DOC_QUEUE_SIZE, DEFAULT_INDEXING_DOC_QUEUE_SIZE); } -} \ No newline at end of file +} diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractPrefetch.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractPrefetch.java index 4771b76223..5803aa119c 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractPrefetch.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractPrefetch.java @@ -29,11 +29,14 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.logging.Level; import org.openide.modules.InstalledFileLocator; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.services.FileManager; import org.sleuthkit.autopsy.coreutils.ExecUtil; import org.sleuthkit.autopsy.coreutils.Logger; @@ -262,7 +265,7 @@ final class ExtractPrefetch extends Extract { AbstractFile pfAbstractFile = getAbstractFile(prefetchFileName, PREFETCH_FILE_LOCATION, dataSource); - List prefetchExecutionTimes = findNonZeroExecutionTimes(executionTimes); + Set prefetchExecutionTimes = findNonZeroExecutionTimes(executionTimes); if (pfAbstractFile != null) { for (Long executionTime : prefetchExecutionTimes) { @@ -321,8 +324,8 @@ final class ExtractPrefetch extends Extract { * * @return List of timestamps that are greater than zero */ - private List findNonZeroExecutionTimes(List executionTimes) { - List prefetchExecutionTimes = new ArrayList<>(); + private Set findNonZeroExecutionTimes(List executionTimes) { + Set prefetchExecutionTimes = new HashSet<>(); for (Long executionTime : executionTimes) { // only add prefetch file entries that have an actual date associated with them if (executionTime > 0) { prefetchExecutionTimes.add(executionTime); diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractSru.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractSru.java index fb85593953..b8dd027278 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractSru.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractSru.java @@ -331,9 +331,9 @@ final class ExtractSru extends Extract { private void createNetUsageArtifacts(String sruDb, AbstractFile sruAbstractFile) { List bba = new ArrayList<>(); - String sqlStatement = "SELECT STRFTIME('%s', timestamp) ExecutionTime, Application_Name, User_Name, " - + " bytesSent, BytesRecvd FROM network_Usage , SruDbIdMapTable " - + " where appId = IdIndex and IdType = 0 order by ExecutionTime;"; //NON-NLS + String sqlStatement = "SELECT STRFTIME('%s', timestamp) ExecutionTime, a.application_name, b.Application_Name formatted_application_name, User_Name, " + + " bytesSent, BytesRecvd FROM network_Usage a, SruDbIdMapTable, exe_to_app b " + + " where appId = IdIndex and IdType = 0 and a.application_name = b.source_name order by ExecutionTime;"; //NON-NLS try (SQLiteDBConnect tempdbconnect = new SQLiteDBConnect("org.sqlite.JDBC", "jdbc:sqlite:" + sruDb); //NON-NLS ResultSet resultSet = tempdbconnect.executeQry(sqlStatement)) { @@ -346,6 +346,7 @@ final class ExtractSru extends Extract { } String applicationName = resultSet.getString("Application_Name"); //NON-NLS + String formattedApplicationName = resultSet.getString("formatted_Application_name"); Long executionTime = Long.valueOf(resultSet.getInt("ExecutionTime")); //NON-NLS Long bytesSent = Long.valueOf(resultSet.getInt("bytesSent")); //NON-NLS Long bytesRecvd = Long.valueOf(resultSet.getInt("BytesRecvd")); //NON-NLS @@ -354,7 +355,7 @@ final class ExtractSru extends Extract { Collection bbattributes = Arrays.asList( new BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, getName(), - applicationName),//NON-NLS + formattedApplicationName),//NON-NLS new BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME, getName(), userName), @@ -395,9 +396,9 @@ final class ExtractSru extends Extract { private void createAppUsageArtifacts(String sruDb, AbstractFile sruAbstractFile) { List bba = new ArrayList<>(); - String sqlStatement = "SELECT STRFTIME('%s', timestamp) ExecutionTime, Application_Name, User_Name " - + " FROM Application_Resource_Usage, SruDbIdMapTable WHERE " - + " idType = 0 and idIndex = appId order by ExecutionTime;"; //NON-NLS + String sqlStatement = "SELECT STRFTIME('%s', timestamp) ExecutionTime, a.application_name, b.Application_Name formatted_application_name, User_Name " + + " FROM Application_Resource_Usage a, SruDbIdMapTable, exe_to_app b WHERE " + + " idType = 0 and idIndex = appId and a.application_name = b.source_name order by ExecutionTime;"; //NON-NLS try (SQLiteDBConnect tempdbconnect = new SQLiteDBConnect("org.sqlite.JDBC", "jdbc:sqlite:" + sruDb); //NON-NLS ResultSet resultSet = tempdbconnect.executeQry(sqlStatement)) { @@ -410,13 +411,14 @@ final class ExtractSru extends Extract { } String applicationName = resultSet.getString("Application_Name"); //NON-NLS + String formattedApplicationName = resultSet.getString("formatted_application_name"); Long executionTime = Long.valueOf(resultSet.getInt("ExecutionTime")); //NON-NLS String userName = resultSet.getString("User_Name"); Collection bbattributes = Arrays.asList( new BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, getName(), - applicationName),//NON-NLS + formattedApplicationName),//NON-NLS new BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME, getName(), userName), diff --git a/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java b/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java index f2aa476590..eaad6b9714 100644 --- a/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java +++ b/Testing/test/qa-functional/src/org/sleuthkit/autopsy/testing/RegressionTest.java @@ -63,7 +63,9 @@ public class RegressionTest extends TestCase { clusters(".*"). enableModules(".*"); if (img_path.isFile()) { - conf = conf.addTest("testNewCaseWizardOpen", + conf = conf.addTest( + "testConfigureCustomCR", + "testNewCaseWizardOpen", "testNewCaseWizard", "testStartAddImageFileDataSource", "testConfigureIngest1", @@ -78,7 +80,9 @@ public class RegressionTest extends TestCase { } if (img_path.isDirectory()) { - conf = conf.addTest("testNewCaseWizardOpen", + conf = conf.addTest( + "testConfigureCustomCR", + "testNewCaseWizardOpen", "testNewCaseWizard", "testStartAddLogicalFilesDataSource", "testConfigureIngest1", @@ -103,7 +107,11 @@ public class RegressionTest extends TestCase { public void setUp() { logger.info("######## " + AutopsyTestCases.getEscapedPath(System.getProperty("img_path")) + " #######"); Timeouts.setDefault("ComponentOperator.WaitComponentTimeout", 1000000); - + } + + public void testConfigureCustomCR() { + // Configure a custom CR before proceeding with the test (and creating + // a case). try { if (Boolean.parseBoolean(System.getProperty("isMultiUser"))) { // Set up a custom postgres CR using the configuration passed diff --git a/thunderbirdparser/nbproject/project.properties b/thunderbirdparser/nbproject/project.properties index 97e5822e65..cfbcc365d4 100644 --- a/thunderbirdparser/nbproject/project.properties +++ b/thunderbirdparser/nbproject/project.properties @@ -5,6 +5,7 @@ file.reference.commons-lang3-3.8.1.jar=release/modules/ext/commons-lang3-3.8.1.j file.reference.apache-mime4j-core-0.8.0.jar=release/modules/ext/apache-mime4j-core-0.8.0-SNAPSHOT.jar file.reference.apache-mime4j-dom-0.8.0.jar=release/modules/ext/apache-mime4j-dom-0.8.0-SNAPSHOT.jar file.reference.apache-mime4j-mbox-iterator-0.8.0.jar=release/modules/ext/apache-mime4j-mbox-iterator-0.8.0-SNAPSHOT.jar +file.reference.commons-validator-1.6.jar=release/modules/ext/commons-validator-1.6.jar file.reference.guava-19.0.jar=release/modules/ext/guava-19.0.jar file.reference.java-libpst-1.0-SNAPSHOT.jar=release/modules/ext/java-libpst-1.0-SNAPSHOT.jar file.reference.ez-vcard-0.10.5.jar=release/modules/ext/ez-vcard-0.10.5.jar diff --git a/thunderbirdparser/nbproject/project.xml b/thunderbirdparser/nbproject/project.xml index b4d9ca8cbf..94e45a2cc8 100644 --- a/thunderbirdparser/nbproject/project.xml +++ b/thunderbirdparser/nbproject/project.xml @@ -100,6 +100,10 @@ ext/vinnie-2.0.2.jar release/modules/ext/vinnie-2.0.2.jar + + ext/commons-validator-1.6.jar + release/modules/ext/commons-validator-1.6.jar + diff --git a/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/MboxParser.java b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/MboxParser.java index a17294b15b..eb4efc7451 100644 --- a/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/MboxParser.java +++ b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/MboxParser.java @@ -40,6 +40,7 @@ import org.apache.james.mime4j.mboxiterator.CharBufferWrapper; import org.apache.james.mime4j.mboxiterator.MboxIterator; import org.apache.tika.parser.txt.CharsetDetector; import org.apache.tika.parser.txt.CharsetMatch; +import org.apache.commons.validator.routines.EmailValidator; import org.openide.util.NbBundle; /** @@ -56,7 +57,13 @@ class MboxParser extends MimeJ4MessageParser implements Iterator { } static boolean isValidMimeTypeMbox(byte[] buffer) { - return (new String(buffer)).startsWith("From "); //NON-NLS + String mboxHeaderLine = new String(buffer); + if (mboxHeaderLine.startsWith("From ")) { + String[] mboxLineValues = mboxHeaderLine.split(" "); + EmailValidator validator = EmailValidator.getInstance(true, true); + return validator.isValid(mboxLineValues[1]); + } + return false; //NON-NLS } /** diff --git a/travis_build.sh b/travis_build.sh index d3753fd934..e40bd161f4 100755 --- a/travis_build.sh +++ b/travis_build.sh @@ -17,7 +17,7 @@ echo `df -h .` if [ "${TRAVIS_OS_NAME}" = "osx" ]; then # if os x, just run it - ant -q test-no-regression + # ant -q test-no-regression elif [ "${TRAVIS_OS_NAME}" = "linux" ]; then # if linux use xvfb xvfb-run ant -q test-no-regression