Package io.crate.module

Source Code of io.crate.module.CrateCoreModule$SubclassOfMatcher

/*
* Licensed to CRATE Technology GmbH ("Crate") under one or more contributor
* license agreements.  See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.  Crate 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.
*
* However, if you have executed another commercial license agreement
* with Crate these terms will supersede the license and you may use the
* software solely pursuant to the terms of the relevant commercial agreement.
*/

package io.crate.module;

import com.google.common.util.concurrent.SettableFuture;
import io.crate.ClusterIdService;
import io.crate.Version;
import io.crate.core.CrateLoader;
import io.crate.rest.CrateRestMainAction;
import org.elasticsearch.common.inject.*;
import org.elasticsearch.common.inject.matcher.AbstractMatcher;
import org.elasticsearch.common.inject.spi.InjectionListener;
import org.elasticsearch.common.inject.spi.TypeEncounter;
import org.elasticsearch.common.inject.spi.TypeListener;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.action.main.RestMainAction;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static org.elasticsearch.common.inject.Modules.createModule;

public class CrateCoreModule extends AbstractModule implements SpawnModules, PreProcessModule {

    final ESLogger logger = Loggers.getLogger(getClass());
    private final CrateLoader crateLoader;
    private final Settings settings;

    public CrateCoreModule(Settings settings) {
        this.settings = settings;
        crateLoader = CrateLoader.getInstance(settings);
    }

    @Override
    protected void configure() {
        Version version = Version.CURRENT;
        logger.info("configuring crate. version: {}", version);

        bind(CrateLoader.class).toInstance(crateLoader);

        /**
         * This is a rather hacky method to overwrite the handler for "/"
         * The ES plugins are loaded before the core ES components. That means that the registration for
         * "/" in {@link CrateRestMainAction} is overwritten once {@link RestMainAction} is instantiated.
         *
         * By using a listener that is called after {@link RestMainAction} is instantiated we can call
         * {@link io.crate.rest.CrateRestMainAction#registerHandler()}  and overwrite it "back".
         */

        // the crateListener is used to retrieve the CrateRestMainAction instance.
        // otherwise there is no way to retrieve it at this point.
        CrateRestMainActionListener crateListener = new CrateRestMainActionListener();
        bindListener(
            new SubclassOfMatcher(CrateRestMainAction.class),
            crateListener);

        // this listener will use the CrateRestMainAction instance and call registerHandler
        // after RestMainAction is created.
        bindListener(
            new SubclassOfMatcher(RestMainAction.class),
            new RestMainActionListener(crateListener.instanceFuture));

        bind(ClusterIdService.class).asEagerSingleton();
    }

    @Override
    public void processModule(Module module) {
        crateLoader.processModule(module);
    }

    @Override
    public Iterable<? extends Module> spawnModules() {
        List<Module> modules = new ArrayList<>();
        Collection<Class<? extends Module>> moduleClasses = crateLoader.modules();
        for (Class<? extends Module> moduleClass : moduleClasses) {
            modules.add(createModule(moduleClass, settings));
        }
        modules.addAll(crateLoader.modules(settings));
        return modules;
    }

    private class RestMainActionListener implements TypeListener {

        private final SettableFuture<CrateRestMainAction> instanceFuture;

        public RestMainActionListener(SettableFuture<CrateRestMainAction> instanceFuture) {
            this.instanceFuture = instanceFuture;
        }

        @Override
        public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
            encounter.register(new InjectionListener<I>() {
                @Override
                public void afterInjection(I injectee) {
                    try {
                        CrateRestMainAction crateRestMainAction = instanceFuture.get(10, TimeUnit.SECONDS);
                        crateRestMainAction.registerHandler();
                    } catch (Exception e) {
                        logger.error("Could not register CrateRestMainAction handler", e);
                    }
                }
            });
        }
    }

    private class SubclassOfMatcher extends AbstractMatcher<TypeLiteral<?>> {

        private final Class<?> klass;

        SubclassOfMatcher(Class<?> klass) {
            this.klass = klass;
        }

        @Override
        public boolean matches(TypeLiteral<?> typeLiteral) {
            return klass.isAssignableFrom(typeLiteral.getRawType());
        }
    }

    private class CrateRestMainActionListener implements TypeListener {

        private final SettableFuture<CrateRestMainAction> instanceFuture;

        public CrateRestMainActionListener() {
            this.instanceFuture = SettableFuture.create();

        }

        @Override
        public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
            encounter.register(new InjectionListener<I>() {
                @Override
                public void afterInjection(I injectee) {
                    instanceFuture.set((CrateRestMainAction)injectee);
                }
            });
        }
    }
}
TOP

Related Classes of io.crate.module.CrateCoreModule$SubclassOfMatcher

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.