org.glassfish.hk2.utilities.binding.AbstractBindingBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ehcache Show documentation
Show all versions of ehcache Show documentation
Ehcache is an open source, standards-based cache used to boost performance,
offload the database and simplify scalability. Ehcache is robust, proven and full-featured and
this has made it the most widely-used Java-based cache.
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2012 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
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* http://glassfish.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package org.glassfish.hk2.utilities.binding;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.glassfish.hk2.api.Descriptor;
import org.glassfish.hk2.api.DynamicConfiguration;
import org.glassfish.hk2.api.Factory;
import org.glassfish.hk2.api.FactoryDescriptors;
import org.glassfish.hk2.api.HK2Loader;
import org.glassfish.hk2.api.TypeLiteral;
import org.glassfish.hk2.utilities.AbstractActiveDescriptor;
import org.glassfish.hk2.utilities.ActiveDescriptorBuilder;
import org.glassfish.hk2.utilities.BuilderHelper;
import org.glassfish.hk2.utilities.reflection.ParameterizedTypeImpl;
import org.jvnet.hk2.component.MultiMap;
/**
* Abstract binding builder implementation.
*
* @param bound service type.
* @author Marek Potociar (marek.potociar at oracle.com)
*/
abstract class AbstractBindingBuilder implements
ServiceBindingBuilder, NamedBindingBuilder, ScopedBindingBuilder, ScopedNamedBindingBuilder {
/**
* Contracts the service should be bound to.
*/
Set contracts = new HashSet();
/**
* Bound service loader.
*/
HK2Loader loader = null;
/**
* Binding metadata (e.g. useful for filtering).
*/
MultiMap metadata = new MultiMap();
/**
* Qualifiers (other than @Named).
*/
Set qualifiers = new HashSet();
/**
* Binding scope.
*/
Class extends Annotation> scope = null;
/**
* Binding rank.
*/
Integer ranked = null;
/**
* Binding name (see @Named).
*/
String name = null;
/**
* Injectee is proxiable.
*/
Boolean proxiable = null;
/**
* Injectee should be proxied even inside the same scope
*/
Boolean proxyForSameScope = null;
@Override
public AbstractBindingBuilder proxy(boolean proxiable) {
this.proxiable = proxiable;
return this;
}
@Override
public AbstractBindingBuilder proxyForSameScope(boolean proxyForSameScope) {
this.proxyForSameScope = proxyForSameScope;
return this;
}
/**
* Analyzer to use with this descriptor
*/
String analyzer = null;
@Override
public AbstractBindingBuilder analyzeWith(String analyzer) {
this.analyzer = analyzer;
return this;
}
@Override
public AbstractBindingBuilder to(Class super T> contract) {
contracts.add(contract);
return this;
}
@Override
public AbstractBindingBuilder to(TypeLiteral> contract) {
contracts.add(contract.getType());
return this;
}
@Override
public AbstractBindingBuilder to(Type contract) {
contracts.add(contract);
return this;
}
@Override
public AbstractBindingBuilder loadedBy(HK2Loader loader) {
this.loader = loader;
return this;
}
@Override
public AbstractBindingBuilder withMetadata(String key, String value) {
this.metadata.add(key, value);
return this;
}
@Override
public AbstractBindingBuilder withMetadata(String key, List values) {
for (String value : values) {
this.metadata.add(key,value);
}
return this;
}
@Override
public AbstractBindingBuilder qualifiedBy(Annotation annotation) {
this.qualifiers.add(annotation);
return this;
}
@Override
public AbstractBindingBuilder in(Class extends Annotation> scopeAnnotation) {
this.scope = scopeAnnotation;
return this;
}
@Override
public AbstractBindingBuilder named(String name) {
this.name = name;
return this;
}
@Override
public void ranked(int rank) {
this.ranked = rank;
}
/**
* Build the binding descriptor and bind it in the {@link DynamicConfiguration
* dynamic configuration}.
*
* @param configuration dynamic binding configuration.
* @param defaultLoader default HK2 loader that should be used in case a custom loader
* was not set.
*/
abstract void complete(DynamicConfiguration configuration, HK2Loader defaultLoader);
private static class ClassBasedBindingBuilder extends AbstractBindingBuilder {
private final Class service;
public ClassBasedBindingBuilder(Class service, Type serviceContractType) {
this.service = service;
if (serviceContractType != null) {
super.contracts.add(serviceContractType);
}
}
@Override
void complete(final DynamicConfiguration configuration, final HK2Loader defaultLoader) {
if (this.loader == null) {
this.loader = defaultLoader;
}
ActiveDescriptorBuilder builder = BuilderHelper.activeLink(service)
.named(name)
.andLoadWith(this.loader)
.analyzeWith(this.analyzer);
if (scope != null) {
builder.in(scope);
}
if (ranked != null) {
builder.ofRank(ranked);
}
for (String key : metadata.keySet()) {
for (String value : metadata.get(key)) {
builder.has(key, value);
}
}
for (Annotation annotation : qualifiers) {
builder.qualifiedBy(annotation);
}
for (Type contract : contracts) {
builder.to(contract);
}
if (proxiable != null) {
builder.proxy(proxiable);
}
if (proxyForSameScope != null) {
builder.proxyForSameScope(proxyForSameScope);
}
configuration.bind(builder.build(), false);
}
}
private static class InstanceBasedBindingBuilder extends AbstractBindingBuilder {
private final T service;
public InstanceBasedBindingBuilder(T service) {
this.service = service;
}
@Override
void complete(DynamicConfiguration configuration, HK2Loader defaultLoader) {
if (this.loader == null) {
this.loader = defaultLoader;
}
AbstractActiveDescriptor> descriptor = BuilderHelper.createConstantDescriptor(service);
descriptor.setName(name);
descriptor.setLoader(this.loader);
descriptor.setClassAnalysisName(this.analyzer);
if (scope != null) {
descriptor.setScope(scope.getName());
}
if (ranked != null) {
descriptor.setRanking(ranked);
}
for (String key : metadata.keySet()) {
for (String value : metadata.get(key)) {
descriptor.addMetadata(key, value);
}
}
for (Annotation annotation : qualifiers) {
descriptor.addQualifierAnnotation(annotation);
}
for (Type contract : contracts) {
descriptor.addContractType(contract);
}
if (proxiable != null) {
descriptor.setProxiable(proxiable);
}
if (proxyForSameScope != null) {
descriptor.setProxyForSameScope(proxyForSameScope);
}
configuration.bind(descriptor, false);
}
}
private static class FactoryInstanceBasedBindingBuilder extends AbstractBindingBuilder {
private final Factory factory;
public FactoryInstanceBasedBindingBuilder(Factory factory) {
this.factory = factory;
}
@Override
void complete(DynamicConfiguration configuration, HK2Loader defaultLoader) {
if (this.loader == null) {
this.loader = defaultLoader;
}
AbstractActiveDescriptor> factoryContractDescriptor = BuilderHelper.createConstantDescriptor(factory);
factoryContractDescriptor.addContractType(factory.getClass());
factoryContractDescriptor.setLoader(this.loader);
ActiveDescriptorBuilder descriptorBuilder = BuilderHelper.activeLink(factory.getClass())
.named(name)
.andLoadWith(this.loader)
.analyzeWith(this.analyzer);
if (scope != null) {
descriptorBuilder.in(scope);
}
if (ranked != null) {
descriptorBuilder.ofRank(ranked);
}
for (Annotation qualifier : qualifiers) {
factoryContractDescriptor.addQualifierAnnotation(qualifier);
descriptorBuilder.qualifiedBy(qualifier);
}
for (Type contract : contracts) {
factoryContractDescriptor.addContractType(new ParameterizedTypeImpl(Factory.class, contract));
descriptorBuilder.to(contract);
}
if (proxiable != null) {
descriptorBuilder.proxy(proxiable);
}
if (proxyForSameScope != null) {
descriptorBuilder.proxyForSameScope(proxyForSameScope);
}
configuration.bind(new FactoryDescriptorsImpl(
factoryContractDescriptor,
descriptorBuilder.buildProvideMethod()));
}
}
private static class FactoryTypeBasedBindingBuilder extends AbstractBindingBuilder {
private final Class extends Factory> factoryClass;
private final Class extends Annotation> factoryScope;
public FactoryTypeBasedBindingBuilder(Class extends Factory> factoryClass, Class extends Annotation> factoryScope) {
this.factoryClass = factoryClass;
this.factoryScope = factoryScope;
}
@Override
void complete(DynamicConfiguration configuration, HK2Loader defaultLoader) {
if (this.loader == null) {
this.loader = defaultLoader;
}
ActiveDescriptorBuilder factoryDescriptorBuilder = BuilderHelper.activeLink(factoryClass)
.named(name)
.andLoadWith(this.loader)
.analyzeWith(this.analyzer);
if (factoryScope != null) {
factoryDescriptorBuilder.in(factoryScope);
}
ActiveDescriptorBuilder descriptorBuilder = BuilderHelper.activeLink(factoryClass)
.named(name)
.andLoadWith(this.loader)
.analyzeWith(this.analyzer);
if (scope != null) {
descriptorBuilder.in(scope);
}
if (ranked != null) {
// factoryContractDescriptor.ofRank(factoryRank);
descriptorBuilder.ofRank(ranked);
}
for (Annotation qualifier : qualifiers) {
factoryDescriptorBuilder.qualifiedBy(qualifier);
descriptorBuilder.qualifiedBy(qualifier);
}
for (Type contract : contracts) {
factoryDescriptorBuilder.to(new ParameterizedTypeImpl(Factory.class, contract));
descriptorBuilder.to(contract);
}
if (proxiable != null) {
descriptorBuilder.proxy(proxiable);
}
if (proxyForSameScope != null) {
descriptorBuilder.proxyForSameScope(proxyForSameScope);
}
configuration.bind(new FactoryDescriptorsImpl(
factoryDescriptorBuilder.build(),
descriptorBuilder.buildProvideMethod()));
}
}
private static class FactoryDescriptorsImpl implements FactoryDescriptors {
private final Descriptor serviceDescriptor;
private final Descriptor factoryDescriptor;
public FactoryDescriptorsImpl(Descriptor serviceDescriptor, Descriptor factoryDescriptor) {
this.serviceDescriptor = serviceDescriptor;
this.factoryDescriptor = factoryDescriptor;
}
@Override
public Descriptor getFactoryAsAService() {
return serviceDescriptor;
}
@Override
public Descriptor getFactoryAsAFactory() {
return factoryDescriptor;
}
@Override
public String toString() {
return "FactoryDescriptorsImpl(\n" +
serviceDescriptor + ",\n" + factoryDescriptor + ",\n\t" + System.identityHashCode(this) + ")";
}
}
/**
* Create a new service binding builder.
*
* @param service type.
* @param serviceType service class.
* @param bindAsContract if {@code true}, the service class will be bound as one of the contracts.
* @return initialized binding builder.
*/
static AbstractBindingBuilder create(Class serviceType, boolean bindAsContract) {
return new ClassBasedBindingBuilder(serviceType, bindAsContract ? serviceType : null);
}
/**
* Create a new service binding builder.
*
* @param service type.
* @param serviceType generic service type.
* @param bindAsContract if {@code true}, the service class will be bound as one of the contracts.
* @return initialized binding builder.
*/
static AbstractBindingBuilder create(TypeLiteral serviceType, boolean bindAsContract) {
return new ClassBasedBindingBuilder(serviceType.getRawType(), bindAsContract ? serviceType.getType() : null);
}
/**
* Create a new service binding builder.
*
* @param service service instance.
* @return initialized binding builder.
*/
static AbstractBindingBuilder create(T service) {
return new InstanceBasedBindingBuilder(service);
}
/**
* Create a new service binding builder.
*
* @param factory service factory instance.
* @return initialized binding builder.
*/
static AbstractBindingBuilder createFactoryBinder(Factory factory) {
return new FactoryInstanceBasedBindingBuilder(factory);
}
/**
* Create a new service binding builder.
*
* @param factoryType service factory class.
* @param factoryScope service factory scope.
* @return initialized binding builder.
*/
static AbstractBindingBuilder createFactoryBinder(Class extends Factory> factoryType, Class extends Annotation> factoryScope) {
return new FactoryTypeBasedBindingBuilder(factoryType, factoryScope);
}
}