/* * Licensed to 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 io.crate.ClusterIdService; import io.crate.plugin.IndexEventListenerProxy; import io.crate.rest.CrateRestMainAction; import io.crate.settings.SharedSettings; import org.apache.logging.log4j.Logger; import org.elasticsearch.common.inject.AbstractModule; import org.elasticsearch.common.inject.TypeLiteral; 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.Loggers; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.rest.action.RestMainAction; import java.util.concurrent.CompletableFuture; public class CrateCoreModule extends AbstractModule { private final Logger logger; private final IndexEventListenerProxy indexEventListenerProxy; public CrateCoreModule(Settings settings, IndexEventListenerProxy indexEventListenerProxy) { logger = Loggers.getLogger(getClass().getPackage().getName(), settings); this.indexEventListenerProxy = indexEventListenerProxy; if (SharedSettings.ENTERPRISE_LICENSE_SETTING.setting().get(settings) && "".equals(SharedSettings.LICENSE_IDENT_SETTING.setting().get(settings))){ logger.warn("You are currently using the Enterprise Edition, " + "but have not configured a license. Please request a license or deactivate the "+ "Enterprise Edition. https://crate.io/enterprise"); } } @Override protected void configure() { /* * 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(); bind(IndexEventListenerProxy.class).toInstance(indexEventListenerProxy); } private class RestMainActionListener implements TypeListener { private final CompletableFuture<CrateRestMainAction> instanceFuture; RestMainActionListener(CompletableFuture<CrateRestMainAction> instanceFuture) { this.instanceFuture = instanceFuture; } @Override public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) { encounter.register((InjectionListener<I>) injectee -> instanceFuture.whenComplete((crateRestMainAction, throwable) -> { if (throwable == null) { crateRestMainAction.registerHandler(); } else { logger.error("Could not register CrateRestMainAction handler", throwable); } })); } } private static 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 static class CrateRestMainActionListener implements TypeListener { private final CompletableFuture<CrateRestMainAction> instanceFuture; CrateRestMainActionListener() { this.instanceFuture = new CompletableFuture<>(); } @Override public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) { encounter.register(new InjectionListener<I>() { @Override public void afterInjection(I injectee) { instanceFuture.complete((CrateRestMainAction) injectee); } }); } } }