You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stanbol.apache.org by rw...@apache.org on 2011/03/18 15:16:03 UTC

svn commit: r1082932 - in /incubator/stanbol/trunk: enhancer/ enhancer/jersey/src/main/java/org/apache/stanbol/enhancer/jersey/ enhancer/launchers/full/src/main/resources/resources/config/ entityhub/model/clerezza/ entityhub/model/clerezza/src/main/jav...

Author: rwesten
Date: Fri Mar 18 14:16:03 2011
New Revision: 1082932

URL: http://svn.apache.org/viewvc?rev=1082932&view=rev
Log:
Summary: 
Implemented support for the EmbeddedSolrServerProvider to manage an internal Solr Server when running outside an OSGI Environment. This will be used to improve current Indexing Tools (related to STANBOL-92). Also improved the configuration capabilities for the storage location of the internal Solr Server and adapted the default configuration of the Apache Stanbol Enhancer full launcher to use this feature.

Details:

Entityhub: SolrYard

The EmbeddedSolrServerProvider can now also initialise and register an EmbeddedSolrServer when running outside an OSGI Environment. This is important for the indexing utils (e.g. for geonames.org, dbPedia.orf ...) because this allows to modify such tools to automatically create an EmbeddedSolrServer within there working directory. Users do no longer setup the SolrServer first! (related to STANBOL-92)

Added support that allows to configure the default location of the managed EmbeddedSolrServer: Within an OSGI environment the component configuration is used otherwise the property is searched in the System properties.
In case an relative path is configured the:
 - "user.dir" property is used when outside an OSGI environment
 - data directory of the SolrYard bundle
is used as root directory (for applying the relative path)
Note that also property substitution is supported so parsing "${user.home}/.stanbol/entityhub/solrYard/indexes" will create the indexes in the home directory of the user!

The internally managed SolrServer is now shutdown if the EmbeddedSolrServerProvider is deactivated. On activation the server is started again.

The SolrYardTest uses now both the support for managing an internal SolrServer when running outside an OSGI environment as the property substitution feature to parse "${basedir}/target/indexes" as index location. The "basedir" property is set by JUnit.
This allowed to remove all the resources previously required for this UnitTest.


Entityhub: ClerezzaYard

Corrected a missing dependency to the ClerezzaModel implementation


Enhancer: Full Launcher Configuration

Added a configuration for the EmbeddedSolrServerProvider so that the default Solr Index of the SolrYard is located at "${user.dir}/sling/entityhub/solrYard/indexes". Previously the index was stored under "/sling/felix/bundle?/data/index" - a location a user would not expect application data.

Added:
    incubator/stanbol/trunk/enhancer/launchers/full/src/main/resources/resources/config/org.apache.stanbol.entityhub.yard.solr.embedded.EmbeddedSolrPorovider.cfg
    incubator/stanbol/trunk/entityhub/model/clerezza/src/main/java/org/apache/stanbol/entityhub/model/clerezza/utils/
    incubator/stanbol/trunk/entityhub/model/clerezza/src/main/java/org/apache/stanbol/entityhub/model/clerezza/utils/Resource2StringAdapter.java   (contents, props changed)
      - copied, changed from r1082503, incubator/stanbol/trunk/entityhub/model/clerezza/src/main/java/org/apache/stanbol/entityhub/model/clerezza/impl/Resource2StringAdapter.java
Removed:
    incubator/stanbol/trunk/entityhub/model/clerezza/src/main/java/org/apache/stanbol/entityhub/model/clerezza/impl/Resource2StringAdapter.java
    incubator/stanbol/trunk/entityhub/yard/solr/src/test/resources/
Modified:
    incubator/stanbol/trunk/enhancer/   (props changed)
    incubator/stanbol/trunk/enhancer/jersey/src/main/java/org/apache/stanbol/enhancer/jersey/JettyServer.java
    incubator/stanbol/trunk/entityhub/model/clerezza/pom.xml
    incubator/stanbol/trunk/entityhub/model/clerezza/src/main/java/org/apache/stanbol/entityhub/model/clerezza/RdfRepresentation.java
    incubator/stanbol/trunk/entityhub/yard/clerezza/src/main/java/org/apache/stanbol/entityhub/yard/clerezza/impl/ClerezzaYard.java
    incubator/stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/embedded/EmbeddedSolrPorovider.java
    incubator/stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/utils/ConfigUtils.java
    incubator/stanbol/trunk/entityhub/yard/solr/src/main/resources/OSGI-INF/metatype/metatype.properties
    incubator/stanbol/trunk/entityhub/yard/solr/src/test/java/org/apache/stanbol/entityhub/yard/solr/SolrYardTest.java

Propchange: incubator/stanbol/trunk/enhancer/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Fri Mar 18 14:16:03 2011
@@ -1,3 +1,5 @@
 .project
 
 .classpath
+
+.settings

Modified: incubator/stanbol/trunk/enhancer/jersey/src/main/java/org/apache/stanbol/enhancer/jersey/JettyServer.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/enhancer/jersey/src/main/java/org/apache/stanbol/enhancer/jersey/JettyServer.java?rev=1082932&r1=1082931&r2=1082932&view=diff
==============================================================================
--- incubator/stanbol/trunk/enhancer/jersey/src/main/java/org/apache/stanbol/enhancer/jersey/JettyServer.java (original)
+++ incubator/stanbol/trunk/enhancer/jersey/src/main/java/org/apache/stanbol/enhancer/jersey/JettyServer.java Fri Mar 18 14:16:03 2011
@@ -28,9 +28,9 @@ public class JettyServer {
 
     private final Logger log = LoggerFactory.getLogger(getClass());
 
-    public static String DEFAULT_BASE_URI = "http://localhost:9998/";
+    public static final String DEFAULT_BASE_URI = "http://localhost:9998/";
 
-    protected Server server = new Server();
+    private Server server = new Server();
 
     private Context context;
 

Added: incubator/stanbol/trunk/enhancer/launchers/full/src/main/resources/resources/config/org.apache.stanbol.entityhub.yard.solr.embedded.EmbeddedSolrPorovider.cfg
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/enhancer/launchers/full/src/main/resources/resources/config/org.apache.stanbol.entityhub.yard.solr.embedded.EmbeddedSolrPorovider.cfg?rev=1082932&view=auto
==============================================================================
--- incubator/stanbol/trunk/enhancer/launchers/full/src/main/resources/resources/config/org.apache.stanbol.entityhub.yard.solr.embedded.EmbeddedSolrPorovider.cfg (added)
+++ incubator/stanbol/trunk/enhancer/launchers/full/src/main/resources/resources/config/org.apache.stanbol.entityhub.yard.solr.embedded.EmbeddedSolrPorovider.cfg Fri Mar 18 14:16:03 2011
@@ -0,0 +1 @@
+org.apache.stanbol.entityhub.yard.solr.embedded.solrDataDir=${user.dir}/sling/entityhub/solrYard/indexes

Modified: incubator/stanbol/trunk/entityhub/model/clerezza/pom.xml
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/model/clerezza/pom.xml?rev=1082932&r1=1082931&r2=1082932&view=diff
==============================================================================
--- incubator/stanbol/trunk/entityhub/model/clerezza/pom.xml (original)
+++ incubator/stanbol/trunk/entityhub/model/clerezza/pom.xml Fri Mar 18 14:16:03 2011
@@ -58,6 +58,7 @@
           <instructions>
             <Export-Package>
               org.apache.stanbol.entityhub.model.clerezza;version=${pom.version},
+              org.apache.stanbol.entityhub.model.clerezza.utils;version=${pom.version},
             </Export-Package>
            <Private-Package>
               org.apache.stanbol.entityhub.model.clerezza.impl;version=${pom.version}

Modified: incubator/stanbol/trunk/entityhub/model/clerezza/src/main/java/org/apache/stanbol/entityhub/model/clerezza/RdfRepresentation.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/model/clerezza/src/main/java/org/apache/stanbol/entityhub/model/clerezza/RdfRepresentation.java?rev=1082932&r1=1082931&r2=1082932&view=diff
==============================================================================
--- incubator/stanbol/trunk/entityhub/model/clerezza/src/main/java/org/apache/stanbol/entityhub/model/clerezza/RdfRepresentation.java (original)
+++ incubator/stanbol/trunk/entityhub/model/clerezza/src/main/java/org/apache/stanbol/entityhub/model/clerezza/RdfRepresentation.java Fri Mar 18 14:16:03 2011
@@ -35,10 +35,10 @@ import org.apache.stanbol.entityhub.core
 import org.apache.stanbol.entityhub.model.clerezza.impl.Literal2TextAdapter;
 import org.apache.stanbol.entityhub.model.clerezza.impl.LiteralAdapter;
 import org.apache.stanbol.entityhub.model.clerezza.impl.NaturalTextFilter;
-import org.apache.stanbol.entityhub.model.clerezza.impl.Resource2StringAdapter;
 import org.apache.stanbol.entityhub.model.clerezza.impl.Resource2ValueAdapter;
 import org.apache.stanbol.entityhub.model.clerezza.impl.UriRef2ReferenceAdapter;
 import org.apache.stanbol.entityhub.model.clerezza.impl.UriRefAdapter;
+import org.apache.stanbol.entityhub.model.clerezza.utils.Resource2StringAdapter;
 import org.apache.stanbol.entityhub.servicesapi.model.Reference;
 import org.apache.stanbol.entityhub.servicesapi.model.Representation;
 import org.apache.stanbol.entityhub.servicesapi.model.Text;

Copied: incubator/stanbol/trunk/entityhub/model/clerezza/src/main/java/org/apache/stanbol/entityhub/model/clerezza/utils/Resource2StringAdapter.java (from r1082503, incubator/stanbol/trunk/entityhub/model/clerezza/src/main/java/org/apache/stanbol/entityhub/model/clerezza/impl/Resource2StringAdapter.java)
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/model/clerezza/src/main/java/org/apache/stanbol/entityhub/model/clerezza/utils/Resource2StringAdapter.java?p2=incubator/stanbol/trunk/entityhub/model/clerezza/src/main/java/org/apache/stanbol/entityhub/model/clerezza/utils/Resource2StringAdapter.java&p1=incubator/stanbol/trunk/entityhub/model/clerezza/src/main/java/org/apache/stanbol/entityhub/model/clerezza/impl/Resource2StringAdapter.java&r1=1082503&r2=1082932&rev=1082932&view=diff
==============================================================================
--- incubator/stanbol/trunk/entityhub/model/clerezza/src/main/java/org/apache/stanbol/entityhub/model/clerezza/impl/Resource2StringAdapter.java (original)
+++ incubator/stanbol/trunk/entityhub/model/clerezza/src/main/java/org/apache/stanbol/entityhub/model/clerezza/utils/Resource2StringAdapter.java Fri Mar 18 14:16:03 2011
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.stanbol.entityhub.model.clerezza.impl;
+package org.apache.stanbol.entityhub.model.clerezza.utils;
 
 import org.apache.clerezza.rdf.core.Literal;
 import org.apache.clerezza.rdf.core.Resource;

Propchange: incubator/stanbol/trunk/entityhub/model/clerezza/src/main/java/org/apache/stanbol/entityhub/model/clerezza/utils/Resource2StringAdapter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stanbol/trunk/entityhub/model/clerezza/src/main/java/org/apache/stanbol/entityhub/model/clerezza/utils/Resource2StringAdapter.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: incubator/stanbol/trunk/entityhub/yard/clerezza/src/main/java/org/apache/stanbol/entityhub/yard/clerezza/impl/ClerezzaYard.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/yard/clerezza/src/main/java/org/apache/stanbol/entityhub/yard/clerezza/impl/ClerezzaYard.java?rev=1082932&r1=1082931&r2=1082932&view=diff
==============================================================================
--- incubator/stanbol/trunk/entityhub/yard/clerezza/src/main/java/org/apache/stanbol/entityhub/yard/clerezza/impl/ClerezzaYard.java (original)
+++ incubator/stanbol/trunk/entityhub/yard/clerezza/src/main/java/org/apache/stanbol/entityhub/yard/clerezza/impl/ClerezzaYard.java Fri Mar 18 14:16:03 2011
@@ -56,7 +56,7 @@ import org.apache.stanbol.entityhub.core
 import org.apache.stanbol.entityhub.core.yard.SimpleYardConfig;
 import org.apache.stanbol.entityhub.model.clerezza.RdfRepresentation;
 import org.apache.stanbol.entityhub.model.clerezza.RdfValueFactory;
-import org.apache.stanbol.entityhub.model.clerezza.impl.Resource2StringAdapter;
+import org.apache.stanbol.entityhub.model.clerezza.utils.Resource2StringAdapter;
 import org.apache.stanbol.entityhub.query.clerezza.RdfQueryResultList;
 import org.apache.stanbol.entityhub.query.clerezza.SparqlFieldQuery;
 import org.apache.stanbol.entityhub.query.clerezza.SparqlFieldQueryFactory;

Modified: incubator/stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/embedded/EmbeddedSolrPorovider.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/embedded/EmbeddedSolrPorovider.java?rev=1082932&r1=1082931&r2=1082932&view=diff
==============================================================================
--- incubator/stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/embedded/EmbeddedSolrPorovider.java (original)
+++ incubator/stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/embedded/EmbeddedSolrPorovider.java Fri Mar 18 14:16:03 2011
@@ -35,6 +35,7 @@ import org.apache.felix.scr.annotations.
 import org.apache.felix.scr.annotations.Service;
 import org.apache.solr.client.solrj.SolrServer;
 import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
+import org.apache.solr.common.ResourceLoader;
 import org.apache.solr.core.CoreContainer;
 import org.apache.solr.core.CoreDescriptor;
 import org.apache.solr.core.SolrCore;
@@ -50,32 +51,40 @@ import org.xml.sax.SAXException;
  * Support for the use of {@link EmbeddedSolrPorovider} in combination with the
  * SolrYard implementation. This implements the {@link SolrServerProvider}
  * interface for the {@link Type#EMBEDDED}.<p>
- * This implementation also adds support for dynamic configuration of an
- * {@link EmbeddedSolrServer} within the "/data" directory provided by the
- * OSGI Environment for the SolrYard bundle. This Embedded SolrServer is 
- * configured using an default configuration part of the SolrYard Bundle. The
- * Indexes are located at an folder with the name {@link #DEFAULT_SOLR_DATA_DIR}
- * (see {@link BundleContext#getDataFile(String)}).<p>
- * If a relative path is parsed as second parameter to 
- * {@link #getSolrServer(org.apache.stanbol.entityhub.yard.solr.provider.SolrServerProvider.Type, String, String...)}
- * than the value is looked up by using the internally managed EmbeddedSolrServer.<p>
- * This implementation also supports the dynamic initialisation, creation and
- * registration of new Cores for the internally managed EmbeddedSolrServer.
- * So if a parsed relative path does not correspond with an existing SolrCore,
- * than the default Core configuration (part of the SolrYard bundle) is used
- * to create the missing core.<p>
- * Note that it is also a valid Scenario that an other components copies data
- * (e.g. a prepared index) to the directory used by the internally managed
- * EmbeddedSolrServer. Than this implementation just registers the new core
- * with the EmbeddedSolrServer (creation and registration of the Core).
+ * This implementation manages an internally managed instance of an 
+ * {@link EmbeddedSolrServer} that is used to create/lookup cores if a
+ * relative path is parsed as second parameter to 
+ * {@link #getSolrServer(Type, String, String...)}. In case such a relative path
+ * refers to a core that does not already exist this provider will create and
+ * initialise a new one. It is also possible for other components to copy the
+ * required files to the according directory and than use this provider to 
+ * initialise the core. The {@link ConfigUtils} class provides some utilities
+ * for that.<p>
+ * The {@link #SOLR_DATA_DIR_PROPERTY} property can be used to define the location
+ * of the internally managed index. By default it is within the 
+ * {@link #DEFAULT_SOLR_DATA_DIR} directory located within the working-directory
+ * (if running outside an OSGI environment) or within the data directory of the
+ * SolrYard bundle (when running within an OSGI environment).<p>
+ * Note that property substitution is supported for the 
+ * {@link #SOLR_DATA_DIR_PROPERTY} property by using {@link System#getProperty(String, String)}
+ * to search for values (empty string is used as default)<p>
+ * Parsing the value "${data.dir}/indexes" will lookup the value of the system
+ * property "data.dir" and the index will be located at "{property-value}/indexes".
  * 
+ * TODO: add functionality to lookup the internally managed {@link CoreContainer}.
+ * Maybe this requires to add a second service
  * @author Rupert Westenthaler
  *
  */
-@Component(immediate=true)
+@Component(immediate=true,metatype=true)
 @Service
 public class EmbeddedSolrPorovider implements SolrServerProvider {
     private final Logger log = LoggerFactory.getLogger(EmbeddedSolrPorovider.class);
+    //define the default values here because they are not accessible via the Solr API
+    public static final String SOLR_XML_NAME = "solr.xml";
+    public static final String SOLR_CONFIG_NAME = "solrconfig.xml";
+    public static final String SOLR_SCHEMA_NAME = "schema.xml";
+    
     /**
      * internally used to keep track of active {@link CoreContainer}s for
      * requested paths.
@@ -83,16 +92,47 @@ public class EmbeddedSolrPorovider imple
     @SuppressWarnings("unchecked")
     private Map<String, CoreContainer> coreContainers = new ReferenceMap(); 
     
-    @Property
-    public static final String SOLR_HOME = "solr.solr.home";
-
+    /**
+     * This property can be used to configure the location of the internally
+     * managed EmbeddedSolrServer.<p>
+     * Configuring an absolute path (starting with {@link File#separatorChar}) 
+     * will cause the index to be initialised in this directory.<p>
+     * Configuring an relative value will use  <ul>
+     * <li> the working directory (<code>Systen.getProperty("user.dir")</code>)
+     *      outside of an OSGI environment
+     * <li> the data directory provided by the SolrYard bundle (by calling
+     *      {@link BundleContext#getDataFile(String)} with the relative path.
+     * </ul>
+     * In case this property is not present the {@link #DEFAULT_SOLR_DATA_DIR}
+     * (an relative path) is used.
+     */
+    @Property(value=EmbeddedSolrPorovider.DEFAULT_SOLR_DATA_DIR)
+    public static final String SOLR_DATA_DIR_PROPERTY = "org.apache.stanbol.entityhub.yard.solr.embedded.solrDataDir";
+    /**
+     * default value for the relative path used if the {@link #SOLR_DATA_DIR_PROPERTY}
+     * is not present
+     */
     public static final String DEFAULT_SOLR_DATA_DIR = "indexes";
     
     /**
+     * The directory used by the internally managed embedded solr server.
+     */
+    private File solrDataDir;
+    
+    /**
      * The component context. Only available when running within an OSGI 
      * Environment and the component is active.
      */
     private ComponentContext componentContext;
+    /**
+     * For some functionality within this component it is important to track
+     * if this instance operates within or outside of an OSGI environment.
+     * because of this this boolean is set to true as soon as the first time
+     * {@link #activate(ComponentContext)} or {@link #deactivate(ComponentContext)}
+     * is called. If someone knows a better method to check that feel free to
+     * change!
+     */
+    private boolean withinOSGI = false;
     
     public EmbeddedSolrPorovider() {
     }
@@ -103,34 +143,42 @@ public class EmbeddedSolrPorovider imple
         if(uriOrPath == null){
             throw new IllegalArgumentException("The Path to the Index MUST NOT be NULL!");
         }
+        log.info("parsed solr server location "+uriOrPath);
+        //first try as file (but keep in mind it could also be an URI)
         File index = new File(uriOrPath);
-        if(!index.exists()){
+        //if it is absolute and it exists -> take it
+        if(!index.isAbsolute() || !index.exists()){
+            //otherwise test if it is an URI
             try {
                 URI fileUri = new URI(uriOrPath);
                 index = new File(fileUri);
             } catch (URISyntaxException e) {
-                //also not an URI -> ignore
+                //not an URI -> ignore
             } catch (IllegalArgumentException e){
-                //URI can not be converted to a file (e.g. not an absolute URI starting with "file:")
+                //this happens if it is a URI but can not be converted to a file
+                //still we should try to work with the parsed file ...
             }
-            if(!index.exists()){
-                //try to init the core via the default EmbeddedSolrServer
-                // -> Initialised based on the default values in the bundle
-                index = initCoreDirectory(uriOrPath);
-                if(index == null){
-                    throw new IllegalArgumentException(String.format("The parsed Index Path %s does not exist",uriOrPath));
+            //ok now we have the file path ... do some evaluation
+            if(!index.isAbsolute()){ //if it is not absolute
+                //use the internally managed EmbeddedSolrServer
+                index = initManagedCoreDirectory(uriOrPath);
+                if(index == null){ 
+                    throw new IllegalArgumentException(String.format("The parsed Index Path %s does not exist and con not be initialised ",uriOrPath));
                 }
+            } else if(!index.exists()){ //if it is absolute -> check that it exist
+                throw new IllegalArgumentException(String.format("The parsed Index Path %s does not exist",uriOrPath));
             }
         }
+        log.info("get solr server for location "+index);
         File coreDir = null;
         if(index.isDirectory()){
-            File solr = getFile(index, "solr.xml");
+            File solr = getFile(index, SOLR_XML_NAME);
             String coreName;
             if(solr != null){
                 //in that case we assume that this is a single core installation
                 coreName = "";
             } else {
-                solr = getFile(index.getParentFile(), "solr.xml");
+                solr = getFile(index.getParentFile(), SOLR_XML_NAME);
                 if(solr != null){
                     //assume this is a multi core
                     coreName = index.getName();
@@ -139,7 +187,7 @@ public class EmbeddedSolrPorovider imple
                 } else {
                     throw new IllegalArgumentException(String.format("The parsed Index Path %s is not an Solr " +
                     		"Index nor a Core of an Multi Core Configuration " +
-                    		"(no \"solr.xml\" was found in this nor the parent directory!)",uriOrPath));
+                    		"(no \""+SOLR_XML_NAME+"\" was found in this nor the parent directory!)",uriOrPath));
                 }
             }
             //now init the EmbeddedSolrServer
@@ -151,16 +199,16 @@ public class EmbeddedSolrPorovider imple
                 /*
                  * NOTE: This assumes that the data for the core are already copied
                  * to the required location, but the core itself is not yet registered
-                 * in the solr.xml.
+                 * in the SOLR_XML_NAME.
                  * This uses the java API to register the core. Changes are saved
-                 * within the solr.xml if persistent="true" is present within the
+                 * within the SOLR_XML_NAME if persistent="true" is present within the
                  * solr element.
                  */
                 /*
                  * NOTE:
                  * We need to reset the ContextClassLoader to the one used for this
                  * Bundle, because Solr uses this ClassLoader to load all the
-                 * plugins configured in the solr.xml and schema.xml.
+                 * plugins configured in the SOLR_XML_NAME and schema.xml.
                  * The finally block resets the context class loader to the previous
                  * value. (Rupert Westenthaler 20010209)
                  */
@@ -178,6 +226,8 @@ public class EmbeddedSolrPorovider imple
                             		"to SolrServer %s!",coreName,index.getAbsoluteFile()),e);
                     }
                     coreContainer.register(coreName, core,false);
+                    //persist the new core to have it available on the next start
+                    coreContainer.persist(); 
                 } finally {
                     Thread.currentThread().setContextClassLoader(classLoader);
                 }
@@ -188,6 +238,45 @@ public class EmbeddedSolrPorovider imple
         }
     }
     /**
+     * The {@link CoreContainer} managed internally for the SolrYard. This is
+     * used whenever a {@link #getSolrServer(Type, String, String...)} parses
+     * an relative path as second parameter.<p>
+     * Within an OSGI Environment this CoreContainer is started/stopped
+     * within the activate/deactivate methods. With the exception if the
+     * {@link #solrDataDir} does not exist, because this means that this internally
+     * managed CoreContainer is not yet used. A lazy initialisation will be
+     * performed when required.<p>
+     * This Method does not perform any initialisation!
+     * @return the managed CoreContainer or <code>null</code> if it is not yet
+     * initialised or if the component is deactivated.
+     */
+    public CoreContainer getManagedCoreContainer(){
+        File managedCoreContainerDir = getManagedSolrDataDir();
+        if(managedCoreContainerDir != null){
+            return coreContainers.get(managedCoreContainerDir.getAbsolutePath());
+        } else {
+            return null;
+        }
+    }
+    /**
+     * This will invalidate all EmbeddedSolrServers created by using this
+     * CoreContainer or any of the Cores associated with this one
+     * ({@link CoreContainer#getCores()})
+     * @return <code>true</code> if the managed core was shutdown <code>false</code>
+     * if the managed core was not active and therefore no change was performed
+     */
+    private boolean shutdownManagedCoreContainer(){
+        File managedCoreContainerDir = getManagedSolrDataDir();
+        if(managedCoreContainerDir != null){
+            CoreContainer managedCoreContainer = coreContainers.remove(managedCoreContainerDir);
+            if(managedCoreContainer != null){
+                managedCoreContainer.shutdown();
+                return true;
+            }
+        }
+        return false;
+    }
+    /**
      * Getter for the defaultCore
      * @param coreName the name of the core or <code>null</code> to get/init the
      * default directory of the default CoreContainer.<p>
@@ -196,29 +285,38 @@ public class EmbeddedSolrPorovider imple
      * <code>null</code> is parsed as coreName). <code>null</code> is returned
      * if the initialisation was not successful.
      */
-    protected final File initCoreDirectory(final String coreName){
-        ComponentContext context = componentContext;
-        if(context == null){ //not within OSGI Environment and active! 
-            return null; //no default core container available
+    protected final File initManagedCoreDirectory(final String coreName){
+        File managedCoreContainerDirectory = getManagedSolrDataDir();
+        if(managedCoreContainerDirectory == null){
+            return null;
         }
-        File defaultCoreDirectory = context.getBundleContext().getDataFile(DEFAULT_SOLR_DATA_DIR);
-        if(!defaultCoreDirectory.exists()){
+        ComponentContext context = componentContext;
+        if(!managedCoreContainerDirectory.exists()){
             try {
-                defaultCoreDirectory = ConfigUtils.copyDefaultConfig(context.getBundleContext().getBundle(),
-                    defaultCoreDirectory, false);
+                if(context != null){ //load via bundle
+                    managedCoreContainerDirectory = ConfigUtils.copyDefaultConfig(
+                        context.getBundleContext().getBundle(),managedCoreContainerDirectory, false);
+                } else { //load from jar
+                    managedCoreContainerDirectory = ConfigUtils.copyDefaultConfig(
+                        (Class<?>)null, managedCoreContainerDirectory, false);
+                }
             } catch (Exception e) {
                 log.warn("Unable to initialise the default EmbeddedSolrServer!",e);
                 return null;
             }
         }
         if(coreName == null){
-            return defaultCoreDirectory;
+            return managedCoreContainerDirectory;
         }
-        File coreDir = new File(defaultCoreDirectory,coreName);
+        File coreDir = new File(managedCoreContainerDirectory,coreName);
         if(!coreDir.exists()){
             try {
-                ConfigUtils.copyCore(context.getBundleContext().getBundle(),
-                    coreDir, null, false);
+                if(context != null){ //load via bundle
+                    ConfigUtils.copyCore(context.getBundleContext().getBundle(),
+                        coreDir, null, false);
+                } else { //load from jar
+                    ConfigUtils.copyCore((Class<?>)null, coreDir, null, false);
+                }
             } catch (Exception e) {
                 log.warn("Unable to initialise the core "+coreName+" with the default Core configuration!",e);
                 return null;
@@ -226,17 +324,96 @@ public class EmbeddedSolrPorovider imple
         }
         return coreDir;
     }
+
+    /**
+     * Internally used during initialisation to get the location of the directory
+     * used for the data of the internally managed {@link CoreContainer}.<p>
+     * This method checks the configuration based on of this EmbeddesSolrServerProvider
+     * operates within or outside of an OSGI environment. It is not intended for
+     * @return the directory of the Solr Home used for the internally managed
+     * {@link CoreContainer} or <code>null</code> if running within an OSGI
+     * Environment and this component is deactivated.
+     */
+    private File getManagedSolrDataDir() {
+        //local copy to avoid NullPointerExceptions when deactivate is called
+        //during this method
+        ComponentContext context = componentContext;
+        if(solrDataDir == null){
+            String configuredDataDir;
+            if(context == null){
+                configuredDataDir = System.getProperty(SOLR_DATA_DIR_PROPERTY,DEFAULT_SOLR_DATA_DIR);
+            } else {
+                Object value = context.getProperties().get(SOLR_DATA_DIR_PROPERTY);
+                if(value != null){
+                    configuredDataDir = value.toString();
+                } else {
+                    configuredDataDir = DEFAULT_SOLR_DATA_DIR;
+                }
+            }
+            //property substitution
+            configuredDataDir = substituteProperty(configuredDataDir);
+            //determine the directory holding the SolrIndex
+            if(!configuredDataDir.isEmpty() && configuredDataDir.charAt(0) == File.separatorChar){
+                //absolute path (same within/outside OSGI environment)
+                if(withinOSGI && context == null){
+                    //however set to  null if within OSGI environment and
+                    //deactivated
+                    solrDataDir = null;
+                } else { //set the the absolute path
+                    solrDataDir = new File(configuredDataDir);
+                }
+            } else { //relative path
+                if(!withinOSGI){ //not within OSGI Environment
+                    String workingDir = System.getProperty("user.dir");
+                    solrDataDir = new File(workingDir,configuredDataDir);
+                } else if(context != null){ //within OSGI && activated
+                    solrDataDir = context.getBundleContext().getDataFile(configuredDataDir);
+                } else { //within OSGI && deactivated
+                    solrDataDir = null;
+                }
+            }
+        }
+        return solrDataDir;
+    }
+
+    /**
+     * Substitutes ${property.name} with the values retrieved via
+     * {@link System#getProperty(String, String)}. An empty string is used as
+     * default<p>
+     * If someone knows a default implementation feel free to replace!
+     * @param value the value to substitute
+     * @return the substituted value
+     */
+    private static String substituteProperty(String value) {
+        int prevAt = 0;
+        int foundAt = 0;
+        StringBuilder substitution = new StringBuilder();
+        while((foundAt = value.indexOf("${",prevAt))>=prevAt){
+            substitution.append(value.substring(prevAt, foundAt));
+            String propertyName = value.substring(
+                foundAt+2,value.indexOf('}',foundAt));
+            substitution.append(System.getProperty(propertyName, ""));
+            prevAt = foundAt+propertyName.length()+3;
+        }
+        substitution.append(value.substring(prevAt, value.length()));
+        return substitution.toString();
+    }
+    public static void main(String[] args) {
+        System.out.println(substituteProperty("this ${user.dir} is ${not.existant} of version ${java.version}"));
+    }
     
+    protected final CoreContainer getCoreContainer(File solrDir) throws IllegalArgumentException, IllegalStateException {
+        return getCoreContainer(solrDir.getAbsolutePath(), new File(solrDir,SOLR_XML_NAME));
+    }
     protected final CoreContainer getCoreContainer(String solrDir, File solrConf) throws IllegalArgumentException, IllegalStateException {
         CoreContainer container = coreContainers.get(solrDir);
         if(container == null){
             container = new CoreContainer(solrDir);
-            coreContainers.put(solrDir, container);
             /*
              * NOTE:
              * We need to reset the ContextClassLoader to the one used for this
              * Bundle, because Solr uses this ClassLoader to load all the
-             * plugins configured in the solr.xml and schema.xml.
+             * plugins configured in the SOLR_XML_NAME and schema.xml.
              * The finally block resets the context class loader to the previous
              * value. (Rupert Westenthaler 20010209)
              */
@@ -253,6 +430,7 @@ public class EmbeddedSolrPorovider imple
             } finally {
                 Thread.currentThread().setContextClassLoader(loader);
             }
+            coreContainers.put(solrDir, container);
         }
         return container;
     }
@@ -263,10 +441,26 @@ public class EmbeddedSolrPorovider imple
     }
     @Activate
     protected void activate(ComponentContext context) {
+        this.withinOSGI = true;
         this.componentContext = context;
+        File managedCoreContainerDir = getManagedSolrDataDir();
+        if(managedCoreContainerDir != null){
+            if(managedCoreContainerDir.exists()) {
+                //this indicated, that the core was alredy used ... so start it
+                getCoreContainer(managedCoreContainerDir);
+            } //else -> the internally managed core was not yet used ->
+            // use lazy initialisation on first usage (no need to load all the
+            //solr stuff in environments that do not use an EmbeddedSolrServer
+        } else {
+            //that should never happen ... 
+            throw new IllegalStateException("Unable to get Directory for the internally managed Solr Server");
+        }
     }
     @Deactivate
     protected void deactivate(ComponentContext context) {
+        this.withinOSGI = true;
+        shutdownManagedCoreContainer();
+        solrDataDir = null;
         this.componentContext = null;
         //should we remove the coreContainers -> currently I don't because
         // (1) activate deactivate do not have any affect

Modified: incubator/stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/utils/ConfigUtils.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/utils/ConfigUtils.java?rev=1082932&r1=1082931&r2=1082932&view=diff
==============================================================================
--- incubator/stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/utils/ConfigUtils.java (original)
+++ incubator/stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/utils/ConfigUtils.java Fri Mar 18 14:16:03 2011
@@ -17,11 +17,15 @@
 package org.apache.stanbol.entityhub.yard.solr.utils;
 
 import java.io.File;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.net.URL;
 import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
 
 import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
 import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
 import org.apache.stanbol.entityhub.yard.solr.embedded.EmbeddedSolrPorovider;
 import org.osgi.framework.Bundle;
@@ -33,8 +37,9 @@ import org.slf4j.LoggerFactory;
  * and copy it to a directory.<p>
  * This is currently used by the {@link EmbeddedSolrPorovider} to initialise the
  * internally managed {@link EmbeddedSolrServer} and/or to add additional cores.
- * However such methods are also useful for the initialisation of an prepared
- * index. Assuming that such prepared indexes are provided as a OSGI bundle.
+ * There are always two variants of the methods. The one taking a bundle as
+ * parameter is supposed to be used when running within an OSGI environment. The
+ * variant taking a Class object works outside of an OSGI environment.
  * @author Rupert Westenthaler
  *
  */
@@ -61,13 +66,15 @@ public final class ConfigUtils {
      * {@link #CONFIG_DIR} (value=" {@value #CONFIG_DIR}") directory.
      * @param rootDir the target directory for the configuration. 
      * @param override if true existing configurations are overridden.
-     * @return the root directory of the solr configuration (same as parsed as rootDir)
+     * @return the root directory of the solr configuration (same as parsed as 
+     * rootDir)
      * @throws IOException On any IO error while coping the configuration
-     * @throws NullPointerException if <code>null</code> is parsed as bundle or rootDir
-     * @throws IllegalStateException If the parsed bundle is in the {@link Bundle#UNINSTALLED}
+     * @throws IllegalStateException If the parsed bundle is in the 
+     * {@link Bundle#UNINSTALLED}
      * state, the parsed rootDir does exist but is not a directory.
-     * @throws IllegalArgumentException If the parsed bundle does not contain the
-     * required information to set up an configuration 
+     * @throws IllegalArgumentException If <code>null</code> is parsed as bundle 
+     * or rootDir or if the parsed bundle does not contain the required 
+     * information to set up an configuration 
      */
     @SuppressWarnings("unchecked") //Enumeration<URL> required by OSGI specification
     public static File copyDefaultConfig(Bundle bundle, File rootDir,boolean override) throws IOException, NullPointerException, IllegalStateException, IllegalArgumentException {
@@ -91,7 +98,80 @@ public final class ConfigUtils {
         log.debug(" ... default Configuration copied to "+rootDir.getAbsolutePath());
         return rootDir;
     }
-
+    /**
+     * Initialises the default configuration for the SolrYard based on data in
+     * the parsed bundle. The configuration will be copied to the parsed root
+     * directory.
+     * @param clazzInArchive This class is used to identify the archive containing
+     * the default configuration. Parsing <code>null</code> causes this class to
+     * be used and therefore initialises the default configuration contained by
+     * the SolrYard bundle.
+     * @param rootDir the target directory for the configuration. 
+     * @param override if true existing configurations are overridden.
+     * @return the root directory of the solr configuration (same as parsed as rootDir)
+     * @throws IOException On any IO error while coping the configuration
+     * @throws IllegalStateException If the parsed rootDir does exist but is not
+     * a directory.
+     * @throws IllegalArgumentException iIf <code>null</code> is parsed as 
+     * rootDir or if the parsed bundle does not contain the required information 
+     * to set up an configuration 
+     */
+    public static File copyDefaultConfig(Class<?> clazzInArchive,File rootDir,boolean override) throws IOException, NullPointerException, IllegalStateException, IllegalArgumentException {
+        if(rootDir == null){
+            throw new IllegalArgumentException("The parsed root directory MUST NOT be NULL!");
+        }
+        if(rootDir.exists() && !rootDir.isDirectory()){
+            throw new IllegalStateException("The parsed root directory "+rootDir.getAbsolutePath()+" extists but is not a directory!");
+        }
+        File sourceRoot = getSource(clazzInArchive!=null?clazzInArchive:ConfigUtils.class); 
+        if(sourceRoot.isFile()){
+            ZipFile archive = new ZipFile(sourceRoot);
+            log.info(String.format("Copy Default Config from jar-file %s to %s (override=%s)",
+                archive.getName(),rootDir.getAbsolutePath(),override));
+            try {
+                for(Enumeration<? extends ZipEntry> entries = archive.entries();entries.hasMoreElements();){
+                    ZipEntry entry = entries.nextElement();
+                    if(entry.getName().startsWith(CONFIG_DIR)){
+                        copyResource(rootDir, archive, entry, CONFIG_DIR, override);
+                    }
+                }
+            } finally {
+                //regardless what happens we need to close the archive!
+                archive.close();
+            }
+        } else { //load from file
+            File source = new File(sourceRoot,CONFIG_DIR);
+            if(source.exists() && source.isDirectory()){
+                FileUtils.copyDirectory(source, rootDir);
+            } else {
+                throw new FileNotFoundException("The SolrIndex default config was not found in directory "+source.getAbsolutePath());
+            }
+        }
+        return rootDir;
+    }
+    /**
+     * Uses the {@link ClassLoader} of the parsed {@link Class} instance to locate
+     * the jar file the class was loaded from.
+     * @param clazz the class used as context to find the jar file
+     * @return the archive the parsed class was loaded from
+     * @throws IOException In case the jar file can not be accessed.
+     */
+    private static File getSource(Class<?> clazz) throws IOException {
+        String classFileName = clazz.getName().replace('.', '/')+".class";
+        URL classLocation = clazz.getClassLoader().getResource(classFileName);
+        String classPath;
+        try {
+            classPath = new File(classLocation.toURI()).getAbsolutePath();
+        } catch (Exception e) {
+            throw new IOException("Unable to Access Source at location "+classLocation,e);
+        }
+        if(classPath.indexOf('!')>0){
+            return new File(classPath.substring(0,classPath.indexOf('!')));
+        } else {
+            return new File(classPath.substring(0,classPath.length()-classFileName.length()));
+        }
+    }
+    
     /**
      * Copies a resource (URL of an resource within a Bundle) to a file
      * @param rootDir the directory used as target
@@ -101,21 +181,80 @@ public final class ConfigUtils {
      * @throws IOException on any IO error
      */
     private static void copyResource(File rootDir, URL resource, String context, boolean override) throws IOException {
+        String resourcePath = resource.toString();
+        File file = prepairCopy(resourcePath, rootDir, context);
+        if(file != null){
+            boolean overrideState = false;
+            if(file.exists() && override){
+                FileUtils.deleteQuietly(file);
+                overrideState = true;
+            }
+            if(!file.exists()) {
+                FileUtils.copyURLToFile(resource, file);
+                log.debug(String.format(" > %s %s",overrideState?"override":"copy",file));
+            }
+        } //else can not cppy logging already provided
+    }
+    /**
+     * Variant of the copyResource method that used an entry of an archive as
+     * source.
+     * @param rootDir the directory used as target
+     * @param archive the archive containing the parsed entry
+     * @param entry the entry to copy to the target directory
+     * @param context the context used to calculate the relative path of the
+     * resource within the target directory
+     * @param override if an existing resource within the target directory should
+     * be deleted
+     * @throws IOException in case of an error while reading or writing the resource
+     */
+    private static void copyResource(File rootDir,ZipFile archive, ZipEntry entry,String context,boolean override) throws IOException {
+        File file = prepairCopy(entry.getName(), rootDir, context);
+        if(file != null){
+            boolean overrideState = false;
+            if(file.exists() && override){
+                FileUtils.deleteQuietly(file);
+                overrideState = true;
+            }
+            if(!file.exists()) {
+                IOUtils.copy(archive.getInputStream(entry), FileUtils.openOutputStream(file));
+                log.debug(String.format(" > %s %s",overrideState?"override":"copy",file));
+            }
+        } //else can not cppy logging already provided
+        
+    }
+    
+    /**
+     * Prepares the copying of a resource. The context is used to determine the
+     * relative path of the resource. Than missing sub-directories are created
+     * in the target directory. Finally the file instance representing this 
+     * resource within the target directory is returned. 
+     * @param resource The path to the resource. This need not be the full path.
+     * It must only be ensured that the parsed context is contained. e.g. the
+     * relative path of a resource within an archive provides enough context for
+     * this method to work
+     * @param targetDir the target directory
+     * @param context the context to determine the relative path of the resource
+     * within the target directory. The context MUST be part of the parsed
+     * resource name. Otherwise this method will return <code>null</code>
+     * @return the file representing the resource within the target directory.
+     * In cases the context can not be found in the parsed resource this method 
+     * returns <code>null</code>
+     */
+    private static File prepairCopy(String resource, File targetDir, String context) {
         if(!(context.charAt(context.length()-1) == '/')){
             context = context+'/';
         }
-        String resourcePath = resource.toString();
-        int contextPos = resourcePath.lastIndexOf(context);
+        int contextPos = resource.lastIndexOf(context);
         if(contextPos >=0){
             contextPos = contextPos+context.length();
         } else {
             log.warn(String.format("Context %s not found in resource %s -> ignored!",
                 context,resource));
-            return;
+            return null;
         }
-        String relativePath = resourcePath.substring(contextPos);
+        String relativePath = resource.substring(contextPos);
         String[] relativePathElements = relativePath.split("/");
-        File parentElement = rootDir;
+        File parentElement = targetDir;
         for(int i=0;i<relativePathElements.length-1;i++){
             File pathElement = new File(parentElement,relativePathElements[i]);
             if(!pathElement.exists()){
@@ -124,15 +263,7 @@ public final class ConfigUtils {
             parentElement = pathElement;
         }
         File file = new File(parentElement,relativePathElements[relativePathElements.length-1]);
-        boolean overrideState = false;
-        if(file.exists() && override){
-            FileUtils.deleteQuietly(file);
-            overrideState = true;
-        }
-        if(!file.exists()) {
-            FileUtils.copyURLToFile(resource, file);
-            log.debug(String.format(" > %s %s",overrideState?"override":"copy",relativePath));
-        }
+        return file;
     }
     /**
      * Copy the configuration of an core.
@@ -144,14 +275,14 @@ public final class ConfigUtils {
      * configurations
      * @param override if files in the target directory should be overridden
      * @throws IOException On any IO error while coping the configuration
-     * @throws NullPointerException if <code>null</code> is parsed as bundle or coreDir
      * @throws IllegalStateException If the parsed bundle is in the {@link Bundle#UNINSTALLED}
      * state, the parsed coreDir does exist but is not a directory.
-     * @throws IllegalArgumentException If the parsed bundle does not contain the
-     * required information to set up an configuration or the parsed coreName is empty.
+     * @throws IllegalArgumentException if <code>null</code> is parsed as bundle or coreDir
+     * or if the parsed bundle does not contain the required information to set 
+     * up an configuration or the parsed coreName is empty.
      */
     @SuppressWarnings("unchecked") //Enumeration<URL> required by OSGI specification
-    public static void copyCore(Bundle bundle, File coreDir, String coreName, boolean override) throws IOException,NullPointerException,IllegalStateException,IllegalArgumentException{
+    public static void copyCore(Bundle bundle, File coreDir, String coreName, boolean override) throws IOException,IllegalStateException,IllegalArgumentException{
         if(bundle == null){
             throw new IllegalArgumentException("The parsed Bundle MUST NOT be NULL!");
         }
@@ -171,4 +302,59 @@ public final class ConfigUtils {
             copyResource(coreDir, resource, context, override);
         }
     }
+    /**
+     * Copy the configuration of an core.
+     * @param clazzInArchive This class is used to identify the archive containing
+     * the default configuration. Parsing <code>null</code> causes this class to
+     * be used and therefore initialises the default core configuration contained by
+     * the SolrYard bundle.
+     * @param coreDir the target directory for the core
+     * @param coreName the core name or <code>null</code> to directly load the
+     * configuration as present under {@value #CONFIG_DIR} in the bundle. This
+     * property can be used if a bundle needs to provide multiple core
+     * configurations
+     * @param override if files in the target directory should be overridden
+     * @throws IOException On any IO error while coping the configuration
+     * @throws IllegalStateException If the parsed coreDir does exist but is not
+     * a directory.
+     * @throws IllegalArgumentException if <code>null</code> is parsed as coreDir
+     * or if the parsed bundle does not contain the required information to set 
+     * up an configuration or the parsed coreName is empty.
+     */
+    public static void copyCore(Class<?> clazzInArchive, File coreDir, String coreName, boolean override) throws IOException, IllegalArgumentException, IllegalStateException{
+        if(coreDir == null){
+            throw new IllegalArgumentException("The parsed core directory MUST NOT be NULL!");
+        }
+        if(coreDir.exists() && !coreDir.isDirectory()){
+            throw new IllegalStateException("The parsed core directory "+coreDir.getAbsolutePath()+" extists but is not a directory!");
+        }
+        if(coreName!= null && coreName.isEmpty()){
+            throw new IllegalArgumentException("The parsed core name MUST NOT be empty (However NULL is supported)!");
+        }
+        String context = CORE_CONFIG_DIR+(coreName!=null?'/'+coreName:"");
+        File sourceRoot = getSource(clazzInArchive!=null?clazzInArchive:ConfigUtils.class);
+        if(sourceRoot.isFile()){
+            ZipFile archive = new ZipFile(sourceRoot);
+            log.info(String.format("Copy core %s config from jar-file %s to %s (override=%s)",
+                (coreName == null?"":coreName),archive.getName(),coreDir.getAbsolutePath(),override));
+            try {
+                for(Enumeration<? extends ZipEntry> entries = archive.entries();entries.hasMoreElements();){
+                    ZipEntry entry = entries.nextElement();
+                    if(entry.getName().startsWith(context)){
+                        copyResource(coreDir, archive, entry, context, override);
+                    }
+                }
+            } finally {
+                //regardless what happens we need to close the archive!
+                archive.close();
+            }
+        } else { //load from file
+            File source = new File(sourceRoot,context);
+            if(source.exists() && source.isDirectory()){
+                FileUtils.copyDirectory(source, coreDir);
+            } else {
+                throw new FileNotFoundException("The SolrIndex default config was not found in directory "+source.getAbsolutePath());
+            }
+        }
+    }
 }

Modified: incubator/stanbol/trunk/entityhub/yard/solr/src/main/resources/OSGI-INF/metatype/metatype.properties
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/yard/solr/src/main/resources/OSGI-INF/metatype/metatype.properties?rev=1082932&r1=1082931&r2=1082932&view=diff
==============================================================================
--- incubator/stanbol/trunk/entityhub/yard/solr/src/main/resources/OSGI-INF/metatype/metatype.properties (original)
+++ incubator/stanbol/trunk/entityhub/yard/solr/src/main/resources/OSGI-INF/metatype/metatype.properties Fri Mar 18 14:16:03 2011
@@ -32,4 +32,12 @@ org.apache.stanbol.entityhub.yard.defaul
 
 #org.apache.stanbol.entityhub.yard.solr.maxBooleanClauses
 org.apache.stanbol.entityhub.yard.solr.maxBooleanClauses.name=Max Boolean Clauses
-org.apache.stanbol.entityhub.yard.solr.maxBooleanClauses.description=This is the maximum number of boolean clauses allowed for Solr queries. This value is configured in the solrconf.xml by the maxBooleanClauses element. 
\ No newline at end of file
+org.apache.stanbol.entityhub.yard.solr.maxBooleanClauses.description=This is the maximum number of boolean clauses allowed for Solr queries. This value is configured in the solrconf.xml by the maxBooleanClauses element.
+
+
+#Properties defined by the org.apache.stanbol.entityhub.yard.solr.embedded.EmbeddedSolrPorovider
+org.apache.stanbol.entityhub.yard.solr.embedded.EmbeddedSolrPorovider.name=Apache Stanbol Embedded Solr Server Provider
+org.apache.stanbol.entityhub.yard.solr.embedded.EmbeddedSolrPorovider.description=This provider enables the use of an embedded SolrServer with the SolrYard implementation. In addition it manages an embedded Solr Server instance that is used to dynamically initialise Solr Indexes for SolrYard instances that do not refer to an external SolrServer.
+
+org.apache.stanbol.entityhub.yard.solr.embedded.solrDataDir.name=Index Location
+org.apache.stanbol.entityhub.yard.solr.embedded.solrDataDir.description=The path to the directory used to store the Solr Index of the internally managed EmbeddedSolrServer. Relative paths will use the data directory of the SolrYard bundle as root folder.
\ No newline at end of file

Modified: incubator/stanbol/trunk/entityhub/yard/solr/src/test/java/org/apache/stanbol/entityhub/yard/solr/SolrYardTest.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/entityhub/yard/solr/src/test/java/org/apache/stanbol/entityhub/yard/solr/SolrYardTest.java?rev=1082932&r1=1082931&r2=1082932&view=diff
==============================================================================
--- incubator/stanbol/trunk/entityhub/yard/solr/src/test/java/org/apache/stanbol/entityhub/yard/solr/SolrYardTest.java (original)
+++ incubator/stanbol/trunk/entityhub/yard/solr/src/test/java/org/apache/stanbol/entityhub/yard/solr/SolrYardTest.java Fri Mar 18 14:16:03 2011
@@ -16,14 +16,19 @@
  */
 package org.apache.stanbol.entityhub.yard.solr;
 
+import java.io.File;
+
 import org.apache.stanbol.entityhub.servicesapi.yard.Yard;
 import org.apache.stanbol.entityhub.servicesapi.yard.YardException;
 import org.apache.stanbol.entityhub.test.yard.YardTest;
+import org.apache.stanbol.entityhub.yard.solr.embedded.EmbeddedSolrPorovider;
 import org.apache.stanbol.entityhub.yard.solr.impl.SolrYard;
 import org.apache.stanbol.entityhub.yard.solr.impl.SolrYardConfig;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * This test uses the system property "basedir" to configure an embedded Solr
@@ -36,16 +41,21 @@ import org.junit.Test;
 public class SolrYardTest extends YardTest {
     
     private static Yard yard;
-    private static String solrServer;
-    public static final String testYardId = "testYard";
+    public static final String TEST_YARD_ID = "testYard";
+    public static final String TEST_SOLR_CORE_NAME = "test";
+    private static final String TEST_INDEX_REL_PATH = 
+        File.separatorChar + "target"+
+        File.separatorChar + EmbeddedSolrPorovider.DEFAULT_SOLR_DATA_DIR;
+    private static final Logger log = LoggerFactory.getLogger(SolrYardTest.class);
     
     @BeforeClass
     public final static void initYard() throws YardException {
         //get the working directory
-        String baseDir = System.getProperty("basedir");
-        solrServer = baseDir+"/src/test/resources/solr/test";
-        System.out.println("BaseDir: "+baseDir);
-        SolrYardConfig config = new SolrYardConfig(testYardId,solrServer);
+        //use property substitution to test this feature!
+        String solrServerDir = "${basedir}"+TEST_INDEX_REL_PATH;
+        log.info("Test Solr Server Directory: "+solrServerDir);
+        System.setProperty(EmbeddedSolrPorovider.SOLR_DATA_DIR_PROPERTY, solrServerDir);
+        SolrYardConfig config = new SolrYardConfig(TEST_YARD_ID,TEST_SOLR_CORE_NAME);
         config.setName("Solr Yard Test");
         config.setDescription("The Solr Yard instance used to execute the Unit Tests defined for the Yard Interface");
         yard = new SolrYard(config);
@@ -65,11 +75,11 @@ public class SolrYardTest extends YardTe
     }
     @Test(expected=IllegalArgumentException.class)
     public void testSolrYardConfigInitWithNullUrl() {
-            new SolrYardConfig(testYardId, null);
+            new SolrYardConfig(TEST_YARD_ID, null);
     }
     @Test(expected=IllegalArgumentException.class)
     public void testSolrYardConfigInitWithNullID() {
-            new SolrYardConfig(null, solrServer);
+            new SolrYardConfig(null, TEST_SOLR_CORE_NAME);
     }
     
     /**