lucene-solr-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ehatc...@apache.org
Subject svn commit: r508485 - in /lucene/solr/trunk: ./ src/java/org/apache/solr/core/ src/java/org/apache/solr/util/ src/test/org/apache/solr/core/ src/test/test-files/solr/conf/
Date Fri, 16 Feb 2007 16:42:50 GMT
Author: ehatcher
Date: Fri Feb 16 08:42:49 2007
New Revision: 508485

URL: http://svn.apache.org/viewvc?view=rev&rev=508485
Log:
SOLR-79: Add system property ${<sys.prop>[:<default>]} substitution for
    configuration files loaded, including schema.xml and solrconfig.xml.
    (Erik Hatcher with inspiration from Andrew Saar)


Added:
    lucene/solr/trunk/src/test/org/apache/solr/core/
    lucene/solr/trunk/src/test/org/apache/solr/core/TestBadConfig.java
    lucene/solr/trunk/src/test/org/apache/solr/core/TestConfig.java
    lucene/solr/trunk/src/test/test-files/solr/conf/bad_solrconfig.xml
Modified:
    lucene/solr/trunk/CHANGES.txt
    lucene/solr/trunk/build.xml
    lucene/solr/trunk/src/java/org/apache/solr/core/Config.java
    lucene/solr/trunk/src/java/org/apache/solr/util/AbstractSolrTestCase.java
    lucene/solr/trunk/src/java/org/apache/solr/util/DOMUtil.java
    lucene/solr/trunk/src/test/test-files/solr/conf/solrconfig.xml

Modified: lucene/solr/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/CHANGES.txt?view=diff&rev=508485&r1=508484&r2=508485
==============================================================================
--- lucene/solr/trunk/CHANGES.txt (original)
+++ lucene/solr/trunk/CHANGES.txt Fri Feb 16 08:42:49 2007
@@ -82,6 +82,10 @@
 
 10. SOLR-116: IndexInfoRequestHandler added. (Erik Hatcher)
 
+11. SOLR-79: Add system property ${<sys.prop>[:<default>]} substitution for
+    configuration files loaded, including schema.xml and solrconfig.xml.
+    (Erik Hatcher with inspiration from Andrew Saar)
+
 Changes in runtime behavior
  1. Highlighting using DisMax will only pick up terms from the main 
     user query, not boost or filter queries (klaas).

Modified: lucene/solr/trunk/build.xml
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/build.xml?view=diff&rev=508485&r1=508484&r2=508485
==============================================================================
--- lucene/solr/trunk/build.xml (original)
+++ lucene/solr/trunk/build.xml Fri Feb 16 08:42:49 2007
@@ -282,6 +282,9 @@
       <syspropertyset>
         <propertyref prefix="solr" />
       </syspropertyset>
+      <!-- solr.test.sys.prop1/2 used by TestConfig -->
+      <sysproperty key="solr.test.sys.prop1" value="propone"/>
+      <sysproperty key="solr.test.sys.prop2" value="proptwo"/>
       <classpath refid="test.run.classpath"/>
       <formatter type="xml"/>
       <batchtest fork="yes" todir="${junit.output.dir}" unless="testcase">

Modified: lucene/solr/trunk/src/java/org/apache/solr/core/Config.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/core/Config.java?view=diff&rev=508485&r1=508484&r2=508485
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/core/Config.java (original)
+++ lucene/solr/trunk/src/java/org/apache/solr/core/Config.java Fri Feb 16 08:42:49 2007
@@ -59,6 +59,8 @@
 
     javax.xml.parsers.DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
     doc = builder.parse(is);
+
+    DOMUtil.substituteSystemProperties(doc);
   }
 
   public Document getDocument() {
@@ -124,7 +126,7 @@
     if (nd==null) return null;
 
     String txt = DOMUtil.getText(nd);
-    
+
     log.fine(name + ' '+path+'='+txt);
     return txt;
 
@@ -255,7 +257,7 @@
 
   /** Singleton classloader loading resources specified in any configs */
   private static ClassLoader classLoader = null;
-  
+
   /**
    * Returns the singleton classloader to be use when loading resources
    * specified in any configs.
@@ -269,7 +271,7 @@
   static ClassLoader getClassLoader() {
     if (null == classLoader) {
       classLoader = Thread.currentThread().getContextClassLoader();
-      
+
       File f = new File(getInstanceDir() + "lib/");
       if (f.canRead() && f.isDirectory()) {
         File[] jarFiles = f.listFiles();

Modified: lucene/solr/trunk/src/java/org/apache/solr/util/AbstractSolrTestCase.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/util/AbstractSolrTestCase.java?view=diff&rev=508485&r1=508484&r2=508485
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/util/AbstractSolrTestCase.java (original)
+++ lucene/solr/trunk/src/java/org/apache/solr/util/AbstractSolrTestCase.java Fri Feb 16 08:42:49
2007
@@ -110,7 +110,7 @@
    * is set.
    */
   public void tearDown() throws Exception {
-    h.close();
+    if (h != null) { h.close(); }
     String skip = System.getProperty("solr.test.leavedatadir");
     if (null != skip && 0 != skip.trim().length()) {
       System.err.println("NOTE: per solr.test.leavedatadir, dataDir will not be removed:
" + dataDir.getAbsolutePath());

Modified: lucene/solr/trunk/src/java/org/apache/solr/util/DOMUtil.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/util/DOMUtil.java?view=diff&rev=508485&r1=508484&r2=508485
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/util/DOMUtil.java (original)
+++ lucene/solr/trunk/src/java/org/apache/solr/util/DOMUtil.java Fri Feb 16 08:42:49 2007
@@ -21,11 +21,14 @@
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
+import org.apache.solr.core.SolrException;
 
 import java.util.Map;
 import java.util.HashMap;
 import java.util.List;
 import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
 
 /**
  * @author yonik
@@ -164,12 +167,12 @@
   public static String getText(Node nd) {
 
     short type = nd.getNodeType();
-    
+
     // for most node types, we can defer to the recursive helper method,
     // but when asked for the text of these types, we must return null
     // (Not the empty string)
     switch (type) {
-      
+
     case Node.DOCUMENT_NODE: /* fall through */
     case Node.DOCUMENT_TYPE_NODE: /* fall through */
     case Node.NOTATION_NODE: /* fall through */
@@ -183,15 +186,15 @@
 
   /** @see #getText(Node) */
   private static void getText(Node nd, StringBuilder buf) {
-    
+
     short type = nd.getNodeType();
 
     switch (type) {
-      
+
     case Node.ELEMENT_NODE: /* fall through */
     case Node.ENTITY_NODE: /* fall through */
     case Node.ENTITY_REFERENCE_NODE: /* fall through */
-    case Node.DOCUMENT_FRAGMENT_NODE: 
+    case Node.DOCUMENT_FRAGMENT_NODE:
       NodeList childs = nd.getChildNodes();
       for (int i = 0; i < childs.getLength(); i++) {
         Node child = childs.item(i);
@@ -202,7 +205,7 @@
         }
       }
       break;
-      
+
     case Node.ATTRIBUTE_NODE: /* fall through */
       /* Putting Attribute nodes in this section does not exactly 
          match the definition of how textContent should behave 
@@ -232,4 +235,131 @@
 
     }
   }
+
+  /**
+   * Replaces ${system.property[:default value]} references in all attributes
+   * and text nodes of supplied node.  If the system property is not defined, an empty string
+   * is substituted or the default value if provided.
+   *
+   * @param node DOM node to walk for substitutions
+   */
+  public static void substituteSystemProperties(Node node) {
+    // loop through child nodes
+    Node child;
+    Node next = node.getFirstChild();
+    while ((child = next) != null) {
+
+      // set next before we change anything
+      next = child.getNextSibling();
+
+      // handle child by node type
+      if (child.getNodeType() == Node.TEXT_NODE) {
+        child.setNodeValue(substituteSystemProperty(child.getNodeValue()));
+      } else if (child.getNodeType() == Node.ELEMENT_NODE) {
+        // handle child elements with recursive call
+        NamedNodeMap attributes = child.getAttributes();
+        for (int i = 0; i < attributes.getLength(); i++) {
+          Node attribute = attributes.item(i);
+          attribute.setNodeValue(substituteSystemProperty(attribute.getNodeValue()));
+        }
+        substituteSystemProperties(child);
+      }
+    }
+  }
+
+  /*
+   * This method borrowed from Ant's PropertyHelper.replaceProperties:
+   *   http://svn.apache.org/repos/asf/ant/core/trunk/src/main/org/apache/tools/ant/PropertyHelper.java
+   */
+  private static String substituteSystemProperty(String value) {
+    if (value == null || value.indexOf('$') == -1) {
+      return value;
+    }
+
+    List<String> fragments = new ArrayList<String>();
+    List<String> propertyRefs = new ArrayList<String>();
+    parsePropertyString(value, fragments, propertyRefs);
+
+    StringBuffer sb = new StringBuffer();
+    Iterator<String> i = fragments.iterator();
+    Iterator<String> j = propertyRefs.iterator();
+
+    while (i.hasNext()) {
+      String fragment = i.next();
+      if (fragment == null) {
+        String propertyName = j.next();
+        String defaultValue = null;
+        int colon_index = propertyName.indexOf(':');
+        if (colon_index > -1) {
+          defaultValue = propertyName.substring(colon_index + 1);
+          propertyName = propertyName.substring(0,colon_index);
+        }
+        fragment = System.getProperty(propertyName,defaultValue);
+        if (fragment == null) {
+          throw new SolrException(500, "No system property or default value specified for
" + propertyName);
+        }
+      }
+      sb.append(fragment);
+    }
+    return sb.toString();
+  }
+
+  /*
+   * This method borrowed from Ant's PropertyHelper.parsePropertyStringDefault:
+   *   http://svn.apache.org/repos/asf/ant/core/trunk/src/main/org/apache/tools/ant/PropertyHelper.java
+   */
+  private static void parsePropertyString(String value, List<String> fragments, List<String>
propertyRefs) {
+      int prev = 0;
+      int pos;
+      //search for the next instance of $ from the 'prev' position
+      while ((pos = value.indexOf("$", prev)) >= 0) {
+
+          //if there was any text before this, add it as a fragment
+          //TODO, this check could be modified to go if pos>prev;
+          //seems like this current version could stick empty strings
+          //into the list
+          if (pos > 0) {
+              fragments.add(value.substring(prev, pos));
+          }
+          //if we are at the end of the string, we tack on a $
+          //then move past it
+          if (pos == (value.length() - 1)) {
+              fragments.add("$");
+              prev = pos + 1;
+          } else if (value.charAt(pos + 1) != '{') {
+              //peek ahead to see if the next char is a property or not
+              //not a property: insert the char as a literal
+              /*
+              fragments.addElement(value.substring(pos + 1, pos + 2));
+              prev = pos + 2;
+              */
+              if (value.charAt(pos + 1) == '$') {
+                  //backwards compatibility two $ map to one mode
+                  fragments.add("$");
+                  prev = pos + 2;
+              } else {
+                  //new behaviour: $X maps to $X for all values of X!='$'
+                  fragments.add(value.substring(pos, pos + 2));
+                  prev = pos + 2;
+              }
+
+          } else {
+              //property found, extract its name or bail on a typo
+              int endName = value.indexOf('}', pos);
+              if (endName < 0) {
+                throw new RuntimeException("Syntax error in property: " + value);
+              }
+              String propertyName = value.substring(pos + 2, endName);
+              fragments.add(null);
+              propertyRefs.add(propertyName);
+              prev = endName + 1;
+          }
+      }
+      //no more $ signs found
+      //if there is any tail to the string, append it
+      if (prev < value.length()) {
+          fragments.add(value.substring(prev));
+      }
+  }
+
 }

Added: lucene/solr/trunk/src/test/org/apache/solr/core/TestBadConfig.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/test/org/apache/solr/core/TestBadConfig.java?view=auto&rev=508485
==============================================================================
--- lucene/solr/trunk/src/test/org/apache/solr/core/TestBadConfig.java (added)
+++ lucene/solr/trunk/src/test/org/apache/solr/core/TestBadConfig.java Fri Feb 16 08:42:49
2007
@@ -0,0 +1,55 @@
+/**
+ * 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.
+ */
+
+package org.apache.solr.core;
+
+import org.apache.solr.util.AbstractSolrTestCase;
+import org.apache.solr.util.TestHarness;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import javax.xml.xpath.XPathConstants;
+import java.io.File;
+
+public class TestBadConfig extends AbstractSolrTestCase {
+
+  public String getSchemaFile() { return "schema.xml"; }
+  public String getSolrConfigFile() { return "bad_solrconfig.xml"; }
+
+  public void setUp() throws Exception {
+
+    dataDir = new File(System.getProperty("java.io.tmpdir")
+                       + System.getProperty("file.separator")
+                       + getClass().getName() + "-" + getName() + "-"
+                       + System.currentTimeMillis());
+    dataDir.mkdirs();
+    try {
+      h = new TestHarness(dataDir.getAbsolutePath(),
+                          getSolrConfigFile(),
+                          getSchemaFile());
+      fail("Exception should have been thrown");
+    } catch (Exception e) {
+      assertTrue(e.getMessage().contains("unset.sys.property"));
+    }
+  }
+    
+
+  public void testNothing() {
+    // Empty test case as the real test is that the initialization of the TestHarness fails
+    assertTrue(true);
+  }
+}
\ No newline at end of file

Added: lucene/solr/trunk/src/test/org/apache/solr/core/TestConfig.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/test/org/apache/solr/core/TestConfig.java?view=auto&rev=508485
==============================================================================
--- lucene/solr/trunk/src/test/org/apache/solr/core/TestConfig.java (added)
+++ lucene/solr/trunk/src/test/org/apache/solr/core/TestConfig.java Fri Feb 16 08:42:49 2007
@@ -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.
+ */
+
+package org.apache.solr.core;
+
+import org.apache.solr.util.AbstractSolrTestCase;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import javax.xml.xpath.XPathConstants;
+
+public class TestConfig extends AbstractSolrTestCase {
+
+  public String getSchemaFile() { return "schema.xml"; }
+  public String getSolrConfigFile() { return "solrconfig.xml"; }
+
+  public void testJavaProperty() {
+    // property values defined in build.xml
+
+    String s = SolrConfig.config.get("propTest");
+    assertEquals("prefix-proptwo-suffix", s);
+
+    s = SolrConfig.config.get("propTest/@attr1", "default");
+    assertEquals("propone-${literal}", s);
+
+    s = SolrConfig.config.get("propTest/@attr2", "default");
+    assertEquals("default-from-config", s);
+
+    s = SolrConfig.config.get("propTest[@attr2='default-from-config']", "default");
+    assertEquals("prefix-proptwo-suffix", s);
+
+    NodeList nl = (NodeList) SolrConfig.config.evaluate("propTest", XPathConstants.NODESET);
+    assertEquals(1, nl.getLength());
+    assertEquals("prefix-proptwo-suffix", nl.item(0).getTextContent());
+
+    Node node = SolrConfig.config.getNode("propTest", true);
+    assertEquals("prefix-proptwo-suffix", node.getTextContent());
+  }
+}
\ No newline at end of file

Added: lucene/solr/trunk/src/test/test-files/solr/conf/bad_solrconfig.xml
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/test/test-files/solr/conf/bad_solrconfig.xml?view=auto&rev=508485
==============================================================================
--- lucene/solr/trunk/src/test/test-files/solr/conf/bad_solrconfig.xml (added)
+++ lucene/solr/trunk/src/test/test-files/solr/conf/bad_solrconfig.xml Fri Feb 16 08:42:49
2007
@@ -0,0 +1,29 @@
+<?xml version="1.0" ?>
+
+<!--
+ 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.
+-->
+
+<!-- $Id: solrconfig.xml 382610 2006-03-03 01:43:03Z yonik $
+     $Source$
+     $Name$
+  -->
+
+<config>
+  <indexDefaults>
+    <useCompoundFile>${unset.sys.property}</useCompoundFile>
+  </indexDefaults>
+</config>

Modified: lucene/solr/trunk/src/test/test-files/solr/conf/solrconfig.xml
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/test/test-files/solr/conf/solrconfig.xml?view=diff&rev=508485&r1=508484&r2=508485
==============================================================================
--- lucene/solr/trunk/src/test/test-files/solr/conf/solrconfig.xml (original)
+++ lucene/solr/trunk/src/test/test-files/solr/conf/solrconfig.xml Fri Feb 16 08:42:49 2007
@@ -261,6 +261,9 @@
     <gettableFiles>solrconfig.xml scheam.xml admin-extra.html</gettableFiles>
   </admin>
 
+  <!-- test getting system property -->
+  <propTest attr1="${solr.test.sys.prop1}-$${literal}"
+            attr2="${non.existent.sys.prop:default-from-config}">prefix-${solr.test.sys.prop2}-suffix</propTest>
 
 
 </config>



Mime
View raw message