blob: 13ac947442fdce0f90576036337af0c9639665dc [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.aries.jpa.cdi;
import javax.enterprise.context.Dependent;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.AnnotatedField;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceUnit;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.aries.jpa.cdi.support.FilterLiteral;
import org.apache.aries.jpa.cdi.support.ForwardingAnnotatedType;
import org.apache.aries.jpa.cdi.support.InjectLiteral;
import org.apache.aries.jpa.cdi.support.ServiceLiteral;
import org.apache.aries.jpa.cdi.support.SimpleBean;
import org.apache.aries.jpa.cdi.support.SyntheticAnnotatedField;
import org.apache.aries.jpa.cdi.support.UniqueIdentifier;
import org.apache.aries.jpa.cdi.support.UniqueIdentifierLitteral;
import org.apache.aries.jpa.template.JpaTemplate;
import org.ops4j.pax.cdi.extension2.api.OsgiExtension;
import static java.util.Collections.unmodifiableSet;
public class PersistenceAnnotatedType<T> extends ForwardingAnnotatedType<T> {
private final BeanManager manager;
private final Set<AnnotatedField<? super T>> fields;
private final List<Bean<?>> beans = new ArrayList<>();
public PersistenceAnnotatedType(BeanManager manager, AnnotatedType<T> delegate) {
super(delegate);
this.manager = manager;
this.fields = new HashSet<>();
for (AnnotatedField<? super T> field : delegate.getFields()) {
if (field.isAnnotationPresent(PersistenceContext.class)) {
field = decorateContext(field);
} else if (field.isAnnotationPresent(PersistenceUnit.class)) {
field = decorateUnit(field);
}
this.fields.add(field);
}
}
private boolean hasUnitName(PersistenceContext pc) {
return !pc.unitName().isEmpty();
}
private boolean hasUnitName(PersistenceUnit pu) {
return !pu.unitName().isEmpty();
}
private <X> AnnotatedField<X> decorateContext(AnnotatedField<X> field) {
final PersistenceContext persistenceContext = field.getAnnotation(PersistenceContext.class);
final UniqueIdentifier identifier = UniqueIdentifierLitteral.random();
Set<Annotation> templateQualifiers = new HashSet<>();
templateQualifiers.add(ServiceLiteral.SERVICE);
if (hasUnitName(persistenceContext)) {
templateQualifiers.add(new FilterLiteral("(osgi.unit.name=" + persistenceContext.unitName() + ")"));
}
Bean<JpaTemplate> bean = manager.getExtension(OsgiExtension.class)
.globalDependency(JpaTemplate.class, templateQualifiers);
Set<Annotation> qualifiers = new HashSet<>();
qualifiers.add(identifier);
Bean<EntityManager> b = new SimpleBean<>(EntityManager.class, Dependent.class, Collections.singleton(EntityManager.class), qualifiers, () -> {
CreationalContext<JpaTemplate> context = manager.createCreationalContext(bean);
JpaTemplate template = (JpaTemplate) manager.getReference(bean, JpaTemplate.class, context);
return EntityManagerProducer.create(template);
});
beans.add(b);
Set<Annotation> fieldAnnotations = new HashSet<>();
fieldAnnotations.add(InjectLiteral.INJECT);
fieldAnnotations.add(identifier);
return new SyntheticAnnotatedField<>(field, fieldAnnotations);
}
private <X> AnnotatedField<X> decorateUnit(AnnotatedField<X> field) {
final PersistenceUnit persistenceUnit = field.getAnnotation(PersistenceUnit.class);
final UniqueIdentifier identifier = UniqueIdentifierLitteral.random();
Set<Annotation> templateQualifiers = new HashSet<>();
templateQualifiers.add(ServiceLiteral.SERVICE);
if (hasUnitName(persistenceUnit)) {
templateQualifiers.add(new FilterLiteral("(osgi.unit.name=" + persistenceUnit.unitName() + ")"));
}
Bean<EntityManagerFactory> bean = manager.getExtension(OsgiExtension.class)
.globalDependency(EntityManagerFactory.class, templateQualifiers);
Set<Annotation> qualifiers = new HashSet<>();
qualifiers.add(identifier);
Bean<EntityManagerFactory> b = new SimpleBean<>(EntityManagerFactory.class, Dependent.class, Collections.singleton(EntityManagerFactory.class), qualifiers, () -> {
CreationalContext<EntityManagerFactory> context = manager.createCreationalContext(bean);
return (EntityManagerFactory) manager.getReference(bean, EntityManagerFactory.class, context);
});
beans.add(b);
Set<Annotation> fieldAnnotations = new HashSet<>();
fieldAnnotations.add(InjectLiteral.INJECT);
fieldAnnotations.add(identifier);
return new SyntheticAnnotatedField<>(field, fieldAnnotations);
}
@Override
public Set<AnnotatedField<? super T>> getFields() {
return unmodifiableSet(fields);
}
public Collection<? extends Bean<?>> getProducers() {
return beans;
}
}