Author: ivol37 at gmail.com
Date: Fri Jan 28 17:24:50 2011
New Revision: 716
Log:
Added:
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/RestHttpProxy.java
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/RestHttpResponse.java
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/bean/
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/bean/SolrErrorBean.java
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/bean/SolrIndexBean.java
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/bean/SolrTenantIndicesBean.java
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/RestHttpProxyImpl.java
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrConfiguration.java
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrConfigurationImpl.java
sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/conf/protwords.txt
sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/conf/schema.xml
sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/conf/solrconfig.xml
sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/conf/stopwords.txt
sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/conf/synonyms.txt
Removed:
sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/conf/default_schema.xml
sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/conf/default_solrconfig.xml
Modified:
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/SolrApi.java
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrApiImpl.java
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrDaemonServiceImpl.java
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrRestServiceImpl.java
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrTest.java
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrUtil.java
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/osgi/Activator.java
Added:
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/RestHttpProxy.java
==============================================================================
--- (empty file)
+++
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/RestHttpProxy.java
Fri Jan 28 17:24:50 2011
@@ -0,0 +1,35 @@
+/*
+ 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 java.io.IOException;
+import java.io.InputStream;
+
+public interface RestHttpProxy {
+ RestHttpResponse invokeGET(String url) throws IOException;
+
+ RestHttpResponse invokePUT(String url) throws IOException;
+
+ /**
+ * Invoke a PUT request to a REST service and stream content to it.
+ * @param url The URL of the REST service
+ * @param is The InputStream to stream to it
+ * @return The result of the REST service invocation
+ * @throws IOException In case any IO related exception occurred while
invoking the REST service.
+ */
+ RestHttpResponse streamPUT(String url, InputStream is) throws IOException;
+}
Added:
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/RestHttpResponse.java
==============================================================================
--- (empty file)
+++
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/RestHttpResponse.java
Fri Jan 28 17:24:50 2011
@@ -0,0 +1,38 @@
+/*
+ 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;
+
+public class RestHttpResponse {
+ private int m_statuscode;
+ private String m_body;
+
+ public int getStatuscode() {
+ return m_statuscode;
+ }
+
+ public void setStatuscode(int statuscode) {
+ m_statuscode = statuscode;
+ }
+
+ public String getBody() {
+ return m_body;
+ }
+
+ public void setBody(String body) {
+ m_body = body;
+ }
+}
Modified:
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/SolrApi.java
==============================================================================
---
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/SolrApi.java
(original)
+++
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/SolrApi.java
Fri Jan 28 17:24:50 2011
@@ -32,7 +32,7 @@
QueryResponse queryIndex(Tenant tenant, String index, String query) throws
SolrServerException;
- Collection<String> getIndices(Tenant tenant) throws SolrServerException;
+ Collection<String> getCores(Tenant tenant) throws SolrServerException;
String getSchema(Tenant tenant, String index) throws IOException;
}
Added:
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/bean/SolrErrorBean.java
==============================================================================
--- (empty file)
+++
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/bean/SolrErrorBean.java
Fri Jan 28 17:24:50 2011
@@ -0,0 +1,29 @@
+package org.amdatu.searchandindex.solr.bean;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+ at SuppressWarnings("restriction")
+ at XmlRootElement(name = "indices")
+ at XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
+public class SolrErrorBean {
+
+ private String m_errorMessage;
+
+ // Providing a default constructor is required when using JAXB
+ public SolrErrorBean() {
+ }
+
+ public SolrErrorBean(String msg) {
+ m_errorMessage = msg;
+ }
+
+ public String getErrorMessage() {
+ return m_errorMessage;
+ }
+
+ public void setErrorMessage(String msg) {
+ m_errorMessage = msg;
+ }
+}
Added:
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/bean/SolrIndexBean.java
==============================================================================
--- (empty file)
+++
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/bean/SolrIndexBean.java
Fri Jan 28 17:24:50 2011
@@ -0,0 +1,69 @@
+/*
+ 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.bean;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+
+ at SuppressWarnings("restriction")
+ at XmlAccessorType(XmlAccessType.FIELD)
+public class SolrIndexBean {
+ @XmlAttribute(name = "id")
+ private String m_id;
+
+ @XmlElement(name = "corename")
+ private String m_coreName;
+
+ @XmlElement(name = "size")
+ private int m_size;
+
+ // Providing a default constructor is required when using JAXB
+ public SolrIndexBean() {
+ }
+
+ public SolrIndexBean(String id, String coreName, int size) {
+ m_id = id;
+ m_coreName = coreName;
+ m_size = size;
+ }
+
+ public String getId() {
+ return m_id;
+ }
+
+ public void setId(String id) {
+ m_id = id;
+ }
+
+ public String getCoreName() {
+ return m_coreName;
+ }
+
+ public void setCoreName(String coreName) {
+ m_coreName = coreName;
+ }
+
+ public int getSize() {
+ return m_size;
+ }
+
+ public void setSize(int size) {
+ m_size = size;
+ }
+}
Added:
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/bean/SolrTenantIndicesBean.java
==============================================================================
--- (empty file)
+++
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/bean/SolrTenantIndicesBean.java
Fri Jan 28 17:24:50 2011
@@ -0,0 +1,80 @@
+/*
+ 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.bean;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.amdatu.core.tenant.Tenant;
+
+ at SuppressWarnings("restriction")
+ at XmlRootElement(name = "tenant")
+ at XmlAccessorType(XmlAccessType.FIELD)
+/**
+ * Bean that represents a tenant.
+ */
+public class SolrTenantIndicesBean {
+ @XmlAttribute(name = "id")
+ private String m_id;
+
+ @XmlElement(name = "name")
+ private String m_name;
+
+ @XmlElement(name = "index")
+ @XmlElementWrapper(name = "indices")
+ private List<SolrIndexBean> m_indices = new ArrayList<SolrIndexBean>();
+
+ // Providing a default constructor is required when using JAXB
+ public SolrTenantIndicesBean() {
+ }
+
+ public SolrTenantIndicesBean(Tenant tenant) {
+ m_id = tenant.getId();
+ m_name = tenant.getName();
+ }
+
+ public String getId() {
+ return m_id;
+ }
+
+ public void setId(String id) {
+ m_id = id;
+ }
+
+ public String getName() {
+ return m_name;
+ }
+
+ public void setName(String name) {
+ m_name = name;
+ }
+
+ public List<SolrIndexBean> getIndices() {
+ return m_indices;
+ }
+
+ public void setIndices(List<SolrIndexBean> indices) {
+ m_indices = indices;
+ }
+}
Added:
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/RestHttpProxyImpl.java
==============================================================================
--- (empty file)
+++
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/RestHttpProxyImpl.java
Fri Jan 28 17:24:50 2011
@@ -0,0 +1,91 @@
+/*
+ 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.IOException;
+import java.io.InputStream;
+
+import org.amdatu.searchandindex.solr.RestHttpProxy;
+import org.amdatu.searchandindex.solr.RestHttpResponse;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpMethod;
+import org.apache.commons.httpclient.methods.DeleteMethod;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.PutMethod;
+import org.apache.commons.httpclient.methods.RequestEntity;
+
+public class RestHttpProxyImpl implements RestHttpProxy {
+
+ public RestHttpResponse invokeGET(String url) throws IOException {
+ return invoke(url, javax.ws.rs.HttpMethod.GET);
+ }
+
+ public RestHttpResponse invokePUT(String url) throws IOException {
+ return invoke(url, javax.ws.rs.HttpMethod.PUT);
+ }
+
+ private RestHttpResponse invoke(String url, String httpMethod) throws
IOException{
+ HttpClient httpClient = new HttpClient();
+ HttpMethod method = null;
+ if (httpMethod.equals(javax.ws.rs.HttpMethod.GET)) {
+ method = new GetMethod(url);
+ } else if (httpMethod.equals(javax.ws.rs.HttpMethod.PUT)) {
+ method = new PutMethod(url);
+ } else if (httpMethod.equals(javax.ws.rs.HttpMethod.DELETE)) {
+ method = new DeleteMethod(url);
+ } else if (httpMethod.equals(javax.ws.rs.HttpMethod.POST)) {
+ method = new PostMethod(url);
+ }
+ try {
+ // Execute the method, this should return a 200
+ int statusCode = httpClient.executeMethod(method);
+ RestHttpResponse result = new RestHttpResponse();
+ result.setStatuscode(statusCode);
+ if (method.getResponseBody() != null) {
+ result.setBody(new String(method.getResponseBody(), "UTF-8"));
+ }
+ return result;
+ }
+ finally {
+ // Release the connection.
+ method.releaseConnection();
+ }
+ }
+
+
+ public RestHttpResponse streamPUT(String url, InputStream is) throws
IOException {
+ HttpClient httpClient = new HttpClient();
+ PutMethod method = new PutMethod(url);
+ try {
+ RequestEntity requestEntity = new InputStreamRequestEntity(is);
+ method.setRequestEntity(requestEntity);
+ int statusCode = httpClient.executeMethod(method);
+ RestHttpResponse response = new RestHttpResponse();
+ response.setStatuscode(statusCode);
+ response.setBody(new String(method.getResponseBody(), "UTF-8"));
+ return response;
+ }
+ finally {
+ // Release the connection.
+ method.releaseConnection();
+ }
+ }
+
+
+}
Modified:
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrApiImpl.java
==============================================================================
---
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrApiImpl.java
(original)
+++
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrApiImpl.java
Fri Jan 28 17:24:50 2011
@@ -20,14 +20,12 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.net.URL;
import java.util.Collection;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLStreamException;
-import org.amdatu.core.config.templates.ConfigTemplateManager;
import org.amdatu.core.tenant.Tenant;
import org.amdatu.searchandindex.solr.SolrApi;
import org.apache.solr.client.solrj.SolrQuery;
@@ -44,41 +42,36 @@
import org.apache.solr.core.SolrCore;
import org.apache.solr.core.SolrResourceLoader;
import org.apache.solr.schema.IndexSchema;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
import org.osgi.service.log.LogService;
import org.xml.sax.SAXException;
@SuppressWarnings("restriction")
public class SolrApiImpl implements SolrApi {
- // Statics
- private static final String DEFAULT_SCHEMA = "conf/default_schema.xml";
- private static final String DEFAULT_SOLRCONFIG =
"conf/default_solrconfig.xml";
-
// Service dependencies injected by the dependency manager
private volatile LogService m_logService;
- private volatile BundleContext m_bundleContext;
- private volatile ConfigTemplateManager m_configTemplateManager;
+ private volatile SolrConfiguration m_solrConfig;
// Private members
- private File m_workDir;
private CoreContainer m_coreContainer;
- public SolrApiImpl(File workDir, CoreContainer coreContainer) {
- m_workDir = workDir;
+ public SolrApiImpl(CoreContainer coreContainer, SolrConfiguration
solrConfig) {
m_coreContainer = coreContainer;
+ m_solrConfig = solrConfig;
}
public void createIndex(Tenant tenant, String index) {
+ createIndex(tenant, index, null);
+ }
+
+ public void createIndex(Tenant tenant, String index, InputStream is) {
// Verify if a core for this index already exists
- String coreDirName = tenant.getId() + "/" + index;
String coreName = tenant.getId() + "_" + index;
if (m_coreContainer.getCore(coreName) == null) {
try {
m_logService.log(LogService.LOG_INFO, "Creating new Solr index
'" + index + "' for tenant '" + tenant.getId() + "'");
// Create a new core. The name of that core will be <tenant
id>/<index name>
- createCore(coreName, coreDirName);
+ createCore(tenant.getId(), index, is);
}
catch (IOException e) {
m_logService.log(LogService.LOG_ERROR, "Could not create Solr
core configuration for '" + coreName + "'", e);
@@ -92,6 +85,14 @@
}
}
+ public void deleteIndex(Tenant tenant, String index) {
+ String coreDirName = tenant.getId() + "/" + index;
+ String coreName = tenant.getId() + "_" + index;
+ deleteCore(coreName, coreDirName);
+ m_solrConfig.deleteCore(tenant.getId(), index);
+ m_logService.log(LogService.LOG_DEBUG, "Index '" + coreName + "'
deleted");
+ }
+
public void updateIndex(Tenant tenant, String index, InputStream is)
throws XMLStreamException, SolrServerException, IOException {
String coreName = tenant.getId() + "_" + index;
m_logService.log(LogService.LOG_DEBUG, "Starting update for index '" +
coreName + "'");
@@ -114,12 +115,16 @@
m_logService.log(LogService.LOG_DEBUG, "Index '" + coreName + "'
updated");
}
- public Collection<String> getIndices(Tenant tenant) throws
SolrServerException {
+ public Collection<String> getCores(Tenant tenant) throws
SolrServerException {
return m_coreContainer.getCoreNames();
}
public QueryResponse queryIndex(Tenant tenant, String index, String query)
throws SolrServerException {
String coreName = tenant.getId() + "_" + index;
+ return queryCore(coreName, query);
+ }
+
+ public QueryResponse queryCore(String coreName, String query) throws
SolrServerException {
SolrServer server = new EmbeddedSolrServer(m_coreContainer, coreName);
SolrQuery solrQuery = new SolrQuery();
solrQuery.setQuery(query);
@@ -127,50 +132,75 @@
}
public String getSchema(Tenant tenant, String index) throws IOException {
- File schema = new File(m_workDir, tenant.getId() + "/" + index +
"/conf/schema.xml");
+ File schema = m_solrConfig.getCoreSchema(tenant.getId(), index);
String contents = SolrUtil.loadFromFile(schema);
return contents;
}
- private void createCore(String coreName, String coreDirName) throws
IOException, ParserConfigurationException, SAXException {
+ public void setSchema(Tenant tenant, String index, InputStream is) throws
IOException {
+ deleteIndex(tenant, index);
+ createIndex(tenant, index, is);
+ }
+
+ private void deleteCore(String coreName, String coreDirName) {
// Save the current context classloader
final ClassLoader contextClassLoader =
Thread.currentThread().getContextClassLoader();
try {
// Classloader switcheroo
final ClassLoader classLoader = this.getClass().getClassLoader();
Thread.currentThread().setContextClassLoader(classLoader);
+ m_coreContainer.remove(coreName);
+ File solr = m_solrConfig.getSolr();
+ m_coreContainer.persistFile(solr);
+ } finally {
+ // Restore classloader
+ Thread.currentThread().setContextClassLoader(contextClassLoader);
+ }
+ }
- // Prepare /conf directory for this core
- File coreDir = new File(m_workDir, coreDirName);
- File coreConfDir = new File(m_workDir, coreDirName + "/conf");
- if (coreConfDir.exists()) {
- coreConfDir.delete();
- }
- coreConfDir.mkdirs();
- File coresConfigFile = new File(m_workDir,
SolrDaemonServiceImpl.SOLR);
+ private void createCore(String tenantId, String indexName, InputStream is)
throws IOException, ParserConfigurationException, SAXException {
+ // Save the current context classloader
+ final ClassLoader contextClassLoader =
Thread.currentThread().getContextClassLoader();
+ try {
+ // Classloader switcheroo
+ final ClassLoader classLoader = this.getClass().getClassLoader();
+ Thread.currentThread().setContextClassLoader(classLoader);
- Bundle bundle = m_bundleContext.getBundle();
+ // Prepare the configuration files of this new core
+ m_solrConfig.prepareCore(tenantId, indexName, is);
- // Write the schema
- URL schema = bundle.getResource(DEFAULT_SCHEMA);
- File targetSchema = new File(m_workDir + "/" + coreDirName +
"/conf/schema.xml");
- m_configTemplateManager.writeConfiguration(schema, targetSchema);
-
- // Write the solrConfig
- URL solrConfig = bundle.getResource(DEFAULT_SOLRCONFIG);
- File targetSolrConfig = new File(m_workDir + "/" + coreDirName +
"/conf/solrconfig.xml");
- m_configTemplateManager.writeConfiguration(solrConfig,
targetSolrConfig);
-
- SolrResourceLoader loader = new
NakamuraSolrResourceLoader(m_workDir.getAbsolutePath(), classLoader);
- SolrConfig config = new NakamuraSolrConfig(loader,
"solrconfig.xml", new FileInputStream(targetSolrConfig));
- IndexSchema indexSchema = new IndexSchema(config, null, new
FileInputStream(targetSchema));
+ // Now create the new core
+ String coreName = getCoreName(tenantId, indexName);
+ File coreDir = m_solrConfig.getCoreDirectory(tenantId, indexName);
+ File solrConfig = m_solrConfig.getCoreSolrConfig(tenantId,
indexName);
+ File schema = m_solrConfig.getCoreSchema(tenantId, indexName);
+ File solr = m_solrConfig.getSolr();
+ File workDir = m_solrConfig.getWorkDirectory();
+
+ SolrResourceLoader loader = new
NakamuraSolrResourceLoader(workDir.getAbsolutePath(), classLoader);
+ SolrConfig config = new NakamuraSolrConfig(loader,
"solrconfig.xml", new FileInputStream(solrConfig));
+ IndexSchema indexSchema = new IndexSchema(config, null, new
FileInputStream(schema));
CoreDescriptor desc = new CoreDescriptor(m_coreContainer,
coreName, coreDir.getAbsolutePath());
SolrCore nakamuraCore = new SolrCore(coreName,
coreDir.getAbsolutePath(), config, indexSchema, desc);
m_coreContainer.register(coreName, nakamuraCore, false);
- m_coreContainer.persistFile(coresConfigFile);
+ m_coreContainer.persistFile(solr);
} finally {
// Restore classloader
Thread.currentThread().setContextClassLoader(contextClassLoader);
}
}
+
+ public String getCoreName(Tenant tenant, String index) {
+ return tenant.getId() + "_" + index;
+ }
+
+ public String getCoreName(String tenantId, String index) {
+ return tenantId + "_" + index;
+ }
+
+ public String getIndexName(Tenant tenant, String coreName) {
+ String corePrefix = tenant.getId() + "_";
+ return coreName.substring(corePrefix.length());
+ }
+
}
Added:
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrConfiguration.java
==============================================================================
--- (empty file)
+++
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrConfiguration.java
Fri Jan 28 17:24:50 2011
@@ -0,0 +1,72 @@
+/*
+ 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.io.InputStream;
+
+public interface SolrConfiguration {
+ File getWorkDirectory();
+
+ /**
+ * Returns the solr.xml file that stores generic Solr configuration (like
the available cores).
+ * @return The solr.xml file
+ */
+ File getSolr();
+
+ /**
+ * Returns the directory that stores all files related to a particular
core.
+ * @param tenantId the tenant of the core
+ * @param indexName the index name of the core
+ * @return the directory that stores all files related to a particular
core.
+ */
+ File getCoreDirectory(String tenantId, String indexName);
+
+ /**
+ * Returns the solr config file of a particular core.
+ * @param tenantId the tenant of the core
+ * @param indexName the index name of the core
+ * @return the solr config file of this core.
+ */
+ File getCoreSolrConfig(String tenantId, String indexName);
+
+ /**
+ * Returns the schema file of a particular core.
+ * @param tenantId the tenant of the core
+ * @param indexName the index name of the core
+ * @return the schema file of this core.
+ */
+ File getCoreSchema(String tenantId, String indexName);
+
+ /**
+ * Initialize generic Solr configuration.
+ * @throws IOException
+ */
+ void initSolr() throws IOException;
+
+ /**
+ * Prepare configuration of a particular core.
+ * @param tenantId
+ * @param indexName
+ * @param schema
+ * @throws IOException
+ */
+ void prepareCore(String tenantId, String indexName, InputStream schema)
throws IOException;
+
+ void deleteCore(String tenantId, String indexName);
+}
Added:
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrConfigurationImpl.java
==============================================================================
--- (empty file)
+++
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrConfigurationImpl.java
Fri Jan 28 17:24:50 2011
@@ -0,0 +1,214 @@
+/*
+ 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.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.channels.FileChannel;
+import java.util.Dictionary;
+
+import org.amdatu.core.config.templates.ConfigTemplateManager;
+import org.amdatu.searchandindex.solr.SolrService;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
+import org.osgi.service.log.LogService;
+
+/**
+ * This class is responsible for management of Solr configuration files. The
default Solr configuation
+ * files are copied to solr/conf upon first startup. Whenever a new core is
added to Solr, these
+ * configuration files are copied to the new cores. If the configuration files
are changed in this directory,
+ * new cores will be created with this new configruation.
+ *
+ * @author ivol
+ */
+public class SolrConfigurationImpl implements SolrConfiguration,
ManagedService {
+ // Statics
+ private static final String CONF_RESDIR = "conf/";
+ private static final String SOLR = "solr.xml";
+ private static final String SOLR_CONFIG = "solrconfig.xml";
+ private static final String DEFAULT_CONFIG_DIR = "conf";
+ private static final String SCHEMA = "schema.xml";
+ private static final String SYNONYMS = "synonyms.txt";
+ private static final String STOPWORDS = "stopwords.txt";
+ private static final String PROTWORDS = "protwords.txt";
+ private static final String CORE_CONF_DIR = "conf";
+
+ // Service dependencies, injected by the framework
+ private volatile BundleContext m_bundleContext;
+ private volatile ConfigTemplateManager m_configTemplateManager;
+ private volatile LogService m_logService;
+
+ private File m_workDir;
+ private File m_defaultConfigDir;
+
+ public void init() {
+ // Be sure the default configuration directory exists
+ m_defaultConfigDir = new File(m_workDir, "/" + DEFAULT_CONFIG_DIR);
+ m_defaultConfigDir.mkdirs();
+ }
+
+ @SuppressWarnings("unchecked")
+ public void updated(Dictionary dictionary) throws ConfigurationException {
+ if (dictionary != null) {
+ if (dictionary.get(SolrService.CONFIG_WORKDIR) == null) {
+ throw new ConfigurationException("Missing configuration key",
SolrService.CONFIG_WORKDIR);
+ }
+ File workBaseDir = new File(System.getProperty("user.dir"),
"work");
+ m_workDir = new File(workBaseDir, (String)
dictionary.get(SolrService.CONFIG_WORKDIR));
+ }
+ }
+
+ /**
+ * Initialize Solr configuration.
+ */
+ public void initSolr() throws IOException {
+ // Check if the solr.xml file exists. If not, we create the necessary
configuration files
+ File solrFile = new File(m_workDir, SOLR);
+ if (!solrFile.exists()) {
+ m_workDir.mkdirs();
+ try {
+ // Write the solr.xml file to the solr root directory
+ extractFile(CONF_RESDIR + SOLR, solrFile);
+
+ // Solr uses this system property to find its storage
location, so set it.
+ System.setProperty("solr.solr.home",
solrFile.getParentFile().getAbsolutePath());
+
+ // Now copy all default configuration files from the bundle
JAR to the default config directory
+ extractDefaultConfigurationFiles();
+ } catch (IOException e) {
+ m_logService.log(LogService.LOG_ERROR, "Could not initialize
Solr configuration", e);
+ }
+ } else {
+ // Solr uses this system property to find its storage location, so
set it.
+ System.setProperty("solr.solr.home",
solrFile.getParentFile().getAbsolutePath());
+ }
+ }
+
+
+ /**
+ * Prepare a new core. Copies configuration files from the default
configuration directory
+ * to the directory created for the new core.
+ * @param coreName
+ * @throws IOException
+ */
+ public void prepareCore(String tenantId, String indexName, InputStream
schema) throws IOException {
+ // Prepare /conf directory for this core
+ File coreConfDir = getCoreConfDirectory(tenantId, indexName);
+ coreConfDir.mkdirs();
+
+ // Copy default configuration files to this directory
+ copyConfigFile(coreConfDir, SOLR_CONFIG);
+ copyConfigFile(coreConfDir, SYNONYMS);
+ copyConfigFile(coreConfDir, STOPWORDS);
+ copyConfigFile(coreConfDir, PROTWORDS);
+
+ if (schema == null || schema.available() == 0) {
+ // If no schema provided, use default schema
+ copyConfigFile(coreConfDir, SCHEMA);
+ } else {
+ // Custom schema provided, write it to disk
+ File schemaFile = new File(coreConfDir, SCHEMA);
+ SolrUtil.writeToFile(schemaFile, schema);
+ }
+ }
+
+ public void deleteCore(String tenantId, String indexName) {
+ SolrUtil.deleteDirectory(getCoreConfDirectory(tenantId, indexName));
+ }
+
+ public File getWorkDirectory() {
+ return m_workDir;
+ }
+ public File getSolr() {
+ return new File(m_workDir, SOLR);
+ }
+
+ public File getCoreDirectory(String tenantId, String indexName) {
+ String coreDirName = tenantId + "/" + indexName;
+ File coreDir = new File(m_workDir, coreDirName);
+ return coreDir;
+ }
+
+ private File getCoreConfDirectory(String tenantId, String indexName) {
+ return new File(getCoreDirectory(tenantId, indexName), CORE_CONF_DIR);
+ }
+
+ public File getCoreSolrConfig(String tenantId, String indexName) {
+ File coreDir = getCoreConfDirectory(tenantId, indexName);
+ return new File(coreDir, SOLR_CONFIG);
+ }
+
+ public File getCoreSchema(String tenantId, String indexName) {
+ File coreDir = getCoreConfDirectory(tenantId, indexName);
+ return new File(coreDir, SCHEMA);
+ }
+
+ private void copyConfigFile(File coreConfDir, String file) throws
IOException {
+ File solrConfig = new File(m_defaultConfigDir, file);
+ copyFile(solrConfig, new File(coreConfDir, file));
+ }
+
+ /**
+ * Copied all default configuration files contained by the bundle JAR file
to the default config
+ * directory.
+ * @throws IOException
+ */
+ public void extractDefaultConfigurationFiles() throws IOException {
+ extractDefaultConfig(SOLR_CONFIG);
+ extractDefaultConfig(SCHEMA);
+ extractDefaultConfig(SYNONYMS);
+ extractDefaultConfig(STOPWORDS);
+ extractDefaultConfig(PROTWORDS);
+ }
+
+ private void extractDefaultConfig(String source) throws IOException {
+ File targetFile = new File(m_defaultConfigDir, source);
+ extractFile(CONF_RESDIR + source, targetFile);
+ }
+
+ private void extractFile(String resource, File target) throws IOException {
+ URL resUrl = m_bundleContext.getBundle().getResource(resource);
+ m_configTemplateManager.writeConfiguration(resUrl, target);
+ }
+
+ private void copyFile(File in, File out) throws IOException {
+ FileChannel inChannel = null;
+ FileChannel outChannel = null;
+ try {
+ inChannel = new FileInputStream(in).getChannel();
+ outChannel = new FileOutputStream(out).getChannel();
+ inChannel.transferTo(0, inChannel.size(), outChannel);
+ }
+ finally {
+ if (inChannel != null) {
+ try {
+ inChannel.close();
+ } finally {
+ if (outChannel != null) {
+ outChannel.close();
+ }
+ }
+ }
+
+ }
+ }
+}
Modified:
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrDaemonServiceImpl.java
==============================================================================
---
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrDaemonServiceImpl.java
(original)
+++
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrDaemonServiceImpl.java
Fri Jan 28 17:24:50 2011
@@ -16,10 +16,7 @@
*/
package org.amdatu.searchandindex.solr.impl;
-import java.io.File;
import java.io.IOException;
-import java.net.URL;
-import java.util.Dictionary;
import org.amdatu.core.config.templates.ConfigTemplateManager;
import org.amdatu.core.tenant.TenantManagementService;
@@ -33,92 +30,33 @@
import org.apache.solr.core.CoreContainer;
import org.apache.solr.core.SolrConfig;
import org.apache.solr.core.SolrCore;
-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 SolrDaemonServiceImpl implements SolrService, ManagedService {
- // Statics
- private static final String DEFAULT_SOLAR_CONFIG =
"default_solrconfig.xml";
- private static final String DEFAULT_SCHEMA = "default_schema.xml";
- static final String SOLR = "solr.xml";
- private static final String CONFIG_DIR = "conf";
-
+public class SolrDaemonServiceImpl implements SolrService {
// Services injected by the Felix dependency manager
private volatile LogService m_logService;
- private volatile BundleContext m_bundleContext;
private volatile DependencyManager m_dependencyManager;
- private volatile ConfigTemplateManager m_configTemplateManager;
+ private volatile SolrConfiguration m_solrConfig;
// Private members
private CoreContainer m_coreContainer;
- private File m_workDir;
-
- public void init() {
- try {
- m_logService.log(LogService.LOG_INFO, "Initializing Solr
configuration");
- // Initialize storage configuration
- // Load the URL of the solr.xml and write it file using the config
template
- // manager, which automatically replaces configuration entries in
that file
- File solrFile = new File(m_workDir, SOLR);
- if (!solrFile.exists()) {
- m_workDir.mkdirs();
- try {
- // Write the solr.xml file to the solr root directory
- copyConfig(SOLR, solrFile);
-
- // Solr uses this system property to find its storage
location.
- System.setProperty("solr.solr.home",
solrFile.getParentFile().getAbsolutePath());
-
- // Update the main config
- File mainConfigDir = new File(m_workDir, "/" + CONFIG_DIR);
- mainConfigDir.mkdirs();
-
- // Write default schema and solr config to /conf
- copyConfig(DEFAULT_SOLAR_CONFIG, new File(mainConfigDir,
"solrconfig.xml"));
- copyConfig(DEFAULT_SCHEMA, new File(mainConfigDir,
"schema.xml"));
- } catch (IOException e) {
- m_logService.log(LogService.LOG_ERROR, "Could not replace
configuration entries in storage-conf.xml", e);
- }
- } else {
- // Solr uses this system property to find its storage location.
- System.setProperty("solr.solr.home",
solrFile.getParentFile().getAbsolutePath());
- }
- } catch (Exception e) {
- m_logService.log(LogService.LOG_ERROR, "Could not create context
component", e);
- }
+ public void init() throws IOException {
+ m_solrConfig.initSolr();
}
- public void start() {
- try {
- // Start the Solr daemon
- startSolrDaemon();
-
- // Register the Solr API service
- SolrApiImpl solrApi = registerSolrApi();
+ public void start() throws Exception {
+ // Start the Solr daemon
+ startSolrDaemon();
- // Register the Solr dispatch filter
- registerRestAPI(solrApi);
- }
- catch (Exception e) {
- m_logService.log(LogService.LOG_ERROR, "Failed to start Solr
Daemon", e);
- }
- }
+ // Register the Solr API service
+ SolrApiImpl solrApi = registerSolrApi();
- @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));
- }
+ // Register the Solr dispatch filter
+ registerRestAPI(solrApi);
}
private void startSolrDaemon() throws Exception {
@@ -162,7 +100,7 @@
// Register the Solr API
private SolrApiImpl registerSolrApi() {
- SolrApiImpl solrApiService = new SolrApiImpl(m_workDir,
m_coreContainer);
+ SolrApiImpl solrApiService = new SolrApiImpl(m_coreContainer,
m_solrConfig);
m_dependencyManager.add(m_dependencyManager.createComponent()
.setImplementation(solrApiService)
.setInterface(SolrApi.class.getName(), null)
@@ -173,7 +111,7 @@
// Register the REST service
private void registerRestAPI(SolrApiImpl solrApi) {
- SolrRestServiceImpl restService = new SolrRestServiceImpl(m_workDir,
solrApi);
+ SolrRestServiceImpl restService = new SolrRestServiceImpl(solrApi);
m_dependencyManager.add(m_dependencyManager.createComponent()
.setImplementation(restService)
.setInterface(new String[]{SolrRestService.class.getName(),
ResourceProvider.class.getName()}, null)
@@ -185,9 +123,4 @@
private ServiceDependency createServiceDependency(Class<?> clazz) {
return
m_dependencyManager.createServiceDependency().setService(clazz).setRequired(true);
}
-
- private void copyConfig(String source, File target) throws IOException {
- URL solrConfig = m_bundleContext.getBundle().getResource("conf/" +
source);
- m_configTemplateManager.writeConfiguration(solrConfig, target);
- }
}
Modified:
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrRestServiceImpl.java
==============================================================================
---
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrRestServiceImpl.java
(original)
+++
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrRestServiceImpl.java
Fri Jan 28 17:24:50 2011
@@ -16,14 +16,12 @@
*/
package org.amdatu.searchandindex.solr.impl;
-import java.io.File;
import java.io.InputStream;
import java.net.URL;
+import java.util.ArrayList;
import java.util.Collection;
-import java.util.Dictionary;
-import java.util.Hashtable;
+import java.util.List;
-import javax.servlet.Filter;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
@@ -31,6 +29,8 @@
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@@ -39,15 +39,17 @@
import org.amdatu.core.tenant.TenantException;
import org.amdatu.core.tenant.TenantManagementService;
import org.amdatu.searchandindex.solr.SolrRestService;
+import org.amdatu.searchandindex.solr.bean.SolrErrorBean;
+import org.amdatu.searchandindex.solr.bean.SolrIndexBean;
+import org.amdatu.searchandindex.solr.bean.SolrTenantIndicesBean;
import org.amdatu.searchandindex.solr.osgi.Activator;
import org.amdatu.web.httpcontext.HttpContextServiceFactory;
import org.amdatu.web.httpcontext.ResourceProvider;
import org.apache.felix.dm.Component;
import org.apache.felix.dm.DependencyManager;
+import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.QueryResponse;
-import org.apache.solr.common.SolrDocumentList;
import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
import org.osgi.service.log.LogService;
/**
* This class provides a REST interface on the Solr index service. The REST
API can be used to create, update
@@ -66,18 +68,21 @@
private volatile TenantManagementService m_tenantService;
private volatile SolrApiImpl m_solrApi;
- // Private members
- private File m_workDir;
+ // Disable HTTP caching in this REST interface
+ private static CacheControl m_cacheControl;
+ static {
+ m_cacheControl = new CacheControl();
+ m_cacheControl.setNoCache(true);
+ }
- public SolrRestServiceImpl(File workDir, SolrApiImpl solrApi) {
- m_workDir = workDir;
+ public SolrRestServiceImpl(SolrApiImpl solrApi) {
m_solrApi = solrApi;
}
public void init() {
m_logService.log(LogService.LOG_INFO, "Initializing Solr REST
interface");
m_contextComponent =
m_httpContextServiceFactory.create(m_bundleContext, this);
- registerSolrDispatchFilter();
+ //registerSolrDispatchFilter();
}
public void destroy() {
@@ -96,7 +101,7 @@
}
// Registers the Solr dispatch filter
- private void registerSolrDispatchFilter() {
+/* private void registerSolrDispatchFilter() {
// Create and register a http servlet filter. This filter is mapped on
.*
Dictionary<String, Object> filterProperties = new Hashtable<String,
Object>();
filterProperties.put("pattern", "/" + Activator.RESOURCE_ID +
"(|\\?.*|/.*)");
@@ -107,7 +112,7 @@
m_dependencyManager.add(m_dependencyManager.createComponent()
.setImplementation(filter)
.setInterface(Filter.class.getName(), filterProperties));
- }
+ }*/
/**
* This method can be used to check the availability of the Index Service.
@@ -115,7 +120,7 @@
* @return The text "Index service online"
*/
@GET
- @Path("{status}")
+ @Path("status")
@Produces( { MediaType.TEXT_PLAIN })
public String status() {
return "Index service online";
@@ -127,61 +132,100 @@
* @return The text "Index service online"
*/
@PUT
- @Path("{index}")
+ @Path("{indexname}")
@Produces({MediaType.APPLICATION_XML})
- public Response createIndex(@PathParam("index") final String index,
@Context final HttpServletRequest request, InputStream is) {
+ public Response createIndex(@PathParam("indexname") final String
indexname, @Context final HttpServletRequest request, InputStream is) {
+ if (indexname == null || indexname.isEmpty()) {
+ m_logService.log(LogService.LOG_ERROR, "Could not create index '"
+ indexname + "'");
+ return Response.status(Response.Status.BAD_REQUEST).build();
+ }
try {
// Resolve tenant from hostname
Tenant tenant = resolveTenant(request);
// This is the tenant for which the index should be created
- m_solrApi.createIndex(tenant, index);
+ m_solrApi.createIndex(tenant, indexname);
if (is.available() > 0) {
// When more then 0 bytes are available, a document is send
along with the PUT request
// that should be added to this index
- m_solrApi.updateIndex(tenant, index, is);
+ m_solrApi.updateIndex(tenant, indexname, is);
}
} catch (Exception e) {
- e.printStackTrace();
+ m_logService.log(LogService.LOG_ERROR, "Could not create index '"
+ indexname + "'", e);
+ throw new WebApplicationException(e);
}
return Response.status(Response.Status.OK).build();
}
/**
* Perform Solr query on the specified index.
- * GET /rest/index/[indexname]/?q=[Solr query]
+ * GET /rest/index/[indexname]?q=[Solr query]
*/
@GET
- @Path("{index}")
- @Produces( { MediaType.TEXT_PLAIN })
- public String queryIndex(@PathParam("index") final String index,
@QueryParam("q") final String q,
+ @Path("{indexname}")
+ @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ public Response queryIndex(@PathParam("indexname") final String indexname,
@QueryParam("q") final String q,
@Context final HttpServletRequest request) {
+ Tenant tenant = null;
+ if (indexname == null || indexname.isEmpty()) {
+ // No indexname passed which is required, return 400 (BAD_REQUEST)
+ m_logService.log(LogService.LOG_ERROR, "Could not query index '" +
indexname + "'");
+ return Response.status(Response.Status.BAD_REQUEST).build();
+ }
try {
- Tenant tenant = resolveTenant(request);
- QueryResponse response = m_solrApi.queryIndex(tenant, index, q);
- SolrDocumentList solrDocuments = response.getResults();
- return "<found>"+solrDocuments.getNumFound()+"</found>";
- } catch (Exception e) {
- e.printStackTrace();
+ tenant = resolveTenant(request);
+ if
(!m_solrApi.getCores(tenant).contains(m_solrApi.getCoreName(tenant,
indexname))) {
+ // Index does not exist, return a 404 (NOT_FOUND)
+ return
Response.noContent().cacheControl(m_cacheControl).build();
+ }
+ String query = q;
+ if (query == null || query.isEmpty()) {
+ query = "*:*";
+ }
+ QueryResponse response = m_solrApi.queryIndex(tenant, indexname,
query);
+ int size = response.getResults().size();
+ SolrIndexBean indexBean = new
SolrIndexBean(m_solrApi.getCoreName(tenant, indexname), indexname, size);
+ return Response.ok(indexBean).cacheControl(m_cacheControl).build();
+ }
+ catch (TenantException e) {
+ m_logService.log(LogService.LOG_ERROR, "Could not retrieve index
'" + indexname + "' for tenant '" + tenant + "'", e);
+ throw new WebApplicationException(e);
+ }
+ catch (SolrServerException e) {
+ m_logService.log(LogService.LOG_ERROR, "Could not retrieve index
'" + indexname + "' for tenant '" + tenant + "'", e);
+ throw new WebApplicationException(e);
}
- return "NOPE";
-
}
/**
- * Returns a list of all available incdices for this tenant.
+ * Returns a list of all available indices for this tenant.
* GET /rest/index
*/
@GET
- @Produces( { MediaType.TEXT_PLAIN })
- public String getIndices(@PathParam("index") final String index, @Context
final HttpServletRequest request) {
+ @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ public Response getIndices(@Context final HttpServletRequest request) {
try {
+ // Resolve tenant and create the tenant indices bean
Tenant tenant = resolveTenant(request);
- Collection<String> indices = m_solrApi.getIndices(tenant);
- return "<found>" + indices + "</found>";
- } catch (Exception e) {
- e.printStackTrace();
+ SolrTenantIndicesBean tenantBean = new
SolrTenantIndicesBean(tenant);
+
+ // Create index beans for each index contained for this tenant
+ List<SolrIndexBean> indexBeans = new ArrayList<SolrIndexBean>();
+ Collection<String> cores = m_solrApi.getCores(tenant);
+ for (String core : cores) {
+ QueryResponse response = m_solrApi.queryCore(core, "*:*");
+ int size = response.getResults().size();
+ indexBeans.add(new SolrIndexBean(core,
m_solrApi.getIndexName(tenant, core), size));
+ }
+ tenantBean.setIndices(indexBeans);
+ return
Response.ok(tenantBean).cacheControl(m_cacheControl).build();
+ } catch (TenantException e) {
+ m_logService.log(LogService.LOG_ERROR, "Could not retrieve
indices", e);
+ throw new WebApplicationException(e);
+ }
+ catch (SolrServerException e) {
+ m_logService.log(LogService.LOG_ERROR, "Could not retrieve
indices", e);
+ throw new WebApplicationException(e);
}
- return "NOPE";
}
/**
@@ -189,12 +233,16 @@
* GET /rest/index/[indexname]/schema
*/
@GET
- @Path("{index}/schema")
+ @Path("{indexname}/schema")
@Produces( { MediaType.TEXT_PLAIN })
- public String getSchema(@PathParam("index") final String index, @Context
final HttpServletRequest request) {
+ public String getSchema(@PathParam("indexname") final String indexname,
@Context final HttpServletRequest request) {
+ if (indexname == null || indexname.isEmpty()) {
+ m_logService.log(LogService.LOG_ERROR, "Could not query index '" +
indexname + "'");
+ return "FAIL";
+ }
try {
Tenant tenant = resolveTenant(request);
- String schema = m_solrApi.getSchema(tenant, index);
+ String schema = m_solrApi.getSchema(tenant, indexname);
return schema;
} catch (Exception e) {
e.printStackTrace();
@@ -202,6 +250,34 @@
return "NOPE";
}
+ /**
+ * Returns a list of all available incdices for this tenant.
+ * GET /rest/index/[indexname]/schema
+ */
+ @PUT
+ @Path("{indexname}/schema")
+ @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ public Response putSchema(@PathParam("indexname") final String indexname,
@Context final HttpServletRequest request, InputStream is) {
+ Tenant tenant = null;
+ try {
+ tenant = resolveTenant(request);
+ if (tenant == null || indexname == null || indexname.isEmpty() ||
is == null || is.available() == 0) {
+ String errorMsg = "Could not update schema for index '" +
indexname + "'.";
+ if (is == null || is.available() == 0) {
+ errorMsg += " No schema provided.";
+ }
+ m_logService.log(LogService.LOG_ERROR, errorMsg);
+ SolrErrorBean errorBean = new SolrErrorBean(errorMsg);
+ return
Response.status(Response.Status.BAD_REQUEST).entity(errorBean).cacheControl(m_cacheControl).build();
+ }
+ m_solrApi.setSchema(tenant, indexname ,is);
+ return Response.ok().cacheControl(m_cacheControl).build();
+ } catch (Exception e) {
+ m_logService.log(LogService.LOG_ERROR, "Could not update schema
for index '" + indexname + "' on tenant '" + tenant + "'", e);
+ throw new WebApplicationException(e);
+ }
+ }
+
private Tenant resolveTenant(HttpServletRequest request) throws
TenantException {
// Resolve tenant from hostname
String serverName = request.getServerName();
Modified:
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrTest.java
==============================================================================
---
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrTest.java
(original)
+++
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrTest.java
Fri Jan 28 17:24:50 2011
@@ -42,7 +42,7 @@
private static int ID = 0;
private static int SIZE = 1;
- public void start() {
+ /* public void start() {
try {
TenantEntity tenant1 = m_tenantService.getTenantById("school_1");
if (tenant1 == null) {
@@ -68,7 +68,7 @@
} catch (TenantException e) {
e.printStackTrace();
}
- }
+ }*/
class TestThread extends Thread {
Modified:
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrUtil.java
==============================================================================
---
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrUtil.java
(original)
+++
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/impl/SolrUtil.java
Fri Jan 28 17:24:50 2011
@@ -4,6 +4,7 @@
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -150,6 +151,42 @@
return contents;
}
+ public static boolean deleteDirectory(File path) {
+ if( path.exists() ) {
+ File[] files = path.listFiles();
+ for (File file : files) {
+ if(file.isDirectory()) {
+ deleteDirectory(file);
+ }
+ else {
+ file.delete();
+ }
+ }
+ }
+ return( path.delete() );
+ }
+
+ public static void writeToFile(File file, InputStream is) throws
IOException {
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(file);
+ byte buf[] = new byte[1024];
+ int len;
+ while((len=is.read(buf))>0) {
+ fos.write(buf,0,len);
+ }
+ } finally {
+ try {
+ if (fos != null) {
+ fos.close();
+ }
+ } finally {
+ is.close();
+ }
+ }
+ }
+
+
public static String convertStreamToString(InputStream is) throws
IOException {
if (is != null) {
Writer writer = new StringWriter();
Modified:
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/osgi/Activator.java
==============================================================================
---
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/osgi/Activator.java
(original)
+++
sandbox/ivol/amdatu-searchandindex/solr/src/main/java/org/amdatu/searchandindex/solr/osgi/Activator.java
Fri Jan 28 17:24:50 2011
@@ -18,9 +18,13 @@
import org.amdatu.core.config.templates.ConfigTemplateManager;
import org.amdatu.core.tenant.TenantManagementService;
+import org.amdatu.searchandindex.solr.RestHttpProxy;
import org.amdatu.searchandindex.solr.SolrApi;
import org.amdatu.searchandindex.solr.SolrRestService;
import org.amdatu.searchandindex.solr.SolrService;
+import org.amdatu.searchandindex.solr.impl.RestHttpProxyImpl;
+import org.amdatu.searchandindex.solr.impl.SolrConfiguration;
+import org.amdatu.searchandindex.solr.impl.SolrConfigurationImpl;
import org.amdatu.searchandindex.solr.impl.SolrDaemonServiceImpl;
import org.amdatu.searchandindex.solr.impl.SolrTest;
import org.apache.felix.dm.DependencyActivatorBase;
@@ -50,12 +54,24 @@
// Create and register the Solr service.
manager.add(createComponent()
- .setInterface(SolrService.class.getName(), null)
- .setImplementation(SolrDaemonServiceImpl.class)
+ .setInterface(RestHttpProxy.class.getName(), null)
+ .setImplementation(RestHttpProxyImpl.class));
+
+ // Create and register the Solr configuration service.
+ manager.add(createComponent()
+ .setInterface(SolrConfiguration.class.getName(), null)
+ .setImplementation(SolrConfigurationImpl.class)
.add(createServiceDependency().setService(LogService.class).setRequired(true))
.add(createServiceDependency().setService(ConfigTemplateManager.class).setRequired(true))
-
.add(createServiceDependency().setService(TenantManagementService.class).setRequired(true))
.add(createConfigurationDependency().setPid(SolrService.PID)));
+
+ // Create and register the Solr service.
+ manager.add(createComponent()
+ .setInterface(SolrService.class.getName(), null)
+ .setImplementation(SolrDaemonServiceImpl.class)
+
.add(createServiceDependency().setService(SolrConfiguration.class).setRequired(true))
+
.add(createServiceDependency().setService(LogService.class).setRequired(true))
+
.add(createServiceDependency().setService(TenantManagementService.class).setRequired(true)));
}
public void destroy(BundleContext context, DependencyManager manager)
throws Exception {
Added:
sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/conf/protwords.txt
==============================================================================
--- (empty file)
+++
sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/conf/protwords.txt
Fri Jan 28 17:24:50 2011
@@ -0,0 +1,21 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#-----------------------------------------------------------------------
+# Use a protected word file to protect against the stemmer reducing two
+# unrelated words to the same base word.
+
+# Some non-words that normally won't be encountered,
+# just to test that they won't be stemmed.
+dontstems
+zwhacky
+
Added:
sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/conf/schema.xml
==============================================================================
--- (empty file)
+++ sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/conf/schema.xml
Fri Jan 28 17:24:50 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="amdatu" 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/solrconfig.xml
==============================================================================
--- (empty file)
+++
sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/conf/solrconfig.xml
Fri Jan 28 17:24:50 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/conf/stopwords.txt
==============================================================================
--- (empty file)
+++
sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/conf/stopwords.txt
Fri Jan 28 17:24:50 2011
@@ -0,0 +1,58 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#-----------------------------------------------------------------------
+# a couple of test stopwords to test that the words are really being
+# configured from this file:
+stopworda
+stopwordb
+
+#Standard english stop words taken from Lucene's StopAnalyzer
+a
+an
+and
+are
+as
+at
+be
+but
+by
+for
+if
+in
+into
+is
+it
+no
+not
+of
+on
+or
+s
+such
+t
+that
+the
+their
+then
+there
+these
+they
+this
+to
+was
+will
+with
+
Added:
sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/conf/synonyms.txt
==============================================================================
--- (empty file)
+++
sandbox/ivol/amdatu-searchandindex/solr/src/main/resources/conf/synonyms.txt
Fri Jan 28 17:24:50 2011
@@ -0,0 +1,31 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#-----------------------------------------------------------------------
+#some test synonym mappings unlikely to appear in real input text
+aaa => aaaa
+bbb => bbbb1 bbbb2
+ccc => cccc1,cccc2
+a\=>a => b\=>b
+a\,a => b\,b
+fooaaa,baraaa,bazaaa
+
+# Some synonym groups specific to this example
+GB,gib,gigabyte,gigabytes
+MB,mib,megabyte,megabytes
+Television, Televisions, TV, TVs
+#notice we use "gib" instead of "GiB" so any WordDelimiterFilter coming
+#after us won't split it into two words.
+
+# Synonym mappings can be used for spelling correction too
+pixima => pixma
+