Author: ivol37 at gmail.com
Date: Mon Jan 24 16:22:35 2011
New Revision: 704

Log:
initial drop-in of search and index bundle based on Solr

Added:
   sandbox/ivol/amdatu-searchandindex/
   sandbox/ivol/amdatu-searchandindex/pom.xml
   sandbox/ivol/amdatu-searchandindex/solr/
   sandbox/ivol/amdatu-searchandindex/solr/pom.xml
   sandbox/ivol/amdatu-searchandindex/solr/src/
   sandbox/ivol/amdatu-searchandindex/solr/src/main/
   sandbox/ivol/amdatu-searchandindex/solr/src/main/java/
   sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/
   sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/
   
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/
   
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/
   
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/SolrService.java
   
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/
   
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrDispatchFilter.java
   
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrServiceImpl.java
   
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/osgi/
   
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/osgi/Activator.java
   sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/apache/
   sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/apache/solr/
   sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/apache/solr/core/
   
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/apache/solr/core/NakamuraSolrConfig.java
   
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/apache/solr/core/NakamuraSolrResourceLoader.java
   sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/
   sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/conf_core_profile/
   
sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/conf_core_profile/schema.xml
   
sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/conf_core_profile/solrconfig.xml
   sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/solr.xml

Added: sandbox/ivol/amdatu-searchandindex/pom.xml
==============================================================================
--- (empty file)
+++ sandbox/ivol/amdatu-searchandindex/pom.xml  Mon Jan 24 16:22:35 2011
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.amdatu</groupId>
+    <artifactId>amdatu</artifactId>
+    <version>0.1.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>org.amdatu.searchandindex</artifactId>
+  <name>Amdatu Search and Index</name>
+  <description>This module provides search and index 
functionality</description>
+  <packaging>pom</packaging>
+
+  <modules>
+    <module>solr</module>
+  </modules>
+
+</project>
\ No newline at end of file

Added: sandbox/ivol/amdatu-searchandindex/solr/pom.xml
==============================================================================
--- (empty file)
+++ sandbox/ivol/amdatu-searchandindex/solr/pom.xml     Mon Jan 24 16:22:35 2011
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.amdatu</groupId>
+    <artifactId>org.amdatu.searchandindex</artifactId>
+    <version>0.1.0-SNAPSHOT</version>
+  </parent>
+  <groupId>org.amdatu.searchandindex</groupId>
+  <artifactId>solr</artifactId>
+  <packaging>bundle</packaging>
+  <name>Amdatu Search and Index - Solr Service</name>
+  <version>${platform.version}</version>
+  <dependencies>
+    <dependency>
+      <artifactId>solr-core</artifactId>
+      <groupId>org.apache.solr</groupId>
+      <version>1.4.1</version>
+      <type>jar</type>
+      <scope>compile</scope>
+      <exclusions>
+        <!-- Exclude woodstox lib as its groupId has bene changed from woodstox
+             to org.codehaus.woodstox -->
+        <exclusion>
+          <groupId>woodstox</groupId>
+          <artifactId>wstx-asl</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>org.codehaus.woodstox</groupId>
+      <artifactId>wstx-asl</artifactId>
+      <version>3.2.7</version>
+      <type>jar</type>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>log4j</groupId>
+      <artifactId>log4j</artifactId>
+      <version>1.2.16</version>
+      <scope>compile</scope>
+    </dependency>
+
+    <!--
+      SLF4J Binding for java.util.logging
+      (http://www.slf4j.org/manual.html)
+    -->
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-jcl</artifactId>
+      <version>1.6.1</version>
+    </dependency>
+    <dependency>
+      <groupId>org.amdatu.web</groupId>
+      <artifactId>httpcontext</artifactId>
+      <version>${platform.version}</version>
+      <scope>provided</scope>
+      <type>bundle</type>
+    </dependency>
+
+    <dependency>
+      <groupId>org.amdatu.authorization.login</groupId>
+      <artifactId>service</artifactId>
+      <version>${platform.version}</version>
+      <scope>provided</scope>
+      <type>bundle</type>
+    </dependency>
+    <dependency>
+      <groupId>org.amdatu.core</groupId>
+      <artifactId>tenant</artifactId>
+      <version>${platform.version}</version>
+      <scope>provided</scope>
+      <type>bundle</type>
+    </dependency>
+    <dependency>
+      <groupId>org.amdatu.core.config</groupId>
+      <artifactId>templates</artifactId>
+      <version>${platform.version}</version>
+      <scope>provided</scope>
+      <type>bundle</type>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            
<Bundle-Activator>org.amdatu.searchandindex.solr.osgi.Activator</Bundle-Activator>
+            
<Bundle-SymbolicName>org.amdatu.searchandindex.solr</Bundle-SymbolicName>
+            <Embed-Dependency>*;scope=compile</Embed-Dependency>
+            <Embed-Transitive>true</Embed-Transitive>
+            <Import-Package>
+              !org.mortbay.*,,
+              !com.sun.*,
+              !javax.mail.*,
+              !javax.jmdns,
+              !javax.jms,
+              !org.relaxng.*,
+              !junit.framework,
+              !javax.portlet,
+              !com.ibm.*,
+              !org.apache.avalon.*,
+              !org.apache.log,
+              *
+            </Import-Package>
+            <Export-Package>
+            </Export-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>

Added: 
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/SolrService.java
==============================================================================
--- (empty file)
+++ 
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/SolrService.java
       Mon Jan 24 16:22:35 2011
@@ -0,0 +1,39 @@
+/*
+    Copyright (C) 2010 Amdatu.org
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.searchandindex.solr;
+
+import org.amdatu.web.httpcontext.ResourceProvider;
+
+/**
+ * Interface for the UserService.
+ */
+public interface SolrService extends ResourceProvider {
+    /**
+     * The "Administrators" group.
+     */
+    String GROUP_ADMINISTRATORS = "Administrators";
+
+    /**
+     * PID for the Solr configuration.
+     */
+    final String PID = "org.amdatu.searchandindex.solr";
+
+    /**
+     * Configuration key for the working directory to use for Solr
+     */
+    final String CONFIG_WORKDIR = "workdir";
+}

Added: 
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrDispatchFilter.java
==============================================================================
--- (empty file)
+++ 
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrDispatchFilter.java
   Mon Jan 24 16:22:35 2011
@@ -0,0 +1,459 @@
+/*
+    Copyright (C) 2010 Amdatu.org
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.searchandindex.solr.impl;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.common.util.SimpleOrderedMap;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.core.CoreDescriptor;
+import org.apache.solr.core.NakamuraSolrConfig;
+import org.apache.solr.core.NakamuraSolrResourceLoader;
+import org.apache.solr.core.SolrConfig;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.core.SolrResourceLoader;
+import org.apache.solr.request.BinaryQueryResponseWriter;
+import org.apache.solr.request.QueryResponseWriter;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.request.SolrQueryResponse;
+import org.apache.solr.request.SolrRequestHandler;
+import org.apache.solr.schema.IndexSchema;
+import org.apache.solr.servlet.SolrRequestParsers;
+import org.apache.solr.servlet.cache.HttpCacheHeaderUtil;
+import org.apache.solr.servlet.cache.Method;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This filter looks at the incoming URL maps them to handlers defined in 
solrconfig.xml
+ * @since solr 1.2
+ */
+public class SolrDispatchFilter implements Filter {
+    final Logger log = LoggerFactory.getLogger(SolrDispatchFilter.class);
+
+    protected CoreContainer cores;
+    protected String pathPrefix; // strip this from the beginning of a path
+    protected String myHomeDir; //
+    protected String abortErrorMessage = null;
+    protected String solrConfigFilename = null;
+    protected final Map<SolrConfig, SolrRequestParsers> parsers = new 
WeakHashMap<SolrConfig, SolrRequestParsers>();
+    // SolrRequestParsers adminRequestParser;
+    private final Map<String, String> myTenantMap = new HashMap<String, 
String>();
+
+    // protected final
+
+    /**
+     * Constructor.
+     */
+    public SolrDispatchFilter(String path, String homedir, Map<String, String> 
tenantMap) {
+        this.pathPrefix = path;
+        this.myHomeDir = homedir;
+        if (tenantMap != null) {
+            myTenantMap.putAll(tenantMap);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void init(FilterConfig filterConfig) throws ServletException {
+        // save the current context classloader
+        final ClassLoader contextClassLoader = 
Thread.currentThread().getContextClassLoader();
+
+        try {
+            try {
+                final ClassLoader classLoader = 
this.getClass().getClassLoader();
+
+                // overwrite the context classloader, restore it later
+                Thread.currentThread().setContextClassLoader(classLoader);
+                SolrResourceLoader loader = new 
NakamuraSolrResourceLoader(myHomeDir, classLoader);
+                final CoreContainer coreContainer = new CoreContainer(loader);
+
+                if (false) {
+                    // adminRequestParser =
+                    // new SolrRequestParsers(new Config(null, "solr", new 
ByteArrayInputStream("<root/>".getBytes()),
+                    // ""));
+
+                    String solrconfig =
+                        
"D:\\users\\dionm\\SVN\\projects\\apache-solr-1.4.1\\example\\solr\\core1\\conf\\solrconfig.xml";
+                    String schemaloc =
+                        
"D:\\users\\dionm\\SVN\\projects\\apache-solr-1.4.1\\example\\solr\\core1\\conf\\schema.xml";
+
+                    File coreDir = new 
File("D:\\users\\dionm\\SVN\\projects\\apache-solr-1.4.1\\example\\solr\\core1");
+                    SolrConfig config =
+                        new NakamuraSolrConfig(loader, "solrconfig.xml", new 
FileInputStream(new File(solrconfig)));
+                    IndexSchema schema = new IndexSchema(config, null, new 
FileInputStream(new File(schemaloc)));
+                    CoreDescriptor desc = new CoreDescriptor(coreContainer, 
"core1", coreDir.getAbsolutePath());
+                    SolrCore nakamuraCore = new SolrCore("core1", 
coreDir.getAbsolutePath(), config, schema, desc);
+                    coreContainer.register("core1", nakamuraCore, false);
+                }
+
+                this.cores = coreContainer;
+            } catch (Exception e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+
+            boolean abortOnConfigurationError = true;
+            CoreContainer.Initializer init = createInitializer();
+            try {
+                // web.xml configuration
+                
init.setSolrConfigFilename(filterConfig.getInitParameter("solrconfig-filename"));
+
+                this.cores = init.initialize();
+                abortOnConfigurationError = init.isAbortOnConfigurationError();
+                log.info("user.dir=" + System.getProperty("user.dir"));
+            } catch (Throwable t) {
+                // catch this so our filter still works
+                log.error("Could not start SOLR. Check solr/home property", t);
+                SolrConfig.severeErrors.add(t);
+                SolrCore.log(t);
+            }
+
+            // Optionally abort if we found a sever error
+            if (abortOnConfigurationError && SolrConfig.severeErrors.size() > 
0) {
+                StringWriter sw = new StringWriter();
+                PrintWriter out = new PrintWriter(sw);
+                out.println("Severe errors in solr configuration.\n");
+                out.println("Check your log files for more detailed 
information on what may be wrong.\n");
+                out.println("If you want solr to continue after configuration 
errors, change: \n");
+                out.println(" 
<abortOnConfigurationError>false</abortOnConfigurationError>\n");
+                out.println("in " + init.getSolrConfigFilename() + "\n");
+
+                for (Throwable t : SolrConfig.severeErrors) {
+                    
out.println("-------------------------------------------------------------");
+                    t.printStackTrace(out);
+                }
+                out.flush();
+
+                // Servlet containers behave slightly differently if you throw 
an exception during
+                // initialization. Resin will display that error for every 
page, jetty prints it in
+                // the logs, but continues normally. (We will see a 404 rather 
then the real error)
+                // rather then leave the behavior undefined, lets cache the 
error and spit it out
+                // for every request.
+                abortErrorMessage = sw.toString();
+                // throw new ServletException( abortErrorMessage );
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            // restore
+            Thread.currentThread().setContextClassLoader(contextClassLoader);
+        }
+    }
+
+    /** Method to override to change how CoreContainer initialization is 
performed. */
+    protected CoreContainer.Initializer createInitializer() {
+        return new CoreContainer.Initializer();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void destroy() {
+        if (cores != null) {
+            try {
+                cores.shutdown();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            cores = null;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain chain) throws IOException,
+    ServletException {
+
+        if (abortErrorMessage != null) {
+            ((HttpServletResponse) response).sendError(500, abortErrorMessage);
+            return;
+        }
+
+        if (request instanceof HttpServletRequest) {
+            HttpServletRequest req = (HttpServletRequest) request;
+            HttpServletResponse resp = (HttpServletResponse) response;
+            SolrRequestHandler handler = null;
+            SolrQueryRequest solrReq = null;
+            SolrCore core = null;
+            String corename = "";
+            try {
+                // put the core container in request attribute
+                req.setAttribute("org.apache.solr.CoreContainer", cores);
+                String path = req.getServletPath();
+                if (req.getPathInfo() != null) {
+                    // this lets you handle /update/commit when /update is a 
servlet
+                    path += req.getPathInfo();
+                }
+                if (pathPrefix != null && path.startsWith(pathPrefix)) {
+                    path = path.substring(pathPrefix.length());
+                }
+                // check for management path
+                String alternate = cores.getManagementPath();
+                if (alternate != null && path.startsWith(alternate)) {
+                    path = path.substring(0, alternate.length());
+                }
+                // unused feature ?
+                int idx = path.indexOf(':');
+                if (idx > 0) {
+                    // save the portion after the ':' for a 'handler' path 
parameter
+                    path = path.substring(0, idx);
+                }
+
+                // Check for the core admin page
+                if (path.equals(cores.getAdminPath())) {
+                    handler = cores.getMultiCoreHandler();
+                    // solrReq = adminRequestParser.parse(null, path, req);
+                    // handleAdminRequest(req, response, handler, solrReq);
+                    return;
+                } else {
+                    // otherwise, we should find a core from the path
+                    idx = path.indexOf("/", 1);
+                    if (idx > 1) {
+                        // try to get the corename as a request parameter first
+                        corename = path.substring(1, idx);
+                        if ("profile".equals(corename)) {
+                            // FIXME: hardcoded
+                            String prefix = 
myTenantMap.get(request.getServerName());
+                            if (prefix == null) {
+                                prefix = "Keyspace3";
+                            }
+                            corename = prefix + "_" + corename;
+                        }
+                        core = cores.getCore(corename);
+                        if (core != null) {
+                            path = path.substring(idx);
+                        }
+                    }
+                    if (core == null) {
+                        corename = "";
+                        core = cores.getCore("");
+                    }
+                }
+
+                // With a valid core...
+                if (core != null) {
+                    final SolrConfig config = core.getSolrConfig();
+                    // get or create/cache the parser for the core
+                    SolrRequestParsers parser = null;
+                    parser = parsers.get(config);
+                    if (parser == null) {
+                        parser = new SolrRequestParsers(config);
+                        parsers.put(config, parser);
+                    }
+
+                    // Determine the handler from the url path if not set
+                    // (we might already have selected the cores handler)
+                    if (handler == null && path.length() > 1) { // don't match 
"" or "/" as valid path
+                        handler = core.getRequestHandler(path);
+                        // no handler yet but allowed to handle select; let's 
check
+                        if (handler == null && parser.isHandleSelect()) {
+                            if ("/select".equals(path) || 
"/select/".equals(path)) {
+                                solrReq = parser.parse(core, path, req);
+                                String qt = 
solrReq.getParams().get(CommonParams.QT);
+                                handler = core.getRequestHandler(qt);
+                                if (handler == null) {
+                                    throw new 
SolrException(SolrException.ErrorCode.BAD_REQUEST, "unknown handler: "
+                                        + qt);
+                                }
+                            }
+                        }
+                    }
+
+                    // With a valid handler and a valid core...
+                    if (handler != null) {
+                        // if not a /select, create the request
+                        if (solrReq == null) {
+                            solrReq = parser.parse(core, path, req);
+                        }
+
+                        final Method reqMethod = 
Method.getMethod(req.getMethod());
+                        HttpCacheHeaderUtil.setCacheControlHeader(config, 
resp, reqMethod);
+                        // unless we have been explicitly told not to, do 
cache validation
+                        // if we fail cache validation, execute the query
+                        if (config.getHttpCachingConfig().isNever304()
+                                        || 
!HttpCacheHeaderUtil.doCacheHeaderValidation(solrReq, req, reqMethod, resp)) {
+                            SolrQueryResponse solrRsp = new 
SolrQueryResponse();
+                            /*
+                             * even for HEAD requests, we need to execute the 
handler to ensure we don't get an error
+                             * (and to make sure the correct 
QueryResponseWriter is selected and we get the correct
+                             * Content-Type)
+                             */
+                            this.execute(req, handler, solrReq, solrRsp);
+                            HttpCacheHeaderUtil.checkHttpCachingVeto(solrRsp, 
resp, reqMethod);
+                            // add info to http headers
+                            // TODO: See SOLR-232 and SOLR-267.
+                            /*
+                             * try { NamedList solrRspHeader = 
solrRsp.getResponseHeader(); for (int i=0;
+                             * i<solrRspHeader.size(); i++) { 
((javax.servlet.http.HttpServletResponse)
+                             * response).addHeader(("Solr-" + 
solrRspHeader.getName(i)),
+                             * String.valueOf(solrRspHeader.getVal(i))); } } 
catch (ClassCastException cce) {
+                             * log.log(Level.WARNING, "exception adding 
response header log information", cce); }
+                             */
+                            QueryResponseWriter responseWriter = 
core.getQueryResponseWriter(solrReq);
+                            writeResponse(solrRsp, response, responseWriter, 
solrReq, reqMethod);
+                        }
+                        return; // we are done with a valid handler
+                    }
+                    // otherwise (we have a core), let's ensure the core is in 
the SolrCore request attribute so
+                    // a servlet/jsp can retrieve it
+                    else {
+                        req.setAttribute("org.apache.solr.SolrCore", core);
+                        // Modify the request so each core gets its own /admin
+                        if (path.startsWith("/admin")) {
+                            req.getRequestDispatcher(pathPrefix == null ? path 
: pathPrefix + path).forward(request,
+                                response);
+                            return;
+                        }
+                    }
+                }
+                log.debug("no handler or core retrieved for " + path + ", 
follow through...");
+            } catch (Throwable ex) {
+                sendError((HttpServletResponse) response, ex);
+                return;
+            } finally {
+                if (solrReq != null) {
+                    solrReq.close();
+                }
+                if (core != null) {
+                    core.close();
+                }
+            }
+        }
+
+        // Otherwise let the webapp handle the request
+        chain.doFilter(request, response);
+    }
+
+    private void handleAdminRequest(HttpServletRequest req, ServletResponse 
response, SolrRequestHandler handler,
+        SolrQueryRequest solrReq) throws IOException {
+        SolrQueryResponse solrResp = new SolrQueryResponse();
+        final NamedList<Object> responseHeader = new 
SimpleOrderedMap<Object>();
+        solrResp.add("responseHeader", responseHeader);
+        NamedList toLog = solrResp.getToLog();
+        toLog.add("webapp", req.getContextPath());
+        toLog.add("path", solrReq.getContext().get("path"));
+        toLog.add("params", "{" + solrReq.getParamString() + "}");
+        handler.handleRequest(solrReq, solrResp);
+        SolrCore.setResponseHeaderValues(handler, solrReq, solrResp);
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < toLog.size(); i++) {
+            String name = toLog.getName(i);
+            Object val = toLog.getVal(i);
+            sb.append(name).append("=").append(val).append(" ");
+        }
+        QueryResponseWriter respWriter =
+            
SolrCore.DEFAULT_RESPONSE_WRITERS.get(solrReq.getParams().get(CommonParams.WT));
+        if (respWriter == null) {
+            respWriter = SolrCore.DEFAULT_RESPONSE_WRITERS.get("standard");
+        }
+        writeResponse(solrResp, response, respWriter, solrReq, 
Method.getMethod(req.getMethod()));
+    }
+
+    private void writeResponse(SolrQueryResponse solrRsp, ServletResponse 
response, QueryResponseWriter responseWriter,
+        SolrQueryRequest solrReq, Method reqMethod) throws IOException {
+        if (solrRsp.getException() != null) {
+            sendError((HttpServletResponse) response, solrRsp.getException());
+        } else {
+            // Now write it out
+            response.setContentType(responseWriter.getContentType(solrReq, 
solrRsp));
+            if (Method.HEAD != reqMethod) {
+                if (responseWriter instanceof BinaryQueryResponseWriter) {
+                    BinaryQueryResponseWriter binWriter = 
(BinaryQueryResponseWriter) responseWriter;
+                    binWriter.write(response.getOutputStream(), solrReq, 
solrRsp);
+                } else {
+                    PrintWriter out = response.getWriter();
+                    responseWriter.write(out, solrReq, solrRsp);
+
+                }
+            }
+            // else http HEAD request, nothing to write out, waited this long 
just to get ContentType
+        }
+    }
+
+    protected void execute(HttpServletRequest req, SolrRequestHandler handler, 
SolrQueryRequest sreq,
+        SolrQueryResponse rsp) {
+        // a custom filter could add more stuff to the request before passing 
it on.
+        // for example: sreq.getContext().put( "HttpServletRequest", req );
+        // used for logging query stats in SolrCore.execute()
+        sreq.getContext().put("webapp", req.getContextPath());
+        sreq.getCore().execute(handler, sreq, rsp);
+    }
+
+    protected void sendError(HttpServletResponse res, Throwable ex) throws 
IOException {
+        int code = 500;
+        String trace = "";
+        if (ex instanceof SolrException) {
+            code = ((SolrException) ex).code();
+        }
+
+        // For any regular code, don't include the stack trace
+        if (code == 500 || code < 100) {
+            StringWriter sw = new StringWriter();
+            ex.printStackTrace(new PrintWriter(sw));
+            trace = "\n\n" + sw.toString();
+
+            SolrException.logOnce(log, null, ex);
+
+            // non standard codes have undefined results with various servers
+            if (code < 100) {
+                log.warn("invalid return code: " + code);
+                code = 500;
+            }
+        }
+        res.sendError(code, ex.getMessage() + trace);
+    }
+
+    // ---------------------------------------------------------------------
+    // ---------------------------------------------------------------------
+
+    /**
+     * Set the prefix for all paths. This is useful if you want to apply the 
filter to something other then /*, perhaps
+     * because you are merging this filter into a larger web application. For 
example, if web.xml specifies:
+     * <filter-mapping> <filter-name>SolrRequestFilter</filter-name> 
<url-pattern>/xxx/*</url-pattern> </filter-mapping>
+     * Make sure to set the PathPrefix to "/xxx" either with this function or 
in web.xml. <init-param>
+     * <param-name>path-prefix</param-name> <param-value>/xxx</param-value> 
</init-param>
+     */
+    public void setPathPrefix(String pathPrefix) {
+        this.pathPrefix = pathPrefix;
+    }
+
+    public String getPathPrefix() {
+        return pathPrefix;
+    }
+}

Added: 
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrServiceImpl.java
==============================================================================
--- (empty file)
+++ 
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrServiceImpl.java
      Mon Jan 24 16:22:35 2011
@@ -0,0 +1,230 @@
+/*
+    Copyright (C) 2010 Amdatu.org
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.searchandindex.solr.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.Filter;
+
+import org.amdatu.core.config.templates.ConfigTemplateManager;
+import org.amdatu.core.tenant.TenantEntity;
+import org.amdatu.core.tenant.TenantException;
+import org.amdatu.core.tenant.TenantManagementService;
+import org.amdatu.searchandindex.solr.SolrService;
+import org.amdatu.searchandindex.solr.osgi.Activator;
+import org.amdatu.web.httpcontext.HttpContextServiceFactory;
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
+import org.osgi.service.log.LogService;
+
+/**
+ * Implementation of the {@link SolrService} interface.
+ */
+public class SolrServiceImpl implements SolrService, ManagedService {
+    // Statics
+    private static final String SOLR_CONFIG_XML = "solr.xml";
+    private static final String CONFIG_DIR = "conf";
+
+    // Services injected by the Felix dependency manager
+    private volatile LogService m_logService;
+    private volatile BundleContext m_bundleContext;
+
+    private volatile DependencyManager m_dependencyManager;
+    private volatile HttpContextServiceFactory m_httpContextServiceFactory;
+    private volatile TenantManagementService m_tenantService;
+    private volatile ConfigTemplateManager m_configTemplateManager;
+    private volatile Component m_contextComponent;
+
+    // Private members
+    private SolrDispatchFilter solrDispatchFilter = null;
+    private File m_workDir;
+
+    /**
+     * The init() method is invoked by the Felix dependency manager.
+     */
+    @SuppressWarnings("unchecked")
+    public void init() {
+        try {
+            m_logService.log(LogService.LOG_INFO, "Initializing Solr 
configuration");
+
+            // Create our own http context and register resources
+            m_contextComponent = 
m_httpContextServiceFactory.create(m_bundleContext, this);
+
+            // Initialize storage configuration
+            // Load the URL of the storage-conf.xml and write it file using 
the config template
+            // manager, which automatically replaces configuration entries in 
that file
+            File storageConfigFile = new File(m_workDir, SOLR_CONFIG_XML);
+            m_workDir.mkdirs();
+            Bundle bundle = m_bundleContext.getBundle();
+            URL url = bundle.getResource(SOLR_CONFIG_XML);
+            try {
+                // Replace placeholders in the solr.xml config file
+                m_configTemplateManager.writeConfiguration(url, 
storageConfigFile);
+
+                // Solr uses this system property to find its storage location.
+                System.setProperty("solr.solr.home", 
storageConfigFile.getParentFile().getAbsolutePath());
+
+                // Update the main config
+                File mainconfdir = new File(m_workDir, "/" + CONFIG_DIR);
+                mainconfdir.mkdirs();
+
+                // Find all entries in our 'conf' directory.
+                final Enumeration<URL> resources = 
bundle.findEntries(CONFIG_DIR, "*.*", true);
+                if (resources != null) {
+                    while (resources.hasMoreElements()) {
+                        final URL resource = resources.nextElement();
+                        File coreConfFile = new File(mainconfdir, 
resource.getFile().replace(CONFIG_DIR + "/", ""));
+                        if (!coreConfFile.exists()) {
+                            // Only write this file if it does not yet exist
+                            
m_configTemplateManager.writeConfiguration(resource, coreConfFile);
+                        }
+                    }
+                }
+
+                // Update the core configs
+                List<String> cores = new ArrayList<String>();
+                cores.add("Keyspace1/profile");
+                cores.add("Keyspace2/profile");
+                cores.add("Keyspace3/profile");
+
+                for (String core : cores) {
+                    File coreconfdir = new File(m_workDir, core + "/conf");
+                    if (coreconfdir.exists()) {
+                        coreconfdir.delete();
+                    }
+                    coreconfdir.mkdirs();
+
+                    // Find all entries in our 'conf' directory.
+                    final Enumeration<URL> resources = 
bundle.findEntries("conf_core_profile", "*.*", true);
+                    if (resources != null) {
+                        while (resources.hasMoreElements()) {
+                            final URL resource = resources.nextElement();
+                            File coreconffile =
+                                new File(coreconfdir, 
resource.getFile().replaceAll("conf_core_profile/", ""));
+                            if (!coreconffile.exists()) {
+                                // Only write this file if it does not yet 
exist
+                                
m_configTemplateManager.writeConfiguration(resource, coreconffile);
+                            }
+                        }
+                    }
+
+                }
+
+            } catch (IOException e) {
+                m_logService.log(LogService.LOG_ERROR, "Could not replace 
configuration entries in storage-conf.xml", e);
+            }
+
+        } catch (Exception e) {
+            m_logService.log(LogService.LOG_ERROR, "Could not create context 
component", e);
+        }
+    }
+
+    /**
+     * The start() method is invoked by the Felix dependency manager.
+     */
+    public void start() {
+        m_logService.log(LogService.LOG_ERROR, getClass().getName() + " 
service Start");
+
+        // Create and register a http servlet filter. This filter is mapped on 
.*
+        Dictionary<String, String> filterProperties = new Hashtable<String, 
String>();
+        filterProperties.put("pattern", "/" + Activator.RESOURCE_ID + 
"(|\\?.*|/.*)");
+        filterProperties.put("service.ranking", "10");
+        filterProperties.put("contextId", Activator.RESOURCE_ID);
+
+        Map<String, String> tenantMap = new HashMap<String, String>();
+        try {
+            for (TenantEntity tenant : m_tenantService.getTenants()) {
+                String tenanthostname = tenant.getProperties().get("hostname");
+                if (tenanthostname != null) {
+                    System.err.println("put: " + tenanthostname + " " + 
tenant.getId());
+                    tenantMap.put(tenanthostname, tenant.getId());
+                }
+            }
+        } catch (TenantException e) {
+            e.printStackTrace();
+        }
+
+        solrDispatchFilter =
+            new SolrDispatchFilter("/" + Activator.RESOURCE_ID, 
m_workDir.getAbsolutePath(), tenantMap);
+        
m_dependencyManager.add(m_dependencyManager.createComponent().setImplementation(solrDispatchFilter)
+            .setInterface(Filter.class.getName(), filterProperties));
+
+    }
+
+    /**
+     * The stop() method is invoked by the Felix dependency manager.
+     */
+    public void stop() {
+        if (solrDispatchFilter != null) {
+            solrDispatchFilter.destroy();
+        }
+
+        m_logService.log(LogService.LOG_ERROR, getClass().getName() + " 
service stopped");
+    }
+
+    /**
+     * The destroy() method is invoked by the Felix dependency manager.
+     */
+    public void destroy() {
+        try {
+            if (m_contextComponent != null) {
+                m_contextComponent.stop();
+            }
+            m_logService.log(LogService.LOG_ERROR, getClass().getName() + " 
service destroyed");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public URL getResource(String input) {
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getResourceId() {
+        return Activator.RESOURCE_ID;
+    }
+
+    @SuppressWarnings("unchecked")
+    public void updated(Dictionary dictionary) throws ConfigurationException {
+        if (dictionary != null) {
+            if (dictionary.get(CONFIG_WORKDIR) == null) {
+                throw new ConfigurationException("Missing configuration key", 
CONFIG_WORKDIR);
+            }
+            File workBaseDir = new File(System.getProperty("user.dir"), 
"work");
+            m_workDir = new File(workBaseDir, (String) 
dictionary.get(CONFIG_WORKDIR));
+        }
+    }
+}

Added: 
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/osgi/Activator.java
==============================================================================
--- (empty file)
+++ 
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/osgi/Activator.java
    Mon Jan 24 16:22:35 2011
@@ -0,0 +1,57 @@
+/*
+    Copyright (C) 2010 Amdatu.org
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.searchandindex.solr.osgi;
+
+import org.amdatu.core.config.templates.ConfigTemplateManager;
+import org.amdatu.core.tenant.TenantManagementService;
+import org.amdatu.searchandindex.solr.SolrService;
+import org.amdatu.searchandindex.solr.impl.SolrServiceImpl;
+import org.amdatu.web.httpcontext.HttpContextServiceFactory;
+import org.apache.felix.dm.DependencyActivatorBase;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.http.HttpService;
+import org.osgi.service.log.LogService;
+
+/**
+ * This is the OSGi activator for this Solr service bundle.
+ * 
+ * @author ivol
+ */
+public class Activator extends DependencyActivatorBase {
+    /**
+     * The resource identifier for this bundle. Resources are only considered 
to be 'ours' when it is prefixed with this
+     * id.
+     */
+    public static final String RESOURCE_ID = "index";
+
+    public void init(BundleContext context, DependencyManager manager) throws 
Exception {
+        // Create and register the Solr service.
+        manager.add(createComponent()
+            .setInterface(SolrService.class.getName(), null)
+            .setImplementation(SolrServiceImpl.class)
+            
.add(createServiceDependency().setService(LogService.class).setRequired(true))
+            
.add(createServiceDependency().setService(HttpContextServiceFactory.class).setRequired(true))
+            
.add(createServiceDependency().setService(ConfigTemplateManager.class).setRequired(true))
+            
.add(createServiceDependency().setService(HttpService.class).setRequired(true))
+            
.add(createServiceDependency().setService(TenantManagementService.class).setRequired(true))
+            .add(createConfigurationDependency().setPid(SolrService.PID)));
+    }
+
+    public void destroy(BundleContext context, DependencyManager manager) 
throws Exception {
+    }
+}

Added: 
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/apache/solr/core/NakamuraSolrConfig.java
==============================================================================
--- (empty file)
+++ 
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/apache/solr/core/NakamuraSolrConfig.java
  Mon Jan 24 16:22:35 2011
@@ -0,0 +1,42 @@
+/*
+    Copyright (C) 2010 Amdatu.org
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.apache.solr.core;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.xml.sax.SAXException;
+
+public class NakamuraSolrConfig extends SolrConfig {
+    final SolrResourceLoader m_loader;
+
+    public NakamuraSolrConfig(SolrResourceLoader loader, String name, 
InputStream is)
+    throws ParserConfigurationException, IOException, SAXException {
+        super(loader, name, is);
+        m_loader = loader;
+    }
+
+    @Override
+    public SolrResourceLoader getResourceLoader() {
+        if (m_loader == null) {
+            return super.getResourceLoader();
+        }
+        return m_loader;
+    }
+}

Added: 
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/apache/solr/core/NakamuraSolrResourceLoader.java
==============================================================================
--- (empty file)
+++ 
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/apache/solr/core/NakamuraSolrResourceLoader.java
  Mon Jan 24 16:22:35 2011
@@ -0,0 +1,36 @@
+/*
+    Copyright (C) 2010 Amdatu.org
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.apache.solr.core;
+
+import java.io.InputStream;
+
+public class NakamuraSolrResourceLoader extends SolrResourceLoader {
+
+    public NakamuraSolrResourceLoader(String instanceDir, ClassLoader loader) {
+        super(instanceDir, loader);
+    }
+
+    @Override
+    public InputStream openResource(String resource) {
+        final ClassLoader classLoader = this.getClass().getClassLoader();
+        InputStream in = classLoader.getResourceAsStream(resource);
+        if (in == null) {
+            in = super.openResource(resource);
+        }
+        return in;
+    }
+}

Added: 
sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/conf_core_profile/schema.xml
==============================================================================
--- (empty file)
+++ 
sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/conf_core_profile/schema.xml
     Mon Jan 24 16:22:35 2011
@@ -0,0 +1,312 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ 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.
+-->
+
+<!--  
+ This is the Solr schema file. This file should be named "schema.xml" and
+ should be in the conf directory under the solr home
+ (i.e. ./solr/conf/schema.xml by default) 
+ or located where the classloader for the Solr webapp can find it.
+
+ This example schema is the recommended starting point for users.
+ It should be kept correct and concise, usable out-of-the-box.
+
+ For more information, on how to customize this file, please see
+ http://wiki.apache.org/solr/SchemaXml
+
+ PERFORMANCE NOTE: this schema includes many optional features and should not
+ be used for benchmarking.  To improve performance one could
+  - set stored="false" for all fields possible (esp large fields) when you
+    only need to search on the field but don't need to return the original
+    value.
+  - set indexed="false" if you don't need to search on the field, but only
+    return the field as a result of searching on other indexed fields.
+  - remove all unneeded copyField statements
+  - for best index size and searching performance, set "index" to false
+    for all general text fields, use copyField to copy them to the
+    catchall "text" field, and use that for searching.
+  - For maximum indexing performance, use the StreamingUpdateSolrServer
+    java client.
+  - Remember to run the JVM in server mode, and use a higher logging level
+    that avoids logging every request
+-->
+
+<schema name="blueconic" version="1.2">
+  <!-- attribute "name" is the name of this schema and is only used for 
display purposes.
+       Applications should change this to reflect the nature of the search 
collection.
+       version="1.2" is Solr's version number for the schema syntax and 
semantics.  It should
+       not normally be changed by applications.
+       1.0: multiValued attribute did not exist, all fields are multiValued by 
nature
+       1.1: multiValued attribute introduced, false by default 
+       1.2: omitTermFreqAndPositions attribute introduced, true by default 
except for text fields.
+     -->
+
+  <types>
+    <!-- field type definitions. The "name" attribute is
+       just a label to be used by field definitions.  The "class"
+       attribute and any other attributes determine the real
+       behavior of the fieldType.
+         Class names starting with "solr" refer to java classes in the
+       org.apache.solr.analysis package.
+    -->
+
+    <!-- The StrField type is not analyzed, but indexed/stored verbatim.  
+       - StrField and TextField support an optional compressThreshold which
+       limits compression (if enabled in the derived fields) to values which
+       exceed a certain size (in characters).
+    -->
+    <fieldType name="string" class="solr.StrField" sortMissingLast="true" 
omitNorms="true"/>
+
+    <!-- boolean type: "true" or "false" -->
+    <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true" 
omitNorms="true"/>
+    <!--Binary data type. The data should be sent/retrieved in as Base64 
encoded Strings -->
+    <fieldtype name="binary" class="solr.BinaryField"/>
+
+    <!-- The optional sortMissingLast and sortMissingFirst attributes are
+         currently supported on types that are sorted internally as strings.
+              This includes 
"string","boolean","sint","slong","sfloat","sdouble","pdate"
+       - If sortMissingLast="true", then a sort on this field will cause 
documents
+         without the field to come after documents with the field,
+         regardless of the requested sort order (asc or desc).
+       - If sortMissingFirst="true", then a sort on this field will cause 
documents
+         without the field to come before documents with the field,
+         regardless of the requested sort order.
+       - If sortMissingLast="false" and sortMissingFirst="false" (the default),
+         then default lucene sorting will be used which places docs without the
+         field first in an ascending sort and last in a descending sort.
+    -->    
+
+    <!--
+      Default numeric field types. For faster range queries, consider the 
tint/tfloat/tlong/tdouble types.
+    -->
+    <fieldType name="int" class="solr.TrieIntField" precisionStep="0" 
omitNorms="true" positionIncrementGap="0"/>
+    <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" 
omitNorms="true" positionIncrementGap="0"/>
+    <fieldType name="long" class="solr.TrieLongField" precisionStep="0" 
omitNorms="true" positionIncrementGap="0"/>
+    <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" 
omitNorms="true" positionIncrementGap="0"/>
+
+    <!--
+     Numeric field types that index each value at various levels of precision
+     to accelerate range queries when the number of values between the range
+     endpoints is large. See the javadoc for NumericRangeQuery for internal
+     implementation details.
+
+     Smaller precisionStep values (specified in bits) will lead to more tokens
+     indexed per value, slightly larger index size, and faster range queries.
+     A precisionStep of 0 disables indexing at different precision levels.
+    -->
+    <fieldType name="tint" class="solr.TrieIntField" precisionStep="8" 
omitNorms="true" positionIncrementGap="0"/>
+    <fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" 
omitNorms="true" positionIncrementGap="0"/>
+    <fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" 
omitNorms="true" positionIncrementGap="0"/>
+    <fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" 
omitNorms="true" positionIncrementGap="0"/>
+
+    <!-- The format for this date field is of the form 1995-12-31T23:59:59Z, 
and
+         is a more restricted form of the canonical representation of dateTime
+         http://www.w3.org/TR/xmlschema-2/#dateTime    
+         The trailing "Z" designates UTC time and is mandatory.
+         Optional fractional seconds are allowed: 1995-12-31T23:59:59.999Z
+         All other components are mandatory.
+
+         Expressions can also be used to denote calculations that should be
+         performed relative to "NOW" to determine the value, ie...
+
+               NOW/HOUR
+                  ... Round to the start of the current hour
+               NOW-1DAY
+                  ... Exactly 1 day prior to now
+               NOW/DAY+6MONTHS+3DAYS
+                  ... 6 months and 3 days in the future from the start of
+                      the current day
+                      
+         Consult the DateField javadocs for more information.
+
+         Note: For faster range queries, consider the tdate type
+      -->
+    <fieldType name="date" class="solr.TrieDateField" omitNorms="true" 
precisionStep="0" positionIncrementGap="0"/>
+
+    <!-- A Trie based date field for faster date range queries and date 
faceting. -->
+    <fieldType name="tdate" class="solr.TrieDateField" omitNorms="true" 
precisionStep="6" positionIncrementGap="0"/>
+
+
+    <!--
+      Note:
+      These should only be used for compatibility with existing indexes 
(created with older Solr versions)
+      or if "sortMissingFirst" or "sortMissingLast" functionality is needed. 
Use Trie based fields instead.
+
+      Plain numeric field types that store and index the text
+      value verbatim (and hence don't support range queries, since the
+      lexicographic ordering isn't equal to the numeric ordering)
+    -->
+    <fieldType name="pint" class="solr.IntField" omitNorms="true"/>
+    <fieldType name="plong" class="solr.LongField" omitNorms="true"/>
+    <fieldType name="pfloat" class="solr.FloatField" omitNorms="true"/>
+    <fieldType name="pdouble" class="solr.DoubleField" omitNorms="true"/>
+    <fieldType name="pdate" class="solr.DateField" sortMissingLast="true" 
omitNorms="true"/>
+
+
+    <!--
+      Note:
+      These should only be used for compatibility with existing indexes 
(created with older Solr versions)
+      or if "sortMissingFirst" or "sortMissingLast" functionality is needed. 
Use Trie based fields instead.
+
+      Numeric field types that manipulate the value into
+      a string value that isn't human-readable in its internal form,
+      but with a lexicographic ordering the same as the numeric ordering,
+      so that range queries work correctly.
+    -->
+    <fieldType name="sint" class="solr.SortableIntField" 
sortMissingLast="true" omitNorms="true"/>
+    <fieldType name="slong" class="solr.SortableLongField" 
sortMissingLast="true" omitNorms="true"/>
+    <fieldType name="sfloat" class="solr.SortableFloatField" 
sortMissingLast="true" omitNorms="true"/>
+    <fieldType name="sdouble" class="solr.SortableDoubleField" 
sortMissingLast="true" omitNorms="true"/>
+
+
+    <!-- The "RandomSortField" is not used to store or search any
+         data.  You can declare fields of this type it in your schema
+         to generate pseudo-random orderings of your docs for sorting 
+         purposes.  The ordering is generated based on the field name 
+         and the version of the index, As long as the index version
+         remains unchanged, and the same field name is reused,
+         the ordering of the docs will be consistent.  
+         If you want different psuedo-random orderings of documents,
+         for the same version of the index, use a dynamicField and
+         change the name
+     -->
+    <fieldType name="random" class="solr.RandomSortField" indexed="true" />
+
+    <!-- solr.TextField allows the specification of custom text analyzers
+         specified as a tokenizer and a list of token filters. Different
+         analyzers may be specified for indexing and querying.
+
+         The optional positionIncrementGap puts space between multiple fields 
of
+         this type on the same document, with the purpose of preventing false 
phrase
+         matching across fields.
+
+         For more info on customizing your analyzer chain, please see
+         http://wiki.apache.org/solr/AnalyzersTokenizersTokenFilters
+     -->
+
+    <!-- One can also specify an existing Analyzer class that has a
+         default constructor via the class attribute on the analyzer element
+    <fieldType name="text_greek" class="solr.TextField">
+      <analyzer class="org.apache.lucene.analysis.el.GreekAnalyzer"/>
+    </fieldType>
+    -->
+
+    <!-- A text field that only splits on whitespace for exact matching of 
words -->
+    <fieldType name="text_ws" class="solr.TextField" 
positionIncrementGap="100">
+    </fieldType>
+
+    <!-- A text field that uses WordDelimiterFilter to enable splitting and 
matching of
+        words on case-change, alpha numeric boundaries, and non-alphanumeric 
chars,
+        so that a query of "wifi" or "wi fi" could match a document containing 
"Wi-Fi".
+        Synonyms and stopwords are customized by external files, and stemming 
is enabled.
+        -->
+    <fieldType name="text" class="solr.TextField" positionIncrementGap="100">
+    </fieldType>
+
+    <!-- A general unstemmed text field - good if one does not know the 
language of the field -->
+    <fieldType name="textgen" class="solr.TextField" 
positionIncrementGap="100">
+    </fieldType>
+
+    <!-- A general unstemmed text field that indexes tokens normally and also
+         reversed (via ReversedWildcardFilterFactory), to enable more 
efficient 
+        leading wildcard queries. -->
+    <fieldType name="text_rev" class="solr.TextField" 
positionIncrementGap="100">
+    </fieldType>
+
+    <!-- since fields of this type are by default not stored or indexed,
+         any data added to them will be ignored outright.  --> 
+    <fieldtype name="ignored" stored="false" indexed="false" 
multiValued="true" class="solr.StrField" /> 
+ </types>
+
+
+ <fields>
+   <!-- Valid attributes for fields:
+     name: mandatory - the name for the field
+     type: mandatory - the name of a previously defined type from the 
+       <types> section
+     indexed: true if this field should be indexed (searchable or sortable)
+     stored: true if this field should be retrievable
+     compressed: [false] if this field should be stored using gzip compression
+       (this will only apply if the field type is compressable; among
+       the standard field types, only TextField and StrField are)
+     multiValued: true if this field may contain multiple values per document
+     omitNorms: (expert) set to true to omit the norms associated with
+       this field (this disables length normalization and index-time
+       boosting for the field, and saves some memory).  Only full-text
+       fields or fields that need an index-time boost need norms.
+     termVectors: [false] set to true to store the term vector for a
+       given field.
+       When using MoreLikeThis, fields used for similarity should be
+       stored for best performance.
+     termPositions: Store position information with the term vector.  
+       This will increase storage costs.
+     termOffsets: Store offset information with the term vector. This 
+       will increase storage costs.
+     default: a value that should be used if no value is specified
+       when adding a document.
+   -->
+
+   <field name="id" type="string" indexed="true" stored="true" required="true" 
/> 
+
+   <!-- catchall field, containing all other searchable text fields 
(implemented
+        via copyField further on in this schema  -->
+   <field name="text" type="text" indexed="true" stored="false" 
multiValued="true"/>
+
+   <field name="timestamp" type="date" indexed="true" stored="false" 
default="NOW" multiValued="false"/>
+   
+   <dynamicField name="*_i"  type="sint" indexed="true" stored="false" 
omitNorms="true" multiValued="true"/>
+   <dynamicField name="*_s"  type="string"  indexed="true"  stored="false" 
multiValued="true"/>
+   <dynamicField name="*_l"  type="long"   indexed="true"  stored="false"/>
+   <dynamicField name="*_t"  type="text"    indexed="true"  stored="false"/>
+   <dynamicField name="*_b"  type="boolean" indexed="true"  stored="false"/>
+   <dynamicField name="*_f"  type="float"  indexed="true"  stored="false"/>
+   <dynamicField name="*_d"  type="double" indexed="true"  stored="false"/>
+   <dynamicField name="*_dt" type="date"    indexed="true"  stored="false"/>
+
+   <!-- some trie-coded dynamic fields for faster range queries -->
+   <dynamicField name="*_ti" type="tint"    indexed="true"  stored="false"/>
+   <dynamicField name="*_tl" type="tlong"   indexed="true"  stored="false"/>
+   <dynamicField name="*_tf" type="tfloat"  indexed="true"  stored="false"/>
+   <dynamicField name="*_td" type="tdouble" indexed="true"  stored="false"/>
+   <dynamicField name="*_tdt" type="tdate"  indexed="true"  stored="false"/>
+
+   <dynamicField name="*_pi"  type="pint"    indexed="true"  stored="false"/>
+
+   <dynamicField name="ignored_*" type="ignored" multiValued="true"/>
+   <dynamicField name="attr_*" type="textgen" indexed="true" stored="false" 
multiValued="true"/>
+
+   <dynamicField name="random_*" type="random" />
+
+   <!-- uncomment the following to ignore any fields that don't already match 
an existing 
+        field name or dynamic field, rather than reporting them as an error. 
+        alternately, change the type="ignored" to some other type e.g. "text" 
if you want 
+        unknown fields indexed and/or stored by default --> 
+   <!--dynamicField name="*" type="ignored" multiValued="true" /-->
+   
+ </fields>
+
+ <!-- Field to use to determine and enforce document uniqueness. 
+      Unless this field is marked with required="false", it will be a required 
field
+   -->
+ <uniqueKey>id</uniqueKey>
+
+ <!-- field for the QueryParser to use when an explicit fieldname is absent -->
+ <defaultSearchField>text</defaultSearchField>
+
+ <!-- SolrQueryParser configuration: defaultOperator="AND|OR" -->
+ <solrQueryParser defaultOperator="OR"/>
+</schema>

Added: 
sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/conf_core_profile/solrconfig.xml
==============================================================================
--- (empty file)
+++ 
sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/conf_core_profile/solrconfig.xml
 Mon Jan 24 16:22:35 2011
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ 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.
+ 
+ http://wiki.apache.org/solr/SolrConfigXml
+ 
+-->
+
+<config>
+  <indexDefaults>
+    <!-- Sets the amount of RAM that may be used by Lucene indexing
+      for buffering added documents and deletions before they are
+      flushed to the Directory.  -->
+    <ramBufferSizeMB>32</ramBufferSizeMB>
+    <lockType>simple</lockType>
+    <!--
+     Expert:
+    Controls how often Lucene loads terms into memory -->
+    <!--<termIndexInterval>256</termIndexInterval>-->
+  </indexDefaults>
+  
+   <jmx />
+   
+     <query>
+       <maxBooleanClauses>102400</maxBooleanClauses>
+     </query>
+    
+  <updateHandler class="solr.DirectUpdateHandler2" />
+
+  <requestDispatcher handleSelect="true" >
+    <requestParsers enableRemoteStreaming="false" 
multipartUploadLimitInKB="2048" />
+  </requestDispatcher>
+  
+  <requestHandler name="standard" class="solr.StandardRequestHandler" 
default="true">
+    <arr name="last-components">
+    </arr>
+  </requestHandler>
+  
+  <requestHandler name="/update" class="solr.XmlUpdateRequestHandler" />
+  <requestHandler name="/admin/" 
class="org.apache.solr.handler.admin.AdminHandlers" />
+        
+  <!-- config for the admin interface --> 
+  <admin>
+    <defaultQuery>solr</defaultQuery>
+  </admin>
+
+</config>
+

Added: sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/solr.xml
==============================================================================
--- (empty file)
+++ sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/solr.xml Mon Jan 
24 16:22:35 2011
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+       <!--
+               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.
+       -->
+
+       <!--
+               All (relative) paths are relative to the installation path 
persistent:
+               Save changes made via the API to this file sharedLib: path to a 
lib
+               directory that will be shared across all cores
+       -->
+
+<solr persistent="true">
+       <!--
+               adminPath: RequestHandler path to manage cores. If 'null' (or 
absent),
+               cores will not be manageable via request handler
+       -->
+       <cores adminPath="/admin/cores">
+               <core name="Keyspace1_profile" instanceDir="Keyspace1/profile" 
/>
+               <core name="Keyspace2_profile" instanceDir="Keyspace2/profile" 
/>
+               <core name="Keyspace3_profile" instanceDir="Keyspace3/profile" 
/>
+       </cores>
+</solr>
\ No newline at end of file

Reply via email to