diff options
author | Harald Musum <musum@verizonmedia.com> | 2021-04-06 14:19:35 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-06 14:19:35 +0200 |
commit | 778894b29b13831115c19ff13285541a10ab2d30 (patch) | |
tree | 62ea7aa8689a3d5421f54cd0ac6c5290e82f23dc /container-core/src | |
parent | 5df00bb90a04082847440716bcb6146bdda0ca06 (diff) |
Revert "Gjoranv/merge di into core (rebased)"
Diffstat (limited to 'container-core/src')
55 files changed, 0 insertions, 5272 deletions
diff --git a/container-core/src/main/java/com/yahoo/container/bundle/BundleInstantiationSpecification.java b/container-core/src/main/java/com/yahoo/container/bundle/BundleInstantiationSpecification.java deleted file mode 100644 index 0fb8a99a957..00000000000 --- a/container-core/src/main/java/com/yahoo/container/bundle/BundleInstantiationSpecification.java +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.bundle; - -import com.yahoo.component.ComponentId; -import com.yahoo.component.ComponentSpecification; - - -/** - * Specifies how a component should be instantiated from a bundle. - * - * Immutable - * - * @author Tony Vaagenes - */ -public final class BundleInstantiationSpecification { - - public final ComponentId id; - public final ComponentSpecification classId; - public final ComponentSpecification bundle; - - public BundleInstantiationSpecification(ComponentSpecification id, ComponentSpecification classId, ComponentSpecification bundle) { - this.id = id.toId(); - this.classId = (classId != null) ? classId : id.withoutNamespace(); - this.bundle = (bundle != null) ? bundle : this.classId; - } - - // Must only be used when classId != null, otherwise the id must be handled as a ComponentSpecification - // (since converting a spec string to a ComponentId and then to a ComponentSpecification causes loss of information). - public BundleInstantiationSpecification(ComponentId id, ComponentSpecification classId, ComponentSpecification bundle) { - this(id.toSpecification(), classId, bundle); - assert (classId!= null); - } - - private static final String defaultInternalBundle = "container-search-and-docproc"; - - private static BundleInstantiationSpecification getInternalSpecificationFromString(String idSpec, String classSpec) { - return new BundleInstantiationSpecification( - new ComponentSpecification(idSpec), - (classSpec == null || classSpec.isEmpty())? null : new ComponentSpecification(classSpec), - new ComponentSpecification(defaultInternalBundle)); - } - - public static BundleInstantiationSpecification getInternalSearcherSpecification(ComponentSpecification idSpec, - ComponentSpecification classSpec) { - return new BundleInstantiationSpecification(idSpec, classSpec, new ComponentSpecification(defaultInternalBundle)); - } - - // TODO: These are the same for now because they are in the same bundle. - public static BundleInstantiationSpecification getInternalHandlerSpecificationFromStrings(String idSpec, String classSpec) { - return getInternalSpecificationFromString(idSpec, classSpec); - } - - public static BundleInstantiationSpecification getInternalProcessingSpecificationFromStrings(String idSpec, String classSpec) { - return getInternalSpecificationFromString(idSpec, classSpec); - } - - public static BundleInstantiationSpecification getInternalSearcherSpecificationFromStrings(String idSpec, String classSpec) { - return getInternalSpecificationFromString(idSpec, classSpec); - } - - public static BundleInstantiationSpecification getFromStrings(String idSpec, String classSpec, String bundleSpec) { - return new BundleInstantiationSpecification( - new ComponentSpecification(idSpec), - (classSpec == null || classSpec.isEmpty())? null : new ComponentSpecification(classSpec), - (bundleSpec == null || bundleSpec.isEmpty())? null : new ComponentSpecification(bundleSpec)); - } - - /** - * Return a new instance of the specification with bundle name altered - * - * @param bundleName the new name of the bundle - * @return the new instance of the specification - */ - public BundleInstantiationSpecification inBundle(String bundleName) { - return new BundleInstantiationSpecification(this.id, this.classId, new ComponentSpecification(bundleName)); - } - - public String getClassName() { - return classId.getName(); - } - - public BundleInstantiationSpecification nestInNamespace(ComponentId namespace) { - return new BundleInstantiationSpecification(id.nestInNamespace(namespace), classId, bundle); - } - -} diff --git a/container-core/src/main/java/com/yahoo/container/bundle/MockBundle.java b/container-core/src/main/java/com/yahoo/container/bundle/MockBundle.java deleted file mode 100644 index a6524b41886..00000000000 --- a/container-core/src/main/java/com/yahoo/container/bundle/MockBundle.java +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.bundle; - -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceReference; -import org.osgi.framework.Version; -import org.osgi.framework.wiring.BundleCapability; -import org.osgi.framework.wiring.BundleRequirement; -import org.osgi.framework.wiring.BundleRevision; -import org.osgi.framework.wiring.BundleWire; -import org.osgi.framework.wiring.BundleWiring; -import org.osgi.resource.Capability; -import org.osgi.resource.Requirement; -import org.osgi.resource.Wire; - -import java.io.File; -import java.io.InputStream; -import java.net.URL; -import java.security.cert.X509Certificate; -import java.util.Collection; -import java.util.Collections; -import java.util.Dictionary; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.List; -import java.util.Map; - -/** - * @author gjoranv - * @author ollivir - */ -public class MockBundle implements Bundle, BundleWiring { - public static final String SymbolicName = "mock-bundle"; - public static final Version BundleVersion = new Version(1, 0, 0); - - private static final Class<BundleWiring> bundleWiringClass = BundleWiring.class; - - @Override - public int getState() { - return Bundle.ACTIVE; - } - - @Override - public void start(int options) { - } - - @Override - public void start() { - } - - @Override - public void stop(int options) { - } - - @Override - public void stop() { - } - - @Override - public void update(InputStream input) { - } - - @Override - public void update() { - } - - @Override - public void uninstall() { - } - - @Override - public Dictionary<String, String> getHeaders(String locale) { - return getHeaders(); - } - - @Override - public String getSymbolicName() { - return SymbolicName; - } - - @Override - public Version getVersion() { - return BundleVersion; - } - - @Override - public String getLocation() { - return getSymbolicName(); - } - - @Override - public long getBundleId() { - return 0L; - } - - @Override - public Dictionary<String, String> getHeaders() { - return new Hashtable<>(); - } - - @Override - public ServiceReference<?>[] getRegisteredServices() { - return new ServiceReference<?>[0]; - } - - @Override - public ServiceReference<?>[] getServicesInUse() { - return getRegisteredServices(); - } - - @Override - public boolean hasPermission(Object permission) { - return true; - } - - @Override - public URL getResource(String name) { - throw new UnsupportedOperationException(); - } - - @Override - public Class<?> loadClass(String name) { - throw new UnsupportedOperationException(); - } - - @Override - public Enumeration<URL> getResources(String name) { - throw new UnsupportedOperationException(); - } - - @Override - public Enumeration<String> getEntryPaths(String path) { - throw new UnsupportedOperationException(); - } - - @Override - public URL getEntry(String path) { - throw new UnsupportedOperationException(); - } - - @Override - public Enumeration<URL> findEntries(String path, String filePattern, boolean recurse) { - return Collections.emptyEnumeration(); - } - - - @Override - public long getLastModified() { - return 1L; - } - - @Override - public BundleContext getBundleContext() { - throw new UnsupportedOperationException(); - } - - @Override - public Map<X509Certificate, List<X509Certificate>> getSignerCertificates(int signersType) { - return Collections.emptyMap(); - } - - @SuppressWarnings("unchecked") - @Override - public <T> T adapt(Class<T> type) { - if (type.equals(bundleWiringClass)) { - return (T) this; - } else { - throw new UnsupportedOperationException(); - } - } - - @Override - public File getDataFile(String filename) { - return null; - } - - @Override - public int compareTo(Bundle o) { - return Long.compare(getBundleId(), o.getBundleId()); - } - - - //TODO: replace with mockito - @Override - public List<URL> findEntries(String p1, String p2, int p3) { - throw new UnsupportedOperationException(); - } - - @Override - public List<Wire> getRequiredResourceWires(String p1) { - throw new UnsupportedOperationException(); - } - - @Override - public List<Capability> getResourceCapabilities(String p1) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isCurrent() { - throw new UnsupportedOperationException(); - } - - @Override - public List<BundleWire> getRequiredWires(String p1) { - throw new UnsupportedOperationException(); - } - - @Override - public List<BundleCapability> getCapabilities(String p1) { - throw new UnsupportedOperationException(); - } - - @Override - public List<Wire> getProvidedResourceWires(String p1) { - throw new UnsupportedOperationException(); - } - - @Override - public List<BundleWire> getProvidedWires(String p1) { - throw new UnsupportedOperationException(); - } - - @Override - public BundleRevision getRevision() { - throw new UnsupportedOperationException(); - } - - @Override - public List<Requirement> getResourceRequirements(String p1) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isInUse() { - throw new UnsupportedOperationException(); - } - - @Override - public Collection<String> listResources(String p1, String p2, int p3) { - return Collections.emptyList(); - } - - @Override - public ClassLoader getClassLoader() { - return MockBundle.class.getClassLoader(); - } - - @Override - public List<BundleRequirement> getRequirements(String p1) { - throw new UnsupportedOperationException(); - } - - @Override - public BundleRevision getResource() { - throw new UnsupportedOperationException(); - } - - @Override - public Bundle getBundle() { - throw new UnsupportedOperationException(); - } -} diff --git a/container-core/src/main/java/com/yahoo/container/bundle/package-info.java b/container-core/src/main/java/com/yahoo/container/bundle/package-info.java deleted file mode 100644 index c9707371626..00000000000 --- a/container-core/src/main/java/com/yahoo/container/bundle/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -@ExportPackage -package com.yahoo.container.bundle; - -import com.yahoo.osgi.annotation.ExportPackage; diff --git a/container-core/src/main/java/com/yahoo/container/di/CloudSubscriberFactory.java b/container-core/src/main/java/com/yahoo/container/di/CloudSubscriberFactory.java deleted file mode 100644 index 065733a719a..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/CloudSubscriberFactory.java +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di; - -import com.yahoo.config.ConfigInstance; -import com.yahoo.config.subscription.ConfigHandle; -import com.yahoo.config.subscription.ConfigSource; -import com.yahoo.config.subscription.ConfigSourceSet; -import com.yahoo.config.subscription.ConfigSubscriber; -import com.yahoo.container.di.config.Subscriber; -import com.yahoo.container.di.config.SubscriberFactory; -import com.yahoo.vespa.config.ConfigKey; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.WeakHashMap; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * @author Tony Vaagenes - * @author ollivir - */ -public class CloudSubscriberFactory implements SubscriberFactory { - - private static final Logger log = Logger.getLogger(CloudSubscriberFactory.class.getName()); - - private final ConfigSource configSource; - private final Map<CloudSubscriber, Integer> activeSubscribers = new WeakHashMap<>(); - - private Optional<Long> testGeneration = Optional.empty(); - - public CloudSubscriberFactory(ConfigSource configSource) { - this.configSource = configSource; - } - - @Override - public Subscriber getSubscriber(Set<? extends ConfigKey<?>> configKeys) { - Set<ConfigKey<ConfigInstance>> subscriptionKeys = new HashSet<>(); - for(ConfigKey<?> key: configKeys) { - @SuppressWarnings("unchecked") // ConfigKey is defined as <CONFIGCLASS extends ConfigInstance> - ConfigKey<ConfigInstance> invariant = (ConfigKey<ConfigInstance>) key; - subscriptionKeys.add(invariant); - } - CloudSubscriber subscriber = new CloudSubscriber(subscriptionKeys, configSource); - - testGeneration.ifPresent(subscriber.subscriber::reload); // TODO: test specific code, remove - activeSubscribers.put(subscriber, 0); - - return subscriber; - } - - //TODO: test specific code, remove - @Override - public void reloadActiveSubscribers(long generation) { - testGeneration = Optional.of(generation); - - List<CloudSubscriber> subscribers = new ArrayList<>(activeSubscribers.keySet()); - subscribers.forEach(s -> s.subscriber.reload(generation)); - } - - private static class CloudSubscriber implements Subscriber { - - private final ConfigSubscriber subscriber; - private final Map<ConfigKey<ConfigInstance>, ConfigHandle<ConfigInstance>> handles = new HashMap<>(); - - // if waitNextGeneration has not yet been called, -1 should be returned - private long generation = -1L; - - private CloudSubscriber(Set<ConfigKey<ConfigInstance>> keys, ConfigSource configSource) { - this.subscriber = new ConfigSubscriber(configSource); - keys.forEach(k -> handles.put(k, subscriber.subscribe(k.getConfigClass(), k.getConfigId()))); - } - - @Override - public boolean configChanged() { - return handles.values().stream().anyMatch(ConfigHandle::isChanged); - } - - @Override - public long generation() { - return generation; - } - - //mapValues returns a view,, so we need to force evaluation of it here to prevent deferred evaluation. - @Override - public Map<ConfigKey<ConfigInstance>, ConfigInstance> config() { - Map<ConfigKey<ConfigInstance>, ConfigInstance> ret = new HashMap<>(); - handles.forEach((k, v) -> ret.put(k, v.getConfig())); - return ret; - } - - @Override - public long waitNextGeneration(boolean isInitializing) { - if (handles.isEmpty()) - throw new IllegalStateException("No config keys registered"); - - // Catch and just log config exceptions due to missing config values for parameters that do - // not have a default value. These exceptions occur when the user has removed a component - // from services.xml, and the component takes a config that has parameters without a - // default value in the def-file. There is a new 'components' config underway, where the - // component is removed, so this old config generation will soon be replaced by a new one. - boolean gotNextGen = false; - int numExceptions = 0; - while ( ! gotNextGen) { - try { - if (subscriber.nextGeneration(isInitializing)) - gotNextGen = true; - } - catch (IllegalArgumentException e) { - numExceptions++; - log.log(Level.WARNING, "Got exception from the config system (ignore if you just removed a " + - "component from your application that used the mentioned config) Subscriber info: " + - subscriber.toString(), e); - if (numExceptions >= 5) - throw new IllegalArgumentException("Failed retrieving the next config generation", e); - } - } - - generation = subscriber.getGeneration(); - return generation; - } - - @Override - public void close() { - subscriber.close(); - } - - } - - public static class Provider implements com.google.inject.Provider<SubscriberFactory> { - @Override - public SubscriberFactory get() { - return new CloudSubscriberFactory(ConfigSourceSet.createDefault()); - } - } - -} diff --git a/container-core/src/main/java/com/yahoo/container/di/ComponentDeconstructor.java b/container-core/src/main/java/com/yahoo/container/di/ComponentDeconstructor.java deleted file mode 100644 index 4e3881a6fe6..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/ComponentDeconstructor.java +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di; - -import org.osgi.framework.Bundle; - -import java.util.Collection; -import java.util.List; - -/** - * @author gjoranv - * @author Tony Vaagenes - */ -public interface ComponentDeconstructor { - - /** Deconstructs the given components in order, then the given bundles. */ - void deconstruct(List<Object> components, Collection<Bundle> bundles); - -} diff --git a/container-core/src/main/java/com/yahoo/container/di/ConfigRetriever.java b/container-core/src/main/java/com/yahoo/container/di/ConfigRetriever.java deleted file mode 100644 index a7ff6c46a8b..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/ConfigRetriever.java +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di; - -import com.google.common.collect.Sets; -import com.yahoo.config.ConfigInstance; -import com.yahoo.container.di.componentgraph.core.Keys; -import com.yahoo.container.di.config.Subscriber; -import com.yahoo.vespa.config.ConfigKey; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.function.Function; -import java.util.logging.Level; -import java.util.logging.Logger; - -import static java.util.logging.Level.FINE; - -/** - * @author Tony Vaagenes - * @author gjoranv - * @author ollivir - */ -public final class ConfigRetriever { - - private static final Logger log = Logger.getLogger(ConfigRetriever.class.getName()); - - private final Set<ConfigKey<? extends ConfigInstance>> bootstrapKeys; - private Set<ConfigKey<? extends ConfigInstance>> componentSubscriberKeys; - private final Subscriber bootstrapSubscriber; - private Subscriber componentSubscriber; - private final Function<Set<ConfigKey<? extends ConfigInstance>>, Subscriber> subscribe; - - public ConfigRetriever(Set<ConfigKey<? extends ConfigInstance>> bootstrapKeys, - Function<Set<ConfigKey<? extends ConfigInstance>>, Subscriber> subscribe) { - this.bootstrapKeys = bootstrapKeys; - this.componentSubscriberKeys = new HashSet<>(); - this.subscribe = subscribe; - if (bootstrapKeys.isEmpty()) { - throw new IllegalArgumentException("Bootstrap key set is empty"); - } - this.bootstrapSubscriber = subscribe.apply(bootstrapKeys); - this.componentSubscriber = subscribe.apply(componentSubscriberKeys); - } - - public ConfigSnapshot getConfigs(Set<ConfigKey<? extends ConfigInstance>> componentConfigKeys, - long leastGeneration, boolean isInitializing) { - // Loop until we get config. - while (true) { - Optional<ConfigSnapshot> maybeSnapshot = getConfigsOnce(componentConfigKeys, leastGeneration, isInitializing); - if (maybeSnapshot.isPresent()) { - var configSnapshot = maybeSnapshot.get(); - resetComponentSubscriberIfBootstrap(configSnapshot); - return configSnapshot; - } - } - } - - Optional<ConfigSnapshot> getConfigsOnce(Set<ConfigKey<? extends ConfigInstance>> componentConfigKeys, - long leastGeneration, boolean isInitializing) { - if (!Sets.intersection(componentConfigKeys, bootstrapKeys).isEmpty()) { - throw new IllegalArgumentException( - "Component config keys [" + componentConfigKeys + "] overlaps with bootstrap config keys [" + bootstrapKeys + "]"); - } - log.log(FINE, "getConfigsOnce: " + componentConfigKeys); - - Set<ConfigKey<? extends ConfigInstance>> allKeys = new HashSet<>(componentConfigKeys); - allKeys.addAll(bootstrapKeys); - setupComponentSubscriber(allKeys); - - return getConfigsOptional(leastGeneration, isInitializing); - } - - private Optional<ConfigSnapshot> getConfigsOptional(long leastGeneration, boolean isInitializing) { - long newestComponentGeneration = componentSubscriber.waitNextGeneration(isInitializing); - log.log(FINE, "getConfigsOptional: new component generation: " + newestComponentGeneration); - - // leastGeneration is only used to ensure newer generation when the previous generation was invalidated due to an exception - if (newestComponentGeneration < leastGeneration) { - return Optional.empty(); - } else if (bootstrapSubscriber.generation() < newestComponentGeneration) { - long newestBootstrapGeneration = bootstrapSubscriber.waitNextGeneration(isInitializing); - log.log(FINE, "getConfigsOptional: new bootstrap generation: " + bootstrapSubscriber.generation()); - Optional<ConfigSnapshot> bootstrapConfig = bootstrapConfigIfChanged(); - if (bootstrapConfig.isPresent()) { - return bootstrapConfig; - } else { - if (newestBootstrapGeneration == newestComponentGeneration) { - log.log(FINE, "Got new components configs with unchanged bootstrap configs."); - return componentsConfigIfChanged(); - } else { - // This should not be a normal case, and hence a warning to allow investigation. - log.warning("Did not get same generation for bootstrap (" + newestBootstrapGeneration + - ") and components configs (" + newestComponentGeneration + ")."); - return Optional.empty(); - } - } - } else { - // bootstrapGen==componentGen (happens only when a new component subscriber returns first config after bootstrap) - return componentsConfigIfChanged(); - } - } - - private Optional<ConfigSnapshot> bootstrapConfigIfChanged() { - return configIfChanged(bootstrapSubscriber, BootstrapConfigs::new); - } - - private Optional<ConfigSnapshot> componentsConfigIfChanged() { - return configIfChanged(componentSubscriber, ComponentsConfigs::new); - } - - private Optional<ConfigSnapshot> configIfChanged(Subscriber subscriber, - Function<Map<ConfigKey<? extends ConfigInstance>, ConfigInstance>, ConfigSnapshot> constructor) { - if (subscriber.configChanged()) { - return Optional.of(constructor.apply(Keys.covariantCopy(subscriber.config()))); - } else { - return Optional.empty(); - } - } - - private void resetComponentSubscriberIfBootstrap(ConfigSnapshot snapshot) { - if (snapshot instanceof BootstrapConfigs) { - setupComponentSubscriber(Collections.emptySet()); - } - } - - private void setupComponentSubscriber(Set<ConfigKey<? extends ConfigInstance>> keys) { - if (! componentSubscriberKeys.equals(keys)) { - componentSubscriber.close(); - componentSubscriberKeys = keys; - try { - log.log(FINE, "Setting up new component subscriber for keys: " + keys); - componentSubscriber = subscribe.apply(keys); - } catch (Throwable e) { - log.log(Level.WARNING, "Failed setting up subscriptions for component configs: " + e.getMessage()); - log.log(Level.WARNING, "Config keys: " + keys); - throw e; - } - } - } - - public void shutdown() { - bootstrapSubscriber.close(); - componentSubscriber.close(); - } - - //TODO: check if these are really needed - public long getBootstrapGeneration() { - return bootstrapSubscriber.generation(); - } - - public long getComponentsGeneration() { - return componentSubscriber.generation(); - } - - public static class ConfigSnapshot { - private final Map<ConfigKey<? extends ConfigInstance>, ConfigInstance> configs; - - ConfigSnapshot(Map<ConfigKey<? extends ConfigInstance>, ConfigInstance> configs) { - this.configs = configs; - } - - public Map<ConfigKey<? extends ConfigInstance>, ConfigInstance> configs() { - return configs; - } - - public int size() { - return configs.size(); - } - } - - public static class BootstrapConfigs extends ConfigSnapshot { - BootstrapConfigs(Map<ConfigKey<? extends ConfigInstance>, ConfigInstance> configs) { - super(configs); - } - } - - public static class ComponentsConfigs extends ConfigSnapshot { - ComponentsConfigs(Map<ConfigKey<? extends ConfigInstance>, ConfigInstance> configs) { - super(configs); - } - } -} diff --git a/container-core/src/main/java/com/yahoo/container/di/Container.java b/container-core/src/main/java/com/yahoo/container/di/Container.java deleted file mode 100644 index 82c7f65bc2a..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/Container.java +++ /dev/null @@ -1,289 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di; - -import com.google.inject.Injector; -import com.yahoo.config.ConfigInstance; -import com.yahoo.config.ConfigurationRuntimeException; -import com.yahoo.config.subscription.ConfigInterruptedException; -import com.yahoo.container.ComponentsConfig; -import com.yahoo.container.bundle.BundleInstantiationSpecification; -import com.yahoo.container.di.ConfigRetriever.BootstrapConfigs; -import com.yahoo.container.di.ConfigRetriever.ComponentsConfigs; -import com.yahoo.container.di.ConfigRetriever.ConfigSnapshot; -import com.yahoo.container.di.componentgraph.core.ComponentGraph; -import com.yahoo.container.di.componentgraph.core.ComponentNode; -import com.yahoo.container.di.componentgraph.core.JerseyNode; -import com.yahoo.container.di.componentgraph.core.Node; -import com.yahoo.container.di.config.ApplicationBundlesConfig; -import com.yahoo.container.di.config.PlatformBundlesConfig; -import com.yahoo.container.di.config.RestApiContext; -import com.yahoo.container.di.config.SubscriberFactory; -import com.yahoo.vespa.config.ConfigKey; -import org.osgi.framework.Bundle; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; - -import static java.util.logging.Level.FINE; - -/** - * @author gjoranv - * @author Tony Vaagenes - * @author ollivir - */ -public class Container { - - private static final Logger log = Logger.getLogger(Container.class.getName()); - - private final SubscriberFactory subscriberFactory; - private final ConfigKey<ApplicationBundlesConfig> applicationBundlesConfigKey; - private final ConfigKey<PlatformBundlesConfig> platformBundlesConfigKey; - private final ConfigKey<ComponentsConfig> componentsConfigKey; - private final ComponentDeconstructor componentDeconstructor; - private final Osgi osgi; - - private final ConfigRetriever configurer; - private List<String> platformBundles; // Used to verify that platform bundles don't change. - private long previousConfigGeneration = -1L; - private long leastGeneration = -1L; - - public Container(SubscriberFactory subscriberFactory, String configId, ComponentDeconstructor componentDeconstructor, Osgi osgi) { - this.subscriberFactory = subscriberFactory; - this.componentDeconstructor = componentDeconstructor; - this.osgi = osgi; - - applicationBundlesConfigKey = new ConfigKey<>(ApplicationBundlesConfig.class, configId); - platformBundlesConfigKey = new ConfigKey<>(PlatformBundlesConfig.class, configId); - componentsConfigKey = new ConfigKey<>(ComponentsConfig.class, configId); - var bootstrapKeys = Set.of(applicationBundlesConfigKey, platformBundlesConfigKey, componentsConfigKey); - this.configurer = new ConfigRetriever(bootstrapKeys, subscriberFactory::getSubscriber); - } - - public Container(SubscriberFactory subscriberFactory, String configId, ComponentDeconstructor componentDeconstructor) { - this(subscriberFactory, configId, componentDeconstructor, new Osgi() { - }); - } - - public ComponentGraph getNewComponentGraph(ComponentGraph oldGraph, Injector fallbackInjector, boolean isInitializing) { - try { - Collection<Bundle> obsoleteBundles = new HashSet<>(); - ComponentGraph newGraph = getConfigAndCreateGraph(oldGraph, fallbackInjector, isInitializing, obsoleteBundles); - newGraph.reuseNodes(oldGraph); - constructComponents(newGraph); - deconstructObsoleteComponents(oldGraph, newGraph, obsoleteBundles); - return newGraph; - } catch (Throwable t) { - invalidateGeneration(oldGraph.generation(), t); - throw t; - } - } - - private ComponentGraph getConfigAndCreateGraph(ComponentGraph graph, - Injector fallbackInjector, - boolean isInitializing, - Collection<Bundle> obsoleteBundles) // NOTE: Return value - { - ConfigSnapshot snapshot; - while (true) { - snapshot = configurer.getConfigs(graph.configKeys(), leastGeneration, isInitializing); - - log.log(FINE, String.format("createNewGraph:\n" + "graph.configKeys = %s\n" + "graph.generation = %s\n" + "snapshot = %s\n", - graph.configKeys(), graph.generation(), snapshot)); - - if (snapshot instanceof BootstrapConfigs) { - if (getBootstrapGeneration() <= previousConfigGeneration) { - throw new IllegalStateException(String.format( - "Got bootstrap configs out of sequence for old config generation %d.\n" + "Previous config generation is %d", - getBootstrapGeneration(), previousConfigGeneration)); - } - log.log(FINE, "Got new bootstrap generation\n" + configGenerationsString()); - - if (graph.generation() == 0) { - platformBundles = getConfig(platformBundlesConfigKey, snapshot.configs()).bundlePaths(); - osgi.installPlatformBundles(platformBundles); - } else { - throwIfPlatformBundlesChanged(snapshot); - } - Collection<Bundle> bundlesToRemove = installApplicationBundles(snapshot.configs()); - obsoleteBundles.addAll(bundlesToRemove); - - graph = createComponentsGraph(snapshot.configs(), getBootstrapGeneration(), fallbackInjector); - - // Continues loop - - } else if (snapshot instanceof ComponentsConfigs) { - break; - } - } - log.log(FINE, "Got components configs,\n" + configGenerationsString()); - return createAndConfigureComponentsGraph(snapshot.configs(), fallbackInjector); - } - - private long getBootstrapGeneration() { - return configurer.getBootstrapGeneration(); - } - - private long getComponentsGeneration() { - return configurer.getComponentsGeneration(); - } - - private String configGenerationsString() { - return String.format("bootstrap generation = %d\n" + "components generation: %d\n" + "previous generation: %d", - getBootstrapGeneration(), getComponentsGeneration(), previousConfigGeneration); - } - - private void throwIfPlatformBundlesChanged(ConfigSnapshot snapshot) { - var checkPlatformBundles = getConfig(platformBundlesConfigKey, snapshot.configs()).bundlePaths(); - if (! checkPlatformBundles.equals(platformBundles)) - throw new RuntimeException("Platform bundles are not allowed to change!\nOld: " + platformBundles + "\nNew: " + checkPlatformBundles); - } - - private ComponentGraph createAndConfigureComponentsGraph(Map<ConfigKey<? extends ConfigInstance>, ConfigInstance> componentsConfigs, - Injector fallbackInjector) { - ComponentGraph componentGraph = createComponentsGraph(componentsConfigs, getComponentsGeneration(), fallbackInjector); - componentGraph.setAvailableConfigs(componentsConfigs); - return componentGraph; - } - - private void constructComponents(ComponentGraph graph) { - graph.nodes().forEach(Node::constructInstance); - } - - private void deconstructObsoleteComponents(ComponentGraph oldGraph, - ComponentGraph newGraph, - Collection<Bundle> obsoleteBundles) { - Map<Object, ?> newComponents = new IdentityHashMap<>(newGraph.size()); - for (Object component : newGraph.allConstructedComponentsAndProviders()) - newComponents.put(component, null); - - List<Object> obsoleteComponents = new ArrayList<>(); - for (Object component : oldGraph.allConstructedComponentsAndProviders()) - if ( ! newComponents.containsKey(component)) - obsoleteComponents.add(component); - - componentDeconstructor.deconstruct(obsoleteComponents, obsoleteBundles); - } - - private Set<Bundle> installApplicationBundles(Map<ConfigKey<? extends ConfigInstance>, ConfigInstance> configsIncludingBootstrapConfigs) { - ApplicationBundlesConfig applicationBundlesConfig = getConfig(applicationBundlesConfigKey, configsIncludingBootstrapConfigs); - return osgi.useApplicationBundles(applicationBundlesConfig.bundles()); - } - - private ComponentGraph createComponentsGraph(Map<ConfigKey<? extends ConfigInstance>, ConfigInstance> configsIncludingBootstrapConfigs, - long generation, Injector fallbackInjector) { - previousConfigGeneration = generation; - - ComponentGraph graph = new ComponentGraph(generation); - ComponentsConfig componentsConfig = getConfig(componentsConfigKey, configsIncludingBootstrapConfigs); - if (componentsConfig == null) { - throw new ConfigurationRuntimeException("The set of all configs does not include a valid 'components' config. Config set: " - + configsIncludingBootstrapConfigs.keySet()); - } - addNodes(componentsConfig, graph); - injectNodes(componentsConfig, graph); - - graph.complete(fallbackInjector); - return graph; - } - - private void addNodes(ComponentsConfig componentsConfig, ComponentGraph graph) { - - for (ComponentsConfig.Components config : componentsConfig.components()) { - BundleInstantiationSpecification specification = bundleInstantiationSpecification(config); - Class<?> componentClass = osgi.resolveClass(specification); - Node componentNode; - - if (RestApiContext.class.isAssignableFrom(componentClass)) { - Class<? extends RestApiContext> nodeClass = componentClass.asSubclass(RestApiContext.class); - componentNode = new JerseyNode(specification.id, config.configId(), nodeClass, osgi); - } else { - componentNode = new ComponentNode(specification.id, config.configId(), componentClass, null); - } - graph.add(componentNode); - } - } - - private void injectNodes(ComponentsConfig config, ComponentGraph graph) { - for (ComponentsConfig.Components component : config.components()) { - Node componentNode = ComponentGraph.getNode(graph, component.id()); - - for (ComponentsConfig.Components.Inject inject : component.inject()) { - //TODO: Support inject.name() - componentNode.inject(ComponentGraph.getNode(graph, inject.id())); - } - } - } - - private void invalidateGeneration(long generation, Throwable cause) { - leastGeneration = Math.max(configurer.getComponentsGeneration(), configurer.getBootstrapGeneration()) + 1; - if (!(cause instanceof InterruptedException) && !(cause instanceof ConfigInterruptedException)) { - log.log(Level.WARNING, newGraphErrorMessage(generation, cause), cause); - } - } - - private static String newGraphErrorMessage(long generation, Throwable cause) { - String failedFirstMessage = "Failed to set up first component graph"; - String failedNewMessage = "Failed to set up new component graph"; - String constructMessage = " due to error when constructing one of the components"; - String retainMessage = ". Retaining previous component generation."; - - if (generation == 0) { - if (cause instanceof ComponentNode.ComponentConstructorException) { - return failedFirstMessage + constructMessage; - } else { - return failedFirstMessage; - } - } else { - if (cause instanceof ComponentNode.ComponentConstructorException) { - return failedNewMessage + constructMessage + retainMessage; - } else { - return failedNewMessage + retainMessage; - } - } - } - - public void shutdown(ComponentGraph graph, ComponentDeconstructor deconstructor) { - shutdownConfigurer(); - if (graph != null) { - deconstructAllComponents(graph, deconstructor); - } - } - - void shutdownConfigurer() { - configurer.shutdown(); - } - - // Reload config manually, when subscribing to non-configserver sources - public void reloadConfig(long generation) { - subscriberFactory.reloadActiveSubscribers(generation); - } - - private void deconstructAllComponents(ComponentGraph graph, ComponentDeconstructor deconstructor) { - // This is only used for shutdown, so no need to uninstall any bundles. - deconstructor.deconstruct(graph.allConstructedComponentsAndProviders(), Collections.emptyList()); - } - - public static <T extends ConfigInstance> T getConfig(ConfigKey<T> key, - Map<ConfigKey<? extends ConfigInstance>, ConfigInstance> configs) { - ConfigInstance inst = configs.get(key); - - if (inst == null || key.getConfigClass() == null) { - throw new RuntimeException("Missing config " + key); - } - - return key.getConfigClass().cast(inst); - } - - private static BundleInstantiationSpecification bundleInstantiationSpecification(ComponentsConfig.Components config) { - return BundleInstantiationSpecification.getFromStrings(config.id(), config.classId(), config.bundle()); - } - -} diff --git a/container-core/src/main/java/com/yahoo/container/di/Osgi.java b/container-core/src/main/java/com/yahoo/container/di/Osgi.java deleted file mode 100644 index 940986e2f38..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/Osgi.java +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di; - -import com.yahoo.component.ComponentSpecification; -import com.yahoo.config.FileReference; -import com.yahoo.container.bundle.BundleInstantiationSpecification; -import com.yahoo.container.bundle.MockBundle; -import com.yahoo.container.di.osgi.BundleClasses; -import org.osgi.framework.Bundle; - -import java.util.Collection; -import java.util.Collections; -import java.util.Set; -import java.util.stream.Collectors; - -import static java.util.Collections.emptySet; - -/** - * @author gjoranv - * @author Tony Vaagenes - * @author ollivir - */ -public interface Osgi { - default BundleClasses getBundleClasses(ComponentSpecification bundle, Set<String> packagesToScan) { - return new BundleClasses(new MockBundle(), Collections.emptySet()); - } - - default void installPlatformBundles(Collection<String> bundlePaths) { - System.out.println("installPlatformBundles " + bundlePaths); - } - - /** - * Returns the set of bundles that is not used by the current application generation, - * and therefore should be scheduled for uninstalling. - */ - default Set<Bundle> useApplicationBundles(Collection<FileReference> bundles) { - System.out.println("useBundles " + bundles.stream().map(Object::toString).collect(Collectors.joining(", "))); - return emptySet(); - } - - default Class<?> resolveClass(BundleInstantiationSpecification spec) { - System.out.println("resolving class " + spec.classId); - try { - return Class.forName(spec.classId.getName()); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - default Bundle getBundle(ComponentSpecification spec) { - System.out.println("resolving bundle " + spec); - return new MockBundle(); - } -} diff --git a/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/ComponentGraph.java b/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/ComponentGraph.java deleted file mode 100644 index fef2809f236..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/ComponentGraph.java +++ /dev/null @@ -1,431 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di.componentgraph.core; - -import com.google.common.collect.Iterables; -import com.google.common.collect.Sets; -import com.google.inject.BindingAnnotation; -import com.google.inject.ConfigurationException; -import com.google.inject.Guice; -import com.google.inject.Injector; -import com.google.inject.Key; -import com.yahoo.collections.Pair; -import com.yahoo.component.ComponentId; -import com.yahoo.component.provider.ComponentRegistry; -import com.yahoo.config.ConfigInstance; -import com.yahoo.container.di.componentgraph.Provider; -import com.yahoo.container.di.componentgraph.cycle.CycleFinder; -import com.yahoo.container.di.componentgraph.cycle.Graph; - -import java.util.Collections; -import java.util.logging.Level; -import com.yahoo.vespa.config.ConfigKey; - -import java.lang.annotation.Annotation; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.lang.reflect.WildcardType; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.logging.Logger; -import java.util.stream.Collectors; - -import static com.yahoo.container.di.componentgraph.core.Exceptions.removeStackTrace; - -/** - * @author Tony Vaagenes - * @author gjoranv - * @author ollivir - * - * Not thread safe. - */ -public class ComponentGraph { - - private static final Logger log = Logger.getLogger(ComponentGraph.class.getName()); - - private final long generation; - private final Map<ComponentId, Node> nodesById = new HashMap<>(); - - public ComponentGraph(long generation) { - this.generation = generation; - } - - public ComponentGraph() { - this(0L); - } - - public long generation() { - return generation; - } - - public int size() { - return nodesById.size(); - } - - public Collection<Node> nodes() { - return nodesById.values(); - } - - public void add(Node component) { - if (nodesById.containsKey(component.componentId())) { - throw new IllegalStateException("Multiple components with the same id " + component.componentId()); - } - nodesById.put(component.componentId(), component); - } - - private Optional<Node> lookupGlobalComponent(Key<?> key) { - if (!(key.getTypeLiteral().getType() instanceof Class)) { - throw new RuntimeException("Type not supported " + key.getTypeLiteral()); - } - Class<?> clazz = key.getTypeLiteral().getRawType(); - - Collection<ComponentNode> components = matchingComponentNodes(nodes(), key); - if (components.isEmpty()) { - return Optional.empty(); - } else if (components.size() == 1) { - return Optional.ofNullable(Iterables.get(components, 0)); - } else { - - List<Node> nonProviderComponents = components.stream().filter(c -> !Provider.class.isAssignableFrom(c.instanceType())) - .collect(Collectors.toList()); - if (nonProviderComponents.isEmpty()) { - throw new IllegalStateException("Multiple global component providers for class '" + clazz.getName() + "' found"); - } else if (nonProviderComponents.size() == 1) { - return Optional.of(nonProviderComponents.get(0)); - } else { - throw new IllegalStateException("Multiple global components with class '" + clazz.getName() + "' found"); - } - } - } - - public <T> T getInstance(Class<T> clazz) { - return getInstance(Key.get(clazz)); - } - - @SuppressWarnings("unchecked") - public <T> T getInstance(Key<T> key) { - // TODO: Combine exception handling with lookupGlobalComponent. - Object ob = lookupGlobalComponent(key).map(Node::component) - .orElseThrow(() -> new IllegalStateException(String.format("No global component with key '%s' ", key))); - return (T) ob; - } - - private Collection<ComponentNode> componentNodes() { - return nodesOfType(nodes(), ComponentNode.class); - } - - private Collection<ComponentRegistryNode> componentRegistryNodes() { - return nodesOfType(nodes(), ComponentRegistryNode.class); - } - - private Collection<ComponentNode> osgiComponentsOfClass(Class<?> clazz) { - return componentNodes().stream().filter(node -> clazz.isAssignableFrom(node.componentType())).collect(Collectors.toList()); - } - - public List<Node> complete(Injector fallbackInjector) { - componentNodes().forEach(node -> completeNode(node, fallbackInjector)); - componentRegistryNodes().forEach(this::completeComponentRegistryNode); - return topologicalSort(nodes()); - } - - public List<Node> complete() { - return complete(Guice.createInjector()); - } - - public Set<ConfigKey<? extends ConfigInstance>> configKeys() { - return nodes().stream().flatMap(node -> node.configKeys().stream()).collect(Collectors.toSet()); - } - - public void setAvailableConfigs(Map<ConfigKey<? extends ConfigInstance>, ConfigInstance> configs) { - componentNodes().forEach(node -> node.setAvailableConfigs(Keys.invariantCopy(configs))); - } - - public void reuseNodes(ComponentGraph old) { - // copy instances if node equal - Set<ComponentId> commonComponentIds = Sets.intersection(nodesById.keySet(), old.nodesById.keySet()); - for (ComponentId id : commonComponentIds) { - if (nodesById.get(id).equals(old.nodesById.get(id))) { - nodesById.get(id).instance = old.nodesById.get(id).instance; - } - } - - // reset instances with modified dependencies - for (Node node : topologicalSort(nodes())) { - for (Node usedComponent : node.usedComponents()) { - if (usedComponent.instance.isEmpty()) { - node.instance = Optional.empty(); - } - } - } - } - - /** All constructed components and providers of this, in reverse creation order, i.e., suited for ordered deconstruction. */ - public List<Object> allConstructedComponentsAndProviders() { - List<Node> orderedNodes = topologicalSort(nodes()); - Collections.reverse(orderedNodes); - return orderedNodes.stream().map(node -> node.constructedInstance().get()).collect(Collectors.toList()); - } - - private void completeComponentRegistryNode(ComponentRegistryNode registry) { - registry.injectAll(osgiComponentsOfClass(registry.componentClass())); - } - - private void completeNode(ComponentNode node, Injector fallbackInjector) { - try { - Object[] arguments = node.getAnnotatedConstructorParams().stream().map(param -> handleParameter(node, fallbackInjector, param)) - .toArray(); - - node.setArguments(arguments); - } catch (Exception e) { - throw removeStackTrace(new RuntimeException("When resolving dependencies of " + node.idAndType(), e)); - } - } - - private Object handleParameter(Node node, Injector fallbackInjector, Pair<Type, List<Annotation>> annotatedParameterType) { - Type parameterType = annotatedParameterType.getFirst(); - List<Annotation> annotations = annotatedParameterType.getSecond(); - - if (parameterType instanceof Class && parameterType.equals(ComponentId.class)) { - return node.componentId(); - } else if (parameterType instanceof Class && ConfigInstance.class.isAssignableFrom((Class<?>) parameterType)) { - return handleConfigParameter((ComponentNode) node, (Class<?>) parameterType); - } else if (parameterType instanceof ParameterizedType - && ((ParameterizedType) parameterType).getRawType().equals(ComponentRegistry.class)) { - ParameterizedType registry = (ParameterizedType) parameterType; - return getComponentRegistry(registry.getActualTypeArguments()[0]); - } else if (parameterType instanceof Class) { - return handleComponentParameter(node, fallbackInjector, (Class<?>) parameterType, annotations); - } else if (parameterType instanceof ParameterizedType) { - throw new RuntimeException("Injection of parameterized type " + parameterType + " is not supported."); - } else { - throw new RuntimeException("Injection of type " + parameterType + " is not supported"); - } - } - - private ComponentRegistryNode newComponentRegistryNode(Class<?> componentClass) { - ComponentRegistryNode registry = new ComponentRegistryNode(componentClass); - add(registry); //TODO: don't mutate nodes here. - return registry; - } - - private ComponentRegistryNode getComponentRegistry(Type componentType) { - Class<?> componentClass; - if (componentType instanceof WildcardType) { - WildcardType wildcardType = (WildcardType) componentType; - if (wildcardType.getLowerBounds().length > 0 || wildcardType.getUpperBounds().length > 1) { - throw new RuntimeException("Can't create ComponentRegistry of unknown wildcard type" + wildcardType); - } - componentClass = (Class<?>) wildcardType.getUpperBounds()[0]; - } else if (componentType instanceof Class) { - componentClass = (Class<?>) componentType; - } else if (componentType instanceof TypeVariable) { - throw new RuntimeException("Can't create ComponentRegistry of unknown type variable " + componentType); - } else { - throw new RuntimeException("Can't create ComponentRegistry of unknown type " + componentType); - } - - for (ComponentRegistryNode node : componentRegistryNodes()) { - if (node.componentClass().equals(componentType)) { - return node; - } - } - return newComponentRegistryNode(componentClass); - } - - @SuppressWarnings("unchecked") - private ConfigKey<ConfigInstance> handleConfigParameter(ComponentNode node, Class<?> clazz) { - Class<ConfigInstance> castClass = (Class<ConfigInstance>) clazz; - return new ConfigKey<>(castClass, node.configId()); - } - - private <T> Key<T> getKey(Class<T> clazz, Optional<Annotation> bindingAnnotation) { - return bindingAnnotation.map(annotation -> Key.get(clazz, annotation)).orElseGet(() -> Key.get(clazz)); - } - - private Optional<GuiceNode> matchingGuiceNode(Key<?> key, Object instance) { - return matchingNodes(nodes(), GuiceNode.class, key).stream().filter(node -> node.component() == instance). // TODO: assert that there is only one (after filter) - findFirst(); - } - - private Node lookupOrCreateGlobalComponent(Node node, Injector fallbackInjector, Class<?> clazz, Key<?> key) { - Optional<Node> component = lookupGlobalComponent(key); - if (component.isEmpty()) { - Object instance; - try { - log.log(Level.FINE, "Trying the fallback injector to create" + messageForNoGlobalComponent(clazz, node)); - instance = fallbackInjector.getInstance(key); - } catch (ConfigurationException e) { - throw removeStackTrace(new IllegalStateException( - (messageForMultipleClassLoaders(clazz).isEmpty()) ? "No global" + messageForNoGlobalComponent(clazz, node) - : messageForMultipleClassLoaders(clazz))); - } - component = Optional.of(matchingGuiceNode(key, instance).orElseGet(() -> { - GuiceNode guiceNode = new GuiceNode(instance, key.getAnnotation()); - add(guiceNode); - return guiceNode; - })); - } - return component.get(); - } - - private Node handleComponentParameter(Node node, Injector fallbackInjector, Class<?> clazz, Collection<Annotation> annotations) { - - List<Annotation> bindingAnnotations = annotations.stream().filter(ComponentGraph::isBindingAnnotation).collect(Collectors.toList()); - Key<?> key = getKey(clazz, bindingAnnotations.stream().findFirst()); - - if (bindingAnnotations.size() > 1) { - throw new RuntimeException(String.format("More than one binding annotation used in class '%s'", node.instanceType())); - } - - Collection<ComponentNode> injectedNodesOfCorrectType = matchingComponentNodes(node.componentsToInject, key); - if (injectedNodesOfCorrectType.size() == 0) { - return lookupOrCreateGlobalComponent(node, fallbackInjector, clazz, key); - } else if (injectedNodesOfCorrectType.size() == 1) { - return Iterables.get(injectedNodesOfCorrectType, 0); - } else { - //TODO: !className for last parameter - throw new RuntimeException( - String.format("Multiple components of type '%s' injected into component '%s'", clazz.getName(), node.instanceType())); - } - } - - private static String messageForNoGlobalComponent(Class<?> clazz, Node node) { - return String.format(" component of class %s to inject into component %s.", clazz.getName(), node.idAndType()); - } - - private String messageForMultipleClassLoaders(Class<?> clazz) { - String errMsg = "Class " + clazz.getName() + " is provided by the framework, and cannot be embedded in a user bundle. " - + "To resolve this problem, please refer to osgi-classloading.html#multiple-implementations in the documentation"; - - try { - Class<?> resolvedClass = Class.forName(clazz.getName(), false, this.getClass().getClassLoader()); - if (!resolvedClass.equals(clazz)) { - return errMsg; - } - } catch (ClassNotFoundException ignored) { - - } - return ""; - } - - public static Node getNode(ComponentGraph graph, String componentId) { - return graph.nodesById.get(new ComponentId(componentId)); - } - - private static <T> Collection<T> nodesOfType(Collection<Node> nodes, Class<T> clazz) { - List<T> ret = new ArrayList<>(); - for (Node node : nodes) { - if (clazz.isInstance(node)) { - ret.add(clazz.cast(node)); - } - } - return ret; - } - - private static Collection<ComponentNode> matchingComponentNodes(Collection<Node> nodes, Key<?> key) { - return matchingNodes(nodes, ComponentNode.class, key); - } - - // Finds all nodes with a given nodeType and instance with given key - private static <T extends Node> Collection<T> matchingNodes(Collection<Node> nodes, Class<T> nodeType, Key<?> key) { - Class<?> clazz = key.getTypeLiteral().getRawType(); - Annotation annotation = key.getAnnotation(); - - List<T> filteredByClass = nodesOfType(nodes, nodeType).stream().filter(node -> clazz.isAssignableFrom(node.componentType())) - .collect(Collectors.toList()); - - if (filteredByClass.size() == 1) { - return filteredByClass; - } else { - List<T> filteredByClassAndAnnotation = filteredByClass.stream() - .filter(node -> (annotation == null && node.instanceKey().getAnnotation() == null) - || annotation.equals(node.instanceKey().getAnnotation())) - .collect(Collectors.toList()); - if (filteredByClassAndAnnotation.size() > 0) { - return filteredByClassAndAnnotation; - } else { - return filteredByClass; - } - } - } - - // Returns true if annotation is a BindingAnnotation, e.g. com.google.inject.name.Named - public static boolean isBindingAnnotation(Annotation annotation) { - LinkedList<Class<?>> queue = new LinkedList<>(); - queue.add(annotation.getClass()); - queue.addAll(Arrays.asList(annotation.getClass().getInterfaces())); - - while (!queue.isEmpty()) { - Class<?> clazz = queue.removeFirst(); - if (clazz.getAnnotation(BindingAnnotation.class) != null) { - return true; - } else { - if (clazz.getSuperclass() != null) { - queue.addFirst(clazz.getSuperclass()); - } - } - } - return false; - } - - /** - * The returned list is the nodes from the graph bottom-up. - * - * For each iteration, the algorithm finds the components that are not "wanted by" any other component, - * and prepends those components into the resulting 'sorted' list. Hence, the first element in the returned - * list is the component that is directly or indirectly wanted by "most" other components. - * - * @return A list where a earlier than b in the list implies that there is no path from a to b - */ - private static List<Node> topologicalSort(Collection<Node> nodes) { - Map<ComponentId, Integer> numIncoming = new HashMap<>(); - - nodes.forEach( - node -> node.usedComponents().forEach( - injectedNode -> numIncoming.merge(injectedNode.componentId(), 1, (a, b) -> a + b))); - - LinkedList<Node> sorted = new LinkedList<>(); - List<Node> unsorted = new ArrayList<>(nodes); - - while (!unsorted.isEmpty()) { - List<Node> ready = new ArrayList<>(); - List<Node> notReady = new ArrayList<>(); - unsorted.forEach(node -> { - if (numIncoming.getOrDefault(node.componentId(), 0) == 0) { - ready.add(node); - } else { - notReady.add(node); - } - }); - - if (ready.isEmpty()) { - throw new IllegalStateException("There is a cycle in the component injection graph: " + findCycle(notReady)); - } - - ready.forEach(node -> node.usedComponents() - .forEach(injectedNode -> numIncoming.merge(injectedNode.componentId(), -1, (a, b) -> a + b))); - sorted.addAll(0, ready); - unsorted = notReady; - } - return sorted; - } - - private static List<String> findCycle(List<Node> nodes) { - var cyclicGraph = new Graph<String>(); - for (var node : nodes) { - for (var adjacent : node.usedComponents()) { - cyclicGraph.edge(node.componentId().stringValue(), - adjacent.componentId().stringValue()); - } - } - return new CycleFinder<>(cyclicGraph).findCycle(); - } - -} diff --git a/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/ComponentNode.java b/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/ComponentNode.java deleted file mode 100644 index b6fa4241e26..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/ComponentNode.java +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di.componentgraph.core; - -import com.google.inject.Inject; -import com.google.inject.Key; -import com.yahoo.collections.Pair; -import com.yahoo.component.AbstractComponent; -import com.yahoo.component.ComponentId; -import com.yahoo.config.ConfigInstance; -import com.yahoo.container.di.componentgraph.Provider; -import com.yahoo.vespa.config.ConfigKey; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.time.Duration; -import java.time.Instant; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.logging.Logger; -import java.util.stream.Collectors; - -import static com.yahoo.container.di.componentgraph.core.Exceptions.cutStackTraceAtConstructor; -import static com.yahoo.container.di.componentgraph.core.Exceptions.removeStackTrace; -import static com.yahoo.container.di.componentgraph.core.Keys.createKey; -import static java.util.logging.Level.FINE; -import static java.util.logging.Level.INFO; - -/** - * @author Tony Vaagenes - * @author gjoranv - * @author ollivir - */ -public class ComponentNode extends Node { - - private static final Logger log = Logger.getLogger(ComponentNode.class.getName()); - - private final Class<?> clazz; - private final Annotation key; - private Object[] arguments = null; - private final String configId; - - private final Constructor<?> constructor; - - private Map<ConfigKey<ConfigInstance>, ConfigInstance> availableConfigs = null; - - - public ComponentNode(ComponentId componentId, - String configId, - Class<?> clazz, Annotation XXX_key) // TODO expose key, not javaAnnotation - { - super(componentId); - if (isAbstract(clazz)) { - throw new IllegalArgumentException("Can't instantiate abstract class " + clazz.getName()); - } - this.configId = configId; - this.clazz = clazz; - this.key = XXX_key; - this.constructor = bestConstructor(clazz); - } - - public ComponentNode(ComponentId componentId, String configId, Class<?> clazz) { - this(componentId, configId, clazz, null); - } - - public String configId() { - return configId; - } - - @Override - public Key<?> instanceKey() { - return createKey(clazz, key); - } - - @Override - public Class<?> instanceType() { - return clazz; - } - - @Override - public List<Node> usedComponents() { - if (arguments == null) { - throw new IllegalStateException("Arguments must be set first."); - } - List<Node> ret = new ArrayList<>(); - for (Object arg : arguments) { - if (arg instanceof Node) { - ret.add((Node) arg); - } - } - return ret; - } - - private static List<Class<?>> allSuperClasses(Class<?> clazz) { - List<Class<?>> ret = new ArrayList<>(); - while (clazz != null) { - ret.add(clazz); - clazz = clazz.getSuperclass(); - } - return ret; - } - - @Override - public Class<?> componentType() { - if (Provider.class.isAssignableFrom(clazz)) { - //TODO: Test what happens if you ask for something that isn't a class, e.g. a parameterized type. - - List<Type> allGenericInterfaces = allSuperClasses(clazz).stream().flatMap(c -> Arrays.stream(c.getGenericInterfaces())).collect(Collectors.toList()); - for (Type t : allGenericInterfaces) { - if (t instanceof ParameterizedType && ((ParameterizedType) t).getRawType().equals(Provider.class)) { - Type[] typeArgs = ((ParameterizedType) t).getActualTypeArguments(); - if (typeArgs != null && typeArgs.length > 0) { - return (Class<?>) typeArgs[0]; - } - } - } - throw new IllegalStateException("Component type cannot be resolved"); - } else { - return clazz; - } - } - - public void setArguments(Object[] arguments) { - this.arguments = arguments; - } - - @Override - protected Object newInstance() { - if (arguments == null) { - throw new IllegalStateException("graph.complete must be called before retrieving instances."); - } - - List<Object> actualArguments = new ArrayList<>(); - for (Object ob : arguments) { - if (ob instanceof Node) { - actualArguments.add(((Node) ob).component()); - } else if (ob instanceof ConfigKey) { - actualArguments.add(availableConfigs.get(ob)); - } else { - actualArguments.add(ob); - } - } - - Object instance; - try { - log.log(FINE, () -> "Constructing " + idAndType()); - Instant start = Instant.now(); - instance = constructor.newInstance(actualArguments.toArray()); - Duration duration = Duration.between(start, Instant.now()); - log.log(duration.compareTo(Duration.ofMinutes(1)) > 0 ? INFO : FINE, - () -> "Finished constructing " + idAndType() + " in " + duration); - } catch (InvocationTargetException | InstantiationException | IllegalAccessException e) { - StackTraceElement dependencyInjectorMarker = new StackTraceElement("============= Dependency Injection =============", "newInstance", null, -1); - throw removeStackTrace(new ComponentConstructorException("Error constructing " + idAndType() + ": " + e.getMessage(), cutStackTraceAtConstructor(e.getCause(), dependencyInjectorMarker))); - } - - return initId(instance); - } - - private Object initId(Object component) { - if (component instanceof AbstractComponent) { - AbstractComponent abstractComponent = (AbstractComponent) component; - if (abstractComponent.hasInitializedId() && !abstractComponent.getId().equals(componentId())) { - throw new IllegalStateException( - "Component with id '" + componentId() + "' is trying to set its component id explicitly: '" + abstractComponent.getId() + "'. " + - "This is not allowed, so please remove any call to super() in your component's constructor."); - } - abstractComponent.initId(componentId()); - } - return component; - } - - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + Arrays.hashCode(arguments); - result = prime * result + ((availableConfigs == null) ? 0 : availableConfigs.hashCode()); - result = prime * result + ((configId == null) ? 0 : configId.hashCode()); - return result; - } - - @Override - public boolean equals(Object other) { - if (other instanceof ComponentNode) { - ComponentNode that = (ComponentNode) other; - return super.equals(that) && equalEdges(Arrays.asList(this.arguments), Arrays.asList(that.arguments)) && this.usedConfigs().equals(that.usedConfigs()); - } else { - return false; - } - } - - private List<ConfigInstance> usedConfigs() { - if (availableConfigs == null) { - throw new IllegalStateException("setAvailableConfigs must be called!"); - } - List<ConfigInstance> ret = new ArrayList<>(); - for (Object arg : arguments) { - if (arg instanceof ConfigKey) { - ret.add(availableConfigs.get(arg)); - } - } - return ret; - } - - protected List<Pair<Type, List<Annotation>>> getAnnotatedConstructorParams() { - Type[] types = constructor.getGenericParameterTypes(); - Annotation[][] annotations = constructor.getParameterAnnotations(); - - List<Pair<Type, List<Annotation>>> ret = new ArrayList<>(); - - for (int i = 0; i < types.length; i++) { - ret.add(new Pair<>(types[i], Arrays.asList(annotations[i]))); - } - return ret; - } - - public void setAvailableConfigs(Map<ConfigKey<ConfigInstance>, ConfigInstance> configs) { - if (arguments == null) { - throw new IllegalStateException("graph.complete must be called before graph.setAvailableConfigs."); - } - this.availableConfigs = configs; - } - - @Override - public Set<ConfigKey<ConfigInstance>> configKeys() { - return configParameterClasses().stream().map(par -> new ConfigKey<>(par, configId)).collect(Collectors.toSet()); - } - - @SuppressWarnings("unchecked") - private List<Class<ConfigInstance>> configParameterClasses() { - List<Class<ConfigInstance>> ret = new ArrayList<>(); - for (Type type : constructor.getGenericParameterTypes()) { - if (type instanceof Class && ConfigInstance.class.isAssignableFrom((Class<?>) type)) { - ret.add((Class<ConfigInstance>) type); - } - } - return ret; - } - - @Override - public String label() { - LinkedList<String> configNames = configKeys().stream().map(k -> k.getName() + ".def").collect(Collectors.toCollection(LinkedList::new)); - - configNames.addFirst(instanceType().getSimpleName()); - configNames.addFirst(Node.packageName(instanceType())); - - return "{" + String.join("|", configNames) + "}"; - } - - private static Constructor<?> bestConstructor(Class<?> clazz) { - Constructor<?>[] publicConstructors = clazz.getConstructors(); - - Constructor<?> annotated = null; - for (Constructor<?> ctor : publicConstructors) { - Annotation annotation = ctor.getAnnotation(Inject.class); - if (annotation != null) { - if (annotated == null) { - annotated = ctor; - } else { - throw componentConstructorException("Multiple constructor annotated with @Inject in class " + clazz.getName()); - } - } - } - if (annotated != null) { - return annotated; - } - - if (publicConstructors.length == 0) { - throw componentConstructorException("No public constructors in class " + clazz.getName()); - } else if (publicConstructors.length == 1) { - return publicConstructors[0]; - } else { - log.warning(String.format("Multiple public constructors found in class %s, there should only be one. " - + "If more than one public constructor is needed, the primary one must be annotated with @Inject.", clazz.getName())); - List<Pair<Constructor<?>, Integer>> withParameterCount = new ArrayList<>(); - for (Constructor<?> ctor : publicConstructors) { - long count = Arrays.stream(ctor.getParameterTypes()).filter(ConfigInstance.class::isAssignableFrom).count(); - withParameterCount.add(new Pair<>(ctor, (int) count)); - } - withParameterCount.sort(Comparator.comparingInt(Pair::getSecond)); - return withParameterCount.get(withParameterCount.size() - 1).getFirst(); - } - } - - private static ComponentConstructorException componentConstructorException(String message) { - return removeStackTrace(new ComponentConstructorException(message)); - } - - public static class ComponentConstructorException extends RuntimeException { - ComponentConstructorException(String message) { - super(message); - } - - ComponentConstructorException(String message, Throwable cause) { - super(message, cause); - } - } - - - private static boolean isAbstract(Class<?> clazz) { - return Modifier.isAbstract(clazz.getModifiers()); - } -}
\ No newline at end of file diff --git a/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/ComponentRegistryNode.java b/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/ComponentRegistryNode.java deleted file mode 100644 index 429052c0039..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/ComponentRegistryNode.java +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di.componentgraph.core; - -import com.google.inject.Key; -import com.google.inject.util.Types; -import com.yahoo.component.ComponentId; -import com.yahoo.component.provider.ComponentRegistry; -import com.yahoo.config.ConfigInstance; -import com.yahoo.vespa.config.ConfigKey; - -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * @author Tony Vaagenes - * @author gjoranv - * @author ollivir - */ -public class ComponentRegistryNode extends Node { - - private static ComponentId componentRegistryNamespace = ComponentId.fromString("ComponentRegistry"); - - private final Class<?> componentClass; - - public ComponentRegistryNode(Class<?> componentClass) { - super(componentId(componentClass)); - this.componentClass = componentClass; - } - - @Override - public List<Node> usedComponents() { - return componentsToInject; - } - - @Override - protected Object newInstance() { - ComponentRegistry<Object> registry = new ComponentRegistry<>(); - componentsToInject.forEach(component -> registry.register(component.componentId(), component.component())); - - return registry; - } - - @Override - public Key<?> instanceKey() { - return Key.get(Types.newParameterizedType(ComponentRegistry.class, componentClass)); - } - - @Override - public Class<?> instanceType() { - return instanceKey().getTypeLiteral().getRawType(); - } - - @Override - public Class<?> componentType() { - return instanceType(); - } - - public Class<?> componentClass() { - return componentClass; - } - - @Override - public Set<ConfigKey<ConfigInstance>> configKeys() { - return Collections.emptySet(); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((componentClass == null) ? 0 : componentClass.hashCode()); - return result; - } - - @Override - public boolean equals(Object other) { - if (other instanceof ComponentRegistryNode) { - ComponentRegistryNode that = (ComponentRegistryNode) other; - return this.componentId().equals(that.componentId()) && this.instanceType().equals(that.instanceType()) - && equalNodeEdges(this.usedComponents(), that.usedComponents()); - } else { - return false; - } - } - - @Override - public String label() { - return String.format("{ComponentRegistry\\<%s\\>|%s}", componentClass.getSimpleName(), Node.packageName(componentClass)); - } - - private static ComponentId componentId(Class<?> componentClass) { - return syntheticComponentId(componentClass.getName(), componentClass, componentRegistryNamespace); - } - - public static boolean equalNodeEdges(List<Node> edges, List<Node> otherEdges) { - if (edges.size() == otherEdges.size()) { - List<ComponentId> left = edges.stream().map(Node::componentId).sorted().collect(Collectors.toList()); - List<ComponentId> right = otherEdges.stream().map(Node::componentId).sorted().collect(Collectors.toList()); - return left.equals(right); - } else { - return false; - } - } - -} diff --git a/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/Exceptions.java b/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/Exceptions.java deleted file mode 100644 index b0d9d1f3921..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/Exceptions.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di.componentgraph.core; - -import java.util.Arrays; - -class Exceptions { - - static <E extends Throwable> E removeStackTrace(E exception) { - if (preserveStackTrace()) { - return exception; - } else { - exception.setStackTrace(new StackTraceElement[0]); - return exception; - } - } - - static boolean preserveStackTrace() { - String preserve = System.getProperty("jdisc.container.preserveStackTrace"); - return (preserve != null && !preserve.isEmpty()); - } - - static Throwable cutStackTraceAtConstructor(Throwable throwable, StackTraceElement marker) { - if (throwable != null && !preserveStackTrace()) { - StackTraceElement[] stackTrace = throwable.getStackTrace(); - int upTo = stackTrace.length - 1; - - // take until ComponentNode is reached - while (upTo >= 0 && !stackTrace[upTo].getClassName().equals(ComponentNode.class.getName())) { - upTo--; - } - - // then drop until <init> is reached - while (upTo >= 0 && !stackTrace[upTo].getMethodName().equals("<init>")) { - upTo--; - } - if (upTo < 0) { - throwable.setStackTrace(new StackTraceElement[0]); - } else { - throwable.setStackTrace(Arrays.copyOfRange(stackTrace, 0, upTo)); - } - - cutStackTraceAtConstructor(throwable.getCause(), marker); - } - return throwable; - } - -} diff --git a/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/GuiceNode.java b/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/GuiceNode.java deleted file mode 100644 index 61d0d9bba8d..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/GuiceNode.java +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di.componentgraph.core; - -import com.google.inject.Key; -import com.yahoo.component.ComponentId; -import com.yahoo.config.ConfigInstance; -import com.yahoo.vespa.config.ConfigKey; - -import java.lang.annotation.Annotation; -import java.util.Collections; -import java.util.List; -import java.util.Set; - -import static com.yahoo.container.di.componentgraph.core.Keys.createKey; - -/** - * @author Tony Vaagenes - * @author gjoranv - * @author ollivir - */ -public final class GuiceNode extends Node { - private static final ComponentId guiceNamespace = ComponentId.fromString("Guice"); - - private final Object myInstance; - private final Annotation annotation; - - public GuiceNode(Object myInstance, - Annotation annotation) { - super(componentId(myInstance)); - this.myInstance = myInstance; - this.annotation = annotation; - } - - @Override - public Set<ConfigKey<ConfigInstance>> configKeys() { - return Collections.emptySet(); - } - - @Override - public Key<?> instanceKey() { - return createKey(myInstance.getClass(), annotation); - } - - @Override - public Class<?> instanceType() { - return myInstance.getClass(); - } - - @Override - public Class<?> componentType() { - return instanceType(); - } - - - @Override - public List<Node> usedComponents() { - return Collections.emptyList(); - } - - @Override - protected Object newInstance() { - return myInstance; - } - - @Override - public void inject(Node component) { - throw new UnsupportedOperationException("Illegal to inject components to a GuiceNode!"); - } - - @Override - public String label() { - return String.format("{{%s|Guice}|%s}", instanceType().getSimpleName(), Node.packageName(instanceType())); - } - - private static ComponentId componentId(Object instance) { - return Node.syntheticComponentId(instance.getClass().getName(), instance, guiceNamespace); - } -} diff --git a/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/JerseyNode.java b/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/JerseyNode.java deleted file mode 100644 index 0f8aa678934..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/JerseyNode.java +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di.componentgraph.core; - -import com.yahoo.component.ComponentId; -import com.yahoo.component.ComponentSpecification; -import com.yahoo.container.di.Osgi; -import com.yahoo.container.di.config.JerseyBundlesConfig; -import com.yahoo.container.di.config.RestApiContext; -import com.yahoo.container.di.config.RestApiContext.BundleInfo; -import com.yahoo.container.di.osgi.BundleClasses; -import org.osgi.framework.Bundle; -import org.osgi.framework.wiring.BundleWiring; - -import java.net.URL; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; - -/** - * Represents an instance of RestApiContext - * - * @author gjoranv - * @author Tony Vaagenes - * @author ollivir - */ -public class JerseyNode extends ComponentNode { - private static final String WEB_INF_URL = "WebInfUrl"; - - private final Osgi osgi; - - public JerseyNode(ComponentId componentId, String configId, Class<?> clazz, Osgi osgi) { - super(componentId, configId, clazz, null); - this.osgi = osgi; - } - - @Override - protected RestApiContext newInstance() { - Object instance = super.newInstance(); - RestApiContext restApiContext = (RestApiContext) instance; - - List<JerseyBundlesConfig.Bundles> bundles = restApiContext.bundlesConfig.bundles(); - for (JerseyBundlesConfig.Bundles bundleConfig : bundles) { - BundleClasses bundleClasses = osgi.getBundleClasses(ComponentSpecification.fromString(bundleConfig.spec()), - new HashSet<>(bundleConfig.packages())); - - restApiContext.addBundle(createBundleInfo(bundleClasses.bundle(), bundleClasses.classEntries())); - } - - componentsToInject.forEach(component -> restApiContext.addInjectableComponent(component.instanceKey(), component.componentId(), - component.component())); - - return restApiContext; - } - - @Override - public int hashCode() { - return super.hashCode(); - } - - @Override - public boolean equals(Object other) { - return super.equals(other) - && (other instanceof JerseyNode && this.componentsToInject.equals(((JerseyNode) other).componentsToInject)); - } - - public static BundleInfo createBundleInfo(Bundle bundle, Collection<String> classEntries) { - BundleInfo bundleInfo = new BundleInfo(bundle.getSymbolicName(), bundle.getVersion(), bundle.getLocation(), webInfUrl(bundle), - bundle.adapt(BundleWiring.class).getClassLoader()); - - bundleInfo.setClassEntries(classEntries); - return bundleInfo; - } - - public static Bundle getBundle(Osgi osgi, String bundleSpec) { - Bundle bundle = osgi.getBundle(ComponentSpecification.fromString(bundleSpec)); - if (bundle == null) { - throw new IllegalArgumentException("Bundle not found: " + bundleSpec); - } - return bundle; - } - - private static URL webInfUrl(Bundle bundle) { - String webInfUrlHeader = bundle.getHeaders().get(WEB_INF_URL); - - if (webInfUrlHeader == null) { - return null; - } else { - return bundle.getEntry(webInfUrlHeader); - } - } - -} diff --git a/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/Keys.java b/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/Keys.java deleted file mode 100644 index be80fc1616d..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/Keys.java +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di.componentgraph.core; - -import com.google.inject.Key; -import com.yahoo.config.ConfigInstance; -import com.yahoo.vespa.config.ConfigKey; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; -import java.util.HashMap; -import java.util.Map; - -/** - * @author ollivir - */ -public class Keys { - - static Key<?> createKey(Type instanceType, Annotation annotation) { - if (annotation == null) { - return Key.get(instanceType); - } else { - return Key.get(instanceType, annotation); - } - } - - @SuppressWarnings("unchecked") - public static Map<ConfigKey<ConfigInstance>, ConfigInstance> invariantCopy(Map<ConfigKey<? extends ConfigInstance>, ConfigInstance> configs) { - Map<ConfigKey<ConfigInstance>, ConfigInstance> ret = new HashMap<>(); - configs.forEach((k, v) -> ret.put((ConfigKey<ConfigInstance>) k, v)); - return ret; - } - - public static Map<ConfigKey<? extends ConfigInstance>, ConfigInstance> covariantCopy(Map<ConfigKey<ConfigInstance>, ConfigInstance> configs) { - Map<ConfigKey<? extends ConfigInstance>, ConfigInstance> ret = new HashMap<>(); - configs.forEach((k, v) -> ret.put(k, v)); - return ret; - } - -} diff --git a/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/Node.java b/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/Node.java deleted file mode 100644 index 3afc8bb817c..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/Node.java +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di.componentgraph.core; - -import com.google.inject.Key; -import com.yahoo.component.ComponentId; -import com.yahoo.config.ConfigInstance; -import com.yahoo.container.di.componentgraph.Provider; -import com.yahoo.vespa.config.ConfigKey; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.logging.Logger; - -import static java.util.logging.Level.FINE; - -/** - * @author Tony Vaagenes - * @author gjoranv - * @author ollivir - */ -public abstract class Node { - - private final static Logger log = Logger.getLogger(Node.class.getName()); - - private final ComponentId componentId; - protected Optional<Object> instance = Optional.empty(); - List<Node> componentsToInject = new ArrayList<>(); - - public Node(ComponentId componentId) { - this.componentId = componentId; - } - - public abstract Key<?> instanceKey(); - - /** - * The components actually used by this node. Consist of a subset of the injected nodes + subset of the global nodes. - */ - public abstract List<Node> usedComponents(); - - protected abstract Object newInstance(); - - /** Constructs the instance represented by this node, if not already done. */ - public void constructInstance() { - if ( ! instance.isPresent()) - instance = Optional.of(newInstance()); - } - - /** - * Returns the component represented by this - which is either the instance, or if the instance is a provider, - * the component returned by it. - */ - public Object component() { - constructInstance(); - if (instance.get() instanceof Provider) { - Provider<?> provider = (Provider<?>) instance.get(); - return provider.get(); - } else { - return instance.get(); - } - } - - public abstract Set<ConfigKey<ConfigInstance>> configKeys(); - - public void inject(Node component) { - componentsToInject.add(component); - } - - public void injectAll(Collection<ComponentNode> componentNodes) { - componentNodes.forEach(this::inject); - } - - public abstract Class<?> instanceType(); - - public abstract Class<?> componentType(); - - public abstract String label(); - - public String idAndType() { - String className = instanceType().getName(); - - if (className.equals(componentId.getName())) { - return "'" + componentId + "'"; - } else { - return "'" + componentId + "' of type '" + className + "'"; - } - } - - private static boolean equalNodes(Object a, Object b) { - if (a instanceof Node && b instanceof Node) { - Node l = (Node) a; - Node r = (Node) b; - return l.componentId.equals(r.componentId); - } else { - return a.equals(b); - } - } - - public static boolean equalEdges(List<?> edges1, List<?> edges2) { - Iterator<?> right = edges2.iterator(); - for (Object l : edges1) { - if (!right.hasNext()) { - return false; - } - Object r = right.next(); - if (!equalNodes(l, r)) { - return false; - } - } - return !right.hasNext(); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((componentId == null) ? 0 : componentId.hashCode()); - result = prime * result + ((componentsToInject == null) ? 0 : componentsToInject.hashCode()); - return result; - } - - @Override - public boolean equals(Object other) { - if (other instanceof Node) { - Node that = (Node) other; - return getClass().equals(that.getClass()) && this.componentId.equals(that.componentId) - && this.instanceType().equals(that.instanceType()) && equalEdges(this.usedComponents(), that.usedComponents()); - } else { - return false; - } - } - - public ComponentId componentId() { - return componentId; - } - - /** Returns the already constructed instance in this, if any */ - public Optional<?> constructedInstance() { - return instance; - } - - /** - * @param identityObject he identifying object that makes the Node unique - */ - protected static ComponentId syntheticComponentId(String className, Object identityObject, ComponentId namespace) { - String name = className + "_" + System.identityHashCode(identityObject); - return ComponentId.fromString(name).nestInNamespace(namespace); - } - - public static String packageName(Class<?> componentClass) { - String fullClassName = componentClass.getName(); - int index = fullClassName.lastIndexOf('.'); - if (index < 0) { - return ""; - } else { - return fullClassName.substring(0, index); - } - } -} diff --git a/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/package-info.java b/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/package-info.java deleted file mode 100644 index e9b5b14d5d8..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/componentgraph/core/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -@ExportPackage -package com.yahoo.container.di.componentgraph.core; - -import com.yahoo.osgi.annotation.ExportPackage; diff --git a/container-core/src/main/java/com/yahoo/container/di/componentgraph/cycle/CycleFinder.java b/container-core/src/main/java/com/yahoo/container/di/componentgraph/cycle/CycleFinder.java deleted file mode 100644 index 327949bb8d0..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/componentgraph/cycle/CycleFinder.java +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di.componentgraph.cycle; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.logging.Logger; -import java.util.stream.Collectors; - -import static com.yahoo.container.di.componentgraph.cycle.CycleFinder.State.BLACK; -import static com.yahoo.container.di.componentgraph.cycle.CycleFinder.State.GRAY; -import static com.yahoo.container.di.componentgraph.cycle.CycleFinder.State.WHITE; -import static java.util.logging.Level.FINE; -import static java.util.Collections.singletonList; - - -/** - * <p>Applies the - * <a href="https://www.geeksforgeeks.org/detect-cycle-direct-graph-using-colors/"> three-color algorithm</a> - * to detect a cycle in a directed graph. If there are multiple cycles, this implementation only detects one - * of them and does not guarantee that the shortest cycle is found. - * </p> - * - * @author gjoranv - */ -public class CycleFinder<T> { - private static final Logger log = Logger.getLogger(CycleFinder.class.getName()); - - enum State { - WHITE, GRAY, BLACK; - } - - private final Graph<T> graph; - - private Map<T, State> colors; - - private List<T> cycle; - - public CycleFinder(Graph<T> graph) { - this.graph = graph; - } - - private void resetState() { - cycle = null; - colors = new LinkedHashMap<>(); - graph.getVertices().forEach(v -> colors.put(v, WHITE)); - } - - /** - * Returns a list of vertices constituting a cycle in the graph, or an empty - * list if no cycle was found. Only the first encountered cycle is returned. - */ - public List<T> findCycle() { - resetState(); - for (T vertex : graph.getVertices()) { - if (colors.get(vertex) == WHITE) { - if (visitDepthFirst(vertex, new ArrayList<>(singletonList(vertex)))) { - if (cycle == null) throw new IllegalStateException("Null cycle - this should never happen"); - if (cycle.isEmpty()) throw new IllegalStateException("Empty cycle - this should never happen"); - log.log(FINE, "Cycle detected: " + cycle); - return cycle; - } - } - } - return new ArrayList<>(); - } - - private boolean visitDepthFirst(T vertex, List<T> path) { - colors.put(vertex, GRAY); - log.log(FINE, "Vertex start " + vertex + " - colors: " + colors + " - path: " + path); - for (T adjacent : graph.getAdjacent(vertex)) { - path.add(adjacent); - if (colors.get(adjacent) == GRAY) { - cycle = removePathIntoCycle(path); - return true; - } - if (colors.get(adjacent) == WHITE && visitDepthFirst(adjacent, path)) { - return true; - } - path.remove(adjacent); - } - colors.put(vertex, BLACK); - log.log(FINE, "Vertex end " + vertex + " - colors: " + colors + " - path: " + path); - return false; - } - - private List<T> removePathIntoCycle(List<T> pathWithCycle) { - T cycleStart = pathWithCycle.get(pathWithCycle.size() - 1); - return pathWithCycle.stream() - .dropWhile(vertex -> ! vertex.equals(cycleStart)) - .collect(Collectors.toList()); - } - -} diff --git a/container-core/src/main/java/com/yahoo/container/di/componentgraph/cycle/Graph.java b/container-core/src/main/java/com/yahoo/container/di/componentgraph/cycle/Graph.java deleted file mode 100644 index 946330668bd..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/componentgraph/cycle/Graph.java +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -package com.yahoo.container.di.componentgraph.cycle; - -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; - -/** - * Class representing a directed graph. - * - * @author gjoranv - */ -public class Graph<T> { - - private final Map<T, LinkedHashSet<T>> adjMap = new LinkedHashMap<>(); - - public void edge(T from, T to) { - if (from == null || to == null) - throw new IllegalArgumentException("Null vertices are not allowed, edge: " + from + "->" + to); - - adjMap.computeIfAbsent(from, k -> new LinkedHashSet<>()).add(to); - adjMap.computeIfAbsent(to, k -> new LinkedHashSet<>()); - } - - Set<T> getVertices() { - return adjMap.keySet(); - } - - /** - * Returns the outgoing edges of the given vertex. - */ - Set<T> getAdjacent(T vertex) { - return adjMap.get(vertex); - } - - private void throwIfMissingVertex(T vertex) { - if (! adjMap.containsKey(vertex)) throw new IllegalArgumentException("No such vertex in the graph: " + vertex); - } -} diff --git a/container-core/src/main/java/com/yahoo/container/di/config/ResolveDependencyException.java b/container-core/src/main/java/com/yahoo/container/di/config/ResolveDependencyException.java deleted file mode 100644 index c88f851909c..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/config/ResolveDependencyException.java +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di.config; - -/** - * @author gjoranv - */ -public class ResolveDependencyException extends RuntimeException { - - public ResolveDependencyException(String message) { - super(message); - } - -} diff --git a/container-core/src/main/java/com/yahoo/container/di/config/RestApiContext.java b/container-core/src/main/java/com/yahoo/container/di/config/RestApiContext.java deleted file mode 100644 index bfb9a8f9160..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/config/RestApiContext.java +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di.config; - -import com.google.common.collect.ImmutableSet; -import com.google.inject.Inject; -import com.google.inject.Key; -import com.yahoo.component.ComponentId; -import org.osgi.framework.Version; - -import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Set; - -/** - * Only for internal JDisc use. - * - * @author gjoranv - */ -public class RestApiContext { - - private final List<BundleInfo> bundles = new ArrayList<>(); - private final List<Injectable> injectableComponents = new ArrayList<>(); - - public final JerseyBundlesConfig bundlesConfig; - public final JerseyInjectionConfig injectionConfig; - - @Inject - public RestApiContext(JerseyBundlesConfig bundlesConfig, JerseyInjectionConfig injectionConfig) { - this.bundlesConfig = bundlesConfig; - this.injectionConfig = injectionConfig; - } - - public List<BundleInfo> getBundles() { - return Collections.unmodifiableList(bundles); - } - - public void addBundle(BundleInfo bundle) { - bundles.add(bundle); - } - - public List<Injectable> getInjectableComponents() { - return Collections.unmodifiableList(injectableComponents); - } - - public void addInjectableComponent(Key<?> key, ComponentId id, Object component) { - injectableComponents.add(new Injectable(key, id, component)); - } - - public static class Injectable { - public final Key<?> key; - public final ComponentId id; - public final Object instance; - - public Injectable(Key<?> key, ComponentId id, Object instance) { - this.key = key; - this.id = id; - this.instance = instance; - } - @Override - public String toString() { - return id.toString(); - } - } - - public static class BundleInfo { - public final String symbolicName; - public final Version version; - public final String fileLocation; - public final URL webInfUrl; - public final ClassLoader classLoader; - - private Set<String> classEntries; - - public BundleInfo(String symbolicName, Version version, String fileLocation, URL webInfUrl, ClassLoader classLoader) { - this.symbolicName = symbolicName; - this.version = version; - this.fileLocation = fileLocation; - this.webInfUrl = webInfUrl; - this.classLoader = classLoader; - } - - @Override - public String toString() { - return symbolicName + ":" + version; - } - - public void setClassEntries(Collection<String> entries) { - this.classEntries = ImmutableSet.copyOf(entries); - } - - public Set<String> getClassEntries() { - return classEntries; - } - } -} diff --git a/container-core/src/main/java/com/yahoo/container/di/config/Subscriber.java b/container-core/src/main/java/com/yahoo/container/di/config/Subscriber.java deleted file mode 100644 index 60207447bfd..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/config/Subscriber.java +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di.config; - -import com.yahoo.config.ConfigInstance; -import com.yahoo.vespa.config.ConfigKey; - -import java.util.Map; - -/** - * @author Tony Vaagenes - * @author gjoranv - */ -public interface Subscriber { - - long waitNextGeneration(boolean isInitializing); - long generation(); - - boolean configChanged(); - Map<ConfigKey<ConfigInstance>, ConfigInstance> config(); - - void close(); - -} diff --git a/container-core/src/main/java/com/yahoo/container/di/config/SubscriberFactory.java b/container-core/src/main/java/com/yahoo/container/di/config/SubscriberFactory.java deleted file mode 100644 index c1c36a1b3de..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/config/SubscriberFactory.java +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di.config; - -import com.google.inject.ProvidedBy; -import com.yahoo.container.di.CloudSubscriberFactory; -import com.yahoo.vespa.config.ConfigKey; - -import java.util.Set; - -/** - * @author Tony Vaagenes - * @author gjoranv - */ -@ProvidedBy(CloudSubscriberFactory.Provider.class) -public interface SubscriberFactory { - - Subscriber getSubscriber(Set<? extends ConfigKey<?>> configKeys); - void reloadActiveSubscribers(long generation); - -} diff --git a/container-core/src/main/java/com/yahoo/container/di/config/package-info.java b/container-core/src/main/java/com/yahoo/container/di/config/package-info.java deleted file mode 100644 index b8f65b1c3c8..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/config/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -@ExportPackage -package com.yahoo.container.di.config; - -import com.yahoo.osgi.annotation.ExportPackage; diff --git a/container-core/src/main/java/com/yahoo/container/di/osgi/BundleClasses.java b/container-core/src/main/java/com/yahoo/container/di/osgi/BundleClasses.java deleted file mode 100644 index bca3ed73d0b..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/osgi/BundleClasses.java +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di.osgi; - -import org.osgi.framework.Bundle; - -import java.util.Collection; - -/** - * @author ollivir - */ -public class BundleClasses { - private final Bundle bundle; - private final Collection<String> classEntries; - - public BundleClasses(Bundle bundle, Collection<String> classEntries) { - this.bundle = bundle; - this.classEntries = classEntries; - } - - public Bundle bundle() { - return bundle; - } - - public Collection<String> classEntries() { - return classEntries; - } -} diff --git a/container-core/src/main/java/com/yahoo/container/di/osgi/OsgiUtil.java b/container-core/src/main/java/com/yahoo/container/di/osgi/OsgiUtil.java deleted file mode 100644 index e1854155e5b..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/osgi/OsgiUtil.java +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di.osgi; - -import com.yahoo.component.ComponentSpecification; -import com.yahoo.osgi.maven.ProjectBundleClassPaths; -import com.yahoo.osgi.maven.ProjectBundleClassPaths.BundleClasspathMapping; -import org.osgi.framework.Bundle; -import org.osgi.framework.wiring.BundleWiring; - -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Set; -import java.util.function.Predicate; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.stream.Collectors; - -import static com.google.common.io.Files.fileTreeTraverser; - -/** - * Tested by com.yahoo.application.container.jersey.JerseyTest - * - * @author Tony Vaagenes - * @author ollivir - */ -public class OsgiUtil { - private static final Logger log = Logger.getLogger(OsgiUtil.class.getName()); - private static final String CLASS_FILE_TYPE_SUFFIX = ".class"; - - public static Collection<String> getClassEntriesInBundleClassPath(Bundle bundle, Set<String> packagesToScan) { - BundleWiring bundleWiring = bundle.adapt(BundleWiring.class); - - if (packagesToScan.isEmpty()) { - return bundleWiring.listResources("/", "*" + CLASS_FILE_TYPE_SUFFIX, - BundleWiring.LISTRESOURCES_LOCAL | BundleWiring.LISTRESOURCES_RECURSE); - } else { - List<String> ret = new ArrayList<>(); - for (String pkg : packagesToScan) { - ret.addAll(bundleWiring.listResources(packageToPath(pkg), "*" + CLASS_FILE_TYPE_SUFFIX, BundleWiring.LISTRESOURCES_LOCAL)); - } - return ret; - } - } - - public static Collection<String> getClassEntriesForBundleUsingProjectClassPathMappings(ClassLoader classLoader, - ComponentSpecification bundleSpec, Set<String> packagesToScan) { - return classEntriesFrom(bundleClassPathMapping(bundleSpec, classLoader).classPathElements, packagesToScan); - } - - private static BundleClasspathMapping bundleClassPathMapping(ComponentSpecification bundleSpec, ClassLoader classLoader) { - ProjectBundleClassPaths projectBundleClassPaths = loadProjectBundleClassPaths(classLoader); - - if (projectBundleClassPaths.mainBundle.bundleSymbolicName.equals(bundleSpec.getName())) { - return projectBundleClassPaths.mainBundle; - } else { - log.log(Level.WARNING, - "Dependencies of the bundle " + bundleSpec + " will not be scanned. Please file a feature request if you need this"); - return matchingBundleClassPathMapping(bundleSpec, projectBundleClassPaths.providedDependencies); - } - } - - public static BundleClasspathMapping matchingBundleClassPathMapping(ComponentSpecification bundleSpec, - Collection<BundleClasspathMapping> providedBundlesClassPathMappings) { - for (BundleClasspathMapping mapping : providedBundlesClassPathMappings) { - if (mapping.bundleSymbolicName.equals(bundleSpec.getName())) { - return mapping; - } - } - throw new RuntimeException("No such bundle: " + bundleSpec); - } - - private static ProjectBundleClassPaths loadProjectBundleClassPaths(ClassLoader classLoader) { - URL classPathMappingsFileLocation = classLoader.getResource(ProjectBundleClassPaths.CLASSPATH_MAPPINGS_FILENAME); - if (classPathMappingsFileLocation == null) { - throw new RuntimeException("Couldn't find " + ProjectBundleClassPaths.CLASSPATH_MAPPINGS_FILENAME + " in the class path."); - } - - try { - return ProjectBundleClassPaths.load(Paths.get(classPathMappingsFileLocation.toURI())); - } catch (IOException | URISyntaxException e) { - throw new RuntimeException(e); - } - } - - private static Collection<String> classEntriesFrom(List<String> classPathEntries, Set<String> packagesToScan) { - Set<String> packagePathsToScan = packagesToScan.stream().map(OsgiUtil::packageToPath).collect(Collectors.toSet()); - List<String> ret = new ArrayList<>(); - - for (String entry : classPathEntries) { - Path path = Paths.get(entry); - if (Files.isDirectory(path)) { - ret.addAll(classEntriesInPath(path, packagePathsToScan)); - } else if (Files.isRegularFile(path) && path.getFileName().toString().endsWith(".jar")) { - ret.addAll(classEntriesInJar(path, packagePathsToScan)); - } else { - throw new RuntimeException("Unsupported path " + path + " in the class path"); - } - } - return ret; - } - - private static String relativePathToClass(Path rootPath, Path pathToClass) { - Path relativePath = rootPath.relativize(pathToClass); - return relativePath.toString(); - } - - private static Collection<String> classEntriesInPath(Path rootPath, Collection<String> packagePathsToScan) { - Iterable<File> fileIterator; - if (packagePathsToScan.isEmpty()) { - fileIterator = fileTreeTraverser().preOrderTraversal(rootPath.toFile()); - } else { - List<File> files = new ArrayList<>(); - for (String packagePath : packagePathsToScan) { - for (File file : fileTreeTraverser().children(rootPath.resolve(packagePath).toFile())) { - files.add(file); - } - } - fileIterator = files; - } - - List<String> ret = new ArrayList<>(); - for (File file : fileIterator) { - if (file.isFile() && file.getName().endsWith(CLASS_FILE_TYPE_SUFFIX)) { - ret.add(relativePathToClass(rootPath, file.toPath())); - } - } - return ret; - } - - private static String packagePath(String name) { - int index = name.lastIndexOf('/'); - if (index < 0) { - return name; - } else { - return name.substring(0, index); - } - } - - private static Collection<String> classEntriesInJar(Path jarPath, Set<String> packagePathsToScan) { - Predicate<String> acceptedPackage; - if (packagePathsToScan.isEmpty()) { - acceptedPackage = ign -> true; - } else { - acceptedPackage = name -> packagePathsToScan.contains(packagePath(name)); - } - - try (JarFile jarFile = new JarFile(jarPath.toFile())) { - return jarFile.stream().map(JarEntry::getName).filter(name -> name.endsWith(CLASS_FILE_TYPE_SUFFIX)).filter(acceptedPackage) - .collect(Collectors.toList()); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - private static String packageToPath(String packageName) { - return packageName.replace('.', '/'); - } -} diff --git a/container-core/src/main/java/com/yahoo/container/di/osgi/package-info.java b/container-core/src/main/java/com/yahoo/container/di/osgi/package-info.java deleted file mode 100644 index 9685cf571bd..00000000000 --- a/container-core/src/main/java/com/yahoo/container/di/osgi/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -/** - * @author Tony Vaagenes - */ -@ExportPackage -package com.yahoo.container.di.osgi; - -import com.yahoo.osgi.annotation.ExportPackage; diff --git a/container-core/src/main/java/com/yahoo/osgi/provider/model/ComponentModel.java b/container-core/src/main/java/com/yahoo/osgi/provider/model/ComponentModel.java deleted file mode 100644 index 8c501963db3..00000000000 --- a/container-core/src/main/java/com/yahoo/osgi/provider/model/ComponentModel.java +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.osgi.provider.model; - -import com.yahoo.component.ComponentId; -import com.yahoo.component.ComponentSpecification; -import com.yahoo.container.bundle.BundleInstantiationSpecification; - -/** - * Describes how a component should be created. - * - * Immutable - * - * @author gjoranv - */ -public class ComponentModel { - - public final BundleInstantiationSpecification bundleInstantiationSpec; - public final String configId; // only used in the container, null when used in the model - - public ComponentModel(BundleInstantiationSpecification bundleInstantiationSpec, String configId) { - if (bundleInstantiationSpec == null) - throw new IllegalArgumentException("Null bundle instantiation spec!"); - - this.bundleInstantiationSpec = bundleInstantiationSpec; - this.configId = configId; - } - - public ComponentModel(String idSpec, String classSpec, String bundleSpec, String configId) { - this(BundleInstantiationSpecification.getFromStrings(idSpec, classSpec, bundleSpec), configId); - } - - // For vespamodel - public ComponentModel(BundleInstantiationSpecification bundleInstantiationSpec) { - this(bundleInstantiationSpec, null); - } - - // For vespamodel - public ComponentModel(String idSpec, String classSpec, String bundleSpec) { - this(BundleInstantiationSpecification.getFromStrings(idSpec, classSpec, bundleSpec)); - } - - public ComponentId getComponentId() { - return bundleInstantiationSpec.id; - } - - public ComponentSpecification getClassId() { - return bundleInstantiationSpec.classId; - } - -} diff --git a/container-core/src/main/java/com/yahoo/osgi/provider/model/package-info.java b/container-core/src/main/java/com/yahoo/osgi/provider/model/package-info.java deleted file mode 100644 index f930f56ae4a..00000000000 --- a/container-core/src/main/java/com/yahoo/osgi/provider/model/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -@ExportPackage -package com.yahoo.osgi.provider.model; - -import com.yahoo.osgi.annotation.ExportPackage; diff --git a/container-core/src/main/resources/configdefinitions/application-bundles.def b/container-core/src/main/resources/configdefinitions/application-bundles.def deleted file mode 100644 index 7e03b1e3ac8..00000000000 --- a/container-core/src/main/resources/configdefinitions/application-bundles.def +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package=com.yahoo.container.di.config - -# References to user bundles to install. -bundles[] file diff --git a/container-core/src/main/resources/configdefinitions/container.components.def b/container-core/src/main/resources/configdefinitions/container.components.def deleted file mode 100644 index f27abc2fa5a..00000000000 --- a/container-core/src/main/resources/configdefinitions/container.components.def +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -namespace=container - -## A list of components. Components depending on other components may use this to -## get its list of components injected. - -## A component -components[].id string -## The component id used by this component to subscribe to its configs (if any) -components[].configId reference default=":parent:" - -## The id of the class to instantiate for this component. -components[].classId string default="" - -## The symbolic name of the Osgi bundle this component is located in. -## Assumed to be the same as the classid if not set. -components[].bundle string default="" - -## The component id of the component to inject to this component -components[].inject[].id string - -## The name to use for the injected component when injected to this component -components[].inject[].name string default="" diff --git a/container-core/src/main/resources/configdefinitions/container.di.config.jersey-bundles.def b/container-core/src/main/resources/configdefinitions/container.di.config.jersey-bundles.def deleted file mode 100644 index a226420274d..00000000000 --- a/container-core/src/main/resources/configdefinitions/container.di.config.jersey-bundles.def +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -namespace=container.di.config - -# The SymbolicName[:Version] of the Jersey bundles -bundles[].spec string - -# The packages to scan for Jersey resources -bundles[].packages[] string diff --git a/container-core/src/main/resources/configdefinitions/container.di.config.jersey-injection.def b/container-core/src/main/resources/configdefinitions/container.di.config.jersey-injection.def deleted file mode 100644 index 9f5be59abbd..00000000000 --- a/container-core/src/main/resources/configdefinitions/container.di.config.jersey-injection.def +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -namespace=container.di.config - -inject[].instance string -inject[].forClass string diff --git a/container-core/src/main/resources/configdefinitions/platform-bundles.def b/container-core/src/main/resources/configdefinitions/platform-bundles.def deleted file mode 100644 index a30a846b565..00000000000 --- a/container-core/src/main/resources/configdefinitions/platform-bundles.def +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package=com.yahoo.container.di.config - -# Paths to platform bundles to install. -bundlePaths[] string diff --git a/container-core/src/test/java/com/yahoo/component/ComponentSpecTestCase.java b/container-core/src/test/java/com/yahoo/component/ComponentSpecTestCase.java deleted file mode 100644 index 6fe58e99fda..00000000000 --- a/container-core/src/test/java/com/yahoo/component/ComponentSpecTestCase.java +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.component; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * @author Arne Bergene Fossaa - */ -public class ComponentSpecTestCase { - - @Test - public void testMatches() { - ComponentId a = new ComponentId("test:1"); - ComponentId b = new ComponentId("test:1.1.1"); - ComponentId c = new ComponentId("test:2"); - ComponentId d = new ComponentId("test:3"); - ComponentId e = new ComponentId("test"); - - ComponentSpecification aspec = new ComponentSpecification("test"); - ComponentSpecification bspec = new ComponentSpecification("test:1"); - ComponentSpecification cspec = new ComponentSpecification("test:2"); - ComponentSpecification dspec = new ComponentSpecification("test1:2"); - - assertTrue(aspec.matches(a)); - assertTrue(aspec.matches(b)); - assertTrue(aspec.matches(c)); - assertTrue(aspec.matches(d)); - assertTrue(aspec.matches(e)); - - assertTrue(bspec.matches(a)); - assertTrue(bspec.matches(b)); - assertFalse(bspec.matches(c)); - assertFalse(bspec.matches(d)); - assertFalse(bspec.matches(e)); - - assertFalse(cspec.matches(a)); - assertFalse(cspec.matches(b)); - assertTrue(cspec.matches(c)); - assertFalse(cspec.matches(d)); - assertFalse(cspec.matches(e)); - - assertFalse(dspec.matches(a)); - assertFalse(dspec.matches(b)); - assertFalse(dspec.matches(c)); - assertFalse(dspec.matches(d)); - assertFalse(dspec.matches(e)); - - } - - @Test - public void testMatchesWithNamespace() { - ComponentId namespace = new ComponentId("namespace:2"); - - ComponentId a = new ComponentId("test", new Version(1), namespace); - ComponentId b = new ComponentId("test:1@namespace:2"); - ComponentId c = new ComponentId("test:1@namespace"); - assertEquals(a, b); - assertFalse(a.equals(c)); - - ComponentSpecification spec = new ComponentSpecification("test", null, namespace); - assertTrue(spec.matches(a)); - assertTrue(spec.matches(b)); - assertFalse(spec.matches(c)); - } - - @Test - public void testStringValue() { - assertStringValueEqualsInputSpec("a:1.0.0.alpha@namespace"); - assertStringValueEqualsInputSpec("a:1.0.0.alpha"); - assertStringValueEqualsInputSpec("a:1.0"); - assertStringValueEqualsInputSpec("a"); - } - - private void assertStringValueEqualsInputSpec(String componentSpec) { - assertEquals(componentSpec, - new ComponentSpecification(componentSpec).stringValue()); - } - -} diff --git a/container-core/src/test/java/com/yahoo/component/provider/test/ComponentRegistryTestCase.java b/container-core/src/test/java/com/yahoo/component/provider/test/ComponentRegistryTestCase.java deleted file mode 100644 index 69eec95b746..00000000000 --- a/container-core/src/test/java/com/yahoo/component/provider/test/ComponentRegistryTestCase.java +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.component.provider.test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -import org.junit.Before; -import org.junit.Test; - -import com.yahoo.component.AbstractComponent; -import com.yahoo.component.ComponentId; -import com.yahoo.component.ComponentSpecification; -import com.yahoo.component.provider.ComponentRegistry; - -/** - * Tests that ComponentRegistry handles namespaces correctly. - * - * @author Tony Vaagenes - */ -public class ComponentRegistryTestCase { - private static class TestComponent extends AbstractComponent { - TestComponent(ComponentId componentId) { - super(componentId); - } - } - - private static final String componentName = "component"; - - private static final String namespace1 = "namespace1"; - private static final String namespace2 = "namespace2"; - private static final String namespace21 = "namespace2:1"; - - private static final TestComponent component1 = componentInNamespace(namespace1); - private static final TestComponent component2 = componentInNamespace(namespace2); - private static final TestComponent component21 = componentInNamespace(namespace21); - - private ComponentRegistry<TestComponent> registry; - - private static ComponentSpecification specInNamespace(String namespace) { - return new ComponentSpecification(componentName + "@" + namespace); - } - - private static ComponentId idInNamespace(String namespace) { - return specInNamespace(namespace).toId(); - } - - private static TestComponent componentInNamespace(String namespace) { - return new TestComponent(idInNamespace(namespace)); - } - - @Before - public void before() { - registry = new ComponentRegistry<>(); - - registry.register(component1.getId(), component1); - registry.register(component2.getId(), component2); - registry.register(component21.getId(), component21); - } - - @Test - public void testAllPresent() { - assertEquals(3, registry.getComponentCount()); - } - - @Test - public void testIdNamespaceLookup() { - assertEquals(component1, registry.getComponent(idInNamespace(namespace1))); - assertEquals(component2, registry.getComponent(idInNamespace(namespace2))); - assertEquals(component21, registry.getComponent(idInNamespace(namespace21))); - } - - @Test - public void testSpecNamespaceLookup() { - assertEquals(component1, registry.getComponent(specInNamespace(namespace1))); - - // Version for namespace must match the specification exactly, so do not return version '1' when an - // empty version is asked for. - assertEquals(component2, registry.getComponent(specInNamespace(namespace2))); - assertEquals(component21, registry.getComponent(specInNamespace(namespace21))); - } - - @Test - public void testInnerComponentNotMixedWithTopLevelComponent() { - assertNull(registry.getComponent(componentName)); - - TestComponent topLevel = new TestComponent(new ComponentId(componentName)); - registry.register(topLevel.getId(), topLevel); - assertEquals(topLevel, registry.getComponent(componentName)); - - assertEquals(component1, registry.getComponent(specInNamespace(namespace1))); - assertEquals(component1, registry.getComponent(idInNamespace(namespace1))); - } - -} diff --git a/container-core/src/test/java/com/yahoo/component/test/ComponentIdTestCase.java b/container-core/src/test/java/com/yahoo/component/test/ComponentIdTestCase.java deleted file mode 100644 index 0842ee4a797..00000000000 --- a/container-core/src/test/java/com/yahoo/component/test/ComponentIdTestCase.java +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.component.test; - -import com.yahoo.component.ComponentId; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * @author bratseth - */ -public class ComponentIdTestCase { - - @Test - public void testFileNameConversion() { - assertFileNameEquals("a","a"); - assertFileNameEquals("a-1","a-1"); - assertFileNameEquals("a-1","a-1.0.0"); - assertFileNameEquals("a-1.0.0.qualifier","a-1.0.0.qualifier"); - assertFileNameEquals("a.b-1.0.0.qualifier","a.b-1.0.0.qualifier"); - assertFileNameEquals("a@space","a@space"); - assertFileNameEquals("a-1@space","a-1@space"); - assertFileNameEquals("a-1@space","a-1.0.0@space"); - assertFileNameEquals("a-1.0.0.qualifier@space","a-1.0.0.qualifier@space"); - assertFileNameEquals("a.b-1.0.0.qualifier@space","a.b-1.0.0.qualifier@space"); - } - - /** Takes two id file names as input */ - private void assertFileNameEquals(String expected,String initial) { - assertEquals("'" + initial + "' became id '" + ComponentId.fromFileName(initial) + "' which should become '" + expected + "'", - expected,ComponentId.fromFileName(initial).toFileName()); - } - - @Test - public void testCompareWithNameSpace() { - ComponentId withNS = ComponentId.fromString("foo@ns"); - ComponentId withoutNS = ComponentId.fromString("foo"); // Should be less than withNs - - assertEquals(withNS.compareTo(withoutNS), 1); - assertEquals(withoutNS.compareTo(withNS), -1); - } - -} diff --git a/container-core/src/test/java/com/yahoo/container/di/ConfigRetrieverTest.java b/container-core/src/test/java/com/yahoo/container/di/ConfigRetrieverTest.java deleted file mode 100644 index 290836d7842..00000000000 --- a/container-core/src/test/java/com/yahoo/container/di/ConfigRetrieverTest.java +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di; - -import com.yahoo.config.ConfigInstance; -import com.yahoo.config.test.Bootstrap1Config; -import com.yahoo.config.test.Bootstrap2Config; -import com.yahoo.config.test.TestConfig; -import com.yahoo.container.di.ConfigRetriever.BootstrapConfigs; -import com.yahoo.container.di.ConfigRetriever.ComponentsConfigs; -import com.yahoo.container.di.ConfigRetriever.ConfigSnapshot; -import com.yahoo.vespa.config.ConfigKey; -import org.hamcrest.Matchers; -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Optional; -import java.util.Set; - -import static org.hamcrest.CoreMatchers.instanceOf; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; - -/** - * - * @author gjoranv - * @author Tony Vaagenes - * @author ollivir - */ -public class ConfigRetrieverTest { - - private DirConfigSource dirConfigSource = null; - - @Before - public void setup() { - dirConfigSource = new DirConfigSource("ConfigRetrieverTest-"); - } - - @After - public void cleanup() { - dirConfigSource.cleanup(); - } - - @Test - public void require_that_bootstrap_configs_come_first() { - writeConfigs(); - ConfigRetriever retriever = createConfigRetriever(); - ConfigSnapshot bootstrapConfigs = retriever.getConfigs(Collections.emptySet(), 0, true); - - assertThat(bootstrapConfigs, Matchers.instanceOf(BootstrapConfigs.class)); - } - - @Test - @SuppressWarnings("unused") - public void require_that_components_comes_after_bootstrap() { - writeConfigs(); - ConfigRetriever retriever = createConfigRetriever(); - ConfigSnapshot bootstrapConfigs = retriever.getConfigs(Collections.emptySet(), 0, true); - - ConfigKey<? extends ConfigInstance> testConfigKey = new ConfigKey<>(TestConfig.class, dirConfigSource.configId()); - ConfigSnapshot componentsConfigs = retriever.getConfigs(Collections.singleton(testConfigKey), 0, true); - - if (componentsConfigs instanceof ComponentsConfigs) { - assertThat(componentsConfigs.size(), is(3)); - } else { - fail("ComponentsConfigs has unexpected type: " + componentsConfigs); - } - } - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Ignore - @SuppressWarnings("unused") - public void require_exception_upon_modified_components_keys_without_bootstrap() { - expectedException.expect(IllegalArgumentException.class); - - writeConfigs(); - ConfigRetriever retriever = createConfigRetriever(); - ConfigKey<? extends ConfigInstance> testConfigKey = new ConfigKey<>(TestConfig.class, dirConfigSource.configId()); - ConfigSnapshot bootstrapConfigs = retriever.getConfigs(Collections.emptySet(), 0, true); - ConfigSnapshot componentsConfigs = retriever.getConfigs(Collections.singleton(testConfigKey), 0, true); - Set<ConfigKey<? extends ConfigInstance>> keys = new HashSet<>(); - keys.add(testConfigKey); - keys.add(new ConfigKey<>(TestConfig.class, "")); - retriever.getConfigs(keys, 0, true); - } - - @Test - public void require_that_empty_components_keys_after_bootstrap_returns_components_configs() { - writeConfigs(); - ConfigRetriever retriever = createConfigRetriever(); - assertThat(retriever.getConfigs(Collections.emptySet(), 0, true), instanceOf(BootstrapConfigs.class)); - assertThat(retriever.getConfigs(Collections.emptySet(), 0, true), instanceOf(ComponentsConfigs.class)); - } - - public void writeConfigs() { - writeConfig("bootstrap1", "dummy \"ignored\""); - writeConfig("bootstrap2", "dummy \"ignored\""); - writeConfig("test", "stringVal \"ignored\""); - } - - private ConfigRetriever createConfigRetriever() { - String configId = dirConfigSource.configId(); - CloudSubscriberFactory subscriber = new CloudSubscriberFactory(dirConfigSource.configSource()); - Set<ConfigKey<? extends ConfigInstance>> keys = new HashSet<>(); - keys.add(new ConfigKey<>(Bootstrap1Config.class, configId)); - keys.add(new ConfigKey<>(Bootstrap2Config.class, configId)); - return new ConfigRetriever(keys, keySet -> subscriber.getSubscriber(keySet)); - } - - private void writeConfig(String name, String contents) { - dirConfigSource.writeConfig(name, contents); - } -} diff --git a/container-core/src/test/java/com/yahoo/container/di/ContainerTest.java b/container-core/src/test/java/com/yahoo/container/di/ContainerTest.java deleted file mode 100644 index b596246a43d..00000000000 --- a/container-core/src/test/java/com/yahoo/container/di/ContainerTest.java +++ /dev/null @@ -1,408 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di; - -import com.google.inject.Guice; -import com.yahoo.component.AbstractComponent; -import com.yahoo.config.di.IntConfig; -import com.yahoo.config.test.TestConfig; -import com.yahoo.container.bundle.MockBundle; -import com.yahoo.container.di.componentgraph.Provider; -import com.yahoo.container.di.componentgraph.core.ComponentGraph; -import com.yahoo.container.di.componentgraph.core.ComponentGraphTest.SimpleComponent; -import com.yahoo.container.di.componentgraph.core.ComponentGraphTest.SimpleComponent2; -import com.yahoo.container.di.componentgraph.core.ComponentNode.ComponentConstructorException; -import com.yahoo.container.di.config.RestApiContext; -import org.junit.Ignore; -import org.junit.Test; -import org.osgi.framework.Bundle; - -import java.util.Collection; -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -/** - * @author Tony Vaagenes - * @author gjoranv - * @author ollivir - */ -public class ContainerTest extends ContainerTestBase { - - @Test - public void components_can_be_created_from_config() { - writeBootstrapConfigs(); - dirConfigSource.writeConfig("test", "stringVal \"myString\""); - - Container container = newContainer(dirConfigSource); - - ComponentTakingConfig component = createComponentTakingConfig(getNewComponentGraph(container)); - assertEquals("myString", component.config.stringVal()); - - container.shutdownConfigurer(); - } - - @Test - public void components_are_reconfigured_after_config_update_without_bootstrap_configs() { - writeBootstrapConfigs(); - dirConfigSource.writeConfig("test", "stringVal \"original\""); - - Container container = newContainer(dirConfigSource); - ComponentGraph componentGraph = getNewComponentGraph(container); - ComponentTakingConfig component = createComponentTakingConfig(componentGraph); - - assertEquals("original", component.config.stringVal()); - - // Reconfigure - dirConfigSource.writeConfig("test", "stringVal \"reconfigured\""); - container.reloadConfig(2); - - ComponentGraph newComponentGraph = getNewComponentGraph(container, componentGraph); - ComponentTakingConfig component2 = createComponentTakingConfig(newComponentGraph); - assertEquals("reconfigured", component2.config.stringVal()); - - container.shutdownConfigurer(); - } - - @Test - public void graph_is_updated_after_bootstrap_update() { - dirConfigSource.writeConfig("test", "stringVal \"original\""); - writeBootstrapConfigs("id1"); - - Container container = newContainer(dirConfigSource); - - ComponentGraph graph = getNewComponentGraph(container); - ComponentTakingConfig component = createComponentTakingConfig(graph); - assertEquals("id1", component.getId().toString()); - - writeBootstrapConfigs( - new ComponentEntry("id1", ComponentTakingConfig.class), - new ComponentEntry("id2", ComponentTakingConfig.class)); - - container.reloadConfig(2); - ComponentGraph newGraph = getNewComponentGraph(container, graph); - - assertNotNull(ComponentGraph.getNode(newGraph, "id1")); - assertNotNull(ComponentGraph.getNode(newGraph, "id2")); - - container.shutdownConfigurer(); - } - - //@Test TODO - public void deconstructor_is_given_guice_components() { - } - - @Test - public void component_is_deconstructed_when_not_reused() { - writeBootstrapConfigs("id1", DestructableComponent.class); - - Container container = newContainer(dirConfigSource); - - ComponentGraph oldGraph = getNewComponentGraph(container); - DestructableComponent componentToDestruct = oldGraph.getInstance(DestructableComponent.class); - - writeBootstrapConfigs("id2", DestructableComponent.class); - container.reloadConfig(2); - getNewComponentGraph(container, oldGraph); - assertTrue(componentToDestruct.deconstructed); - } - - @Ignore // because logAndDie is impossible(?) to verify programmatically - @Test - public void manually_verify_what_happens_when_first_graph_contains_component_that_throws_exception_in_ctor() { - writeBootstrapConfigs("thrower", ComponentThrowingExceptionInConstructor.class); - Container container = newContainer(dirConfigSource); - try { - getNewComponentGraph(container); - fail("Expected to log and die."); - } catch (Throwable t) { - fail("Expected to log and die"); - } - } - - @Test - public void previous_graph_is_retained_when_new_graph_contains_component_that_throws_exception_in_ctor() { - ComponentEntry simpleComponentEntry = new ComponentEntry("simpleComponent", SimpleComponent.class); - - writeBootstrapConfigs(simpleComponentEntry); - Container container = newContainer(dirConfigSource); - ComponentGraph currentGraph = getNewComponentGraph(container); - - SimpleComponent simpleComponent = currentGraph.getInstance(SimpleComponent.class); - - writeBootstrapConfigs("thrower", ComponentThrowingExceptionInConstructor.class); - container.reloadConfig(2); - try { - currentGraph = getNewComponentGraph(container, currentGraph); - fail("Expected exception"); - } catch (ComponentConstructorException ignored) { - // Expected, do nothing - } catch (Throwable t) { - fail("Expected ComponentConstructorException"); - } - assertEquals(1, currentGraph.generation()); - - // Also verify that next reconfig is successful - ComponentEntry componentTakingConfigEntry = new ComponentEntry("componentTakingConfig", ComponentTakingConfig.class); - dirConfigSource.writeConfig("test", "stringVal \"myString\""); - writeBootstrapConfigs(simpleComponentEntry, componentTakingConfigEntry); - container.reloadConfig(3); - currentGraph = getNewComponentGraph(container, currentGraph); - - assertEquals(3, currentGraph.generation()); - assertSame(simpleComponent, currentGraph.getInstance(SimpleComponent.class)); - assertNotNull(currentGraph.getInstance(ComponentTakingConfig.class)); - } - - @Test - public void previous_graph_is_retained_when_new_graph_throws_exception_for_missing_config() { - ComponentEntry simpleComponentEntry = new ComponentEntry("simpleComponent", SimpleComponent.class); - - writeBootstrapConfigs(simpleComponentEntry); - Container container = newContainer(dirConfigSource); - ComponentGraph currentGraph = getNewComponentGraph(container); - - currentGraph.getInstance(SimpleComponent.class); - - writeBootstrapConfigs("thrower", ComponentThrowingExceptionForMissingConfig.class); - dirConfigSource.writeConfig("test", "stringVal \"myString\""); - container.reloadConfig(2); - try { - currentGraph = getNewComponentGraph(container, currentGraph); - fail("Expected exception"); - } catch (IllegalArgumentException ignored) { - // Expected, do nothing - } catch (Throwable t) { - fail("Expected IllegalArgumentException"); - } - assertEquals(1, currentGraph.generation()); - } - - @Test - public void getNewComponentGraph_hangs_waiting_for_valid_config_after_invalid_config() throws Exception { - dirConfigSource.writeConfig("test", "stringVal \"original\""); - writeBootstrapConfigs("myId", ComponentTakingConfig.class); - - Container container = newContainer(dirConfigSource); - final ComponentGraph currentGraph = getNewComponentGraph(container); - - writeBootstrapConfigs("thrower", ComponentThrowingExceptionForMissingConfig.class); - container.reloadConfig(2); - - try { - getNewComponentGraph(container, currentGraph); - fail("expected exception"); - } catch (Exception ignored) { - } - ExecutorService exec = Executors.newFixedThreadPool(1); - Future<ComponentGraph> newGraph = exec.submit(() -> getNewComponentGraph(container, currentGraph)); - - try { - newGraph.get(1, TimeUnit.SECONDS); - fail("Expected waiting for new config."); - } catch (Exception ignored) { - // expect to time out - } - - writeBootstrapConfigs("myId2", ComponentTakingConfig.class); - container.reloadConfig(3); - - assertNotNull(newGraph.get(5, TimeUnit.MINUTES)); - } - - - @Test - public void bundle_info_is_set_on_rest_api_context() { - Class<RestApiContext> clazz = RestApiContext.class; - - writeBootstrapConfigs("restApiContext", clazz); - dirConfigSource.writeConfig("jersey-bundles", "bundles[0].spec \"mock-entry-to-enforce-a-MockBundle\""); - dirConfigSource.writeConfig("jersey-injection", "inject[0]"); - - Container container = newContainer(dirConfigSource); - ComponentGraph componentGraph = getNewComponentGraph(container); - - RestApiContext restApiContext = componentGraph.getInstance(clazz); - assertNotNull(restApiContext); - - assertEquals(1, restApiContext.getBundles().size()); - assertEquals(MockBundle.SymbolicName, restApiContext.getBundles().get(0).symbolicName); - assertEquals(MockBundle.BundleVersion, restApiContext.getBundles().get(0).version); - - container.shutdownConfigurer(); - } - - @Test - public void restApiContext_has_all_components_injected() { - Class<RestApiContext> restApiClass = RestApiContext.class; - Class<SimpleComponent> injectedClass = SimpleComponent.class; - String injectedComponentId = "injectedComponent"; - Class<SimpleComponent2> anotherComponentClass = SimpleComponent2.class; - String anotherComponentId = "anotherComponent"; - - String componentsConfig = - new ComponentEntry(injectedComponentId, injectedClass).asConfig(0) + "\n" + - new ComponentEntry(anotherComponentId, anotherComponentClass).asConfig(1) + "\n" + - new ComponentEntry("restApiContext", restApiClass).asConfig(2) + "\n" + - "components[2].inject[0].id " + injectedComponentId + "\n" + - "components[2].inject[1].id " + anotherComponentId + "\n"; - - String injectionConfig = "inject[1]\n" +// - "inject[0].instance " + injectedComponentId + "\n" +// - "inject[0].forClass \"" + injectedClass.getName() + "\"\n"; - - dirConfigSource.writeConfig("components", componentsConfig); - dirConfigSource.writeConfig("platform-bundles", ""); - dirConfigSource.writeConfig("application-bundles", ""); - dirConfigSource.writeConfig("jersey-bundles", "bundles[0].spec \"mock-entry-to-enforce-a-MockBundle\""); - dirConfigSource.writeConfig("jersey-injection", injectionConfig); - - Container container = newContainer(dirConfigSource); - ComponentGraph componentGraph = getNewComponentGraph(container); - - RestApiContext restApiContext = componentGraph.getInstance(restApiClass); - - assertFalse(restApiContext.getInjectableComponents().isEmpty()); - assertEquals(2, restApiContext.getInjectableComponents().size()); - - container.shutdownConfigurer(); - } - - @Test - public void providers_are_destructed() { - writeBootstrapConfigs("id1", DestructableProvider.class); - - ComponentDeconstructor deconstructor = (components, bundles) -> { - components.forEach(component -> { - if (component instanceof AbstractComponent) { - ((AbstractComponent) component).deconstruct(); - } else if (component instanceof Provider) { - ((Provider<?>) component).deconstruct(); - } - }); - if (! bundles.isEmpty()) throw new IllegalArgumentException("This test should not use bundles"); - }; - - Container container = newContainer(dirConfigSource, deconstructor); - - ComponentGraph oldGraph = getNewComponentGraph(container); - DestructableEntity destructableEntity = oldGraph.getInstance(DestructableEntity.class); - - writeBootstrapConfigs("id2", DestructableProvider.class); - container.reloadConfig(2); - getNewComponentGraph(container, oldGraph); - - assertTrue(destructableEntity.deconstructed); - } - - @Test - public void providers_are_invoked_only_when_needed() { - writeBootstrapConfigs("id1", FailOnGetProvider.class); - - Container container = newContainer(dirConfigSource); - - ComponentGraph oldGraph = getNewComponentGraph(container); - } - - static class DestructableEntity { - private boolean deconstructed = false; - } - - public static class DestructableProvider implements Provider<DestructableEntity> { - DestructableEntity instance = new DestructableEntity(); - - public DestructableEntity get() { - return instance; - } - - public void deconstruct() { - assertFalse(instance.deconstructed); - instance.deconstructed = true; - } - } - - public static class FailOnGetProvider implements Provider<Integer> { - - public Integer get() { - fail("Should never be called."); - return null; - } - - public void deconstruct() { - } - - } - - public static class ComponentTakingConfig extends AbstractComponent { - private final TestConfig config; - - public ComponentTakingConfig(TestConfig config) { - assertNotNull(config); - this.config = config; - } - } - - public static class ComponentThrowingExceptionInConstructor { - public ComponentThrowingExceptionInConstructor() { - throw new RuntimeException("This component fails upon construction."); - } - } - - public static class ComponentThrowingExceptionForMissingConfig extends AbstractComponent { - public ComponentThrowingExceptionForMissingConfig(IntConfig intConfig) { - fail("This component should never be created. Only used for tests where 'int' config is missing."); - } - } - - public static class DestructableComponent extends AbstractComponent { - private boolean deconstructed = false; - - @Override - public void deconstruct() { - deconstructed = true; - } - } - - public static class TestDeconstructor implements ComponentDeconstructor { - @Override - public void deconstruct(List<Object> components, Collection<Bundle> bundles) { - components.forEach(component -> { - if (component instanceof DestructableComponent) { - DestructableComponent vespaComponent = (DestructableComponent) component; - vespaComponent.deconstruct(); - } - }); - if (! bundles.isEmpty()) throw new IllegalArgumentException("This test should not use bundles"); - } - } - - private static Container newContainer(DirConfigSource dirConfigSource, - ComponentDeconstructor deconstructor) { - return new Container(new CloudSubscriberFactory(dirConfigSource.configSource), dirConfigSource.configId(), deconstructor); - } - - private static Container newContainer(DirConfigSource dirConfigSource) { - return newContainer(dirConfigSource, new TestDeconstructor()); - } - - ComponentGraph getNewComponentGraph(Container container, ComponentGraph oldGraph) { - return container.getNewComponentGraph(oldGraph, Guice.createInjector(), true); - } - - ComponentGraph getNewComponentGraph(Container container) { - return container.getNewComponentGraph(new ComponentGraph(), Guice.createInjector(), true); - } - - private ComponentTakingConfig createComponentTakingConfig(ComponentGraph componentGraph) { - return componentGraph.getInstance(ComponentTakingConfig.class); - } - -} diff --git a/container-core/src/test/java/com/yahoo/container/di/ContainerTestBase.java b/container-core/src/test/java/com/yahoo/container/di/ContainerTestBase.java deleted file mode 100644 index 2106a1f3671..00000000000 --- a/container-core/src/test/java/com/yahoo/container/di/ContainerTestBase.java +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di; - -import com.google.inject.Guice; -import com.yahoo.component.ComponentSpecification; -import com.yahoo.config.FileReference; -import com.yahoo.container.bundle.BundleInstantiationSpecification; -import com.yahoo.container.di.ContainerTest.ComponentTakingConfig; -import com.yahoo.container.di.componentgraph.core.ComponentGraph; -import com.yahoo.container.di.osgi.BundleClasses; -import org.junit.After; -import org.junit.Before; -import org.osgi.framework.Bundle; - -import java.util.Collection; -import java.util.Set; - -import static java.util.Collections.emptySet; - -/** - * @author Tony Vaagenes - * @author gjoranv - * @author ollivir - */ -public class ContainerTestBase { - - private ComponentGraph componentGraph; - protected DirConfigSource dirConfigSource = null; - - @Before - public void setup() { - dirConfigSource = new DirConfigSource("ContainerTest-"); - } - - @After - public void cleanup() { - dirConfigSource.cleanup(); - } - - @Before - public void createGraph() { - componentGraph = new ComponentGraph(0); - } - - public void complete() { - try { - Container container = new Container(new CloudSubscriberFactory(dirConfigSource.configSource()), dirConfigSource.configId(), - new ContainerTest.TestDeconstructor(), new Osgi() { - @SuppressWarnings("unchecked") - @Override - public Class<Object> resolveClass(BundleInstantiationSpecification spec) { - try { - return (Class<Object>) Class.forName(spec.classId.getName()); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - @Override - public BundleClasses getBundleClasses(ComponentSpecification bundle, Set<String> packagesToScan) { - throw new UnsupportedOperationException("getBundleClasses not supported"); - } - - @Override - public Set<Bundle> useApplicationBundles(Collection<FileReference> bundles) { - return emptySet(); - } - - @Override - public Bundle getBundle(ComponentSpecification spec) { - throw new UnsupportedOperationException("getBundle not supported."); - } - }); - componentGraph = container.getNewComponentGraph(componentGraph, Guice.createInjector(), true); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - public <T> T getInstance(Class<T> componentClass) { - return componentGraph.getInstance(componentClass); - } - - protected void writeBootstrapConfigs(ComponentEntry... componentEntries) { - dirConfigSource.writeConfig("platform-bundles", ""); - dirConfigSource.writeConfig("application-bundles", ""); - StringBuilder components = new StringBuilder(); - for (int i = 0; i < componentEntries.length; i++) { - components.append(componentEntries[i].asConfig(i)); - components.append('\n'); - } - dirConfigSource.writeConfig("components", String.format("components[%s]\n%s", componentEntries.length, components)); - } - - protected void writeBootstrapConfigs(String componentId, Class<?> classId) { - writeBootstrapConfigs(new ComponentEntry(componentId, classId)); - } - - protected void writeBootstrapConfigs(String componentId) { - writeBootstrapConfigs(componentId, ComponentTakingConfig.class); - } - - protected void writeBootstrapConfigs() { - writeBootstrapConfigs(ComponentTakingConfig.class.getName(), ComponentTakingConfig.class); - } - - protected class ComponentEntry { - private final String componentId; - private final Class<?> classId; - - ComponentEntry(String componentId, Class<?> classId) { - this.componentId = componentId; - this.classId = classId; - } - - String asConfig(int position) { - return "<config>\n" + // - "components[" + position + "].id \"" + componentId + "\"\n" + // - "components[" + position + "].classId \"" + classId.getName() + "\"\n" + // - "components[" + position + "].configId \"" + dirConfigSource.configId() + "\"\n" + // - "</config>"; - } - } - -} diff --git a/container-core/src/test/java/com/yahoo/container/di/DirConfigSource.java b/container-core/src/test/java/com/yahoo/container/di/DirConfigSource.java deleted file mode 100644 index ec937a1a4ef..00000000000 --- a/container-core/src/test/java/com/yahoo/container/di/DirConfigSource.java +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di; - -import com.yahoo.config.subscription.ConfigSource; -import com.yahoo.config.subscription.ConfigSourceSet; -import org.junit.rules.TemporaryFolder; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.Random; - -/** - * @author Tony Vaagenes - * @author gjoranv - * @author ollivir - */ -public class DirConfigSource { - private final TemporaryFolder tempFolder = createTemporaryFolder(); - public final ConfigSource configSource; - - public DirConfigSource(String testSourcePrefix) { - this.configSource = new ConfigSourceSet(testSourcePrefix + new Random().nextLong()); - } - - public void writeConfig(String name, String contents) { - File file = new File(tempFolder.getRoot(), name + ".cfg"); - if (!file.exists()) { - try { - file.createNewFile(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - printFile(file, contents + "\n"); - } - - public String configId() { - return "dir:" + tempFolder.getRoot().getPath(); - } - - public ConfigSource configSource() { - return configSource; - } - - public void cleanup() { - tempFolder.delete(); - } - - private static void printFile(File f, String content) { - try (OutputStream out = new FileOutputStream(f)) { - out.write(content.getBytes("UTF-8")); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - private static TemporaryFolder createTemporaryFolder() { - TemporaryFolder folder = new TemporaryFolder(); - try { - folder.create(); - } catch (IOException e) { - throw new RuntimeException(e); - } - return folder; - } -} diff --git a/container-core/src/test/java/com/yahoo/container/di/componentgraph/core/ComponentGraphTest.java b/container-core/src/test/java/com/yahoo/container/di/componentgraph/core/ComponentGraphTest.java deleted file mode 100644 index 70dc4c8665c..00000000000 --- a/container-core/src/test/java/com/yahoo/container/di/componentgraph/core/ComponentGraphTest.java +++ /dev/null @@ -1,750 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di.componentgraph.core; - -import com.google.inject.AbstractModule; -import com.google.inject.Guice; -import com.google.inject.Inject; -import com.google.inject.Injector; -import com.google.inject.Key; -import com.google.inject.name.Named; -import com.google.inject.name.Names; -import com.yahoo.collections.Pair; -import com.yahoo.component.AbstractComponent; -import com.yahoo.component.ComponentId; -import com.yahoo.component.provider.ComponentRegistry; -import com.yahoo.config.ConfigInstance; -import com.yahoo.config.subscription.ConfigGetter; -import com.yahoo.config.test.Test2Config; -import com.yahoo.config.test.TestConfig; -import com.yahoo.container.di.Osgi; -import com.yahoo.container.di.componentgraph.Provider; -import com.yahoo.container.di.config.JerseyBundlesConfig; -import com.yahoo.container.di.config.JerseyInjectionConfig; -import com.yahoo.container.di.config.RestApiContext; -import com.yahoo.vespa.config.ConfigKey; -import org.junit.Test; - -import java.lang.annotation.Annotation; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Set; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.function.Supplier; - -import static com.yahoo.container.di.componentgraph.core.ComponentGraph.isBindingAnnotation; -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.not; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.sameInstance; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -/** - * @author gjoranv - * @author Tony Vaagenes - * @author ollivir - */ -public class ComponentGraphTest { - - public static class ConfigMap extends HashMap<ConfigKey<? extends ConfigInstance>, ConfigInstance> { - public ConfigMap() { - super(); - } - - public <T extends ConfigInstance> ConfigMap add(Class<T> clazz, String configId) { - ConfigKey<T> key = new ConfigKey<>(clazz, configId); - put(key, ConfigGetter.getConfig(key.getConfigClass(), key.getConfigId())); - return this; - } - - public static <T extends ConfigInstance> ConfigMap newMap(Class<T> clazz, String configId) { - ConfigMap ret = new ConfigMap(); - ret.add(clazz, configId); - return ret; - } - } - - @Test - public void component_taking_config_can_be_instantiated() { - ComponentGraph componentGraph = new ComponentGraph(); - String configId = "raw:stringVal \"test-value\""; - Node componentNode = mockComponentNode(ComponentTakingConfig.class, configId); - - componentGraph.add(componentNode); - componentGraph.complete(); - componentGraph.setAvailableConfigs(ConfigMap.newMap(TestConfig.class, configId)); - - ComponentTakingConfig instance = componentGraph.getInstance(ComponentTakingConfig.class); - assertNotNull(instance); - assertThat(instance.config.stringVal(), is("test-value")); - } - - @Test - public void all_created_components_are_returned_in_reverse_topological_order() { - for (int i = 0; i < 10; i++) { - Node innerComponent = mockComponentNode(SimpleComponent.class); - Node middleComponent = mockComponentNode(ComponentTakingComponent.class); - Node outerComponent = mockComponentNode(ComponentTakingComponentTakingComponent.class); - - ComponentGraph componentGraph = new ComponentGraph(); - componentGraph.add(innerComponent); - componentGraph.add(middleComponent); - componentGraph.add(outerComponent); - componentGraph.complete(); - - innerComponent.constructInstance(); - middleComponent.constructInstance(); - outerComponent.constructInstance(); - - assertEquals(List.of(outerComponent.constructedInstance().get(), middleComponent.constructedInstance().get(), innerComponent.constructedInstance().get()), - componentGraph.allConstructedComponentsAndProviders()); - } - } - - @Test - public void component_can_be_injected_into_another_component() { - Node injectedComponent = mockComponentNode(SimpleComponent.class); - Node targetComponent = mockComponentNode(ComponentTakingComponent.class); - targetComponent.inject(injectedComponent); - - Node destroyGlobalLookupComponent = mockComponentNode(SimpleComponent.class); - - ComponentGraph componentGraph = new ComponentGraph(); - componentGraph.add(injectedComponent); - componentGraph.add(targetComponent); - componentGraph.add(destroyGlobalLookupComponent); - componentGraph.complete(); - - ComponentTakingComponent instance = componentGraph.getInstance(ComponentTakingComponent.class); - assertNotNull(instance); - } - - @Test - public void interface_implementation_can_be_injected() { - ComponentGraph componentGraph = new ComponentGraph(); - componentGraph.add(mockComponentNode(ComponentImpl.class)); - componentGraph.add(mockComponentNode(ComponentTakingInterface.class)); - componentGraph.complete(); - - ComponentTakingInterface instance = componentGraph.getInstance(ComponentTakingInterface.class); - assertTrue(instance.injected instanceof ComponentImpl); - } - - @Test - public void private_class_with_public_ctor_can_be_instantiated() { - ComponentGraph componentGraph = new ComponentGraph(); - componentGraph.add(mockComponentNode(PrivateClassComponent.class)); - componentGraph.complete(); - - PrivateClassComponent instance = componentGraph.getInstance(PrivateClassComponent.class); - assertNotNull(instance); - } - - @Test - public void all_components_of_a_type_can_be_injected() { - ComponentGraph componentGraph = new ComponentGraph(); - componentGraph.add(mockComponentNode(SimpleComponent.class)); - componentGraph.add(mockComponentNode(SimpleComponent.class)); - componentGraph.add(mockComponentNode(SimpleDerivedComponent.class)); - componentGraph.add(mockComponentNode(ComponentTakingAllSimpleComponents.class)); - componentGraph.complete(); - - ComponentTakingAllSimpleComponents instance = componentGraph.getInstance(ComponentTakingAllSimpleComponents.class); - assertThat(instance.simpleComponents.allComponents().size(), is(3)); - } - - @Test - public void empty_component_registry_can_be_injected() { - ComponentGraph componentGraph = new ComponentGraph(); - componentGraph.add(mockComponentNode(ComponentTakingAllSimpleComponents.class)); - componentGraph.complete(); - - ComponentTakingAllSimpleComponents instance = componentGraph.getInstance(ComponentTakingAllSimpleComponents.class); - assertThat(instance.simpleComponents.allComponents().size(), is(0)); - } - - @Test - public void component_registry_with_wildcard_upper_bound_can_be_injected() { - ComponentGraph componentGraph = new ComponentGraph(); - componentGraph.add(mockComponentNode(SimpleComponent.class)); - componentGraph.add(mockComponentNode(SimpleDerivedComponent.class)); - componentGraph.add(mockComponentNode(ComponentTakingAllSimpleComponentsUpperBound.class)); - componentGraph.complete(); - - ComponentTakingAllSimpleComponentsUpperBound instance = componentGraph - .getInstance(ComponentTakingAllSimpleComponentsUpperBound.class); - assertThat(instance.simpleComponents.allComponents().size(), is(2)); - } - - @Test(expected = RuntimeException.class) - public void require_exception_when_injecting_registry_with_unknown_type_variable() { - @SuppressWarnings("rawtypes") - Class<ComponentTakingAllComponentsWithTypeVariable> clazz = ComponentTakingAllComponentsWithTypeVariable.class; - - ComponentGraph componentGraph = new ComponentGraph(); - componentGraph.add(mockComponentNode(SimpleComponent.class)); - componentGraph.add(mockComponentNode(SimpleDerivedComponent.class)); - componentGraph.add(mockComponentNode(clazz)); - componentGraph.complete(); - - componentGraph.getInstance(clazz); - } - - @Test - public void components_are_shared() { - ComponentGraph componentGraph = new ComponentGraph(); - componentGraph.add(mockComponentNode(SimpleComponent.class)); - componentGraph.complete(); - - SimpleComponent instance1 = componentGraph.getInstance(SimpleComponent.class); - SimpleComponent instance2 = componentGraph.getInstance(SimpleComponent.class); - assertThat(instance1, sameInstance(instance2)); - } - - @Test - public void singleton_components_can_be_injected() { - ComponentGraph componentGraph = new ComponentGraph(); - String configId = "raw:stringVal \"test-value\""; - - componentGraph.add(mockComponentNode(ComponentTakingComponent.class)); - componentGraph.add(mockComponentNode(ComponentTakingConfig.class, configId)); - componentGraph.add(mockComponentNode(SimpleComponent2.class)); - componentGraph.complete(); - componentGraph.setAvailableConfigs(ConfigMap.newMap(TestConfig.class, configId)); - - ComponentTakingComponent instance = componentGraph.getInstance(ComponentTakingComponent.class); - ComponentTakingConfig injected = (ComponentTakingConfig) instance.injectedComponent; - assertThat(injected.config.stringVal(), is("test-value")); - } - - @Test(expected = RuntimeException.class) - public void require_error_when_multiple_components_match_a_singleton_dependency() { - ComponentGraph componentGraph = new ComponentGraph(); - componentGraph.add(mockComponentNode(SimpleDerivedComponent.class)); - componentGraph.add(mockComponentNode(SimpleComponent.class)); - componentGraph.add(mockComponentNode(ComponentTakingComponent.class)); - componentGraph.complete(); - } - - @Test - public void named_component_can_be_injected() { - ComponentGraph componentGraph = new ComponentGraph(); - componentGraph.add(mockComponentNode(SimpleComponent.class)); - componentGraph.add(mockComponentNode(SimpleComponent.class, Names.named("named-test"))); - componentGraph.add(mockComponentNode(ComponentTakingNamedComponent.class)); - componentGraph.complete(); - } - - @Test - public void config_keys_can_be_retrieved() { - ComponentGraph componentGraph = new ComponentGraph(); - componentGraph.add(mockComponentNode(ComponentTakingConfig.class, "raw:stringVal \"component1\"")); - componentGraph.add(mockComponentNode(ComponentTakingConfig.class, "raw:stringVal \"component2\"")); - componentGraph.add(new ComponentRegistryNode(ComponentTakingConfig.class)); - componentGraph.complete(); - - Set<ConfigKey<? extends ConfigInstance>> configKeys = componentGraph.configKeys(); - assertThat(configKeys.size(), is(2)); - - configKeys.forEach(key -> { - assertThat(key.getConfigClass(), equalTo(TestConfig.class)); - assertThat(key.getConfigId(), containsString("component")); - }); - } - - @Test - public void providers_can_be_instantiated() { - ComponentGraph componentGraph = new ComponentGraph(); - componentGraph.add(mockComponentNode(ExecutorProvider.class)); - componentGraph.complete(); - - assertNotNull(componentGraph.getInstance(Executor.class)); - } - - @Test - public void providers_can_be_inherited() { - ComponentGraph componentGraph = new ComponentGraph(); - componentGraph.add(mockComponentNode(DerivedExecutorProvider.class)); - componentGraph.complete(); - - assertNotNull(componentGraph.getInstance(Executor.class)); - } - - @Test - public void providers_can_deliver_a_new_instance_for_each_component() { - ComponentGraph componentGraph = new ComponentGraph(); - componentGraph.add(mockComponentNode(NewIntProvider.class)); - componentGraph.complete(); - - Integer instance1 = componentGraph.getInstance(Integer.class); - Integer instance2 = componentGraph.getInstance(Integer.class); - assertEquals(1, instance1.intValue()); - assertEquals(2, instance2.intValue()); - } - - @Test - public void providers_can_be_injected_explicitly() { - ComponentGraph componentGraph = new ComponentGraph(); - - Node componentTakingExecutor = mockComponentNode(ComponentTakingExecutor.class); - Node executorProvider = mockComponentNode(ExecutorProvider.class); - componentTakingExecutor.inject(executorProvider); - - componentGraph.add(executorProvider); - componentGraph.add(mockComponentNode(ExecutorProvider.class)); - - componentGraph.add(componentTakingExecutor); - - componentGraph.complete(); - assertNotNull(componentGraph.getInstance(ComponentTakingExecutor.class)); - } - - @Test - public void global_providers_can_be_injected() { - ComponentGraph componentGraph = new ComponentGraph(); - - componentGraph.add(mockComponentNode(ComponentTakingExecutor.class)); - componentGraph.add(mockComponentNode(ExecutorProvider.class)); - componentGraph.add(mockComponentNode(FailOnGetIntProvider.class)); - componentGraph.complete(); - - assertNotNull(componentGraph.getInstance(ComponentTakingExecutor.class)); - } - - @Test(expected = RuntimeException.class) - public void throw_if_multiple_global_providers_exist() { - ComponentGraph componentGraph = new ComponentGraph(); - - componentGraph.add(mockComponentNode(ExecutorProvider.class)); - componentGraph.add(mockComponentNode(ExecutorProvider.class)); - componentGraph.add(mockComponentNode(ComponentTakingExecutor.class)); - componentGraph.complete(); - } - - @Test - public void provider_is_not_used_when_component_of_provided_class_exists() { - ComponentGraph componentGraph = new ComponentGraph(); - - componentGraph.add(mockComponentNode(SimpleComponent.class)); - componentGraph.add(mockComponentNode(SimpleComponentProviderThatThrows.class)); - componentGraph.add(mockComponentNode(ComponentTakingComponent.class)); - componentGraph.complete(); - - SimpleComponent injectedComponent = componentGraph.getInstance(ComponentTakingComponent.class).injectedComponent; - assertNotNull(injectedComponent); - } - - //TODO: move - @Test - public void check_if_annotation_is_a_binding_annotation() { - assertTrue(isBindingAnnotation(Names.named("name"))); - assertFalse(isBindingAnnotation(Named.class.getAnnotations()[0])); - } - - @Test - public void cycles_gives_exception() { - ComponentGraph componentGraph = new ComponentGraph(); - - Node node1 = mockComponentNode(ComponentCausingCycle.class); - Node node2 = mockComponentNode(ComponentCausingCycle.class); - - node1.inject(node2); - node2.inject(node1); - - componentGraph.add(node1); - componentGraph.add(node2); - - try { - componentGraph.complete(); - fail("Cycle exception expected."); - } catch (Throwable e) { - assertThat(e.getMessage(), containsString("cycle")); - assertThat(e.getMessage(), containsString("ComponentCausingCycle")); - } - } - - @Test(expected = IllegalArgumentException.class) - public void abstract_classes_are_rejected() { - new ComponentNode(ComponentId.fromString("Test"), "", AbstractClass.class); - } - - @Test - public void inject_constructor_is_preferred() { - assertThatComponentCanBeCreated(ComponentWithInjectConstructor.class); - } - - @Test - public void constructor_with_most_parameters_is_preferred() { - assertThatComponentCanBeCreated(ComponentWithMultipleConstructors.class); - } - - public void assertThatComponentCanBeCreated(Class<?> clazz) { - ComponentGraph componentGraph = new ComponentGraph(); - String configId = "raw:stringVal \"dummy\""; - - componentGraph.add(mockComponentNode(clazz, configId)); - componentGraph.complete(); - - componentGraph.setAvailableConfigs(ConfigMap.newMap(TestConfig.class, configId).add(Test2Config.class, configId)); - - assertNotNull(componentGraph.getInstance(clazz)); - } - - @Test - public void require_fallback_to_child_injector() { - ComponentGraph componentGraph = new ComponentGraph(); - - componentGraph.add(mockComponentNode(ComponentTakingExecutor.class)); - - componentGraph.complete(singletonExecutorInjector); - assertNotNull(componentGraph.getInstance(ComponentTakingExecutor.class)); - } - - @Test - public void child_injector_can_inject_multiple_instances_for_same_key() { - Pair<Integer, Pair<Executor, Executor>> graph = buildGraphWithChildInjector(Executors::newSingleThreadExecutor); - int graphSize = graph.getFirst(); - Executor executorA = graph.getSecond().getFirst(); - Executor executorB = graph.getSecond().getSecond(); - - assertThat(graphSize, is(4)); - assertThat(executorA, not(sameInstance(executorB))); - } - - @Test - public void components_injected_via_child_injector_can_be_shared() { - Executor commonExecutor = Executors.newSingleThreadExecutor(); - Pair<Integer, Pair<Executor, Executor>> graph = buildGraphWithChildInjector(() -> commonExecutor); - int graphSize = graph.getFirst(); - Executor executorA = graph.getSecond().getFirst(); - Executor executorB = graph.getSecond().getSecond(); - - assertThat(graphSize, is(3)); - assertThat(executorA, sameInstance(executorB)); - } - - private Pair<Integer, Pair<Executor, Executor>> buildGraphWithChildInjector(Supplier<Executor> executorProvider) { - Injector childInjector = Guice.createInjector(new AbstractModule() { - @Override - public void configure() { - bind(Executor.class).toProvider(executorProvider::get); - } - }); - - ComponentGraph componentGraph = new ComponentGraph(); - - Key<ComponentTakingExecutor> keyA = Key.get(ComponentTakingExecutor.class, Names.named("A")); - Key<ComponentTakingExecutor> keyB = Key.get(ComponentTakingExecutor.class, Names.named("B")); - - componentGraph.add(mockComponentNode(keyA)); - componentGraph.add(mockComponentNode(keyB)); - - componentGraph.complete(childInjector); - - return new Pair<>(componentGraph.size(), - new Pair<>(componentGraph.getInstance(keyA).executor, componentGraph.getInstance(keyB).executor)); - } - - @Test - public void providers_can_be_reused() { - - ComponentGraph oldGraph = createReusingGraph(); - Executor executor = oldGraph.getInstance(Executor.class); - - ComponentGraph newGraph = createReusingGraph(); - newGraph.reuseNodes(oldGraph); - - Executor newExecutor = newGraph.getInstance(Executor.class); - assertThat(executor, sameInstance(newExecutor)); - } - - private ComponentGraph createReusingGraph() { - ComponentGraph graph = new ComponentGraph(); - graph.add(mockComponentNodeWithId(ExecutorProvider.class, "dummyId")); - graph.complete(); - graph.setAvailableConfigs(Collections.emptyMap()); - return graph; - } - - @Test - public void component_id_can_be_injected() { - String componentId = "myId:1.2@namespace"; - - ComponentGraph componentGraph = new ComponentGraph(); - componentGraph.add(mockComponentNodeWithId(ComponentTakingComponentId.class, componentId)); - componentGraph.complete(); - - assertThat(componentGraph.getInstance(ComponentTakingComponentId.class).componentId, is(ComponentId.fromString(componentId))); - } - - @Test - public void rest_api_context_can_be_instantiated() { - String configId = "raw:\"\""; - - Class<RestApiContext> clazz = RestApiContext.class; - JerseyNode jerseyNode = new JerseyNode(uniqueComponentId(clazz.getName()), configId, clazz, new Osgi() { - }); - - ComponentGraph componentGraph = new ComponentGraph(); - componentGraph.add(jerseyNode); - componentGraph.complete(); - - componentGraph - .setAvailableConfigs(ConfigMap.newMap(JerseyBundlesConfig.class, configId).add(JerseyInjectionConfig.class, configId)); - - RestApiContext restApiContext = componentGraph.getInstance(clazz); - assertNotNull(restApiContext); - assertThat(restApiContext.getBundles().size(), is(0)); - } - - //Note that all Components must be defined in a static context, - //otherwise their constructor will take the outer class as the first parameter. - private static int counter = 0; - - private class PrivateClassComponent { - public PrivateClassComponent() { } - } - - public static class SimpleComponent extends AbstractComponent { - } - - public static class SimpleComponent2 extends AbstractComponent { - } - - public static class SimpleDerivedComponent extends SimpleComponent { - } - - public interface ComponentBase { } - public static class ComponentImpl implements ComponentBase { } - public static class ComponentTakingInterface { - ComponentBase injected; - public ComponentTakingInterface(ComponentBase componentBase) { - injected = componentBase; - } - } - - public static class ComponentTakingConfig extends SimpleComponent { - private final TestConfig config; - - public ComponentTakingConfig(TestConfig config) { - assertThat(config, notNullValue()); - this.config = config; - } - } - - public static class ComponentTakingComponent extends AbstractComponent { - private final SimpleComponent injectedComponent; - - public ComponentTakingComponent(SimpleComponent injectedComponent) { - assertThat(injectedComponent, notNullValue()); - this.injectedComponent = injectedComponent; - } - } - - public static class ComponentTakingComponentTakingComponent extends AbstractComponent { - private final ComponentTakingComponent injectedComponent; - - public ComponentTakingComponentTakingComponent(ComponentTakingComponent injectedComponent) { - assertThat(injectedComponent, notNullValue()); - this.injectedComponent = injectedComponent; - } - } - - @SuppressWarnings("unused") - public static class ComponentTakingConfigAndComponent extends AbstractComponent { - private final TestConfig config; - private final SimpleComponent simpleComponent; - - public ComponentTakingConfigAndComponent(TestConfig config, SimpleComponent injectedComponent) { - assertThat(config, notNullValue()); - assertThat(injectedComponent, notNullValue()); - this.config = config; - this.simpleComponent = injectedComponent; - } - } - - public static class ComponentTakingAllSimpleComponents extends AbstractComponent { - public final ComponentRegistry<SimpleComponent> simpleComponents; - - public ComponentTakingAllSimpleComponents(ComponentRegistry<SimpleComponent> simpleComponents) { - assertThat(simpleComponents, notNullValue()); - this.simpleComponents = simpleComponents; - } - } - - public static class ComponentTakingAllSimpleComponentsUpperBound extends AbstractComponent { - private final ComponentRegistry<? extends SimpleComponent> simpleComponents; - - public ComponentTakingAllSimpleComponentsUpperBound(ComponentRegistry<? extends SimpleComponent> simpleComponents) { - assertThat(simpleComponents, notNullValue()); - this.simpleComponents = simpleComponents; - } - } - - public static class ComponentTakingAllComponentsWithTypeVariable<COMPONENT extends AbstractComponent> extends AbstractComponent { - public ComponentTakingAllComponentsWithTypeVariable(ComponentRegistry<COMPONENT> simpleComponents) { - assertThat(simpleComponents, notNullValue()); - } - } - - public static class ComponentTakingNamedComponent extends AbstractComponent { - public ComponentTakingNamedComponent(@Named("named-test") SimpleComponent injectedComponent) { - assertThat(injectedComponent, notNullValue()); - } - } - - public static class ComponentCausingCycle extends AbstractComponent { - public ComponentCausingCycle(ComponentCausingCycle component) { - } - } - - public static class SimpleComponentProviderThatThrows implements Provider<SimpleComponent> { - public SimpleComponent get() { - throw new AssertionError("Should never be called."); - } - - public void deconstruct() { - } - } - - public static class ExecutorProvider implements Provider<Executor> { - private Executor executor = Executors.newSingleThreadExecutor(); - - public Executor get() { - return executor; - } - - public void deconstruct() { - /*TODO */ } - } - - public static class DerivedExecutorProvider extends ExecutorProvider { - } - - public static class FailOnGetIntProvider implements Provider<Integer> { - - public Integer get() { - fail("Should never be called."); - return null; - } - - public void deconstruct() { - } - - } - - public static class NewIntProvider implements Provider<Integer> { - int i = 0; - - public Integer get() { - return ++i; - } - - public void deconstruct() { - } - } - - public static class ComponentTakingExecutor extends AbstractComponent { - private final Executor executor; - - public ComponentTakingExecutor(Executor executor) { - assertThat(executor, notNullValue()); - this.executor = executor; - } - } - - public static class ComponentWithInjectConstructor { - - public ComponentWithInjectConstructor(TestConfig c, Test2Config c2) { - throw new RuntimeException("Should not be called"); - } - - @Inject - public ComponentWithInjectConstructor(Test2Config c) { - } - - } - - public static class ComponentWithMultipleConstructors { - - private ComponentWithMultipleConstructors(int dummy) { - } - - public ComponentWithMultipleConstructors() { - this(0); - throw new RuntimeException("Should not be called"); - } - - public ComponentWithMultipleConstructors(TestConfig c, Test2Config c2) { - this(0); - } - - public ComponentWithMultipleConstructors(Test2Config c) { - this(); - } - - } - - public static class ComponentTakingComponentId { - private final ComponentId componentId; - - public ComponentTakingComponentId(ComponentId componentId) { - this.componentId = componentId; - } - } - - public static ComponentId uniqueComponentId(String className) { - counter += 1; - return ComponentId.fromString(className + counter); - } - - public static Node mockComponentNode(Key<?> key) { - return mockComponentNode(key.getTypeLiteral().getRawType(), "", key.getAnnotation()); - } - - public static Node mockComponentNode(Class<?> clazz, String configId, Annotation key) { - return new ComponentNode(uniqueComponentId(clazz.getName()), configId, clazz, key); - } - - public static Node mockComponentNode(Class<?> clazz, String configId) { - return new ComponentNode(uniqueComponentId(clazz.getName()), configId, clazz, null); - } - - public static Node mockComponentNode(Class<?> clazz, Annotation key) { - return new ComponentNode(uniqueComponentId(clazz.getName()), "", clazz, key); - } - - public static Node mockComponentNode(Class<?> clazz) { - return new ComponentNode(uniqueComponentId(clazz.getName()), "", clazz, null); - } - - public static Node mockComponentNodeWithId(Class<?> clazz, String componentId, String configId /*= ""*/, Annotation key /*= null*/) { - return new ComponentNode(ComponentId.fromString(componentId), configId, clazz, key); - } - - public static Node mockComponentNodeWithId(Class<?> clazz, String componentId, String configId /*= ""*/) { - return new ComponentNode(ComponentId.fromString(componentId), configId, clazz, null); - } - - public static Node mockComponentNodeWithId(Class<?> clazz, String componentId) { - return new ComponentNode(ComponentId.fromString(componentId), "", clazz, null); - } - - public static Injector singletonExecutorInjector = Guice.createInjector(new AbstractModule() { - @Override - public void configure() { - bind(Executor.class).toInstance(Executors.newSingleThreadExecutor()); - } - }); - - public static abstract class AbstractClass { - } -} diff --git a/container-core/src/test/java/com/yahoo/container/di/componentgraph/core/FallbackToGuiceInjectorTest.java b/container-core/src/test/java/com/yahoo/container/di/componentgraph/core/FallbackToGuiceInjectorTest.java deleted file mode 100644 index 7c517d67960..00000000000 --- a/container-core/src/test/java/com/yahoo/container/di/componentgraph/core/FallbackToGuiceInjectorTest.java +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di.componentgraph.core; - -import com.google.inject.AbstractModule; -import com.google.inject.Guice; -import com.google.inject.Inject; -import com.google.inject.Injector; -import com.google.inject.name.Named; -import com.google.inject.name.Names; -import com.yahoo.component.AbstractComponent; -import com.yahoo.component.ComponentId; -import com.yahoo.config.ConfigInstance; -import com.yahoo.container.di.componentgraph.core.ComponentGraph; -import com.yahoo.container.di.componentgraph.core.ComponentNode; -import com.yahoo.container.di.componentgraph.core.Node; -import com.yahoo.vespa.config.ConfigKey; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; - -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertNotNull; - -/** - * @author Tony Vaagenes - * @author gjoranv - */ -@SuppressWarnings("unused") -public class FallbackToGuiceInjectorTest { - - private ComponentGraph componentGraph; - private Injector injector; - private Map<ConfigKey<? extends ConfigInstance>, ConfigInstance> configs = - new HashMap<>(); - - @Rule - public final ExpectedException exception = ExpectedException.none(); - - @Before - public void createGraph() { - injector = Guice.createInjector(); - componentGraph = new ComponentGraph(0); - } - - public static class MyComponent extends AbstractComponent { - private final String url; - private final Executor executor; - - @Inject - public MyComponent(@Named("url") String url, Executor executor) { - this.url = url; - this.executor = executor; - } - - public MyComponent() { - throw new RuntimeException("Constructor annotated with @Inject is preferred."); - } - } - - public static class ComponentTakingDefaultString{ - private final String injectedString; - - public ComponentTakingDefaultString(String empty_string_created_by_guice) { - this.injectedString = empty_string_created_by_guice; - } - } - - public static class ComponentThatCannotBeConstructed { - public ComponentThatCannotBeConstructed(Integer cannot_be_injected_because_Integer_has_no_default_ctor) { } - } - - @Test - public void guice_injector_is_used_when_no_global_component_exists() { - setInjector( - Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - bind(Executor.class).toInstance(Executors.newSingleThreadExecutor()); - bind(String.class).annotatedWith(Names.named("url")).toInstance("http://yahoo.com"); - } - })); - - register(MyComponent.class); - complete(); - - MyComponent component = getInstance(MyComponent.class); - assertThat(component.url, is("http://yahoo.com")); - assertNotNull(component.executor); - } - - @Test - public void guice_injector_creates_a_new_instance_with_default_ctor_when_no_explicit_binding_exists() { - setInjector(emptyGuiceInjector()); - register(ComponentTakingDefaultString.class); - complete(); - - ComponentTakingDefaultString component = getInstance(ComponentTakingDefaultString.class); - assertThat(component.injectedString, is("")); - } - - @Test - public void guice_injector_fails_when_no_explicit_binding_exists_and_class_has_no_default_ctor() { - setInjector(emptyGuiceInjector()); - register(ComponentThatCannotBeConstructed.class); - - exception.expect(RuntimeException.class); - exception.expectMessage("When resolving dependencies of 'com.yahoo.container.di.componentgraph.core.FallbackToGuiceInjectorTest$ComponentThatCannotBeConstructed'"); - complete(); - } - - public void register(Class<?> componentClass) { - componentGraph.add(mockComponentNode(componentClass)); - } - - public ComponentId toId(Class<?> componentClass) { - return ComponentId.fromString(componentClass.getName()); - } - - @SuppressWarnings("unchecked") - private Node mockComponentNode(Class<?> componentClass) { - return new ComponentNode(toId(componentClass), toId(componentClass).toString(), (Class<Object>)componentClass, null); - } - - public <T> T getInstance(Class<T> componentClass) { - return componentGraph.getInstance(componentClass); - } - - public void complete() { - componentGraph.complete(injector); - componentGraph.setAvailableConfigs(configs); - } - - public void setInjector(Injector injector) { - this.injector = injector; - } - - private Injector emptyGuiceInjector() { - return Guice.createInjector(new AbstractModule() { - @Override - protected void configure() { - } - }); - } -} diff --git a/container-core/src/test/java/com/yahoo/container/di/componentgraph/core/JerseyNodeTest.java b/container-core/src/test/java/com/yahoo/container/di/componentgraph/core/JerseyNodeTest.java deleted file mode 100644 index f30f9260830..00000000000 --- a/container-core/src/test/java/com/yahoo/container/di/componentgraph/core/JerseyNodeTest.java +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di.componentgraph.core; - -import com.yahoo.container.bundle.MockBundle; -import com.yahoo.container.di.config.RestApiContext; -import com.yahoo.container.di.osgi.OsgiUtil; -import org.junit.Test; -import org.osgi.framework.wiring.BundleWiring; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.junit.Assert.assertThat; - -/** - * @author gjoranv - * @author ollivir - */ - -public class JerseyNodeTest { - private MockBundle bundle; - private List<String> bundleClasses; - private final Map<String, String> resources; - - public JerseyNodeTest() { - resources = new HashMap<>(); - resources.put("com/foo", "com/foo/Foo.class"); - resources.put("com/bar", "com/bar/Bar.class"); - bundle = new MockBundle() { - @Override - public Collection<String> listResources(String path, String ignored, int options) { - if ((options & BundleWiring.LISTRESOURCES_RECURSE) != 0 && path.equals("/")) { - return resources.values(); - } else { - return Collections.singleton(resources.get(path)); - } - } - }; - bundleClasses = new ArrayList<>(resources.values()); - } - - @Test - public void all_bundle_entries_are_returned_when_no_packages_are_given() { - Collection<String> entries = OsgiUtil.getClassEntriesInBundleClassPath(bundle, Collections.emptySet()); - assertThat(entries, containsInAnyOrder(bundleClasses.toArray())); - } - - @Test - public void only_bundle_entries_from_the_given_packages_are_returned() { - Collection<String> entries = OsgiUtil.getClassEntriesInBundleClassPath(bundle, Collections.singleton("com.foo")); - assertThat(entries, contains(resources.get("com/foo"))); - } - - @Test - public void bundle_info_is_initialized() { - RestApiContext.BundleInfo bundleInfo = JerseyNode.createBundleInfo(bundle, Collections.emptyList()); - assertThat(bundleInfo.symbolicName, is(bundle.getSymbolicName())); - assertThat(bundleInfo.version, is(bundle.getVersion())); - assertThat(bundleInfo.fileLocation, is(bundle.getLocation())); - } -} diff --git a/container-core/src/test/java/com/yahoo/container/di/componentgraph/core/ReuseComponentsTest.java b/container-core/src/test/java/com/yahoo/container/di/componentgraph/core/ReuseComponentsTest.java deleted file mode 100644 index e61e90cd718..00000000000 --- a/container-core/src/test/java/com/yahoo/container/di/componentgraph/core/ReuseComponentsTest.java +++ /dev/null @@ -1,254 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.container.di.componentgraph.core; - -import com.yahoo.component.ComponentId; -import com.yahoo.component.provider.ComponentRegistry; -import com.yahoo.config.subscription.ConfigGetter; -import com.yahoo.config.test.TestConfig; -import com.yahoo.container.di.componentgraph.core.ComponentGraphTest.ComponentTakingAllSimpleComponents; -import com.yahoo.container.di.componentgraph.core.ComponentGraphTest.ComponentTakingComponent; -import com.yahoo.container.di.componentgraph.core.ComponentGraphTest.ComponentTakingConfig; -import com.yahoo.container.di.componentgraph.core.ComponentGraphTest.ComponentTakingConfigAndComponent; -import com.yahoo.container.di.componentgraph.core.ComponentGraphTest.ComponentTakingExecutor; -import com.yahoo.container.di.componentgraph.core.ComponentGraphTest.ExecutorProvider; -import com.yahoo.container.di.componentgraph.core.ComponentGraphTest.SimpleComponent; -import com.yahoo.container.di.componentgraph.core.ComponentGraphTest.SimpleComponent2; -import com.yahoo.vespa.config.ConfigKey; -import org.junit.Test; - -import java.util.Collections; -import java.util.concurrent.Executor; -import java.util.function.Function; -import java.util.function.Supplier; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.not; -import static org.hamcrest.CoreMatchers.sameInstance; -import static org.junit.Assert.assertThat; - -/** - * @author gjoranv - * @author Tony Vaagenes - * @author ollivir - */ -public class ReuseComponentsTest { - @Test - public void require_that_component_is_reused_when_componentNode_is_unmodified() { - reuseAndTest(SimpleComponent.class, SimpleComponent.class); - reuseAndTest(ExecutorProvider.class, Executor.class); - } - - private <T> void reuseAndTest(Class<?> classToRegister, Class<T> classToLookup) { - ComponentGraph graph = buildGraphAndSetNoConfigs(classToRegister); - T instance = getComponent(graph, classToLookup); - - ComponentGraph newGraph = buildGraphAndSetNoConfigs(classToRegister); - newGraph.reuseNodes(graph); - T instance2 = getComponent(newGraph, classToLookup); - - assertThat(instance2, sameInstance(instance)); - } - - @Test(expected = IllegalStateException.class) - public void require_that_component_is_not_reused_when_class_is_changed() { - ComponentGraph graph = buildGraphAndSetNoConfigs(SimpleComponent.class); - SimpleComponent instance = getComponent(graph, SimpleComponent.class); - - ComponentGraph newGraph = buildGraphAndSetNoConfigs(SimpleComponent2.class); - newGraph.reuseNodes(graph); - SimpleComponent2 instance2 = getComponent(newGraph, SimpleComponent2.class); - - assertThat(instance2.getId(), is(instance.getId())); - @SuppressWarnings("unused") - SimpleComponent throwsException = getComponent(newGraph, SimpleComponent.class); - } - - @Test - public void require_that_component_is_not_reused_when_config_is_changed() { - Class<ComponentTakingConfig> componentClass = ComponentTakingConfig.class; - - ComponentGraph graph = buildGraph(componentClass); - graph.setAvailableConfigs(Collections.singletonMap(new ConfigKey<>(TestConfig.class, "component"), - ConfigGetter.getConfig(TestConfig.class, "raw: stringVal \"oldConfig\""))); - ComponentTakingConfig instance = getComponent(graph, componentClass); - - ComponentGraph newGraph = buildGraph(componentClass); - newGraph.setAvailableConfigs(Collections.singletonMap(new ConfigKey<>(TestConfig.class, "component"), - ConfigGetter.getConfig(TestConfig.class, "raw: stringVal \"newConfig\""))); - newGraph.reuseNodes(graph); - ComponentTakingConfig instance2 = getComponent(newGraph, componentClass); - - assertThat(instance2, not(sameInstance(instance))); - } - - @Test - public void require_that_component_is_not_reused_when_injected_component_is_changed() { - Function<String, ComponentGraph> buildGraph = config -> { - ComponentGraph graph = new ComponentGraph(); - - ComponentNode rootComponent = mockComponentNode(ComponentTakingComponent.class, "root_component"); - - String configId = "componentTakingConfigId"; - ComponentNode injectedComponent = mockComponentNode(ComponentTakingConfig.class, "injected_component", configId); - - rootComponent.inject(injectedComponent); - - graph.add(rootComponent); - graph.add(injectedComponent); - - graph.complete(); - graph.setAvailableConfigs(Collections.singletonMap(new ConfigKey<>(TestConfig.class, configId), - ConfigGetter.getConfig(TestConfig.class, "raw: stringVal \"" + config + "\""))); - - return graph; - }; - - ComponentGraph oldGraph = buildGraph.apply("oldGraph"); - ComponentTakingComponent oldInstance = getComponent(oldGraph, ComponentTakingComponent.class); - - ComponentGraph newGraph = buildGraph.apply("newGraph"); - newGraph.reuseNodes(oldGraph); - ComponentTakingComponent newInstance = getComponent(newGraph, ComponentTakingComponent.class); - - assertThat(newInstance, not(sameInstance(oldInstance))); - } - - @Test - public void require_that_component_is_not_reused_when_injected_component_registry_has_one_component_removed() { - Function<Boolean, ComponentGraph> buildGraph = useBothInjectedComponents -> { - ComponentGraph graph = new ComponentGraph(); - graph.add(mockComponentNode(ComponentTakingAllSimpleComponents.class, "root_component")); - - /* Below if-else has code duplication, but explicit ordering of the two components - * was necessary to reproduce erroneous behaviour in ComponentGraph.reuseNodes that - * occurred before ComponentRegistryNode got its own 'equals' implementation. - */ - if (useBothInjectedComponents) { - graph.add(mockComponentNode(SimpleComponent.class, "injected_component2")); - graph.add(mockComponentNode(SimpleComponent.class, "injected_component1")); - } else { - graph.add(mockComponentNode(SimpleComponent.class, "injected_component1")); - } - - graph.complete(); - graph.setAvailableConfigs(Collections.emptyMap()); - return graph; - }; - - ComponentGraph oldGraph = buildGraph.apply(true); - ComponentRegistry<SimpleComponent> oldSimpleComponentRegistry = getComponent(oldGraph, ComponentTakingAllSimpleComponents.class).simpleComponents; - - ComponentGraph newGraph = buildGraph.apply(false); - newGraph.reuseNodes(oldGraph); - ComponentRegistry<SimpleComponent> newSimpleComponentRegistry = getComponent(newGraph, ComponentTakingAllSimpleComponents.class).simpleComponents; - - assertThat(newSimpleComponentRegistry, not(sameInstance(oldSimpleComponentRegistry))); - } - - @Test - public void require_that_injected_component_is_reused_even_when_dependent_component_is_changed() { - Function<String, ComponentGraph> buildGraph = config -> { - ComponentGraph graph = new ComponentGraph(); - - String configId = "componentTakingConfigAndComponent"; - ComponentNode rootComponent = mockComponentNode(ComponentTakingConfigAndComponent.class, "root_component", configId); - - ComponentNode injectedComponent = mockComponentNode(SimpleComponent.class, "injected_component"); - - rootComponent.inject(injectedComponent); - - graph.add(rootComponent); - graph.add(injectedComponent); - - graph.complete(); - graph.setAvailableConfigs(Collections.singletonMap(new ConfigKey<>(TestConfig.class, configId), - ConfigGetter.getConfig(TestConfig.class, "raw: stringVal \"" + config + "\""))); - - return graph; - }; - - ComponentGraph oldGraph = buildGraph.apply("oldGraph"); - SimpleComponent oldInjectedComponent = getComponent(oldGraph, SimpleComponent.class); - ComponentTakingConfigAndComponent oldDependentComponent = getComponent(oldGraph, ComponentTakingConfigAndComponent.class); - - ComponentGraph newGraph = buildGraph.apply("newGraph"); - newGraph.reuseNodes(oldGraph); - SimpleComponent newInjectedComponent = getComponent(newGraph, SimpleComponent.class); - ComponentTakingConfigAndComponent newDependentComponent = getComponent(newGraph, ComponentTakingConfigAndComponent.class); - - assertThat(newDependentComponent, not(sameInstance(oldDependentComponent))); - assertThat(newInjectedComponent, sameInstance(oldInjectedComponent)); - } - - @Test - public void require_that_node_depending_on_guice_node_is_reused() { - Supplier<ComponentGraph> makeGraph = () -> { - ComponentGraph graph = new ComponentGraph(); - graph.add(mockComponentNode(ComponentTakingExecutor.class, "dummyId")); - graph.complete(ComponentGraphTest.singletonExecutorInjector); - graph.setAvailableConfigs(Collections.emptyMap()); - return graph; - }; - - Function<ComponentGraph, ComponentTakingExecutor> componentRetriever = graph -> getComponent(graph, ComponentTakingExecutor.class); - - ComponentGraph oldGraph = makeGraph.get(); - componentRetriever.apply(oldGraph); // Ensure creation of GuiceNode - ComponentGraph newGraph = makeGraph.get(); - newGraph.reuseNodes(oldGraph); - assertThat(componentRetriever.apply(oldGraph), sameInstance(componentRetriever.apply(newGraph))); - } - - @Test - public void require_that_node_equals_only_checks_first_level_components_to_inject() { - Function<String, Node> createNodeWithInjectedNodeWithInjectedNode = indirectlyInjectedComponentId -> { - ComponentNode targetComponent = mockComponentNode(SimpleComponent.class, "target"); - ComponentNode directlyInjectedComponent = mockComponentNode(SimpleComponent.class, "directlyInjected"); - ComponentNode indirectlyInjectedComponent = mockComponentNode(SimpleComponent.class, indirectlyInjectedComponentId); - directlyInjectedComponent.inject(indirectlyInjectedComponent); - targetComponent.inject(directlyInjectedComponent); - - completeNode(targetComponent); - completeNode(directlyInjectedComponent); - completeNode(indirectlyInjectedComponent); - - return targetComponent; - }; - - Node targetNode1 = createNodeWithInjectedNodeWithInjectedNode.apply("indirectlyInjected_1"); - Node targetNode2 = createNodeWithInjectedNodeWithInjectedNode.apply("indirectlyInjected_2"); - assertThat(targetNode1, equalTo(targetNode2)); - } - - private void completeNode(ComponentNode node) { - node.setArguments(new Object[0]); - node.setAvailableConfigs(Collections.emptyMap()); - } - - private ComponentGraph buildGraph(Class<?> componentClass) { - String commonComponentId = "component"; - ComponentGraph g = new ComponentGraph(); - g.add(mockComponentNode(componentClass, commonComponentId, commonComponentId)); - g.complete(); - return g; - } - - private ComponentGraph buildGraphAndSetNoConfigs(Class<?> componentClass) { - ComponentGraph g = buildGraph(componentClass); - g.setAvailableConfigs(Collections.emptyMap()); - return g; - } - - private static ComponentNode mockComponentNode(Class<?> clazz, String componentId, String configId) { - return new ComponentNode(new ComponentId(componentId), configId, clazz); - } - - private static ComponentNode mockComponentNode(Class<?> clazz, String componentId) { - return mockComponentNode(clazz, componentId, ""); - } - - private static <T> T getComponent(ComponentGraph graph, Class<T> clazz) { - return graph.getInstance(clazz); - } -} diff --git a/container-core/src/test/java/com/yahoo/container/di/componentgraph/cycle/CycleFinderTest.java b/container-core/src/test/java/com/yahoo/container/di/componentgraph/cycle/CycleFinderTest.java deleted file mode 100644 index 174ca301c59..00000000000 --- a/container-core/src/test/java/com/yahoo/container/di/componentgraph/cycle/CycleFinderTest.java +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -package com.yahoo.container.di.componentgraph.cycle; - -import org.junit.Test; - -import static com.yahoo.container.di.componentgraph.cycle.CycleFinderTest.Vertices.A; -import static com.yahoo.container.di.componentgraph.cycle.CycleFinderTest.Vertices.B; -import static com.yahoo.container.di.componentgraph.cycle.CycleFinderTest.Vertices.C; -import static com.yahoo.container.di.componentgraph.cycle.CycleFinderTest.Vertices.D; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.empty; -import static org.junit.Assert.assertThat; - -/** - * @author gjoranv - */ -public class CycleFinderTest { - - enum Vertices {A, B, C, D} - - @Test - public void graph_without_cycles_returns_no_cycle() { - var graph = new Graph<Vertices>(); - graph.edge(A, B); - graph.edge(B, C); - graph.edge(A, C); - graph.edge(D, A); - - var cycleFinder = new CycleFinder<>(graph); - assertThat(cycleFinder.findCycle(), empty()); - } - - @Test - public void graph_with_cycle_returns_cycle() { - var graph = new Graph<Vertices>(); - graph.edge(A, B); - graph.edge(B, C); - graph.edge(C, A); - - var cycleFinder = new CycleFinder<>(graph); - assertThat(cycleFinder.findCycle(), contains(A, B, C, A)); - } - - @Test - public void graph_with_self_referencing_vertex_returns_cycle() { - var graph = new Graph<Vertices>(); - graph.edge(A, A); - - var cycleFinder = new CycleFinder<>(graph); - assertThat(cycleFinder.findCycle(), contains(A, A)); - } - - @Test - public void leading_nodes_are_stripped_from_cycle() { - var graph = new Graph<Vertices>(); - graph.edge(A, B); - graph.edge(B, C); - graph.edge(C, B); - - var cycleFinder = new CycleFinder<>(graph); - assertThat(cycleFinder.findCycle(), contains(B, C, B)); - } - - @Test - public void findCycle_is_idempotent_with_cycle() { - var graph = new Graph<Vertices>(); - graph.edge(A, A); - - var cycleFinder = new CycleFinder<>(graph); - assertThat(cycleFinder.findCycle(), contains(A, A)); - assertThat(cycleFinder.findCycle(), contains(A, A)); - } - - @Test - public void findCycle_is_idempotent_without_cycle() { - var graph = new Graph<Vertices>(); - graph.edge(A, B); - - var cycleFinder = new CycleFinder<>(graph); - assertThat(cycleFinder.findCycle(), empty()); - assertThat(cycleFinder.findCycle(), empty()); - } - -} diff --git a/container-core/src/test/java/com/yahoo/container/di/componentgraph/cycle/GraphTest.java b/container-core/src/test/java/com/yahoo/container/di/componentgraph/cycle/GraphTest.java deleted file mode 100644 index 069f72ad8e7..00000000000 --- a/container-core/src/test/java/com/yahoo/container/di/componentgraph/cycle/GraphTest.java +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -package com.yahoo.container.di.componentgraph.cycle; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import static com.yahoo.container.di.componentgraph.cycle.GraphTest.Vertices.A; -import static com.yahoo.container.di.componentgraph.cycle.GraphTest.Vertices.B; -import static com.yahoo.container.di.componentgraph.cycle.GraphTest.Vertices.C; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.Matchers.empty; -import static org.junit.Assert.assertThat; - -/** - * @author gjoranv - */ -public class GraphTest { - - enum Vertices {A, B, C} - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Test - public void vertices_and_edges_are_added_and_can_be_retrieved() { - var graph = new Graph<Vertices>(); - graph.edge(A, B); - graph.edge(B, C); - graph.edge(A, C); - - assertThat(graph.getVertices().size(), is(3)); - assertThat(graph.getAdjacent(A), containsInAnyOrder(B, C)); - assertThat(graph.getAdjacent(B), containsInAnyOrder(C)); - assertThat(graph.getAdjacent(C), empty()); - } - - @Test - public void null_vertices_are_not_allowed() { - var graph = new Graph<Vertices>(); - - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Null vertices are not allowed"); - graph.edge(A, null); - } - - @Test - public void duplicate_edges_are_ignored() { - var graph = new Graph<Vertices>(); - graph.edge(A, B); - graph.edge(A, B); - - assertThat(graph.getAdjacent(A).size(), is(1)); - } - - @Test - public void self_edges_are_allowed() { - var graph = new Graph<Vertices>(); - graph.edge(A, A); - - assertThat(graph.getAdjacent(A), contains(A)); - } - -} diff --git a/container-core/src/test/vespa-configdef/config.di.int.def b/container-core/src/test/vespa-configdef/config.di.int.def deleted file mode 100644 index a34539c4a0f..00000000000 --- a/container-core/src/test/vespa-configdef/config.di.int.def +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -namespace=config.di - -intVal int default=1 diff --git a/container-core/src/test/vespa-configdef/config.di.string.def b/container-core/src/test/vespa-configdef/config.di.string.def deleted file mode 100644 index 396afe54f3f..00000000000 --- a/container-core/src/test/vespa-configdef/config.di.string.def +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -namespace=config.di - -stringVal string default="_default_" diff --git a/container-core/src/test/vespa-configdef/config.test.bootstrap1.def b/container-core/src/test/vespa-configdef/config.test.bootstrap1.def deleted file mode 100644 index bdee16d99ea..00000000000 --- a/container-core/src/test/vespa-configdef/config.test.bootstrap1.def +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -namespace=config.test - -dummy string default="" diff --git a/container-core/src/test/vespa-configdef/config.test.bootstrap2.def b/container-core/src/test/vespa-configdef/config.test.bootstrap2.def deleted file mode 100644 index b4fbffd8ae6..00000000000 --- a/container-core/src/test/vespa-configdef/config.test.bootstrap2.def +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -namespace=config.test - -dummy string default="" - diff --git a/container-core/src/test/vespa-configdef/config.test.components1.def b/container-core/src/test/vespa-configdef/config.test.components1.def deleted file mode 100644 index bdee16d99ea..00000000000 --- a/container-core/src/test/vespa-configdef/config.test.components1.def +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -namespace=config.test - -dummy string default="" diff --git a/container-core/src/test/vespa-configdef/config.test.test.def b/container-core/src/test/vespa-configdef/config.test.test.def deleted file mode 100644 index d3e0ed17748..00000000000 --- a/container-core/src/test/vespa-configdef/config.test.test.def +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -namespace=config.test - -stringVal string default="default" diff --git a/container-core/src/test/vespa-configdef/config.test.test2.def b/container-core/src/test/vespa-configdef/config.test.test2.def deleted file mode 100644 index d3e0ed17748..00000000000 --- a/container-core/src/test/vespa-configdef/config.test.test2.def +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -namespace=config.test - -stringVal string default="default" diff --git a/container-core/src/test/vespa-configdef/config.test.thread-pool.def b/container-core/src/test/vespa-configdef/config.test.thread-pool.def deleted file mode 100644 index 9e6b6694e84..00000000000 --- a/container-core/src/test/vespa-configdef/config.test.thread-pool.def +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -namespace=config.test - -numThreads int |