blob: 8c1128c1f69bd21495c162f706bf05693a49da34 [file] [log] [blame]
/*
* Copyright 2017 HugeGraph Authors
*
* 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 com.baidu.hugegraph.config;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.Log;
public final class OptionSpace {
private static final Logger LOG = Log.logger(OptionSpace.class);
private static final Map<String, Class<? extends OptionHolder>> HOLDERS;
private static final Map<String, TypedOption<?, ?>> OPTIONS;
private static final String INSTANCE_METHOD = "instance";
static {
HOLDERS = new ConcurrentHashMap<>();
OPTIONS = new ConcurrentHashMap<>();
}
public static void register(String module, String holder) {
ClassLoader classLoader = OptionSpace.class.getClassLoader();
Class<?> clazz;
try {
clazz = classLoader.loadClass(holder);
} catch (ClassNotFoundException e) {
throw new ConfigException(
"Failed to load class of option holder '%s'", e, holder);
}
// Check subclass
if (!OptionHolder.class.isAssignableFrom(clazz)) {
throw new ConfigException(
"Class '%s' is not a subclass of OptionHolder", holder);
}
OptionHolder instance = null;
Exception exception = null;
try {
Method method = clazz.getMethod(INSTANCE_METHOD);
if (!Modifier.isStatic(method.getModifiers())) {
throw new NoSuchMethodException(INSTANCE_METHOD);
}
instance = (OptionHolder) method.invoke(null);
if (instance == null) {
exception = new ConfigException(
"Returned null from %s() method",
INSTANCE_METHOD);
}
} catch (NoSuchMethodException e) {
LOG.warn("Class {} does not has static method {}.",
holder, INSTANCE_METHOD);
exception = e;
} catch (InvocationTargetException e) {
LOG.warn("Can't call static method {} from class {}.",
INSTANCE_METHOD, holder);
exception = e;
} catch (IllegalAccessException e) {
LOG.warn("Illegal access while calling method {} from class {}.",
INSTANCE_METHOD, holder);
exception = e;
}
if (exception != null) {
throw new ConfigException("Failed to instantiate option holder: %s",
exception, holder);
}
register(module, instance);
}
public static void register(String module, OptionHolder holder) {
// Check exists
if (HOLDERS.containsKey(module)) {
LOG.warn("Already registered option holder: {} ({})",
module, HOLDERS.get(module));
}
E.checkArgumentNotNull(holder, "OptionHolder can't be null");
HOLDERS.put(module, holder.getClass());
OPTIONS.putAll(holder.options());
LOG.debug("Registered options for OptionHolder: {}",
holder.getClass().getSimpleName());
}
public static Set<String> keys() {
return Collections.unmodifiableSet(OPTIONS.keySet());
}
public static boolean containKey(String key) {
return OPTIONS.containsKey(key);
}
public static TypedOption<?, ?> get(String key) {
return OPTIONS.get(key);
}
}