Java tutorial
/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.solr.core; import org.apache.lucene.util.Version; import org.apache.solr.common.SolrException; import org.apache.solr.common.util.DOMUtil; import org.apache.solr.common.util.SystemIdResolver; import org.apache.solr.common.util.XMLErrorLogger; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.apache.commons.io.IOUtils; import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.concurrent.atomic.AtomicBoolean; /** * @version $Id: Config.java 1075090 2011-02-27 17:20:30Z uschindler $ */ public class Config { public static final Logger log = LoggerFactory.getLogger(Config.class); private static final XMLErrorLogger xmllog = new XMLErrorLogger(log); static final XPathFactory xpathFactory = XPathFactory.newInstance(); private final Document doc; private final String prefix; private final String name; private final SolrResourceLoader loader; /** * @deprecated Use {@link #Config(SolrResourceLoader, String, InputSource, String)} instead. */ @Deprecated public Config(String name, InputStream is, String prefix) throws ParserConfigurationException, IOException, SAXException { this(null, name, new InputSource(is), prefix); } /** * Builds a config from a resource name with no xpath prefix. * @param loader * @param name * @throws javax.xml.parsers.ParserConfigurationException * @throws java.io.IOException * @throws org.xml.sax.SAXException */ public Config(SolrResourceLoader loader, String name) throws ParserConfigurationException, IOException, SAXException { this(loader, name, (InputSource) null, null); } /** * Builds a config: * <p> * Note that the 'name' parameter is used to obtain a valid input stream if no valid one is provided through 'is'. * If no valid stream is provided, a valid SolrResourceLoader instance should be provided through 'loader' so * the resource can be opened (@see SolrResourceLoader#openResource); if no SolrResourceLoader instance is provided, a default one * will be created. * </p> * <p> * Consider passing a non-null 'name' parameter in all use-cases since it is used for logging & exception reporting. * </p> * @param loader the resource loader used to obtain an input stream if 'is' is null * @param name the resource name used if the input stream 'is' is null * @param is the resource as a stream * @param prefix an optional prefix that will be preprended to all non-absolute xpath expressions * @throws javax.xml.parsers.ParserConfigurationException * @throws java.io.IOException * @throws org.xml.sax.SAXException * @deprecated Use {@link #Config(SolrResourceLoader, String, InputSource, String)} instead. */ @Deprecated public Config(SolrResourceLoader loader, String name, InputStream is, String prefix) throws ParserConfigurationException, IOException, SAXException { this(loader, name, (is == null) ? null : new InputSource(is), prefix); } /** * Builds a config: * <p> * Note that the 'name' parameter is used to obtain a valid input stream if no valid one is provided through 'is'. * If no valid stream is provided, a valid SolrResourceLoader instance should be provided through 'loader' so * the resource can be opened (@see SolrResourceLoader#openResource); if no SolrResourceLoader instance is provided, a default one * will be created. * </p> * <p> * Consider passing a non-null 'name' parameter in all use-cases since it is used for logging & exception reporting. * </p> * @param loader the resource loader used to obtain an input stream if 'is' is null * @param name the resource name used if the input stream 'is' is null * @param is the resource as a SAX InputSource * @param prefix an optional prefix that will be preprended to all non-absolute xpath expressions * @throws javax.xml.parsers.ParserConfigurationException * @throws java.io.IOException * @throws org.xml.sax.SAXException */ public Config(SolrResourceLoader loader, String name, InputSource is, String prefix) throws ParserConfigurationException, IOException, SAXException { if (loader == null) { loader = new SolrResourceLoader(null); } this.loader = loader; this.name = name; this.prefix = (prefix != null && !prefix.endsWith("/")) ? prefix + '/' : prefix; try { javax.xml.parsers.DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); if (is == null) { is = new InputSource(loader.openConfig(name)); is.setSystemId(SystemIdResolver.createSystemIdFromResourceName(name)); } // only enable xinclude, if a SystemId is available if (is.getSystemId() != null) { try { dbf.setXIncludeAware(true); dbf.setNamespaceAware(true); } catch (UnsupportedOperationException e) { log.warn(name + " XML parser doesn't support XInclude option"); } } final DocumentBuilder db = dbf.newDocumentBuilder(); db.setEntityResolver(new SystemIdResolver(loader)); db.setErrorHandler(xmllog); try { doc = db.parse(is); } finally { // some XML parsers are broken and don't close the byte stream (but they should according to spec) IOUtils.closeQuietly(is.getByteStream()); } DOMUtil.substituteProperties(doc, loader.getCoreProperties()); } catch (ParserConfigurationException e) { SolrException.log(log, "Exception during parsing file: " + name, e); throw e; } catch (SAXException e) { SolrException.log(log, "Exception during parsing file: " + name, e); throw e; } catch (SolrException e) { SolrException.log(log, "Error in " + name, e); throw e; } } /** * @since solr 1.3 */ public SolrResourceLoader getResourceLoader() { return loader; } /** * @since solr 1.3 */ public String getResourceName() { return name; } public String getName() { return name; } public Document getDocument() { return doc; } public XPath getXPath() { return xpathFactory.newXPath(); } private String normalize(String path) { return (prefix == null || path.startsWith("/")) ? path : prefix + path; } public Object evaluate(String path, QName type) { XPath xpath = xpathFactory.newXPath(); try { String xstr = normalize(path); // TODO: instead of prepending /prefix/, we could do the search rooted at /prefix... Object o = xpath.evaluate(xstr, doc, type); return o; } catch (XPathExpressionException e) { throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error in xpath:" + path + " for " + name, e, false); } } public Node getNode(String path, boolean errIfMissing) { XPath xpath = xpathFactory.newXPath(); Node nd = null; String xstr = normalize(path); try { nd = (Node) xpath.evaluate(xstr, doc, XPathConstants.NODE); if (nd == null) { if (errIfMissing) { throw new RuntimeException(name + " missing " + path); } else { log.debug(name + " missing optional " + path); return null; } } log.trace(name + ":" + path + "=" + nd); return nd; } catch (XPathExpressionException e) { SolrException.log(log, "Error in xpath", e); throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error in xpath:" + xstr + " for " + name, e, false); } 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, false); } } public String getVal(String path, boolean errIfMissing) { Node nd = getNode(path, errIfMissing); if (nd == null) return null; String txt = DOMUtil.getText(nd); log.debug(name + ' ' + path + '=' + txt); return txt; /****** short typ = nd.getNodeType(); if (typ==Node.ATTRIBUTE_NODE || typ==Node.TEXT_NODE) { return nd.getNodeValue(); } return nd.getTextContent(); ******/ } public String get(String path) { return getVal(path, true); } public String get(String path, String def) { String val = getVal(path, false); return val != null ? val : def; } public int getInt(String path) { return Integer.parseInt(getVal(path, true)); } public int getInt(String path, int def) { String val = getVal(path, false); return val != null ? Integer.parseInt(val) : def; } public boolean getBool(String path) { return Boolean.parseBoolean(getVal(path, true)); } public boolean getBool(String path, boolean def) { String val = getVal(path, false); return val != null ? Boolean.parseBoolean(val) : def; } public float getFloat(String path) { return Float.parseFloat(getVal(path, true)); } public float getFloat(String path, float def) { String val = getVal(path, false); return val != null ? Float.parseFloat(val) : def; } public double getDouble(String path) { return Double.parseDouble(getVal(path, true)); } public double getDouble(String path, double def) { String val = getVal(path, false); return val != null ? Double.parseDouble(val) : def; } public Version getLuceneVersion(String path) { return parseLuceneVersionString(getVal(path, true)); } public Version getLuceneVersion(String path, Version def) { String val = getVal(path, false); if (val == null) { if (!versionWarningAlreadyLogged.getAndSet(true)) { log.warn("the luceneMatchVersion is not specified, defaulting to " + def + " emulation. You should at some point declare and reindex to at least 3.0, " + "because 2.4 emulation is deprecated and will be removed in 4.0. " + "This parameter will be mandatory in 4.0."); } return def; } else { return parseLuceneVersionString(val); } } private static final AtomicBoolean versionWarningAlreadyLogged = new AtomicBoolean(false); public static final Version parseLuceneVersionString(final String matchVersion) { String parsedMatchVersion = matchVersion.toUpperCase(Locale.ENGLISH); // be lenient with the supplied version parameter parsedMatchVersion = parsedMatchVersion.replaceFirst("^(\\d)\\.(\\d)$", "LUCENE_$1$2"); final Version version; try { version = Version.valueOf(parsedMatchVersion); } catch (IllegalArgumentException iae) { throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Invalid luceneMatchVersion '" + matchVersion + "', valid values are: " + Arrays.toString(Version.values()) + " or a string in format 'V.V'", iae, false); } if (version == Version.LUCENE_CURRENT && !versionWarningAlreadyLogged.getAndSet(true)) { log.warn("You should not use LUCENE_CURRENT as luceneMatchVersion property: " + "if you use this setting, and then Solr upgrades to a newer release of Lucene, " + "sizable changes may happen. If precise back compatibility is important " + "then you should instead explicitly specify an actual Lucene version."); } return version; } // The following functions were moved to ResourceLoader //----------------------------------------------------------------------------- /** * @deprecated Use {@link SolrResourceLoader#getConfigDir()} instead. */ @Deprecated public String getConfigDir() { return loader.getConfigDir(); } /** * @deprecated Use {@link SolrResourceLoader#openResource(String)} instead. */ @Deprecated public InputStream openResource(String resource) { return loader.openResource(resource); } /** * @deprecated Use {@link SolrResourceLoader#getLines(String)} instead. */ @Deprecated public List<String> getLines(String resource) throws IOException { return loader.getLines(resource); } /** * @deprecated Use {@link SolrResourceLoader#findClass(String, String[])} instead. */ @Deprecated public Class findClass(String cname, String... subpackages) { return loader.findClass(cname, subpackages); } /** * @deprecated Use {@link SolrResourceLoader#newInstance(String, String[])} instead. */ @Deprecated public Object newInstance(String cname, String... subpackages) { return loader.newInstance(cname, subpackages); } /** * @deprecated Use {@link SolrResourceLoader#getInstanceDir()} instead. */ @Deprecated public String getInstanceDir() { return loader.getInstanceDir(); } }