From 81149d35c6ed638eddaa4f18d6a5cbc1f4c07146 Mon Sep 17 00:00:00 2001 From: Harald Musum Date: Thu, 8 Jun 2017 14:23:16 +0200 Subject: Revert "Gjoranv/remove default ctor4" --- .../com/yahoo/vespa/model/InstanceResolver.java | 60 ++++++++++++++++++---- .../com/yahoo/config/codegen/ConfigGenerator.scala | 12 ++--- 2 files changed, 52 insertions(+), 20 deletions(-) diff --git a/config-model/src/main/java/com/yahoo/vespa/model/InstanceResolver.java b/config-model/src/main/java/com/yahoo/vespa/model/InstanceResolver.java index fdb9fdf9796..9c761e425a7 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/InstanceResolver.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/InstanceResolver.java @@ -11,7 +11,6 @@ import com.yahoo.vespa.config.buildergen.ConfigDefinition; import com.yahoo.yolean.Exceptions; import com.yahoo.vespa.config.*; -import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.List; @@ -47,19 +46,13 @@ class InstanceResolver { * @param targetDef the def to use * @return the config instance or null of no producer for this found in model */ - @SuppressWarnings("unchecked") static ConfigInstance resolveToInstance(ConfigKey key, ConfigBuilder builder, InnerCNode targetDef) { + ConfigDefinitionKey defKey = new ConfigDefinitionKey(key); try { if (targetDef != null) applyDef(builder, targetDef); - Class clazz = builder.getClass().getEnclosingClass(); - if (!(ConfigInstance.class.isAssignableFrom(clazz))) { - throw new ConfigurationRuntimeException("Cannot produce config for the name '" + key.getName() + ", as " - + clazz.getName() + " is not a ConfigInstance."); - } - Class configClass = (Class)clazz; - Constructor constructor = configClass.getDeclaredConstructor(builder.getClass(), boolean.class); - constructor.setAccessible(true); - return constructor.newInstance(builder, /*throwIfUninitialized*/ false); + ConfigInstance instance = getInstance(defKey, builder.getClass().getClassLoader()); + Class clazz = instance.getClass(); + return clazz.getConstructor(new Class[]{builder.getClass()}).newInstance(builder); } catch (Exception e) { throw new ConfigurationRuntimeException(e); } @@ -150,6 +143,51 @@ class InstanceResolver { } } + /** + * Create a ConfigBuilder given a definition key and a payload + * @param key The key to use to create the correct builder. + * @param payload The payload to populate the builder with. + * @return A ConfigBuilder initialized with payload. + */ + static ConfigBuilder createBuilderFromPayload(ConfigDefinitionKey key, VespaModel model, ConfigPayload payload, ConfigDefinition targetDef) { + ConfigBuilder builderInstance = model.createBuilder(key, targetDef); + if (builderInstance == null || builderInstance instanceof GenericConfig.GenericConfigBuilder) { + if (log.isLoggable(LogLevel.SPAM)) { + log.log(LogLevel.SPAM, "Creating generic builder for key=" + key); + } + return new GenericConfig.GenericConfigBuilder(key, new ConfigPayloadBuilder(payload)); + } + ConfigTransformer transformer = new ConfigTransformer(builderInstance.getClass().getDeclaringClass()); + return transformer.toConfigBuilder(payload); + } + + /** + * Returns a {@link ConfigInstance} of right type for given key using reflection + * + * @param cKey a ConfigKey + * @return a {@link ConfigInstance} or null if not available in classpath + */ + static ConfigInstance getInstance(ConfigDefinitionKey cKey, ClassLoader instanceLoader) { + String className = ConfigGenerator.createClassName(cKey.getName()); + Class clazz; + String fullClassName = packageName(cKey) + "." + className; + try { + clazz = instanceLoader != null ? instanceLoader.loadClass(fullClassName) : Class.forName(fullClassName); + } catch (ClassNotFoundException e) { + return null; + } + Object i; + try { + i = clazz.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + throw new ConfigurationRuntimeException(e); + } + if (!(i instanceof ConfigInstance)) { + throw new ConfigurationRuntimeException(fullClassName + " is not a ConfigInstance, can not produce config for the name '" + cKey.getName() + "'."); + } + return (ConfigInstance) i; + } + static String packageName(ConfigDefinitionKey cKey) { String prefix = "com.yahoo."; return prefix + (cKey.getNamespace().isEmpty() ? CNode.DEFAULT_NAMESPACE : cKey.getNamespace()); diff --git a/configgen/src/main/scala/com/yahoo/config/codegen/ConfigGenerator.scala b/configgen/src/main/scala/com/yahoo/config/codegen/ConfigGenerator.scala index 533b9b2be23..716f2a60c33 100644 --- a/configgen/src/main/scala/com/yahoo/config/codegen/ConfigGenerator.scala +++ b/configgen/src/main/scala/com/yahoo/config/codegen/ConfigGenerator.scala @@ -180,14 +180,8 @@ object ConfigGenerator { } } - // TODO: The default ctor is possibly still needed for innerArrays, because of InnerNodeVector.createNew() - def defaultConstructorIfArray = { - inner match { - case array: InnerCNode if inner.isArray => defaultConstructor - case scalar: InnerCNode => "" - } - } - + // TODO: The default ctor can be removed if the config library uses builders to set values from payload, but ... + // a default ctor is also needed for all innerArrays, because of InnerNodeVector.createNew() def defaultConstructor = { // TODO @link gives javadoc warnings, although the syntax seems to be valid //def link = "{@link " + {nodeClass(inner)} + "#" + {nodeClass(inner)} + "(Builder)}" @@ -208,7 +202,7 @@ object ConfigGenerator { // TODO: merge these two constructors into one when the config library uses builders to set values from payload. - |{defaultConstructorIfArray} + |{defaultConstructor} | |public {nodeClass(inner)}(Builder builder) {{ | this(builder, true); -- cgit v1.2.3