org.apache.solr.core.RequestHandlers.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.solr.core.RequestHandlers.java

Source

/*
 * 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 java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.solr.common.util.StrUtils;
import org.apache.solr.request.SolrRequestHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 */
public final class RequestHandlers {
    private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

    protected final SolrCore core;

    final PluginBag<SolrRequestHandler> handlers;

    /**
     * Trim the trailing '/' if it's there, and convert null to empty string.
     * 
     * we want:
     *  /update/csv   and
     *  /update/csv/
     * to map to the same handler 
     * 
     */
    public static String normalize(String p) {
        if (p == null)
            return "";
        if (p.endsWith("/") && p.length() > 1)
            return p.substring(0, p.length() - 1);

        return p;
    }

    public RequestHandlers(SolrCore core) {
        this.core = core;
        // we need a thread safe registry since methods like register are currently documented to be thread safe.
        handlers = new PluginBag<>(SolrRequestHandler.class, core, true);
    }

    /**
     * @return the RequestHandler registered at the given name 
     */
    public SolrRequestHandler get(String handlerName) {
        return handlers.get(normalize(handlerName));
    }

    /**
     * Handlers must be initialized before calling this function.  As soon as this is
     * called, the handler can immediately accept requests.
     * 
     * This call is thread safe.
     * 
     * @return the previous handler at the given path or null
     */
    public SolrRequestHandler register(String handlerName, SolrRequestHandler handler) {
        String norm = normalize(handlerName);
        if (handler == null) {
            return handlers.remove(norm);
        }
        return handlers.put(norm, handler);
        //    return register(handlerName, new PluginRegistry.PluginHolder<>(null, handler));
    }

    /**
     * Returns an unmodifiable Map containing the registered handlers
     */
    public PluginBag<SolrRequestHandler> getRequestHandlers() {
        return handlers;
    }

    /**
     * Read solrconfig.xml and register the appropriate handlers
     * 
     * This function should <b>only</b> be called from the SolrCore constructor.  It is
     * not intended as a public API.
     * 
     * While the normal runtime registration contract is that handlers MUST be initialized
     * before they are registered, this function does not do that exactly.
     *
     * This function registers all handlers first and then calls init() for each one.
     *
     * This is OK because this function is only called at startup and there is no chance that
     * a handler could be asked to handle a request before it is initialized.
     * 
     * The advantage to this approach is that handlers can know what path they are registered
     * to and what other handlers are available at startup.
     * 
     * Handlers will be registered and initialized in the order they appear in solrconfig.xml
     */

    void initHandlersFromConfig(SolrConfig config) {
        List<PluginInfo> implicits = core.getImplicitHandlers();
        // use link map so we iterate in the same order
        Map<String, PluginInfo> infoMap = new LinkedHashMap<>();
        //deduping implicit and explicit requesthandlers
        for (PluginInfo info : implicits)
            infoMap.put(info.name, info);
        for (PluginInfo info : config.getPluginInfos(SolrRequestHandler.class.getName()))
            infoMap.put(info.name, info);
        ArrayList<PluginInfo> infos = new ArrayList<>(infoMap.values());

        List<PluginInfo> modifiedInfos = new ArrayList<>();
        for (PluginInfo info : infos) {
            modifiedInfos.add(applyInitParams(config, info));
        }
        handlers.init(Collections.emptyMap(), core, modifiedInfos);
        handlers.alias(handlers.getDefault(), "");
        log.debug("Registered paths: {}", StrUtils.join(new ArrayList<>(handlers.keySet()), ','));
        if (handlers.get("") == null && !handlers.alias("/select", "")) {
            if (handlers.get("") == null && !handlers.alias("standard", "")) {
                log.warn("no default request handler is registered (either '/select' or 'standard')");
            }
        }
    }

    private PluginInfo applyInitParams(SolrConfig config, PluginInfo info) {
        List<InitParams> ags = new ArrayList<>();
        String p = info.attributes.get(InitParams.TYPE);
        if (p != null) {
            for (String arg : StrUtils.splitSmart(p, ',')) {
                if (config.getInitParams().containsKey(arg))
                    ags.add(config.getInitParams().get(arg));
                else
                    log.warn("INVALID paramSet {} in requestHandler {}", arg, info.toString());
            }
        }
        for (InitParams args : config.getInitParams().values())
            if (args.matchPath(info.name))
                ags.add(args);
        if (!ags.isEmpty()) {
            info = info.copy();
            for (InitParams initParam : ags) {
                initParam.apply(info);
            }
        }
        return info;
    }

    public void close() {
        handlers.close();
    }
}