mirror of https://github.com/apache/lucene.git
SOLR-4658: In preparation for REST API requests that can modify the schema, a "managed schema" is introduced.
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1463182 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
0f1738e265
commit
b1e4ba6843
|
@ -97,6 +97,12 @@ New Features
|
|||
"dynamicFields", respectively, to align with all other REST API outputs, which
|
||||
use camelCase.
|
||||
(Steve Rowe)
|
||||
|
||||
* SOLR-4658: In preparation for REST API requests that can modify the schema,
|
||||
a "managed schema" is introduced.
|
||||
Add '<schemaFactory class="ManagedSchemaFactory" mutable="true"/>' to solrconfig.xml
|
||||
in order to use it, and to enable schema modifications via REST API requests.
|
||||
(Steve Rowe, Robert Muir)
|
||||
|
||||
Bug Fixes
|
||||
----------------------
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.apache.lucene.analysis.commongrams.CommonGramsFilterFactory;
|
|||
import org.apache.lucene.analysis.core.StopFilterFactory;
|
||||
import org.apache.solr.analysis.TokenizerChain;
|
||||
import org.apache.solr.schema.IndexSchema;
|
||||
import org.apache.solr.schema.ManagedIndexSchema;
|
||||
import org.carrot2.core.LanguageCode;
|
||||
import org.carrot2.core.attribute.Init;
|
||||
import org.carrot2.core.attribute.Processing;
|
||||
|
@ -37,6 +38,7 @@ import org.carrot2.text.util.MutableCharArray;
|
|||
import org.carrot2.util.attribute.Attribute;
|
||||
import org.carrot2.util.attribute.Bindable;
|
||||
import org.carrot2.util.attribute.Input;
|
||||
import org.carrot2.util.attribute.constraint.ImplementingClasses;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
|
@ -60,6 +62,7 @@ public class SolrStopwordsCarrot2LexicalDataFactory implements
|
|||
@Init
|
||||
@Input
|
||||
@Attribute(key = "solrIndexSchema")
|
||||
@ImplementingClasses(classes = { IndexSchema.class, ManagedIndexSchema.class })
|
||||
private IndexSchema schema;
|
||||
|
||||
@Processing
|
||||
|
|
|
@ -125,4 +125,7 @@ public class ZkSolrResourceLoader extends SolrResourceLoader {
|
|||
return collectionZkPath;
|
||||
}
|
||||
|
||||
public ZkController getZkController() {
|
||||
return zkController;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,10 @@ import org.apache.solr.common.util.XMLErrorLogger;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
@ -41,6 +44,13 @@ import javax.xml.xpath.XPathExpressionException;
|
|||
import javax.xml.xpath.XPathFactory;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
|
@ -235,6 +245,98 @@ public class Config {
|
|||
}
|
||||
}
|
||||
|
||||
public NodeList getNodeList(String path, boolean errIfMissing) {
|
||||
XPath xpath = xpathFactory.newXPath();
|
||||
String xstr = normalize(path);
|
||||
|
||||
try {
|
||||
NodeList nodeList = (NodeList)xpath.evaluate(xstr, doc, XPathConstants.NODESET);
|
||||
|
||||
if (null == nodeList) {
|
||||
if (errIfMissing) {
|
||||
throw new RuntimeException(name + " missing "+path);
|
||||
} else {
|
||||
log.debug(name + " missing optional " + path);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
log.trace(name + ":" + path + "=" + nodeList);
|
||||
return nodeList;
|
||||
|
||||
} catch (XPathExpressionException e) {
|
||||
SolrException.log(log,"Error in xpath",e);
|
||||
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,"Error in xpath:" + xstr + " for " + name,e);
|
||||
} catch (SolrException e) {
|
||||
throw(e);
|
||||
} catch (Throwable e) {
|
||||
SolrException.log(log,"Error in xpath",e);
|
||||
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,"Error in xpath:" + xstr+ " for " + name,e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of attributes on the given element that are not among the given knownAttributes,
|
||||
* or null if all attributes are known.
|
||||
*/
|
||||
public Set<String> getUnknownAttributes(Element element, String... knownAttributes) {
|
||||
Set<String> knownAttributeSet = new HashSet<String>(Arrays.asList(knownAttributes));
|
||||
Set<String> unknownAttributeSet = null;
|
||||
NamedNodeMap attributes = element.getAttributes();
|
||||
for (int i = 0 ; i < attributes.getLength() ; ++i) {
|
||||
final String attributeName = attributes.item(i).getNodeName();
|
||||
if ( ! knownAttributeSet.contains(attributeName)) {
|
||||
if (null == unknownAttributeSet) {
|
||||
unknownAttributeSet = new HashSet<String>();
|
||||
}
|
||||
unknownAttributeSet.add(attributeName);
|
||||
}
|
||||
}
|
||||
return unknownAttributeSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an error and throws an exception if any of the element(s) at the given elementXpath
|
||||
* contains an attribute name that is not among knownAttributes.
|
||||
*/
|
||||
public void complainAboutUnknownAttributes(String elementXpath, String... knownAttributes) {
|
||||
SortedMap<String,SortedSet<String>> problems = new TreeMap<String,SortedSet<String>>();
|
||||
NodeList nodeList = getNodeList(elementXpath, false);
|
||||
for (int i = 0 ; i < nodeList.getLength() ; ++i) {
|
||||
Element element = (Element)nodeList.item(i);
|
||||
Set<String> unknownAttributes = getUnknownAttributes(element, knownAttributes);
|
||||
if (null != unknownAttributes) {
|
||||
String elementName = element.getNodeName();
|
||||
SortedSet<String> allUnknownAttributes = problems.get(elementName);
|
||||
if (null == allUnknownAttributes) {
|
||||
allUnknownAttributes = new TreeSet<String>();
|
||||
problems.put(elementName, allUnknownAttributes);
|
||||
}
|
||||
allUnknownAttributes.addAll(unknownAttributes);
|
||||
}
|
||||
}
|
||||
if (problems.size() > 0) {
|
||||
StringBuilder message = new StringBuilder();
|
||||
for (Map.Entry<String,SortedSet<String>> entry : problems.entrySet()) {
|
||||
if (message.length() > 0) {
|
||||
message.append(", ");
|
||||
}
|
||||
message.append('<');
|
||||
message.append(entry.getKey());
|
||||
for (String attributeName : entry.getValue()) {
|
||||
message.append(' ');
|
||||
message.append(attributeName);
|
||||
message.append("=\"...\"");
|
||||
}
|
||||
message.append('>');
|
||||
}
|
||||
message.insert(0, "Unknown attribute(s) on element(s): ");
|
||||
String msg = message.toString();
|
||||
SolrException.log(log, msg);
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, msg);
|
||||
}
|
||||
}
|
||||
|
||||
public String getVal(String path, boolean errIfMissing) {
|
||||
Node nd = getNode(path,errIfMissing);
|
||||
if (nd==null) return null;
|
||||
|
|
|
@ -19,8 +19,6 @@ package org.apache.solr.core;
|
|||
|
||||
import org.apache.solr.cloud.ZkController;
|
||||
import org.apache.solr.handler.component.ShardHandlerFactory;
|
||||
import org.apache.solr.schema.IndexSchema;
|
||||
import org.apache.zookeeper.KeeperException;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
@ -58,9 +56,6 @@ public interface ConfigSolr {
|
|||
|
||||
public Properties getSolrProperties(ConfigSolr cfg, String context);
|
||||
|
||||
public IndexSchema getSchemaFromZk(ZkController zkController, String zkConfigName, String schemaName,
|
||||
SolrConfig config) throws KeeperException, InterruptedException;
|
||||
|
||||
public SolrConfig getSolrConfigFromZk(ZkController zkController, String zkConfigName, String solrConfigFileName,
|
||||
SolrResourceLoader resourceLoader);
|
||||
|
||||
|
|
|
@ -21,12 +21,10 @@ import org.apache.solr.cloud.ZkController;
|
|||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.handler.component.HttpShardHandlerFactory;
|
||||
import org.apache.solr.handler.component.ShardHandlerFactory;
|
||||
import org.apache.solr.schema.IndexSchema;
|
||||
import org.apache.solr.util.DOMUtil;
|
||||
import org.apache.solr.util.PropertiesUtil;
|
||||
import org.apache.solr.util.SystemIdResolver;
|
||||
import org.apache.solr.util.plugin.PluginInfoInitialized;
|
||||
import org.apache.zookeeper.KeeperException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
|
@ -197,16 +195,6 @@ public class ConfigSolrXmlBackCompat extends Config implements ConfigSolr {
|
|||
return attrs;
|
||||
}
|
||||
|
||||
public IndexSchema getSchemaFromZk(ZkController zkController, String zkConfigName, String schemaName,
|
||||
SolrConfig config)
|
||||
throws KeeperException, InterruptedException {
|
||||
byte[] configBytes = zkController.getConfigFileData(zkConfigName, schemaName);
|
||||
InputSource is = new InputSource(new ByteArrayInputStream(configBytes));
|
||||
is.setSystemId(SystemIdResolver.createSystemIdFromResourceName(schemaName));
|
||||
IndexSchema schema = new IndexSchema(config, schemaName, is);
|
||||
return schema;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SolrConfig getSolrConfigFromZk(ZkController zkController, String zkConfigName, String solrConfigFileName,
|
||||
SolrResourceLoader resourceLoader) {
|
||||
|
|
|
@ -71,6 +71,7 @@ import org.apache.solr.logging.LogWatcher;
|
|||
import org.apache.solr.logging.jul.JulWatcher;
|
||||
import org.apache.solr.logging.log4j.Log4jWatcher;
|
||||
import org.apache.solr.schema.IndexSchema;
|
||||
import org.apache.solr.schema.IndexSchemaFactory;
|
||||
import org.apache.solr.update.SolrCoreState;
|
||||
import org.apache.solr.util.DefaultSolrThreadFactory;
|
||||
import org.apache.solr.util.FileUtils;
|
||||
|
@ -868,7 +869,7 @@ public class CoreContainer
|
|||
}
|
||||
solrLoader = new ZkSolrResourceLoader(instanceDir, zkConfigName, libLoader, SolrProperties.getCoreProperties(instanceDir, dcore), zkController);
|
||||
config = getSolrConfigFromZk(zkConfigName, dcore.getConfigName(), solrLoader);
|
||||
schema = getSchemaFromZk(zkConfigName, dcore.getSchemaName(), config);
|
||||
schema = IndexSchemaFactory.buildIndexSchema(dcore.getSchemaName(), config);
|
||||
return new SolrCore(dcore.getName(), null, config, schema, dcore);
|
||||
|
||||
} catch (KeeperException e) {
|
||||
|
@ -912,7 +913,7 @@ public class CoreContainer
|
|||
schema = indexSchemaCache.get(key);
|
||||
if (schema == null) {
|
||||
log.info("creating new schema object for core: " + dcore.getProperty(CoreDescriptor.CORE_NAME));
|
||||
schema = new IndexSchema(config, dcore.getSchemaName(), null);
|
||||
schema = IndexSchemaFactory.buildIndexSchema(dcore.getSchemaName(), config);
|
||||
indexSchemaCache.put(key, schema);
|
||||
} else {
|
||||
log.info("re-using schema object for core: " + dcore.getProperty(CoreDescriptor.CORE_NAME));
|
||||
|
@ -921,7 +922,7 @@ public class CoreContainer
|
|||
}
|
||||
|
||||
if (schema == null) {
|
||||
schema = new IndexSchema(config, dcore.getSchemaName(), null);
|
||||
schema = IndexSchemaFactory.buildIndexSchema(dcore.getSchemaName(), config);
|
||||
}
|
||||
|
||||
SolrCore core = new SolrCore(dcore.getName(), null, config, schema, dcore);
|
||||
|
@ -1361,12 +1362,6 @@ public class CoreContainer
|
|||
log.error(msg, ex);
|
||||
return new SolrException(ErrorCode.SERVER_ERROR, msg, ex);
|
||||
}
|
||||
|
||||
private IndexSchema getSchemaFromZk(String zkConfigName, String schemaName,
|
||||
SolrConfig config)
|
||||
throws KeeperException, InterruptedException {
|
||||
return cfg.getSchemaFromZk(zkController, zkConfigName, schemaName, config);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@ package org.apache.solr.core;
|
|||
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.SolrException.ErrorCode;
|
||||
import org.apache.solr.schema.IndexSchema;
|
||||
import org.apache.solr.schema.IndexSchemaFactory;
|
||||
import org.apache.solr.util.DOMUtil;
|
||||
import org.apache.solr.util.RegexFileFilter;
|
||||
import org.apache.solr.handler.component.SearchComponent;
|
||||
|
@ -214,9 +216,9 @@ public class SolrConfig extends Config {
|
|||
loadPluginInfo(QueryConverter.class,"queryConverter",true, true);
|
||||
|
||||
// this is hackish, since it picks up all SolrEventListeners,
|
||||
// regardless of when/how/why thye are used (or even if they are
|
||||
// regardless of when/how/why they are used (or even if they are
|
||||
// declared outside of the appropriate context) but there's no nice
|
||||
// way arround that in the PluginInfo framework
|
||||
// way around that in the PluginInfo framework
|
||||
loadPluginInfo(SolrEventListener.class, "//listener",false, true);
|
||||
|
||||
loadPluginInfo(DirectoryFactory.class,"directoryFactory",false, true);
|
||||
|
@ -225,6 +227,7 @@ public class SolrConfig extends Config {
|
|||
loadPluginInfo(IndexReaderFactory.class,"indexReaderFactory",false, true);
|
||||
loadPluginInfo(UpdateRequestProcessorChain.class,"updateRequestProcessorChain",false, false);
|
||||
loadPluginInfo(UpdateLog.class,"updateHandler/updateLog",false, false);
|
||||
loadPluginInfo(IndexSchemaFactory.class,"schemaFactory",false, true);
|
||||
|
||||
updateHandlerInfo = loadUpdatehandlerInfo();
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@ import org.apache.solr.response.XMLResponseWriter;
|
|||
import org.apache.solr.response.transform.TransformerFactory;
|
||||
import org.apache.solr.schema.FieldType;
|
||||
import org.apache.solr.schema.IndexSchema;
|
||||
import org.apache.solr.schema.IndexSchemaFactory;
|
||||
import org.apache.solr.schema.SchemaAware;
|
||||
import org.apache.solr.search.QParserPlugin;
|
||||
import org.apache.solr.search.SolrFieldCacheMBean;
|
||||
|
@ -393,11 +394,9 @@ public final class SolrCore implements SolrInfoMBean {
|
|||
public SolrCore reload(SolrResourceLoader resourceLoader, SolrCore prev) throws IOException,
|
||||
ParserConfigurationException, SAXException {
|
||||
|
||||
SolrConfig config = new SolrConfig(resourceLoader,
|
||||
getSolrConfig().getName(), null);
|
||||
SolrConfig config = new SolrConfig(resourceLoader, getSolrConfig().getName(), null);
|
||||
|
||||
IndexSchema schema = new IndexSchema(config,
|
||||
getSchema().getResourceName(), null);
|
||||
IndexSchema schema = IndexSchemaFactory.buildIndexSchema(getSchema().getResourceName(), config);
|
||||
|
||||
solrCoreState.increfSolrCoreState();
|
||||
|
||||
|
@ -681,7 +680,7 @@ public final class SolrCore implements SolrInfoMBean {
|
|||
log.info(logid+"Opening new SolrCore at " + resourceLoader.getInstanceDir() + ", dataDir="+dataDir);
|
||||
|
||||
if (schema==null) {
|
||||
schema = new IndexSchema(config, IndexSchema.DEFAULT_SCHEMA_FILE, null);
|
||||
schema = IndexSchemaFactory.buildIndexSchema(IndexSchema.DEFAULT_SCHEMA_FILE, config);
|
||||
}
|
||||
|
||||
if (null != cd && null != cd.getCloudDescriptor()) {
|
||||
|
@ -689,7 +688,7 @@ public final class SolrCore implements SolrInfoMBean {
|
|||
//
|
||||
// In cloud mode, version field is required for correct consistency
|
||||
// ideally this check would be more fine grained, and individual features
|
||||
// would assert it when they initialize, but DistribuedUpdateProcessor
|
||||
// would assert it when they initialize, but DistributedUpdateProcessor
|
||||
// is currently a big ball of wax that does more then just distributing
|
||||
// updates (ie: partial document updates), so it needs to work in no cloud
|
||||
// mode as well, and can't assert version field support on init.
|
||||
|
|
|
@ -24,11 +24,9 @@ import org.apache.solr.common.SolrException;
|
|||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.handler.component.HttpShardHandlerFactory;
|
||||
import org.apache.solr.handler.component.ShardHandlerFactory;
|
||||
import org.apache.solr.schema.IndexSchema;
|
||||
import org.apache.solr.util.PropertiesUtil;
|
||||
import org.apache.solr.util.SystemIdResolver;
|
||||
import org.apache.solr.util.plugin.PluginInfoInitialized;
|
||||
import org.apache.zookeeper.KeeperException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.xml.sax.InputSource;
|
||||
|
@ -410,18 +408,6 @@ public class SolrProperties implements ConfigSolr {
|
|||
}
|
||||
|
||||
|
||||
// Copied verbatim from the old code, presumably this will be tested when we eliminate solr.xml
|
||||
@Override
|
||||
public IndexSchema getSchemaFromZk(ZkController zkController, String zkConfigName, String schemaName,
|
||||
SolrConfig config)
|
||||
throws KeeperException, InterruptedException {
|
||||
byte[] configBytes = zkController.getConfigFileData(zkConfigName, schemaName);
|
||||
InputSource is = new InputSource(new ByteArrayInputStream(configBytes));
|
||||
is.setSystemId(SystemIdResolver.createSystemIdFromResourceName(schemaName));
|
||||
IndexSchema schema = new IndexSchema(config, schemaName, is);
|
||||
return schema;
|
||||
}
|
||||
|
||||
// Copied verbatim from the old code, presumably this will be tested when we eliminate solr.xml
|
||||
@Override
|
||||
public SolrConfig getSolrConfigFromZk(ZkController zkController, String zkConfigName, String solrConfigFileName,
|
||||
|
|
|
@ -40,8 +40,15 @@ import org.slf4j.LoggerFactory;
|
|||
* @lucene.internal
|
||||
*/
|
||||
public class SchemaXmlWriter extends TextResponseWriter {
|
||||
final static Logger log = LoggerFactory.getLogger(SchemaXmlWriter.class);
|
||||
private static final Logger log = LoggerFactory.getLogger(SchemaXmlWriter.class);
|
||||
private static final char[] XML_DECLARATION = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>".toCharArray();
|
||||
private static final char[] MANAGED_SCHEMA_DO_NOT_EDIT_WARNING
|
||||
= "<!-- Solr managed schema - automatically generated - DO NOT EDIT -->".toCharArray();
|
||||
|
||||
private boolean emitManagedSchemaDoNotEditWarning = false;
|
||||
public void setEmitManagedSchemaDoNotEditWarning(boolean emitManagedSchemaDoNotEditWarning) {
|
||||
this.emitManagedSchemaDoNotEditWarning = emitManagedSchemaDoNotEditWarning;
|
||||
}
|
||||
|
||||
public static void writeResponse(Writer writer, SolrQueryRequest req, SolrQueryResponse rsp) throws IOException {
|
||||
SchemaXmlWriter schemaXmlWriter = null;
|
||||
|
@ -62,6 +69,13 @@ public class SchemaXmlWriter extends TextResponseWriter {
|
|||
public void writeResponse() throws IOException {
|
||||
|
||||
writer.write(XML_DECLARATION);
|
||||
if (emitManagedSchemaDoNotEditWarning) {
|
||||
if (doIndent) {
|
||||
writer.write('\n');
|
||||
}
|
||||
writer.write(MANAGED_SCHEMA_DO_NOT_EDIT_WARNING);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") SimpleOrderedMap<Object> schemaProperties
|
||||
= (SimpleOrderedMap<Object>)rsp.getValues().get(IndexSchema.SCHEMA);
|
||||
|
||||
|
@ -139,7 +153,6 @@ public class SchemaXmlWriter extends TextResponseWriter {
|
|||
}
|
||||
decLevel();
|
||||
endTag(IndexSchema.SCHEMA);
|
||||
|
||||
}
|
||||
|
||||
private void writeFieldTypes(List<SimpleOrderedMap<Object>> fieldTypePropertiesList) throws IOException {
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
package org.apache.solr.schema;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.SolrException.ErrorCode;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.core.SolrConfig;
|
||||
import org.apache.solr.core.SolrResourceLoader;
|
||||
import org.apache.solr.util.SystemIdResolver;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
public class ClassicIndexSchemaFactory extends IndexSchemaFactory {
|
||||
private static final Logger log = LoggerFactory.getLogger(ClassicIndexSchemaFactory.class);
|
||||
|
||||
@Override
|
||||
public void init(NamedList args) {
|
||||
// no arguments expected
|
||||
if (args.size() > 0) {
|
||||
String msg = "Unexpected arg(s): " + args;
|
||||
log.error(msg);
|
||||
throw new SolrException(ErrorCode.SERVER_ERROR, msg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IndexSchema create(String resourceName, SolrConfig config) {
|
||||
SolrResourceLoader loader = config.getResourceLoader();
|
||||
InputStream schemaInputStream = null;
|
||||
|
||||
if (null == resourceName) {
|
||||
resourceName = IndexSchema.DEFAULT_SCHEMA_FILE;
|
||||
}
|
||||
|
||||
try {
|
||||
schemaInputStream = loader.openSchema(resourceName);
|
||||
} catch (Exception e) {
|
||||
final String msg = "Error loading schema resource " + resourceName;
|
||||
log.error(msg, e);
|
||||
throw new SolrException(ErrorCode.SERVER_ERROR, msg, e);
|
||||
}
|
||||
InputSource inputSource = new InputSource(schemaInputStream);
|
||||
inputSource.setSystemId(SystemIdResolver.createSystemIdFromResourceName(resourceName));
|
||||
IndexSchema schema = new IndexSchema(config, resourceName, inputSource);
|
||||
return schema;
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package org.apache.solr.schema;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
import org.apache.lucene.analysis.AnalyzerWrapper;
|
||||
import org.apache.lucene.index.IndexableField;
|
||||
|
@ -24,17 +25,27 @@ import org.apache.lucene.index.StorableField;
|
|||
import org.apache.lucene.index.StoredDocument;
|
||||
import org.apache.lucene.search.similarities.Similarity;
|
||||
import org.apache.lucene.util.Version;
|
||||
import org.apache.solr.cloud.ZkController;
|
||||
import org.apache.solr.cloud.ZkSolrResourceLoader;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.SolrException.ErrorCode;
|
||||
import org.apache.solr.common.cloud.ZkCmdExecutor;
|
||||
import org.apache.solr.common.cloud.ZooKeeperException;
|
||||
import org.apache.solr.common.params.SolrParams;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.common.util.SimpleOrderedMap;
|
||||
import org.apache.solr.request.LocalSolrQueryRequest;
|
||||
import org.apache.solr.response.SchemaXmlWriter;
|
||||
import org.apache.solr.response.SolrQueryResponse;
|
||||
import org.apache.solr.util.DOMUtil;
|
||||
import org.apache.solr.util.FileUtils;
|
||||
import org.apache.solr.util.SystemIdResolver;
|
||||
import org.apache.solr.core.SolrConfig;
|
||||
import org.apache.solr.core.Config;
|
||||
import org.apache.solr.core.SolrResourceLoader;
|
||||
import org.apache.solr.search.similarities.DefaultSimilarityFactory;
|
||||
import org.apache.solr.util.plugin.SolrCoreAware;
|
||||
import org.apache.zookeeper.KeeperException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
|
@ -47,7 +58,13 @@ import org.xml.sax.InputSource;
|
|||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
@ -71,7 +88,7 @@ import java.util.regex.Pattern;
|
|||
*
|
||||
*
|
||||
*/
|
||||
public final class IndexSchema {
|
||||
public class IndexSchema {
|
||||
public static final String COPY_FIELD = "copyField";
|
||||
public static final String COPY_FIELDS = COPY_FIELD + "s";
|
||||
public static final String DEFAULT_OPERATOR = "defaultOperator";
|
||||
|
@ -108,7 +125,7 @@ public final class IndexSchema {
|
|||
|
||||
final static Logger log = LoggerFactory.getLogger(IndexSchema.class);
|
||||
private final SolrConfig solrConfig;
|
||||
private final String resourceName;
|
||||
private String resourceName;
|
||||
private String name;
|
||||
private float version;
|
||||
private final SolrResourceLoader loader;
|
||||
|
@ -145,24 +162,21 @@ public final class IndexSchema {
|
|||
|
||||
/**
|
||||
* Constructs a schema using the specified resource name and stream.
|
||||
* If the is stream is null, the resource loader will load the schema resource by name.
|
||||
* @see SolrResourceLoader#openSchema
|
||||
* By default, this follows the normal config path directory searching rules.
|
||||
* @see SolrResourceLoader#openResource
|
||||
*/
|
||||
public IndexSchema(SolrConfig solrConfig, String name, InputSource is) {
|
||||
assert null != solrConfig : "SolrConfig should never be null";
|
||||
assert null != name : "schema resource name should never be null";
|
||||
assert null != is : "schema InputSource should never be null";
|
||||
|
||||
this.solrConfig = solrConfig;
|
||||
if (name == null)
|
||||
name = DEFAULT_SCHEMA_FILE;
|
||||
this.resourceName = name;
|
||||
loader = solrConfig.getResourceLoader();
|
||||
try {
|
||||
if (is == null) {
|
||||
is = new InputSource(loader.openSchema(name));
|
||||
is.setSystemId(SystemIdResolver.createSystemIdFromResourceName(name));
|
||||
}
|
||||
readSchema(is);
|
||||
loader.inform( loader );
|
||||
loader.inform(loader);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -179,7 +193,12 @@ public final class IndexSchema {
|
|||
public String getResourceName() {
|
||||
return resourceName;
|
||||
}
|
||||
|
||||
|
||||
/** Sets the name of the resource used to instantiate this schema. */
|
||||
public void setResourceName(String resourceName) {
|
||||
this.resourceName = resourceName;
|
||||
}
|
||||
|
||||
/** Gets the name of the schema as specified in the schema resource. */
|
||||
public String getSchemaName() {
|
||||
return name;
|
||||
|
@ -345,6 +364,24 @@ public final class IndexSchema {
|
|||
queryAnalyzer = new SolrQueryAnalyzer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the schema in schema.xml format to the given writer
|
||||
*/
|
||||
void persist(Writer writer) throws IOException {
|
||||
final SolrQueryResponse response = new SolrQueryResponse();
|
||||
response.add(IndexSchema.SCHEMA, getNamedPropertyValues());
|
||||
final NamedList args = new NamedList(Arrays.<Object>asList("indent", "on"));
|
||||
final LocalSolrQueryRequest req = new LocalSolrQueryRequest(null, args);
|
||||
final SchemaXmlWriter schemaXmlWriter = new SchemaXmlWriter(writer, req, response);
|
||||
schemaXmlWriter.setEmitManagedSchemaDoNotEditWarning(true);
|
||||
schemaXmlWriter.writeResponse();
|
||||
schemaXmlWriter.close();
|
||||
}
|
||||
|
||||
public boolean isMutable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private class SolrIndexAnalyzer extends AnalyzerWrapper {
|
||||
protected final HashMap<String, Analyzer> analyzers;
|
||||
|
||||
|
@ -392,7 +429,7 @@ public final class IndexSchema {
|
|||
}
|
||||
|
||||
private void readSchema(InputSource is) {
|
||||
log.info("Reading Solr Schema");
|
||||
log.info("Reading Solr Schema from " + resourceName);
|
||||
|
||||
try {
|
||||
// pass the config resource loader to avoid building an empty one for no reason:
|
||||
|
@ -1239,7 +1276,7 @@ public final class IndexSchema {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get a map of property name -> value for this field.
|
||||
* Get a map of property name -> value for the whole schema.
|
||||
*/
|
||||
public SimpleOrderedMap<Object> getNamedPropertyValues() {
|
||||
SimpleOrderedMap<Object> topLevel = new SimpleOrderedMap<Object>();
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package org.apache.solr.schema;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import org.apache.solr.core.PluginInfo;
|
||||
import org.apache.solr.core.SolrConfig;
|
||||
import org.apache.solr.util.plugin.NamedListInitializedPlugin;
|
||||
|
||||
public abstract class IndexSchemaFactory implements NamedListInitializedPlugin {
|
||||
|
||||
public abstract IndexSchema create(String resourceName, SolrConfig config);
|
||||
|
||||
public static IndexSchema buildIndexSchema(String resourceName, SolrConfig config) {
|
||||
PluginInfo info = config.getPluginInfo(IndexSchemaFactory.class.getName());
|
||||
IndexSchemaFactory factory;
|
||||
if (null != info) {
|
||||
factory = config.getResourceLoader().newInstance(info.className, IndexSchemaFactory.class);
|
||||
factory.init(info.initArgs);
|
||||
} else {
|
||||
factory = new ClassicIndexSchemaFactory();
|
||||
}
|
||||
IndexSchema schema = factory.create(resourceName, config);
|
||||
return schema;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package org.apache.solr.schema;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import org.apache.solr.core.SolrConfig;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
/** Solr-managed schema - non-user-editable, but can be mutable via internal and external REST API requests. */
|
||||
public final class ManagedIndexSchema extends IndexSchema {
|
||||
|
||||
private boolean isMutable = false;
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return isMutable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a schema using the specified resource name and stream.
|
||||
*
|
||||
* @see org.apache.solr.core.SolrResourceLoader#openSchema
|
||||
* By default, this follows the normal config path directory searching rules.
|
||||
* @see org.apache.solr.core.SolrResourceLoader#openResource
|
||||
*/
|
||||
ManagedIndexSchema(SolrConfig solrConfig, String name, InputSource is, boolean isMutable) {
|
||||
super(solrConfig, name, is);
|
||||
this.isMutable = isMutable;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,359 @@
|
|||
package org.apache.solr.schema;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.solr.cloud.ZkController;
|
||||
import org.apache.solr.cloud.ZkSolrResourceLoader;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.SolrException.ErrorCode;
|
||||
import org.apache.solr.common.cloud.ZkCmdExecutor;
|
||||
import org.apache.solr.common.cloud.ZooKeeperException;
|
||||
import org.apache.solr.common.params.SolrParams;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.core.SolrConfig;
|
||||
import org.apache.solr.core.SolrResourceLoader;
|
||||
import org.apache.solr.util.FileUtils;
|
||||
import org.apache.solr.util.SystemIdResolver;
|
||||
import org.apache.zookeeper.KeeperException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
public class ManagedIndexSchemaFactory extends IndexSchemaFactory {
|
||||
private static final Logger log = LoggerFactory.getLogger(ManagedIndexSchemaFactory.class);
|
||||
private static final String UPGRADED_SCHEMA_EXTENSION = ".bak";
|
||||
|
||||
private boolean isMutable;
|
||||
private String managedSchemaResourceName;
|
||||
private SolrConfig config;
|
||||
private SolrResourceLoader loader;
|
||||
private String resourceName;
|
||||
private IndexSchema schema;
|
||||
|
||||
@Override
|
||||
public void init(NamedList args) {
|
||||
SolrParams params = SolrParams.toSolrParams(args);
|
||||
isMutable = params.getBool("mutable", false);
|
||||
args.remove("mutable");
|
||||
managedSchemaResourceName = params.get("managedSchemaResourceName", "managed-schema");
|
||||
args.remove("managedSchemaResourceName");
|
||||
if ("schema.xml".equals(managedSchemaResourceName)) {
|
||||
String msg = "managedSchemaResourceName can't be 'schema.xml'";
|
||||
log.error(msg);
|
||||
throw new SolrException(ErrorCode.SERVER_ERROR, msg);
|
||||
}
|
||||
|
||||
if (args.size() > 0) {
|
||||
String msg = "Unexpected arg(s): " + args;
|
||||
log.error(msg);
|
||||
throw new SolrException(ErrorCode.SERVER_ERROR, msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* First, try to locate the managed schema file named in the managedSchemaResourceName
|
||||
* param. If the managed schema file exists and is accessible, it is used to instantiate
|
||||
* an IndexSchema.
|
||||
*
|
||||
* If the managed schema file can't be found, the resource named by the resourceName
|
||||
* parameter is used to instantiate an IndexSchema.
|
||||
*
|
||||
* Once the IndexSchema is instantiated, if the managed schema file does not exist,
|
||||
* the instantiated IndexSchema is persisted to the managed schema file named in the
|
||||
* managedSchemaResourceName param, in the directory given by
|
||||
* {@link org.apache.solr.core.SolrResourceLoader#getConfigDir()}, or if configs are
|
||||
* in ZooKeeper, under {@link org.apache.solr.cloud.ZkSolrResourceLoader#collectionZkPath}.
|
||||
*
|
||||
* After the managed schema file is persisted, the original schema file is
|
||||
* renamed by appending the extension named in {@link #UPGRADED_SCHEMA_EXTENSION}.
|
||||
*/
|
||||
public IndexSchema create(String resourceName, SolrConfig config) {
|
||||
this.resourceName = resourceName;
|
||||
this.config = config;
|
||||
SolrResourceLoader loader = config.getResourceLoader();
|
||||
this.loader = loader;
|
||||
InputStream schemaInputStream = null;
|
||||
boolean shouldUpgrade = false;
|
||||
String loadedResource = null;
|
||||
|
||||
if (null == resourceName) {
|
||||
resourceName = IndexSchema.DEFAULT_SCHEMA_FILE;
|
||||
}
|
||||
|
||||
try {
|
||||
// Attempt to load the managed schema
|
||||
schemaInputStream = loader.openSchema(managedSchemaResourceName);
|
||||
loadedResource = managedSchemaResourceName;
|
||||
|
||||
// Check if the non-managed schema is also present
|
||||
if ( ! resourceName.equals(managedSchemaResourceName)) {
|
||||
if (nonManagedSchemaExists()) {
|
||||
// Warn if the non-managed schema is present
|
||||
log.warn("The schema has been upgraded to managed, but the non-managed schema " + resourceName
|
||||
+ " is still loadable. PLEASE REMOVE THIS FILE.");
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.info("SolrConfig.isManagedSchema = true, but managed schema resource " + managedSchemaResourceName
|
||||
+ " not found - loading non-managed schema " + resourceName + " instead");
|
||||
}
|
||||
if (null == schemaInputStream) {
|
||||
// The managed schema file could not be found - load the non-managed schema
|
||||
try {
|
||||
schemaInputStream = loader.openSchema(resourceName);
|
||||
loadedResource = resourceName;
|
||||
shouldUpgrade = true;
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
// Retry to load the managed schema, in case it was created since the first attempt
|
||||
schemaInputStream = loader.openSchema(managedSchemaResourceName);
|
||||
loadedResource = managedSchemaResourceName;
|
||||
} catch (IOException e1) {
|
||||
final String msg = "Error loading both non-managed schema '" + resourceName + "' and managed schema '"
|
||||
+ managedSchemaResourceName + "'";
|
||||
log.error(msg, e);
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, msg, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
InputSource inputSource = new InputSource(schemaInputStream);
|
||||
inputSource.setSystemId(SystemIdResolver.createSystemIdFromResourceName(loadedResource));
|
||||
schema = new ManagedIndexSchema(config, loadedResource, inputSource, isMutable);
|
||||
|
||||
if (shouldUpgrade) {
|
||||
// Persist the managed schema if it doesn't already exist
|
||||
upgradeToManagedSchema();
|
||||
}
|
||||
return schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether a non-managed schema exists, either in local storage or on ZooKeeper.
|
||||
*/
|
||||
private boolean nonManagedSchemaExists() {
|
||||
boolean exists = false;
|
||||
SolrResourceLoader loader = config.getResourceLoader();
|
||||
if (loader instanceof ZkSolrResourceLoader) {
|
||||
ZkSolrResourceLoader zkLoader = (ZkSolrResourceLoader)loader;
|
||||
String nonManagedSchemaPath = zkLoader.getCollectionZkPath() + "/" + resourceName;
|
||||
try {
|
||||
exists = zkLoader.getZkController().pathExists(nonManagedSchemaPath);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt(); // Restore the interrupted status
|
||||
log.warn("", e); // Log as warning and suppress the exception
|
||||
} catch (KeeperException e) {
|
||||
// log as warning and suppress the exception
|
||||
log.warn("Error checking for the existence of the non-managed schema " + resourceName, e);
|
||||
}
|
||||
} else { // Config is not in ZooKeeper
|
||||
InputStream nonManagedSchemaInputStream = null;
|
||||
try {
|
||||
nonManagedSchemaInputStream = loader.openSchema(resourceName);
|
||||
if (null != nonManagedSchemaInputStream) {
|
||||
exists = true;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// This is expected when the non-managed schema does not exist
|
||||
} finally {
|
||||
IOUtils.closeQuietly(nonManagedSchemaInputStream);
|
||||
}
|
||||
}
|
||||
return exists;
|
||||
}
|
||||
|
||||
/**
|
||||
* Persist the managed schema and rename the non-managed schema
|
||||
* by appending {@link #UPGRADED_SCHEMA_EXTENSION}.
|
||||
*
|
||||
* Failure to rename the non-managed schema will be logged as a warning,
|
||||
* and no exception will be thrown.
|
||||
*/
|
||||
private void upgradeToManagedSchema() {
|
||||
SolrResourceLoader loader = config.getResourceLoader();
|
||||
if (loader instanceof ZkSolrResourceLoader) {
|
||||
zkUgradeToManagedSchema();
|
||||
} else {
|
||||
// Configs are not on ZooKeeper
|
||||
File managedSchemaFile = new File(loader.getConfigDir(), managedSchemaResourceName);
|
||||
OutputStreamWriter writer = null;
|
||||
try {
|
||||
File parentDir = managedSchemaFile.getParentFile();
|
||||
if (!parentDir.isDirectory()) {
|
||||
if (!parentDir.mkdirs()) {
|
||||
final String msg = "Can't create managed schema directory " + parentDir.getAbsolutePath();
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, msg);
|
||||
}
|
||||
}
|
||||
final FileOutputStream out = new FileOutputStream(managedSchemaFile);
|
||||
writer = new OutputStreamWriter(out, "UTF-8");
|
||||
schema.persist(writer);
|
||||
log.info("Upgraded to managed schema at " + managedSchemaFile.getPath());
|
||||
} catch (IOException e) {
|
||||
final String msg = "Error persisting managed schema " + managedSchemaFile;
|
||||
log.error(msg, e);
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, msg, e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(writer);
|
||||
try {
|
||||
FileUtils.sync(managedSchemaFile);
|
||||
} catch (IOException e) {
|
||||
final String msg = "Error syncing the managed schema file " + managedSchemaFile;
|
||||
log.error(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
// After successfully persisting the managed schema, rename the non-managed
|
||||
// schema file by appending UPGRADED_SCHEMA_EXTENSION to its name.
|
||||
|
||||
if (resourceName.equals(managedSchemaResourceName)) {
|
||||
log.info("On upgrading to managed schema, did not rename non-managed schema '"
|
||||
+ resourceName + "' because it's the same as the managed schema's name.");
|
||||
} else {
|
||||
final File nonManagedSchemaFile = locateConfigFile(resourceName);
|
||||
if (null == nonManagedSchemaFile) {
|
||||
// Don't throw an exception for failure to rename the non-managed schema
|
||||
log.warn("On upgrading to managed schema, did not rename non-managed schema "
|
||||
+ resourceName + " because it's neither an absolute file "
|
||||
+ "nor under SolrConfig.getConfigDir() or the current directory."
|
||||
+ " PLEASE REMOVE THIS FILE.");
|
||||
} else {
|
||||
File upgradedSchemaFile = new File(nonManagedSchemaFile.getPath() + UPGRADED_SCHEMA_EXTENSION);
|
||||
if (nonManagedSchemaFile.renameTo(upgradedSchemaFile)) {
|
||||
// Set the resource name to the managed schema so that the CoreAdminHandler returns a findable filename
|
||||
schema.setResourceName(managedSchemaResourceName);
|
||||
|
||||
log.info("After upgrading to managed schema, renamed the non-managed schema "
|
||||
+ nonManagedSchemaFile + " to " + upgradedSchemaFile);
|
||||
} else {
|
||||
// Don't throw an exception for failure to rename the non-managed schema
|
||||
log.warn("Can't rename " + nonManagedSchemaFile.toString() + " to "
|
||||
+ upgradedSchemaFile.toString() + " - PLEASE REMOVE THIS FILE.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds any resource by its name on the filesystem. The classpath is not consulted.
|
||||
*
|
||||
* If the resource is not absolute, the resource is sought in $configDir and then in the current directory.
|
||||
*
|
||||
*@return the File for the named resource, or null if it can't be found
|
||||
*/
|
||||
private File locateConfigFile(String resource) {
|
||||
File located = null;
|
||||
File file = new File(resource);
|
||||
if (file.isAbsolute()) {
|
||||
if (file.isFile() && file.canRead()) {
|
||||
located = file;
|
||||
}
|
||||
} else {
|
||||
// try $configDir/$resource
|
||||
File fileUnderConfigDir = new File(config.getResourceLoader().getConfigDir() + resource);
|
||||
if (fileUnderConfigDir.isFile() && fileUnderConfigDir.canRead()) {
|
||||
located = fileUnderConfigDir;
|
||||
} else {
|
||||
// no success with $configDir/$resource - try $CWD/$resource
|
||||
if (file.isFile() && file.canRead()) {
|
||||
located = file;
|
||||
}
|
||||
}
|
||||
}
|
||||
return located;
|
||||
}
|
||||
|
||||
/**
|
||||
* Persist the managed schema to ZooKeeper and rename the non-managed schema
|
||||
* by appending {@link #UPGRADED_SCHEMA_EXTENSION}.
|
||||
*
|
||||
* Failure to rename the non-managed schema will be logged as a warning,
|
||||
* and no exception will be thrown.
|
||||
*/
|
||||
private void zkUgradeToManagedSchema() {
|
||||
ZkSolrResourceLoader zkLoader = (ZkSolrResourceLoader)config.getResourceLoader();
|
||||
ZkCmdExecutor zkCmdExecutor = new ZkCmdExecutor(30);
|
||||
ZkController zkController = zkLoader.getZkController();
|
||||
final String managedSchemaPath = zkLoader.getCollectionZkPath() + "/" + managedSchemaResourceName;
|
||||
try {
|
||||
// Create the managed schema znode
|
||||
zkCmdExecutor.ensureExists(managedSchemaPath, zkController.getZkClient());
|
||||
// Persist the managed schema
|
||||
StringWriter writer = new StringWriter();
|
||||
schema.persist(writer);
|
||||
zkController.getZkClient().setData(managedSchemaPath, writer.toString().getBytes("UTF-8"), true);
|
||||
log.info("Upgraded to managed schema at " + managedSchemaPath + "");
|
||||
} catch (Exception e) {
|
||||
if (e instanceof InterruptedException) {
|
||||
Thread.currentThread().interrupt(); // Restore the interrupted status
|
||||
log.error("", e);
|
||||
throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR, "", e);
|
||||
} else {
|
||||
final String msg = "Error persisting managed schema resource " + managedSchemaResourceName;
|
||||
log.error(msg, e);
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
// After successfully persisting the managed schema, rename the non-managed
|
||||
// schema znode by appending UPGRADED_SCHEMA_EXTENSION to its name.
|
||||
|
||||
if (resourceName.equals(managedSchemaResourceName)) {
|
||||
log.info("On upgrading to managed schema, did not rename non-managed schema "
|
||||
+ resourceName + " because it's the same as the managed schema's name.");
|
||||
} else {
|
||||
// Rename the non-managed schema znode in ZooKeeper
|
||||
final String nonManagedSchemaPath = zkLoader.getCollectionZkPath() + "/" + resourceName;
|
||||
try {
|
||||
if (zkController.pathExists(nonManagedSchemaPath)) {
|
||||
// First, copy the non-managed schema znode content to the upgraded schema znode
|
||||
byte[] bytes = zkController.getZkClient().getData(nonManagedSchemaPath, null, null, true);
|
||||
final String upgradedSchemaPath = nonManagedSchemaPath + UPGRADED_SCHEMA_EXTENSION;
|
||||
zkCmdExecutor.ensureExists(upgradedSchemaPath, zkController.getZkClient());
|
||||
zkController.getZkClient().setData(upgradedSchemaPath, bytes, true);
|
||||
// Then delete the non-managed schema znode
|
||||
zkController.getZkClient().delete(nonManagedSchemaPath, -1, true);
|
||||
|
||||
// Set the resource name to the managed schema so that the CoreAdminHandler returns a findable filename
|
||||
schema.setResourceName(managedSchemaResourceName);
|
||||
|
||||
log.info("After upgrading to managed schema in ZooKeeper, renamed the non-managed schema "
|
||||
+ nonManagedSchemaPath + " to " + upgradedSchemaPath);
|
||||
} else {
|
||||
log.info("After upgrading to managed schema in ZooKeeper, the non-managed schema "
|
||||
+ nonManagedSchemaPath + " no longer exists.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (e instanceof InterruptedException) {
|
||||
Thread.currentThread().interrupt(); // Restore the interrupted status
|
||||
log.warn("", e); // Log as warning and suppress the exception
|
||||
} else {
|
||||
final String msg = "Error persisting managed schema resource " + managedSchemaResourceName;
|
||||
log.warn(msg, e); // Log as warning and suppress the exception
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" ?>
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<config>
|
||||
|
||||
<luceneMatchVersion>${tests.luceneMatchVersion:LUCENE_CURRENT}</luceneMatchVersion>
|
||||
|
||||
<!-- managed schema can't be named schema.xml -->
|
||||
<schemaFactory class="ManagedIndexSchemaFactory">
|
||||
<bool name="mutable">false</bool>
|
||||
<str name="managedSchemaResourceName">schema.xml</str>
|
||||
</schemaFactory>
|
||||
|
||||
</config>
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" ?>
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<config>
|
||||
|
||||
<luceneMatchVersion>${tests.luceneMatchVersion:LUCENE_CURRENT}</luceneMatchVersion>
|
||||
|
||||
<!-- schema must be managed in order to be mutable -->
|
||||
<!-- managed schema can't be named schema.xml -->
|
||||
<schemaFactory class="ClassicIndexSchemaFactory">
|
||||
<bool name="mutable">false</bool>
|
||||
<str name="managedSchemaResourceName">schema.xml</str>
|
||||
</schemaFactory>
|
||||
|
||||
|
||||
</config>
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" ?>
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<config>
|
||||
|
||||
<luceneMatchVersion>${tests.luceneMatchVersion:LUCENE_CURRENT}</luceneMatchVersion>
|
||||
|
||||
<!-- The presence of bogusParam should trigger failure -->
|
||||
<schemaFactory class="ManagedIndexSchemaFactory">
|
||||
<bool name="mutable">false</bool>
|
||||
<str name="managedSchemaResourceName">managed-schema</str>
|
||||
<str name="bogusParam">bogusValue</str>
|
||||
</schemaFactory>
|
||||
|
||||
|
||||
</config>
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" ?>
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<config>
|
||||
<luceneMatchVersion>${tests.luceneMatchVersion:LUCENE_CURRENT}</luceneMatchVersion>
|
||||
|
||||
<schemaFactory class="ManagedIndexSchemaFactory">
|
||||
<bool name="mutable">false</bool>
|
||||
<str name="managedSchemaResourceName">managed-schema</str>
|
||||
</schemaFactory>
|
||||
|
||||
</config>
|
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" ?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<config>
|
||||
<jmx />
|
||||
|
||||
<luceneMatchVersion>${tests.luceneMatchVersion:LUCENE_CURRENT}</luceneMatchVersion>
|
||||
|
||||
<schemaFactory class="ManagedIndexSchemaFactory">
|
||||
<bool name="mutable">false</bool>
|
||||
<str name="managedSchemaResourceName">managed-schema</str>
|
||||
</schemaFactory>
|
||||
|
||||
<directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}">
|
||||
<!-- used to keep RAM reqs down for HdfsDirectoryFactory -->
|
||||
<int name="solr.hdfs.blockcache.blocksperbank">${solr.hdfs.blockcache.blocksperbank:1024}</int>
|
||||
</directoryFactory>
|
||||
|
||||
<dataDir>${solr.data.dir:}</dataDir>
|
||||
|
||||
<indexConfig>
|
||||
<lockType>${solr.lock.type:native}</lockType>
|
||||
</indexConfig>
|
||||
|
||||
<!-- an update processor the explicitly excludes distrib to test
|
||||
clean errors when people attempt atomic updates w/o it
|
||||
-->
|
||||
<updateRequestProcessorChain name="nodistrib" >
|
||||
<processor class="solr.NoOpDistributingUpdateProcessorFactory" />
|
||||
<processor class="solr.RunUpdateProcessorFactory" />
|
||||
</updateRequestProcessorChain>
|
||||
|
||||
<requestHandler name="standard" class="solr.StandardRequestHandler">
|
||||
</requestHandler>
|
||||
|
||||
<requestHandler name="/get" class="solr.RealTimeGetHandler">
|
||||
<lst name="defaults">
|
||||
<str name="omitHeader">true</str>
|
||||
</lst>
|
||||
</requestHandler>
|
||||
|
||||
<requestHandler name="/replication" class="solr.ReplicationHandler" startup="lazy" />
|
||||
|
||||
<requestHandler name="/update" class="solr.UpdateRequestHandler" />
|
||||
|
||||
<updateHandler class="solr.DirectUpdateHandler2">
|
||||
<updateLog>
|
||||
<str name="dir">${solr.ulog.dir:}</str>
|
||||
</updateLog>
|
||||
</updateHandler>
|
||||
|
||||
<updateRequestProcessorChain name="dedupe">
|
||||
<processor class="org.apache.solr.update.processor.SignatureUpdateProcessorFactory">
|
||||
<bool name="enabled">true</bool>
|
||||
<bool name="overwriteDupes">true</bool>
|
||||
<str name="fields">v_t,t_field</str>
|
||||
<str name="signatureClass">org.apache.solr.update.processor.TextProfileSignature</str>
|
||||
</processor>
|
||||
<processor class="solr.RunUpdateProcessorFactory" />
|
||||
</updateRequestProcessorChain>
|
||||
<updateRequestProcessorChain name="stored_sig">
|
||||
<!-- this chain is valid even though the signature field is not
|
||||
indexed, because we are not asking for dups to be overwritten
|
||||
-->
|
||||
<processor class="org.apache.solr.update.processor.SignatureUpdateProcessorFactory">
|
||||
<bool name="enabled">true</bool>
|
||||
<str name="signatureField">non_indexed_signature_sS</str>
|
||||
<bool name="overwriteDupes">false</bool>
|
||||
<str name="fields">v_t,t_field</str>
|
||||
<str name="signatureClass">org.apache.solr.update.processor.TextProfileSignature</str>
|
||||
</processor>
|
||||
<processor class="solr.RunUpdateProcessorFactory" />
|
||||
</updateRequestProcessorChain>
|
||||
|
||||
<requestHandler name="/admin/" class="org.apache.solr.handler.admin.AdminHandlers" />
|
||||
|
||||
<updateRequestProcessorChain name="distrib-dup-test-chain-explicit">
|
||||
<!-- explicit test using processors before and after distrib -->
|
||||
<processor class="solr.RegexReplaceProcessorFactory">
|
||||
<str name="fieldName">regex_dup_A_s</str>
|
||||
<str name="pattern">x</str>
|
||||
<str name="replacement">x_x</str>
|
||||
</processor>
|
||||
<processor class="solr.DistributedUpdateProcessorFactory" />
|
||||
<processor class="solr.RegexReplaceProcessorFactory">
|
||||
<str name="fieldName">regex_dup_B_s</str>
|
||||
<str name="pattern">x</str>
|
||||
<str name="replacement">x_x</str>
|
||||
</processor>
|
||||
<processor class="solr.RunUpdateProcessorFactory" />
|
||||
</updateRequestProcessorChain>
|
||||
|
||||
<updateRequestProcessorChain name="distrib-dup-test-chain-implicit">
|
||||
<!-- implicit test w/o distrib declared-->
|
||||
<processor class="solr.RegexReplaceProcessorFactory">
|
||||
<str name="fieldName">regex_dup_A_s</str>
|
||||
<str name="pattern">x</str>
|
||||
<str name="replacement">x_x</str>
|
||||
</processor>
|
||||
<processor class="solr.RegexReplaceProcessorFactory">
|
||||
<str name="fieldName">regex_dup_B_s</str>
|
||||
<str name="pattern">x</str>
|
||||
<str name="replacement">x_x</str>
|
||||
</processor>
|
||||
<processor class="solr.RunUpdateProcessorFactory" />
|
||||
</updateRequestProcessorChain>
|
||||
|
||||
</config>
|
|
@ -53,6 +53,7 @@ import org.apache.solr.response.ResultContext;
|
|||
import org.apache.solr.response.SolrQueryResponse;
|
||||
import org.apache.solr.response.XMLWriter;
|
||||
import org.apache.solr.schema.IndexSchema;
|
||||
import org.apache.solr.schema.IndexSchemaFactory;
|
||||
import org.apache.solr.schema.SchemaField;
|
||||
import org.apache.solr.search.DocIterator;
|
||||
import org.apache.solr.search.DocList;
|
||||
|
@ -530,7 +531,7 @@ public class BasicFunctionalityTest extends SolrTestCaseJ4 {
|
|||
@Test
|
||||
public void testTermVectorFields() {
|
||||
|
||||
IndexSchema ischema = new IndexSchema(solrConfig, getSchemaFile(), null);
|
||||
IndexSchema ischema = IndexSchemaFactory.buildIndexSchema(getSchemaFile(), solrConfig);
|
||||
SchemaField f; // Solr field type
|
||||
StorableField luf; // Lucene field
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.apache.lucene.util.automaton.SpecialOperations;
|
|||
import org.apache.solr.SolrTestCaseJ4;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.schema.IndexSchema;
|
||||
import org.apache.solr.schema.IndexSchemaFactory;
|
||||
import org.apache.solr.search.QParser;
|
||||
import org.apache.solr.search.SolrQueryParser;
|
||||
import org.junit.Before;
|
||||
|
@ -56,7 +57,7 @@ public class TestReversedWildcardFilterFactory extends SolrTestCaseJ4 {
|
|||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
schema = new IndexSchema(solrConfig, getSchemaFile(), null);
|
||||
schema = IndexSchemaFactory.buildIndexSchema(getSchemaFile(), solrConfig);
|
||||
clearIndex();
|
||||
assertU(commit());
|
||||
}
|
||||
|
|
|
@ -23,10 +23,6 @@ import org.apache.solr.common.SolrException.ErrorCode;
|
|||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.script.ScriptEngineManager;
|
||||
|
||||
import org.junit.Assume;
|
||||
|
||||
public abstract class AbstractBadConfigTestBase extends SolrTestCaseJ4 {
|
||||
|
||||
/**
|
||||
|
@ -35,13 +31,30 @@ public abstract class AbstractBadConfigTestBase extends SolrTestCaseJ4 {
|
|||
* files causes an error matching the specified errString ot be thrown.
|
||||
*/
|
||||
protected final void assertConfigs(final String solrconfigFile,
|
||||
final String schemaFile,
|
||||
final String schemaFile,
|
||||
final String errString)
|
||||
throws Exception {
|
||||
assertConfigs(solrconfigFile, schemaFile, null, errString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a solrconfig.xml file name, a schema file name, a solr home directory,
|
||||
* and an expected errString, asserts that initializing a core with these
|
||||
* files causes an error matching the specified errString ot be thrown.
|
||||
*/
|
||||
protected final void assertConfigs(final String solrconfigFile,
|
||||
final String schemaFile,
|
||||
final String solrHome,
|
||||
final String errString)
|
||||
throws Exception {
|
||||
|
||||
ignoreException(Pattern.quote(errString));
|
||||
try {
|
||||
initCore( solrconfigFile, schemaFile );
|
||||
if (null == solrHome) {
|
||||
initCore( solrconfigFile, schemaFile );
|
||||
} else {
|
||||
initCore( solrconfigFile, schemaFile, solrHome );
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// short circuit out if we found what we expected
|
||||
if (-1 != e.getMessage().indexOf(errString)) return;
|
||||
|
|
|
@ -64,4 +64,18 @@ public class TestBadConfig extends AbstractBadConfigTestBase {
|
|||
"DummyMergePolicy");
|
||||
}
|
||||
|
||||
public void testSchemaMutableButNotManaged() throws Exception {
|
||||
assertConfigs("bad-solrconfig-schema-mutable-but-not-managed.xml",
|
||||
"schema-minimal.xml", "Unexpected arg(s): {mutable=false,managedSchemaResourceName=schema.xml}");
|
||||
}
|
||||
|
||||
public void testManagedSchemaCannotBeNamedSchemaDotXml() throws Exception {
|
||||
assertConfigs("bad-solrconfig-managed-schema-named-schema.xml.xml",
|
||||
"schema-minimal.xml", "managedSchemaResourceName can't be 'schema.xml'");
|
||||
}
|
||||
|
||||
public void testUnknownSchemaAttribute() throws Exception {
|
||||
assertConfigs("bad-solrconfig-unexpected-schema-attribute.xml", "schema-minimal.xml",
|
||||
"Unexpected arg(s): {bogusParam=bogusValue}");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ public class PrimitiveFieldTypeTest extends SolrTestCaseJ4 {
|
|||
// ***********************
|
||||
// With schema version 1.4:
|
||||
// ***********************
|
||||
schema = new IndexSchema(config, testConfHome + "schema12.xml", null);
|
||||
schema = IndexSchemaFactory.buildIndexSchema(testConfHome + "schema12.xml", config);
|
||||
|
||||
dt = new DateField();
|
||||
dt.init(schema, initMap);
|
||||
|
@ -130,7 +130,7 @@ public class PrimitiveFieldTypeTest extends SolrTestCaseJ4 {
|
|||
// ***********************
|
||||
// With schema version 1.5
|
||||
// ***********************
|
||||
schema = new IndexSchema(config, testConfHome + "schema15.xml", null);
|
||||
schema = IndexSchemaFactory.buildIndexSchema(testConfHome + "schema15.xml", config);
|
||||
|
||||
dt = new DateField();
|
||||
dt.init(schema, initMap);
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
package org.apache.solr.schema;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.solr.client.solrj.ResponseParser;
|
||||
import org.apache.solr.client.solrj.SolrServer;
|
||||
import org.apache.solr.client.solrj.SolrServerException;
|
||||
import org.apache.solr.client.solrj.impl.HttpSolrServer;
|
||||
import org.apache.solr.client.solrj.request.QueryRequest;
|
||||
import org.apache.solr.cloud.AbstractFullDistribZkTestBase;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.params.CoreAdminParams;
|
||||
import org.apache.solr.common.params.ModifiableSolrParams;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class TestCloudManagedSchema extends AbstractFullDistribZkTestBase {
|
||||
|
||||
public TestCloudManagedSchema() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCloudSolrConfig() {
|
||||
return "solrconfig-tlog-managed-schema.xml";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doTest() throws Exception {
|
||||
ModifiableSolrParams params = new ModifiableSolrParams();
|
||||
params.set(CoreAdminParams.ACTION, CoreAdminParams.CoreAdminAction.STATUS.toString());
|
||||
QueryRequest request = new QueryRequest(params);
|
||||
request.setPath("/admin/cores");
|
||||
int which = r.nextInt(clients.size());
|
||||
HttpSolrServer client = (HttpSolrServer)clients.get(which);
|
||||
String previousBaseURL = client.getBaseURL();
|
||||
// Strip /collection1 step from baseURL - requests fail otherwise
|
||||
client.setBaseURL(previousBaseURL.substring(0, previousBaseURL.lastIndexOf("/")));
|
||||
NamedList namedListResponse = client.request(request);
|
||||
client.setBaseURL(previousBaseURL); // Restore baseURL
|
||||
NamedList status = (NamedList)namedListResponse.get("status");
|
||||
NamedList collectionStatus = (NamedList)status.get("collection1");
|
||||
String collectionSchema = (String)collectionStatus.get(CoreAdminParams.SCHEMA);
|
||||
// Make sure the upgrade to managed schema happened
|
||||
assertEquals("Schema resource name differs from expected name", "managed-schema", collectionSchema);
|
||||
|
||||
// Make sure "DO NOT EDIT" is in the content of the managed schema
|
||||
String fileContent = getFileContentFromZooKeeper("managed-schema");
|
||||
assertTrue("Managed schema is missing", fileContent.contains("DO NOT EDIT"));
|
||||
|
||||
// Make sure the original non-managed schema is no longer in ZooKeeper
|
||||
assertFileNotInZooKeeper("schema.xml");
|
||||
|
||||
// Make sure the renamed non-managed schema is present in ZooKeeper
|
||||
fileContent = getFileContentFromZooKeeper("schema.xml.bak");
|
||||
assertTrue("schema file doesn't contain '<schema'", fileContent.contains("<schema"));
|
||||
}
|
||||
|
||||
private String getFileContentFromZooKeeper(String fileName) throws IOException, SolrServerException {
|
||||
QueryRequest request = new QueryRequest(params("file", fileName));
|
||||
request.setPath("/admin/file");
|
||||
RawResponseParser responseParser = new RawResponseParser();
|
||||
request.setResponseParser(responseParser);
|
||||
int which = r.nextInt(clients.size());
|
||||
// For some reason, /admin/file requests work without stripping the /collection1 step from the URL
|
||||
// (unlike /admin/cores requests - see above)
|
||||
SolrServer client = clients.get(which);
|
||||
client.request(request);
|
||||
return responseParser.getRawFileContent();
|
||||
}
|
||||
|
||||
private class RawResponseParser extends ResponseParser {
|
||||
// Stolen from ShowFileRequestHandlerTest
|
||||
private String rawFileContent = null;
|
||||
String getRawFileContent() { return rawFileContent; }
|
||||
@Override
|
||||
public String getWriterType() {
|
||||
return "mock";//unfortunately this gets put onto params wt=mock but it apparently has no effect
|
||||
}
|
||||
@Override
|
||||
public NamedList<Object> processResponse(InputStream body, String encoding) {
|
||||
try {
|
||||
rawFileContent = IOUtils.toString(body, encoding);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public NamedList<Object> processResponse(Reader reader) {
|
||||
throw new UnsupportedOperationException("TODO unimplemented");//TODO
|
||||
}
|
||||
}
|
||||
|
||||
protected final void assertFileNotInZooKeeper(String fileName) throws Exception {
|
||||
// Stolen from AbstractBadConfigTestBase
|
||||
String errString = "returned non ok status:404, message:Not Found";
|
||||
ignoreException(Pattern.quote(errString));
|
||||
String rawContent = null;
|
||||
try {
|
||||
rawContent = getFileContentFromZooKeeper(fileName);
|
||||
} catch (Exception e) {
|
||||
// short circuit out if we found what we expected
|
||||
if (-1 != e.getMessage().indexOf(errString)) return;
|
||||
// otherwise, rethrow it, possibly completely unrelated
|
||||
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
|
||||
"Unexpected error, expected error matching: " + errString, e);
|
||||
} finally {
|
||||
resetExceptionIgnores();
|
||||
}
|
||||
fail("File '" + fileName + "' was unexpectedly found in ZooKeeper. Content starts with '"
|
||||
+ rawContent.substring(0, 100) + " [...]'");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
package org.apache.solr.schema;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.solr.common.params.CoreAdminParams;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.core.AbstractBadConfigTestBase;
|
||||
import org.apache.solr.core.CoreContainer;
|
||||
import org.apache.solr.handler.admin.CoreAdminHandler;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.response.SolrQueryResponse;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
public class TestManagedSchema extends AbstractBadConfigTestBase {
|
||||
|
||||
private static File tmpSolrHome;
|
||||
private static File tmpConfDir;
|
||||
|
||||
private static final String collection = "collection1";
|
||||
private static final String confDir = collection + "/conf";
|
||||
|
||||
@Before
|
||||
private void initManagedSchemaCore() throws Exception {
|
||||
createTempDir();
|
||||
final String tmpSolrHomePath
|
||||
= TEMP_DIR + File.separator + TestManagedSchema.class.getSimpleName() + System.currentTimeMillis();
|
||||
tmpSolrHome = new File(tmpSolrHomePath).getAbsoluteFile();
|
||||
tmpConfDir = new File(tmpSolrHome, confDir);
|
||||
File testHomeConfDir = new File(TEST_HOME(), confDir);
|
||||
FileUtils.copyFileToDirectory(new File(testHomeConfDir, "solrconfig-managed-schema.xml"), tmpConfDir);
|
||||
FileUtils.copyFileToDirectory(new File(testHomeConfDir, "solrconfig-basic.xml"), tmpConfDir);
|
||||
FileUtils.copyFileToDirectory(new File(testHomeConfDir, "schema-minimal.xml"), tmpConfDir);
|
||||
// initCore will trigger an upgrade to managed schema, since the solrconfig has
|
||||
// <schemaFactory class="ManagedIndexSchemaFactory" ... />
|
||||
initCore("solrconfig-managed-schema.xml", "schema-minimal.xml", tmpSolrHome.getPath());
|
||||
}
|
||||
|
||||
@After
|
||||
private void deleteCoreAndTempSolrHomeDirectory() throws Exception {
|
||||
deleteCore();
|
||||
FileUtils.deleteDirectory(tmpSolrHome);
|
||||
}
|
||||
|
||||
public void testUpgrade() throws Exception {
|
||||
File managedSchemaFile = new File(tmpConfDir, "managed-schema");
|
||||
assertTrue(managedSchemaFile.exists());
|
||||
String managedSchema = FileUtils.readFileToString(managedSchemaFile, "UTF-8");
|
||||
assertTrue(managedSchema.contains("DO NOT EDIT"));
|
||||
File upgradedOriginalSchemaFile = new File(tmpConfDir, "schema-minimal.xml.bak");
|
||||
assertTrue(upgradedOriginalSchemaFile.exists());
|
||||
assertSchemaResource(collection, "managed-schema");
|
||||
}
|
||||
|
||||
public void testUpgradeThenRestart() throws Exception {
|
||||
assertSchemaResource(collection, "managed-schema");
|
||||
deleteCore();
|
||||
File nonManagedSchemaFile = new File(tmpConfDir, "schema-minimal.xml");
|
||||
assertFalse(nonManagedSchemaFile.exists());
|
||||
initCore("solrconfig-managed-schema.xml", "schema-minimal.xml", tmpSolrHome.getPath());
|
||||
File managedSchemaFile = new File(tmpConfDir, "managed-schema");
|
||||
assertTrue(managedSchemaFile.exists());
|
||||
String managedSchema = FileUtils.readFileToString(managedSchemaFile, "UTF-8");
|
||||
assertTrue(managedSchema.contains("DO NOT EDIT"));
|
||||
File upgradedOriginalSchemaFile = new File(tmpConfDir, "schema-minimal.xml.bak");
|
||||
assertTrue(upgradedOriginalSchemaFile.exists());
|
||||
assertSchemaResource(collection, "managed-schema");
|
||||
}
|
||||
|
||||
public void testUpgradeThenRestartNonManaged() throws Exception {
|
||||
deleteCore();
|
||||
// After upgrade to managed schema, fail to restart when solrconfig doesn't contain
|
||||
// <schemaFactory class="ManagedIndexSchemaFactory">...</schemaFactory>
|
||||
assertConfigs("solrconfig-basic.xml", "schema-minimal.xml", tmpSolrHome.getPath(),
|
||||
"Can't find resource 'schema-minimal.xml'");
|
||||
}
|
||||
|
||||
public void testUpgradeThenRestartNonManagedAfterPuttingBackNonManagedSchema() throws Exception {
|
||||
assertSchemaResource(collection, "managed-schema");
|
||||
deleteCore();
|
||||
File nonManagedSchemaFile = new File(tmpConfDir, "schema-minimal.xml");
|
||||
assertFalse(nonManagedSchemaFile.exists());
|
||||
File upgradedOriginalSchemaFile = new File(tmpConfDir, "schema-minimal.xml.bak");
|
||||
assertTrue(upgradedOriginalSchemaFile.exists());
|
||||
|
||||
// After upgrade to managed schema, downgrading to non-managed should work after putting back the non-managed schema.
|
||||
FileUtils.moveFile(upgradedOriginalSchemaFile, nonManagedSchemaFile);
|
||||
initCore("solrconfig-basic.xml", "schema-minimal.xml", tmpSolrHome.getPath());
|
||||
assertSchemaResource(collection, "schema-minimal.xml");
|
||||
}
|
||||
|
||||
private void assertSchemaResource(String collection, String expectedSchemaResource) throws Exception {
|
||||
final CoreContainer cores = h.getCoreContainer();
|
||||
cores.setPersistent(false);
|
||||
final CoreAdminHandler admin = new CoreAdminHandler(cores);
|
||||
SolrQueryRequest request = req(CoreAdminParams.ACTION, CoreAdminParams.CoreAdminAction.STATUS.toString());
|
||||
SolrQueryResponse response = new SolrQueryResponse();
|
||||
admin.handleRequestBody(request, response);
|
||||
assertNull("Exception on create", response.getException());
|
||||
NamedList responseValues = response.getValues();
|
||||
NamedList status = (NamedList)responseValues.get("status");
|
||||
NamedList collectionStatus = (NamedList)status.get(collection);
|
||||
String collectionSchema = (String)collectionStatus.get(CoreAdminParams.SCHEMA);
|
||||
assertEquals("Schema resource name differs from expected name", expectedSchemaResource, collectionSchema);
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@ import java.io.File;
|
|||
import org.apache.solr.SolrTestCaseJ4;
|
||||
import org.apache.solr.core.SolrConfig;
|
||||
import org.apache.solr.schema.IndexSchema;
|
||||
import org.apache.solr.schema.IndexSchemaFactory;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
|
@ -34,7 +35,7 @@ public class SolrIndexConfigTest extends SolrTestCaseJ4 {
|
|||
try {
|
||||
SolrConfig solrConfig = new SolrConfig("bad-mp-solrconfig.xml");
|
||||
SolrIndexConfig solrIndexConfig = new SolrIndexConfig(solrConfig, null, null);
|
||||
IndexSchema indexSchema = new IndexSchema(solrConfig, "schema.xml", null);
|
||||
IndexSchema indexSchema = IndexSchemaFactory.buildIndexSchema("schema.xml", solrConfig);
|
||||
solrIndexConfig.toIndexWriterConfig(indexSchema);
|
||||
fail("a mergePolicy should have an empty constructor in order to be instantiated in Solr thus this should fail ");
|
||||
} catch (Exception e) {
|
||||
|
@ -51,7 +52,7 @@ public class SolrIndexConfigTest extends SolrTestCaseJ4 {
|
|||
assertNotNull(solrIndexConfig);
|
||||
assertEquals("org.apache.lucene.index.TieredMergePolicy",
|
||||
solrIndexConfig.defaultMergePolicyClassName);
|
||||
IndexSchema indexSchema = new IndexSchema(solrConfig, "schema.xml", null);
|
||||
IndexSchema indexSchema = IndexSchemaFactory.buildIndexSchema("schema.xml", solrConfig);
|
||||
solrIndexConfig.toIndexWriterConfig(indexSchema);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,28 @@
|
|||
|
||||
<lib dir="../../../../dist/" regex="solr-dataimporthandler-.*\.jar" />
|
||||
|
||||
<!-- To enable dynamic schema REST APIs, use the following for <schemaFactory>:
|
||||
|
||||
<schemaFactory class="ManagedIndexSchemaFactory">
|
||||
<bool name="mutable">true</bool>
|
||||
<str name="managedSchemaResourceName">managed-schema</str>
|
||||
</schemaFactory>
|
||||
|
||||
When ManagedIndexSchemaFactory is specified, Solr will load the schema from
|
||||
he resource named in 'managedSchemaResourceName', rather than from schema.xml.
|
||||
Note that the managed schema resource CANNOT be named schema.xml. If the managed
|
||||
schema does not exist, Solr will create it after reading schema.xml, then rename
|
||||
'schema.xml' to 'schema.xml.bak'.
|
||||
|
||||
Do NOT hand edit the managed schema - external modifications will be ignored and
|
||||
overwritten as a result of schema modification REST API calls.
|
||||
|
||||
When ManagedIndexSchemaFactory is specified with mutable = true, schema
|
||||
modification REST API calls will be allowed; otherwise, error responses will be
|
||||
sent back for these requests.
|
||||
-->
|
||||
<schemaFactory class="ClassicIndexSchemaFactory"/>
|
||||
|
||||
<!-- <indexConfig> section could go here, but we want the defaults -->
|
||||
|
||||
<!-- the default high-performance update handler -->
|
||||
|
|
|
@ -52,6 +52,28 @@
|
|||
-->
|
||||
<jmx />
|
||||
|
||||
<!-- To enable dynamic schema REST APIs, use the following for <schemaFactory>:
|
||||
|
||||
<schemaFactory class="ManagedIndexSchemaFactory">
|
||||
<bool name="mutable">true</bool>
|
||||
<str name="managedSchemaResourceName">managed-schema</str>
|
||||
</schemaFactory>
|
||||
|
||||
When ManagedIndexSchemaFactory is specified, Solr will load the schema from
|
||||
he resource named in 'managedSchemaResourceName', rather than from schema.xml.
|
||||
Note that the managed schema resource CANNOT be named schema.xml. If the managed
|
||||
schema does not exist, Solr will create it after reading schema.xml, then rename
|
||||
'schema.xml' to 'schema.xml.bak'.
|
||||
|
||||
Do NOT hand edit the managed schema - external modifications will be ignored and
|
||||
overwritten as a result of schema modification REST API calls.
|
||||
|
||||
When ManagedIndexSchemaFactory is specified with mutable = true, schema
|
||||
modification REST API calls will be allowed; otherwise, error responses will be
|
||||
sent back for these requests.
|
||||
-->
|
||||
<schemaFactory class="ClassicIndexSchemaFactory"/>
|
||||
|
||||
<!-- the default high-performance update handler -->
|
||||
<updateHandler class="solr.DirectUpdateHandler2">
|
||||
|
||||
|
|
|
@ -30,6 +30,28 @@
|
|||
|
||||
<lib dir="../../../../dist/" regex="solr-dataimporthandler-.*\.jar" />
|
||||
|
||||
<!-- To enable dynamic schema REST APIs, use the following for <schemaFactory>:
|
||||
|
||||
<schemaFactory class="ManagedIndexSchemaFactory">
|
||||
<bool name="mutable">true</bool>
|
||||
<str name="managedSchemaResourceName">managed-schema</str>
|
||||
</schemaFactory>
|
||||
|
||||
When ManagedIndexSchemaFactory is specified, Solr will load the schema from
|
||||
he resource named in 'managedSchemaResourceName', rather than from schema.xml.
|
||||
Note that the managed schema resource CANNOT be named schema.xml. If the managed
|
||||
schema does not exist, Solr will create it after reading schema.xml, then rename
|
||||
'schema.xml' to 'schema.xml.bak'.
|
||||
|
||||
Do NOT hand edit the managed schema - external modifications will be ignored and
|
||||
overwritten as a result of schema modification REST API calls.
|
||||
|
||||
When ManagedIndexSchemaFactory is specified with mutable = true, schema
|
||||
modification REST API calls will be allowed; otherwise, error responses will be
|
||||
sent back for these requests.
|
||||
-->
|
||||
<schemaFactory class="ClassicIndexSchemaFactory"/>
|
||||
|
||||
<!-- <indexConfig> section could go here, but we want the defaults -->
|
||||
|
||||
<!-- the default high-performance update handler -->
|
||||
|
|
|
@ -30,6 +30,28 @@
|
|||
|
||||
<lib dir="../../../../dist/" regex="solr-dataimporthandler-.*\.jar" />
|
||||
|
||||
<!-- To enable dynamic schema REST APIs, use the following for <schemaFactory>:
|
||||
|
||||
<schemaFactory class="ManagedIndexSchemaFactory">
|
||||
<bool name="mutable">true</bool>
|
||||
<str name="managedSchemaResourceName">managed-schema</str>
|
||||
</schemaFactory>
|
||||
|
||||
When ManagedIndexSchemaFactory is specified, Solr will load the schema from
|
||||
he resource named in 'managedSchemaResourceName', rather than from schema.xml.
|
||||
Note that the managed schema resource CANNOT be named schema.xml. If the managed
|
||||
schema does not exist, Solr will create it after reading schema.xml, then rename
|
||||
'schema.xml' to 'schema.xml.bak'.
|
||||
|
||||
Do NOT hand edit the managed schema - external modifications will be ignored and
|
||||
overwritten as a result of schema modification REST API calls.
|
||||
|
||||
When ManagedIndexSchemaFactory is specified with mutable = true, schema
|
||||
modification REST API calls will be allowed; otherwise, error responses will be
|
||||
sent back for these requests.
|
||||
-->
|
||||
<schemaFactory class="ClassicIndexSchemaFactory"/>
|
||||
|
||||
<!-- <indexConfig> section could go here, but we want the defaults -->
|
||||
|
||||
<!-- the default high-performance update handler -->
|
||||
|
|
|
@ -36,6 +36,28 @@
|
|||
<lib dir="../../../../contrib/dataimporthandler/lib/" regex=".*jar$" />
|
||||
<lib dir="../../../../dist/" regex="solr-dataimporthandler-.*\.jar" />
|
||||
|
||||
<!-- To enable dynamic schema REST APIs, use the following for <schemaFactory>:
|
||||
|
||||
<schemaFactory class="ManagedIndexSchemaFactory">
|
||||
<bool name="mutable">true</bool>
|
||||
<str name="managedSchemaResourceName">managed-schema</str>
|
||||
</schemaFactory>
|
||||
|
||||
When ManagedIndexSchemaFactory is specified, Solr will load the schema from
|
||||
he resource named in 'managedSchemaResourceName', rather than from schema.xml.
|
||||
Note that the managed schema resource CANNOT be named schema.xml. If the managed
|
||||
schema does not exist, Solr will create it after reading schema.xml, then rename
|
||||
'schema.xml' to 'schema.xml.bak'.
|
||||
|
||||
Do NOT hand edit the managed schema - external modifications will be ignored and
|
||||
overwritten as a result of schema modification REST API calls.
|
||||
|
||||
When ManagedIndexSchemaFactory is specified with mutable = true, schema
|
||||
modification REST API calls will be allowed; otherwise, error responses will be
|
||||
sent back for these requests.
|
||||
-->
|
||||
<schemaFactory class="ClassicIndexSchemaFactory"/>
|
||||
|
||||
<!-- <indexConfig> section could go here, but we want the defaults -->
|
||||
|
||||
<!-- the default high-performance update handler -->
|
||||
|
|
|
@ -29,6 +29,28 @@
|
|||
|
||||
<dataDir>${solr.core0.data.dir:}</dataDir>
|
||||
|
||||
<!-- To enable dynamic schema REST APIs, use the following for <schemaFactory>:
|
||||
|
||||
<schemaFactory class="ManagedIndexSchemaFactory">
|
||||
<bool name="mutable">true</bool>
|
||||
<str name="managedSchemaResourceName">managed-schema</str>
|
||||
</schemaFactory>
|
||||
|
||||
When ManagedIndexSchemaFactory is specified, Solr will load the schema from
|
||||
he resource named in 'managedSchemaResourceName', rather than from schema.xml.
|
||||
Note that the managed schema resource CANNOT be named schema.xml. If the managed
|
||||
schema does not exist, Solr will create it after reading schema.xml, then rename
|
||||
'schema.xml' to 'schema.xml.bak'.
|
||||
|
||||
Do NOT hand edit the managed schema - external modifications will be ignored and
|
||||
overwritten as a result of schema modification REST API calls.
|
||||
|
||||
When ManagedIndexSchemaFactory is specified with mutable = true, schema
|
||||
modification REST API calls will be allowed; otherwise, error responses will be
|
||||
sent back for these requests.
|
||||
-->
|
||||
<schemaFactory class="ClassicIndexSchemaFactory"/>
|
||||
|
||||
<updateHandler class="solr.DirectUpdateHandler2">
|
||||
<updateLog>
|
||||
<str name="dir">${solr.core0.data.dir:}</str>
|
||||
|
|
|
@ -29,6 +29,28 @@
|
|||
|
||||
<dataDir>${solr.core1.data.dir:}</dataDir>
|
||||
|
||||
<!-- To enable dynamic schema REST APIs, use the following for <schemaFactory>:
|
||||
|
||||
<schemaFactory class="ManagedIndexSchemaFactory">
|
||||
<bool name="mutable">true</bool>
|
||||
<str name="managedSchemaResourceName">managed-schema</str>
|
||||
</schemaFactory>
|
||||
|
||||
When ManagedIndexSchemaFactory is specified, Solr will load the schema from
|
||||
he resource named in 'managedSchemaResourceName', rather than from schema.xml.
|
||||
Note that the managed schema resource CANNOT be named schema.xml. If the managed
|
||||
schema does not exist, Solr will create it after reading schema.xml, then rename
|
||||
'schema.xml' to 'schema.xml.bak'.
|
||||
|
||||
Do NOT hand edit the managed schema - external modifications will be ignored and
|
||||
overwritten as a result of schema modification REST API calls.
|
||||
|
||||
When ManagedIndexSchemaFactory is specified with mutable = true, schema
|
||||
modification REST API calls will be allowed; otherwise, error responses will be
|
||||
sent back for these requests.
|
||||
-->
|
||||
<schemaFactory class="ClassicIndexSchemaFactory"/>
|
||||
|
||||
<updateHandler class="solr.DirectUpdateHandler2">
|
||||
<updateLog>
|
||||
<str name="dir">${solr.core1.data.dir:}</str>
|
||||
|
|
|
@ -132,6 +132,28 @@
|
|||
-->
|
||||
<codecFactory class="solr.SchemaCodecFactory"/>
|
||||
|
||||
<!-- To enable dynamic schema REST APIs, use the following for <schemaFactory>:
|
||||
|
||||
<schemaFactory class="ManagedIndexSchemaFactory">
|
||||
<bool name="mutable">true</bool>
|
||||
<str name="managedSchemaResourceName">managed-schema</str>
|
||||
</schemaFactory>
|
||||
|
||||
When ManagedIndexSchemaFactory is specified, Solr will load the schema from
|
||||
he resource named in 'managedSchemaResourceName', rather than from schema.xml.
|
||||
Note that the managed schema resource CANNOT be named schema.xml. If the managed
|
||||
schema does not exist, Solr will create it after reading schema.xml, then rename
|
||||
'schema.xml' to 'schema.xml.bak'.
|
||||
|
||||
Do NOT hand edit the managed schema - external modifications will be ignored and
|
||||
overwritten as a result of schema modification REST API calls.
|
||||
|
||||
When ManagedIndexSchemaFactory is specified with mutable = true, schema
|
||||
modification REST API calls will be allowed; otherwise, error responses will be
|
||||
sent back for these requests.
|
||||
-->
|
||||
<schemaFactory class="ClassicIndexSchemaFactory"/>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Index Config - These settings control low-level behavior of indexing
|
||||
Most example settings here show the default value, but are commented
|
||||
|
@ -1709,6 +1731,7 @@
|
|||
<queryResponseWriter name="php" class="solr.PHPResponseWriter"/>
|
||||
<queryResponseWriter name="phps" class="solr.PHPSerializedResponseWriter"/>
|
||||
<queryResponseWriter name="csv" class="solr.CSVResponseWriter"/>
|
||||
<queryResponseWriter name="schema.xml" class="solr.SchemaXmlResponseWriter"/>
|
||||
-->
|
||||
|
||||
<queryResponseWriter name="json" class="solr.JSONResponseWriter">
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.apache.solr.request.SolrRequestInfo;
|
|||
import org.apache.solr.response.QueryResponseWriter;
|
||||
import org.apache.solr.response.SolrQueryResponse;
|
||||
import org.apache.solr.schema.IndexSchema;
|
||||
import org.apache.solr.schema.IndexSchemaFactory;
|
||||
import org.apache.solr.servlet.DirectSolrConnection;
|
||||
import org.apache.solr.common.util.NamedList.NamedListEntry;
|
||||
|
||||
|
@ -97,7 +98,7 @@ public class TestHarness extends BaseTestHarness {
|
|||
String dataDirectory,
|
||||
SolrConfig solrConfig,
|
||||
String schemaFile) {
|
||||
this( coreName, dataDirectory, solrConfig, new IndexSchema(solrConfig, schemaFile, null));
|
||||
this( coreName, dataDirectory, solrConfig, IndexSchemaFactory.buildIndexSchema(schemaFile, solrConfig));
|
||||
}
|
||||
/**
|
||||
* @param coreName to initialize
|
||||
|
@ -119,7 +120,7 @@ public class TestHarness extends BaseTestHarness {
|
|||
public TestHarness( String dataDirectory,
|
||||
SolrConfig solrConfig,
|
||||
String schemaFile) {
|
||||
this( dataDirectory, solrConfig, new IndexSchema(solrConfig, schemaFile, null));
|
||||
this( dataDirectory, solrConfig, IndexSchemaFactory.buildIndexSchema(schemaFile, solrConfig));
|
||||
}
|
||||
/**
|
||||
* @param dataDirectory path for index data, will not be cleaned up
|
||||
|
|
Loading…
Reference in New Issue