// load up the elevation map
  private Map<String, ElevationObj> loadElevationMap(Config cfg) throws IOException {
    XPath xpath = XPathFactory.newInstance().newXPath();
    Map<String, ElevationObj> map = new HashMap<String, ElevationObj>();
    NodeList nodes = (NodeList) cfg.evaluate("elevate/query", XPathConstants.NODESET);
    for (int i = 0; i < nodes.getLength(); i++) {
      Node node = nodes.item(i);
      String qstr = DOMUtil.getAttr(node, "text", "missing query 'text'");

      NodeList children = null;
      try {
        children = (NodeList) xpath.evaluate("doc", node, XPathConstants.NODESET);
      } catch (XPathExpressionException e) {
        throw new SolrException(
            SolrException.ErrorCode.SERVER_ERROR, "query requires '<doc .../>' child");
      }

      ArrayList<String> include = new ArrayList<String>();
      ArrayList<String> exclude = new ArrayList<String>();
      for (int j = 0; j < children.getLength(); j++) {
        Node child = children.item(j);
        String id = DOMUtil.getAttr(child, "id", "missing 'id'");
        String e = DOMUtil.getAttr(child, EXCLUDE, null);
        if (e != null) {
          if (Boolean.valueOf(e)) {
            exclude.add(id);
            continue;
          }
        }
        include.add(id);
      }

      ElevationObj elev = new ElevationObj(qstr, include, exclude);
      if (map.containsKey(elev.analyzed)) {
        throw new SolrException(
            SolrException.ErrorCode.SERVER_ERROR,
            "Boosting query defined twice for query: '" + elev.text + "' (" + elev.analyzed + "')");
      }
      map.put(elev.analyzed, elev);
    }
    return map;
  }
Beispiel #2
0
  //
  // <analyzer><tokenizer class="...."/><tokenizer class="...." arg="....">
  //
  //
  private Analyzer readAnalyzer(final Node node) throws XPathExpressionException {
    // parent node used to be passed in as "fieldtype"
    // if (!fieldtype.hasChildNodes()) return null;
    // Node node = DOMUtil.getChild(fieldtype,"analyzer");

    if (node == null) return null;
    final NamedNodeMap attrs = node.getAttributes();
    final String analyzerName = DOMUtil.getAttr(attrs, "class");
    if (analyzerName != null) {
      // No need to be core-aware as Analyzers are not in the core-aware list
      final Class<? extends Analyzer> clazz =
          loader.findClass(analyzerName).asSubclass(Analyzer.class);
      try {
        try {
          // first try to use a ctor with version parameter (needed for many new Analyzers that have
          // no default one anymore)
          final Constructor<? extends Analyzer> cnstr = clazz.getConstructor(Version.class);
          final String matchVersionStr = DOMUtil.getAttr(attrs, LUCENE_MATCH_VERSION_PARAM);
          final Version luceneMatchVersion =
              (matchVersionStr == null)
                  ? this.luceneMatchVersion
                  : Config.parseLuceneVersionString(matchVersionStr);
          if (luceneMatchVersion == null) {
            throw new SolrException(
                SolrException.ErrorCode.SERVER_ERROR,
                "Configuration Error: Analyzer '"
                    + clazz.getName()
                    + "' needs a 'luceneMatchVersion' parameter");
          }
          return cnstr.newInstance(luceneMatchVersion);
        } catch (final NoSuchMethodException nsme) {
          // otherwise use default ctor
          return clazz.newInstance();
        }
      } catch (final Exception e) {
        throw new SolrException(
            SolrException.ErrorCode.SERVER_ERROR, "Cannot load analyzer: " + analyzerName);
      }
    }

    final XPath xpath = XPathFactory.newInstance().newXPath();

    // Load the CharFilters
    // --------------------------------------------------------------------------------
    final ArrayList<CharFilterFactory> charFilters = new ArrayList<CharFilterFactory>();
    final AbstractPluginLoader<CharFilterFactory> charFilterLoader =
        new AbstractPluginLoader<CharFilterFactory>(
            "[schema.xml] analyzer/charFilter", false, false) {
          @Override
          protected void init(final CharFilterFactory plugin, final Node node) throws Exception {
            if (plugin != null) {
              final Map<String, String> params = DOMUtil.toMapExcept(node.getAttributes(), "class");
              // copy the luceneMatchVersion from config, if not set
              if (!params.containsKey(LUCENE_MATCH_VERSION_PARAM))
                params.put(LUCENE_MATCH_VERSION_PARAM, luceneMatchVersion.toString());
              plugin.init(params);
              charFilters.add(plugin);
            }
          }

          @Override
          protected CharFilterFactory register(final String name, final CharFilterFactory plugin)
              throws Exception {
            return null; // used for map registration
          }
        };
    charFilterLoader.load(
        loader, (NodeList) xpath.evaluate("./charFilter", node, XPathConstants.NODESET));

    // Load the Tokenizer
    // Although an analyzer only allows a single Tokenizer, we load a list to make sure
    // the configuration is ok
    // --------------------------------------------------------------------------------
    final ArrayList<TokenizerFactory> tokenizers = new ArrayList<TokenizerFactory>(1);
    final AbstractPluginLoader<TokenizerFactory> tokenizerLoader =
        new AbstractPluginLoader<TokenizerFactory>(
            "[schema.xml] analyzer/tokenizer", false, false) {
          @Override
          protected void init(final TokenizerFactory plugin, final Node node) throws Exception {
            if (!tokenizers.isEmpty()) {
              throw new SolrException(
                  SolrException.ErrorCode.SERVER_ERROR,
                  "The schema defines multiple tokenizers for: " + node);
            }
            final Map<String, String> params = DOMUtil.toMapExcept(node.getAttributes(), "class");
            // copy the luceneMatchVersion from config, if not set
            if (!params.containsKey(LUCENE_MATCH_VERSION_PARAM))
              params.put(LUCENE_MATCH_VERSION_PARAM, luceneMatchVersion.toString());
            plugin.init(params);
            tokenizers.add(plugin);
          }

          @Override
          protected TokenizerFactory register(final String name, final TokenizerFactory plugin)
              throws Exception {
            return null; // used for map registration
          }
        };
    tokenizerLoader.load(
        loader, (NodeList) xpath.evaluate("./tokenizer", node, XPathConstants.NODESET));

    // Make sure something was loaded
    if (tokenizers.isEmpty()) {
      throw new SolrException(
          SolrException.ErrorCode.SERVER_ERROR,
          "analyzer without class or tokenizer & filter list");
    }

    // Load the Filters
    // --------------------------------------------------------------------------------
    final ArrayList<TokenFilterFactory> filters = new ArrayList<TokenFilterFactory>();
    final AbstractPluginLoader<TokenFilterFactory> filterLoader =
        new AbstractPluginLoader<TokenFilterFactory>("[schema.xml] analyzer/filter", false, false) {
          @Override
          protected void init(final TokenFilterFactory plugin, final Node node) throws Exception {
            if (plugin != null) {
              final Map<String, String> params = DOMUtil.toMapExcept(node.getAttributes(), "class");
              // copy the luceneMatchVersion from config, if not set
              if (!params.containsKey(LUCENE_MATCH_VERSION_PARAM))
                params.put(LUCENE_MATCH_VERSION_PARAM, luceneMatchVersion.toString());
              plugin.init(params);
              filters.add(plugin);
            }
          }

          @Override
          protected TokenFilterFactory register(final String name, final TokenFilterFactory plugin)
              throws Exception {
            return null; // used for map registration
          }
        };
    filterLoader.load(loader, (NodeList) xpath.evaluate("./filter", node, XPathConstants.NODESET));

    return new TokenizerChain(
        charFilters.toArray(new CharFilterFactory[charFilters.size()]),
        tokenizers.get(0),
        filters.toArray(new TokenFilterFactory[filters.size()]));
  };
Beispiel #3
0
  private void readSchema(final InputStream is) {
    log.info("Reading Solr Schema");

    try {
      // pass the config resource loader to avoid building an empty one for no reason:
      // in the current case though, the stream is valid so we wont load the resource by name
      final Config schemaConf = new Config(loader, "schema", is, "/schema/");
      final Document document = schemaConf.getDocument();
      final XPath xpath = schemaConf.getXPath();
      final List<SchemaAware> schemaAware = new ArrayList<SchemaAware>();
      final Node nd = (Node) xpath.evaluate("/schema/@name", document, XPathConstants.NODE);
      if (nd == null) {
        log.warn("schema has no name!");
      } else {
        name = nd.getNodeValue();
        log.info("Schema name=" + name);
      }

      version = schemaConf.getFloat("/schema/@version", 1.0f);

      final AbstractPluginLoader<FieldType> fieldLoader =
          new AbstractPluginLoader<FieldType>("[schema.xml] fieldType", true, true) {

            @Override
            protected FieldType create(
                final ResourceLoader loader,
                final String name,
                final String className,
                final Node node)
                throws Exception {
              final FieldType ft = (FieldType) loader.newInstance(className);
              if (!(ft instanceof SubTextField)) {
                throw new SolrException(ErrorCode.FORBIDDEN, "Subschema must use SubTextField");
              }
              ((SubTextField) ft).setTypeName(name);

              String expression = "./analyzer[@type='query']";
              Node anode = (Node) xpath.evaluate(expression, node, XPathConstants.NODE);
              Analyzer queryAnalyzer = SubIndexSchema.this.readAnalyzer(anode);

              // An analyzer without a type specified, or with type="index"
              expression = "./analyzer[not(@type)] | ./analyzer[@type='index']";
              anode = (Node) xpath.evaluate(expression, node, XPathConstants.NODE);
              Analyzer analyzer = SubIndexSchema.this.readAnalyzer(anode);

              if (queryAnalyzer == null) queryAnalyzer = analyzer;
              if (analyzer == null) analyzer = queryAnalyzer;
              if (analyzer != null) {
                ft.setAnalyzer(analyzer);
                ft.setQueryAnalyzer(queryAnalyzer);
              }
              return ft;
            }

            @Override
            protected void init(final FieldType plugin, final Node node) throws Exception {}

            @Override
            protected FieldType register(final String name, final FieldType plugin)
                throws Exception {
              log.trace("fieldtype defined: " + plugin);
              return fieldTypes.put(name, plugin);
            }
          };

      final String expression = "/schema/types/fieldtype | /schema/types/fieldType";
      final NodeList nodes =
          (NodeList) xpath.evaluate(expression, document, XPathConstants.NODESET);
      fieldLoader.load(loader, nodes);
    } catch (final SolrException e) {
      SolrConfig.severeErrors.add(e);
      throw e;
    } catch (final Exception e) {
      // unexpected exception...
      SolrConfig.severeErrors.add(e);
      throw new SolrException(
          SolrException.ErrorCode.SERVER_ERROR, "Schema Parsing Failed", e, false);
    }
  }