Skip to content

Commit

Permalink
InjectionManager can test and register its specific implementation's …
Browse files Browse the repository at this point in the history
…objects.

Change-Id: I090e0edff2af611b5c343324e42fae11b834492f
  • Loading branch information
Petr Bouda committed Mar 15, 2017
1 parent d22d0c9 commit 364e980
Show file tree
Hide file tree
Showing 16 changed files with 423 additions and 109 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
import java.util.logging.Logger;
import java.util.stream.Collectors;

import org.glassfish.jersey.internal.LocalizationMessages;
import org.glassfish.jersey.internal.inject.Binder;
import org.glassfish.jersey.internal.inject.Binding;
import org.glassfish.jersey.internal.inject.ClassBinding;
Expand Down Expand Up @@ -146,7 +145,7 @@ public void initialize(String name, Object parent, Binder... binders) {
ServiceLocatorRuntimeBean serviceLocatorRuntimeBean = locator.getService(ServiceLocatorRuntimeBean.class);
if (serviceLocatorRuntimeBean != null) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine(LocalizationMessages.CLEARING_HK_2_CACHE(
LOGGER.fine(LocalizationMessages.HK_2_CLEARING_CACHE(
serviceLocatorRuntimeBean.getServiceCacheSize(),
serviceLocatorRuntimeBean.getReflectionCacheSize()));
}
Expand All @@ -162,7 +161,7 @@ public void initialize(String name, Object parent, Binder... binders) {
*/
private static void assertParentLocatorType(Object parent) {
if (parent != null && !(parent instanceof ServiceLocator || parent instanceof HK2InjectionManager)) {
throw new RuntimeException(LocalizationMessages.HK_2_UNKNOWN_PARENT_INSTANCE_MANAGER(
throw new IllegalArgumentException(LocalizationMessages.HK_2_UNKNOWN_PARENT_INJECTION_MANAGER(
parent.getClass().getSimpleName()));
}
}
Expand Down Expand Up @@ -192,8 +191,17 @@ public void register(Binder binder) {
}

@Override
public void register(org.glassfish.hk2.utilities.Binder... binder) {
ServiceLocatorUtilities.bind(locator, binder);
public void register(Object provider) {
if (isRegistrable(provider.getClass())) {
ServiceLocatorUtilities.bind(locator, (org.glassfish.hk2.utilities.Binder) provider);
} else {
throw new IllegalArgumentException();
}
}

@Override
public boolean isRegistrable(Class<?> clazz) {
return org.glassfish.hk2.utilities.Binder.class.isAssignableFrom(clazz);
}

@Override
Expand Down Expand Up @@ -244,7 +252,8 @@ private ForeignDescriptor createAndTranslateForeignDescriptor(Binding binding) {
} else if (InstanceBinding.class.isAssignableFrom(binding.getClass())) {
activeDescriptor = Hk2Helper.translateToActiveDescriptor((InstanceBinding<?>) binding);
} else {
throw new RuntimeException(LocalizationMessages.UNKNOWN_DESCRIPTOR_TYPE(binding.getClass().getSimpleName()));
throw new RuntimeException(org.glassfish.jersey.internal.LocalizationMessages.UNKNOWN_DESCRIPTOR_TYPE(
binding.getClass().getSimpleName()));
}

return ForeignDescriptor.wrap(activeDescriptor, activeDescriptor::dispose);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
import javax.inject.Singleton;

import org.glassfish.jersey.internal.Errors;
import org.glassfish.jersey.internal.LocalizationMessages;
import org.glassfish.jersey.internal.inject.AbstractBinder;

import org.glassfish.hk2.api.ErrorInformation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@
public interface InjectionManager {

/**
* This will initialize the {@code InjectionManager} and underlying DI provider. The method may get the array of binders to
* Initializes {@code InjectionManager} and underlying DI provider. The method may get the array of binders to
* register {@link Binding} them during initialization process. {@code name} and {@code parent} are not required parameters
* and can be null without the initialization exception.
* and can be {@code null} without the initialization exception.
*
* @param name Name of the injection manager.
* @param parent Parent object of the underlying DI provider on which new injection manager should be dependent. A specific
Expand All @@ -68,12 +68,36 @@ public interface InjectionManager {
void initialize(String name, Object parent, Binder... binders);

/**
* This will shutdown the entire injection manager and underlying DI provider along with injected executors and schedulers.
* Initializes {@code InjectionManager} and underlying DI provider. The method may get the array of binders to
* register {@link Binding} them during initialization process. {@code parent} is not required parameters and can be
* {@code null} without the initialization exception.
*
* @param parent Parent object of the underlying DI provider on which new injection manager should be dependent. A specific
* DI provider checks whether the parent object is in the proper type of underlying service storage or
* a proper implementation of {@link InjectionManager}.
* @param binders Binders with descriptions to include them during initialization process.
*/
default void initialize(Object parent, Binder... binders) {
initialize(null, parent, binders);
}

/**
* Initializes {@code InjectionManager} and underlying DI provider. The method may get the array of binders to
* register {@link Binding} them during initialization process.
* @param binders Binders with descriptions to include them during initialization process.
*/
default void initialize(Binder... binders) {
initialize(null, null, binders);
}

/**
* Shuts down the entire {@link InjectionManager}and underlying DI provider along with injected executors and schedulers.
*/
void shutdown();

/**
* This will register one bean represented using fields in the provided descriptor. The final bean can be direct bean or
* Registers one bean represented using fields in the provided descriptor. The final bean can be direct bean or
* factory object which will create the bean at the time of injection. {@code InjectionManager} is able to register a bean
* represented by a class or direct instance.
*
Expand All @@ -86,7 +110,7 @@ public interface InjectionManager {
void register(Binding binding);

/**
* This will register a collection of beans represented using fields in the provided descriptors. The final bean can be
* Registers a collection of beans represented using fields in the provided descriptors. The final bean can be
* direct bean or factory object which will create the bean at the time of injection. {@code InjectionManager} is able to
* register a bean represented by a class or direct instance.
*
Expand All @@ -99,7 +123,7 @@ public interface InjectionManager {
void register(Iterable<Binding> descriptors);

/**
* This will register beans which are included in {@link Binder}. {@code Binder} can contains all descriptors extending
* Registers beans which are included in {@link Binder}. {@code Binder} can contains all descriptors extending
* {@link Binding} or other binders which are installed together in tree-structure. This method will get all descriptors
* bound in the given binder and register them in the order how the binders are installed together. In the tree structure,
* the deeper on the left side will be processed first.
Expand All @@ -113,20 +137,26 @@ public interface InjectionManager {
void register(Binder binder);

/**
* Register a HK2 Binder.
* Registers a provider. An implementation of the {@link InjectionManager} should test whether the type of the object can be
* registered using the method {@link #isRegistrable(Class)}. Then a caller has an certainty that the instance of the tested
* class can be registered in {@code InjectionManager}. If {@code InjectionManager} is not able to register the provider
* then {@link IllegalArgumentException} is thrown.
*
* For compatibility reasons only, to be removed.
* @param provider object that can be registered in {@code InjectionManager}.
* @throws IllegalArgumentException provider cannot be registered.
*/
void register(Object provider);

/**
* Tests whether the provided {@code clazz} can be registered by the implementation of the {@link InjectionManager}.
*
* @param binder collection of descriptors.
* @see ClassBinding
* @see InstanceBinding
* @see SupplierClassBinding
* @see SupplierInstanceBinding
* @param clazz type that is tested whether is registrable by the implementation of {@code InjectionManager}.
* @return {@code true} if the {@code InjectionManager} is able to register this type.
*/
void register(org.glassfish.hk2.utilities.Binder... binder);
boolean isRegistrable(Class<?> clazz);

/**
* This method creates, injects and post-constructs an object with the given class. This is equivalent to calling the
* Creates, injects and post-constructs an object with the given class. This is equivalent to calling the
* {@code create-class} method followed by the {@code inject-class} method followed by the {@code post-construct} method.
* <p>
* The object created is not managed by the injection manager.
Expand Down Expand Up @@ -234,7 +264,7 @@ public interface InjectionManager {
<T> List<T> getAllInstances(Type contractOrImpl);

/**
* This will analyze the given object and inject into its fields and methods.
* Analyzes the given object and inject into its fields and methods.
* The object injected in this way will not be managed by HK2
*
* @param injectMe The object to be analyzed and injected into
Expand All @@ -251,7 +281,7 @@ public interface InjectionManager {
void inject(Object injectMe, String classAnalyzer);

/**
* This will analyze the given object and call the preDestroy method. The object given will not be managed by bean manager.
* Analyzes the given object and call the preDestroy method. The object given will not be managed by bean manager.
*
* @param preDestroyMe The object to preDestroy
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,7 @@ public static void bindProviders(ComponentBag componentBag,
RuntimeType constrainedTo,
Set<Class<?>> registeredClasses,
InjectionManager injectionManager) {
Predicate<ContractProvider> filter =
input -> ComponentBag.EXCLUDE_EMPTY.test(input) && ComponentBag.EXCLUDE_META_PROVIDERS.test(input);
Predicate<ContractProvider> filter = ComponentBag.EXCLUDE_EMPTY.and(ComponentBag.excludeMetaProviders(injectionManager));

/*
* Check the {@code component} whether it is correctly configured for client or server {@link RuntimeType runtime}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@ private static Map<Class<?>, ProviderRuntime> getExternalProviderInterfaces() {
interfaces.putAll(JAX_RS_PROVIDER_INTERFACE_WHITELIST);
interfaces.put(javax.ws.rs.core.Feature.class, ProviderRuntime.BOTH);
interfaces.put(Binder.class, ProviderRuntime.BOTH);
interfaces.put(org.glassfish.hk2.utilities.Binder.class, ProviderRuntime.BOTH);
return interfaces;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2012-2016 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012-2017 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
Expand Down Expand Up @@ -66,10 +66,11 @@ public final class ContractProvider implements Scoped, NameBound {
/**
* Create new contract provider model builder.
*
* @param implementationClass class which the contracts belong to.
* @return new contract provider builder.
*/
public static Builder builder() {
return new Builder();
public static Builder builder(Class<?> implementationClass) {
return new Builder(implementationClass);
}

/**
Expand All @@ -87,21 +88,21 @@ public static Builder builder(final ContractProvider original) {
*/
public static final class Builder {

private static final ContractProvider EMPTY_MODEL = new ContractProvider(
Singleton.class,
Collections.emptyMap(),
NO_PRIORITY,
Collections.emptySet());
private static final ContractProvider EMPTY_MODEL =
new ContractProvider(null, Singleton.class, Collections.emptyMap(), NO_PRIORITY, Collections.emptySet());

private Class<?> implementationClass = null;
private Class<? extends Annotation> scope = null;
private Map<Class<?>, Integer> contracts = new HashMap<>();
private int defaultPriority = NO_PRIORITY;
private Set<Class<? extends Annotation>> nameBindings = Collections.newSetFromMap(new IdentityHashMap<>());

private Builder() {
private Builder(Class<?> implementationClass) {
this.implementationClass = implementationClass;
}

private Builder(final ContractProvider original) {
this.implementationClass = original.implementationClass;
this.scope = original.scope;
this.contracts.putAll(original.contracts);
this.defaultPriority = original.defaultPriority;
Expand Down Expand Up @@ -248,25 +249,29 @@ public ContractProvider build() {
final Set<Class<? extends Annotation>> bindings = (nameBindings.isEmpty())
? Collections.emptySet() : Collections.unmodifiableSet(nameBindings);

if (scope == Singleton.class && _contracts.isEmpty() && defaultPriority == NO_PRIORITY && bindings.isEmpty()) {
if (implementationClass == null && scope == Singleton.class && _contracts.isEmpty() && defaultPriority == NO_PRIORITY
&& bindings.isEmpty()) {
return EMPTY_MODEL;
}

return new ContractProvider(scope, _contracts, defaultPriority, bindings);
return new ContractProvider(implementationClass, scope, _contracts, defaultPriority, bindings);
}
}

private final Class<?> implementationClass;
private final Map<Class<?>, Integer> contracts;
private final int defaultPriority;
private final Set<Class<? extends Annotation>> nameBindings;
private final Class<? extends Annotation> scope;

private ContractProvider(
final Class<?> implementationClass,
final Class<? extends Annotation> scope,
final Map<Class<?>, Integer> contracts,
final int defaultPriority,
final Set<Class<? extends Annotation>> nameBindings) {

this.implementationClass = implementationClass;
this.scope = scope;
this.contracts = contracts;
this.defaultPriority = defaultPriority;
Expand All @@ -278,6 +283,15 @@ public Class<? extends Annotation> getScope() {
return scope;
}

/**
* Get the implementation class which the contracts belong to.
*
* @return implementation class.
*/
public Class<?> getImplementationClass() {
return implementationClass;
}

/**
* Get provided contracts recognized by Jersey.
*
Expand Down
Loading

0 comments on commit 364e980

Please sign in to comment.