org.apache.druid.guice.JsonConfigProvider Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of druid-processing Show documentation
Show all versions of druid-processing Show documentation
A module that is everything required to understands Druid Segments
/*
* 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;
}
}