blob: 61b4a2c6ec18c5bd52f78085c6e4637004c69a9f [file] [log] [blame]
/*
* Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package org.glassfish.jersey.inject.weld.internal.inject;
import org.glassfish.jersey.internal.inject.AliasBinding;
import org.glassfish.jersey.internal.inject.Binding;
import org.glassfish.jersey.internal.inject.Bindings;
import org.glassfish.jersey.internal.inject.InstanceBinding;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Injection binding description of a bean bound directly as a specific instance to be created in a pre-initialization phase
* and initialized in runtime.
*
* @param <T> Type of the service described by this injection binding.
*/
public class InitializableInstanceBinding<T> extends MatchableBinding<T, InitializableInstanceBinding<T>> implements Cloneable {
protected T service;
private AtomicBoolean isInit = new AtomicBoolean(false);
private Class<T> implementationType;
/**
* Creates a service as an instance.
*
* @param service service's instance.
*/
protected InitializableInstanceBinding(T service) {
this(service, null);
}
/**
* Creates a service as an instance.
*
* @param service service's instance.
* @param contractType service's contractType.
*/
private InitializableInstanceBinding(T service, Type contractType) {
this.service = service;
this.implementationType = service == null ? null : (Class<T>) service.getClass();
if (contractType != null) {
this.to(contractType);
}
}
/**
* Gets service' class.
*
* @return service's class.
*/
public T getService() {
if (!isInit.get()) {
String types = Arrays.toString(getContracts().toArray());
throw new IllegalStateException("Not initialized " + service + "(" + types + ")");
}
return service;
}
/**
* Gets service's type.
*
* @return service's type.
*/
public Class<T> getImplementationType() {
return implementationType;
}
public void init(T service) {
if (!isInit.getAndSet(true)) {
this.service = service;
implementationType = (Class<T>) service.getClass();
} else if (this.service != service) {
throw new IllegalStateException("Multiple initialized for " + service.getClass());
}
}
public boolean isInit() {
return isInit.get();
}
public Matching<InitializableInstanceBinding<T>> matches(Binding other) {
return super.matches(other);
}
@Override
public InitializableInstanceBinding<T> clone() {
throw new RuntimeException(new CloneNotSupportedException());
}
public static <T> InitializableInstanceBinding<T> from(InstanceBinding<T> instanceBinding) {
return new InitializableWrappingInstanceBinding(instanceBinding);
}
@Override
protected MatchLevel bestMatchLevel() {
return MatchLevel.IMPLEMENTATION;
}
private static class InitializableWrappingInstanceBinding<T> extends InitializableInstanceBinding<T> {
private final InstanceBinding<T> wrapped;
public InitializableWrappingInstanceBinding(InstanceBinding<T> binding) {
super(binding.getService());
wrapped = binding;
}
private InitializableWrappingInstanceBinding(InitializableWrappingInstanceBinding<T> binding) {
super(binding.service);
wrapped = binding.wrapped;
}
@Override
public Class<T> getImplementationType() {
return super.getImplementationType();
}
@Override
public T getService() {
return super.getService();
}
@Override
public Class<? extends Annotation> getScope() {
return wrapped.getScope();
}
@Override
public Set<Type> getContracts() {
return wrapped.getContracts();
}
@Override
public Integer getRank() {
return wrapped.getRank();
}
@Override
public Set<AliasBinding> getAliases() {
return wrapped.getAliases();
}
@Override
public Set<Annotation> getQualifiers() {
return wrapped.getQualifiers();
}
@Override
public String getAnalyzer() {
return wrapped.getAnalyzer();
}
@Override
public String getName() {
return wrapped.getName();
}
@Override
public String toString() {
return "InitializableWrappingInstanceBinding(" + wrapped.getService().getClass() + ")";
}
@Override
public InitializableWrappingInstanceBinding clone() {
return new InitializableWrappingInstanceBinding(this);
}
}
}