All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.druid.guice.JsonConfigProvider Maven / Gradle / Ivy

There is a newer version: 30.0.1
Show newest version
/*
 * 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.druid.guice;

import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.inject.Binder;
import com.google.inject.Inject;
import com.google.inject.Key;
import com.google.inject.Provider;
import com.google.inject.util.Types;
import org.apache.druid.guice.annotations.PublicApi;

import javax.annotation.Nullable;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.util.Properties;


/**
 * Provides a singleton value of type {@code } from {@code Properties} bound in guice.
 * 
*

Usage

* To install this provider, bind it in your guice module, like below. * *
 * JsonConfigProvider.bind(binder, "druid.server", DruidServerConfig.class);
 * 
*
* In the above case, {@code druid.server} should be a key found in the {@code Properties} bound elsewhere. * The value of that key should directly relate to the fields in {@code DruidServerConfig.class}. * *

Implementation

*
* The state of {@code } is defined by the value of the property {@code propertyBase}. * This value is a json structure, decoded via {@link JsonConfigurator#configurate(Properties, String, Class)}. *
* * An example might be if DruidServerConfig.class were * *
 *   public class DruidServerConfig
 *   {
 *     @JsonProperty @NotNull public String hostname = null;
 *     @JsonProperty @Min(1025) public int port = 8080;
 *   }
 * 
* * And your Properties object had in it * *
 *   druid.server.hostname=0.0.0.0
 *   druid.server.port=3333
 * 
* * Then this would bind a singleton instance of a DruidServerConfig object with hostname = "0.0.0.0" and port = 3333. * * If the port weren't set in the properties, then the default of 8080 would be taken. Essentially, it is the same as * subtracting the "druid.server" prefix from the properties and building a Map which is then passed into * ObjectMapper.convertValue() * * @param type of config object to provide. */ @PublicApi public class JsonConfigProvider implements Provider { @SuppressWarnings("unchecked") public static void bind(Binder binder, String propertyBase, Class classToProvide) { bind( binder, propertyBase, classToProvide, Key.get(classToProvide), (Key) Key.get(Types.newParameterizedType(Supplier.class, classToProvide)) ); } @SuppressWarnings("unchecked") public static void bindWithDefault( Binder binder, String propertyBase, Class classToProvide, Class defaultClass ) { bind( binder, propertyBase, classToProvide, defaultClass, Key.get(classToProvide), (Key) Key.get(Types.newParameterizedType(Supplier.class, classToProvide)) ); } @SuppressWarnings("unchecked") public static void bind(Binder binder, String propertyBase, Class classToProvide, Annotation annotation) { bind( binder, propertyBase, classToProvide, Key.get(classToProvide, annotation), (Key) Key.get(Types.newParameterizedType(Supplier.class, classToProvide), annotation) ); } @SuppressWarnings("unchecked") public static void bind( Binder binder, String propertyBase, Class classToProvide, Class annotation ) { bind( binder, propertyBase, classToProvide, Key.get(classToProvide, annotation), (Key) Key.get(Types.newParameterizedType(Supplier.class, classToProvide), annotation) ); } public static void bind( Binder binder, String propertyBase, Class clazz, Key instanceKey, Key> supplierKey ) { binder.bind(instanceKey).toProvider(new JsonConfigProvider<>(propertyBase, clazz, null)).in(LazySingleton.class); binder.bind(supplierKey).toProvider(new ProviderBasedGoogleSupplierProvider<>(instanceKey)).in(LazySingleton.class); } public static void bind( Binder binder, String propertyBase, Class clazz, Class defaultClass, Key instanceKey, Key> supplierKey ) { binder.bind(instanceKey) .toProvider(new JsonConfigProvider<>(propertyBase, clazz, defaultClass)) .in(LazySingleton.class); binder.bind(supplierKey).toProvider(new ProviderBasedGoogleSupplierProvider<>(instanceKey)).in(LazySingleton.class); } @SuppressWarnings("unchecked") public static void bindInstance( Binder binder, Key bindKey, T instance ) { binder.bind(bindKey).toInstance(instance); final ParameterizedType supType = Types.newParameterizedType(Supplier.class, bindKey.getTypeLiteral().getType()); final Key supplierKey; if (bindKey.getAnnotationType() != null) { supplierKey = Key.get(supType, bindKey.getAnnotationType()); } else if (bindKey.getAnnotation() != null) { supplierKey = Key.get(supType, bindKey.getAnnotation()); } else { supplierKey = Key.get(supType); } binder.bind(supplierKey).toInstance(Suppliers.ofInstance(instance)); } public static JsonConfigProvider of(String propertyBase, Class classToProvide) { return of(propertyBase, classToProvide, null); } public static JsonConfigProvider of( String propertyBase, Class classToProvide, Class defaultClass ) { return new JsonConfigProvider<>(propertyBase, classToProvide, defaultClass); } private final String propertyBase; private final Class classToProvide; private final Class defaultClass; private Properties props; private JsonConfigurator configurator; private T retVal = null; public JsonConfigProvider( String propertyBase, Class classToProvide, @Nullable Class defaultClass ) { this.propertyBase = propertyBase; this.classToProvide = classToProvide; this.defaultClass = defaultClass; } @Inject public void inject( Properties props, JsonConfigurator configurator ) { this.props = props; this.configurator = configurator; } @Override public T get() { if (retVal == null) { retVal = configurator.configurate(props, propertyBase, classToProvide, defaultClass); } return retVal; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy