| /* |
| * 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.blueprint.impl; |
| |
| import static org.osgi.service.jpa.EntityManagerFactoryBuilder.JPA_UNIT_NAME; |
| |
| import java.lang.reflect.AccessibleObject; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| |
| import javax.persistence.EntityManager; |
| import javax.persistence.PersistenceContext; |
| import javax.persistence.PersistenceUnit; |
| |
| import org.apache.aries.blueprint.ComponentDefinitionRegistry; |
| import org.apache.aries.blueprint.ComponentDefinitionRegistryProcessor; |
| import org.apache.aries.blueprint.Interceptor; |
| import org.apache.aries.blueprint.ParserContext; |
| import org.apache.aries.blueprint.PassThroughMetadata; |
| import org.apache.aries.blueprint.mutable.MutableBeanMetadata; |
| import org.apache.aries.blueprint.mutable.MutableRefMetadata; |
| import org.apache.aries.blueprint.mutable.MutableReferenceMetadata; |
| import org.apache.aries.blueprint.mutable.MutableServiceMetadata; |
| import org.osgi.framework.Bundle; |
| import org.osgi.service.blueprint.container.BlueprintContainer; |
| import org.osgi.service.blueprint.reflect.ComponentMetadata; |
| import org.osgi.service.blueprint.reflect.ReferenceMetadata; |
| import org.osgi.service.blueprint.reflect.Target; |
| import org.osgi.service.coordinator.Coordinator; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| public class JpaComponentProcessor implements ComponentDefinitionRegistryProcessor { |
| private static final String JPA_COORDINATOR = "jpa_Coordinator"; |
| private static final Logger LOGGER = LoggerFactory.getLogger(JpaComponentProcessor.class); |
| private AnnotationScanner annotationScanner; |
| private ParserContext pc; |
| |
| public JpaComponentProcessor() { |
| annotationScanner = new AnnotationScanner(); |
| } |
| |
| public void setPc(ParserContext pc) { |
| this.pc = pc; |
| } |
| |
| @Override |
| public void process(ComponentDefinitionRegistry cdr) { |
| BlueprintContainer container = getComponent(cdr, "blueprintContainer"); |
| Bundle bundle = getComponent(cdr, "blueprintBundle"); |
| cdr.registerComponentDefinition(createServiceRef(JPA_COORDINATOR, Coordinator.class)); |
| |
| Set<String> components = new HashSet<String>(cdr.getComponentDefinitionNames()); |
| for (String component : components) { |
| ComponentMetadata compDef = cdr.getComponentDefinition(component); |
| |
| if (compDef instanceof MutableBeanMetadata && !((MutableBeanMetadata)compDef).isProcessor()) { |
| // Normal bean def |
| handleComponent((MutableBeanMetadata)compDef, bundle, cdr, container); |
| } else if(compDef instanceof MutableServiceMetadata) { |
| // Bean inlined into service def |
| MutableServiceMetadata sMeta = (MutableServiceMetadata)compDef; |
| Target target = sMeta.getServiceComponent(); |
| if (target instanceof MutableBeanMetadata) { |
| handleComponent((MutableBeanMetadata)target, bundle, cdr, container); |
| } |
| } |
| } |
| } |
| |
| private void handleComponent(MutableBeanMetadata compDef, Bundle bundle, ComponentDefinitionRegistry cdr, BlueprintContainer container) { |
| final String compName = compDef.getId(); |
| if (compDef.getClassName() == null) { |
| LOGGER.debug("No classname for " + compDef.getId()); |
| return; |
| } |
| Class<?> compClass; |
| try { |
| compClass = bundle.loadClass(compDef.getClassName()); |
| } catch (final ClassNotFoundException e) { |
| throw new IllegalArgumentException("Bean class not found " + compDef.getClassName(), e); |
| } |
| compDef.setFieldInjection(true); |
| List<AccessibleObject> pcMembers = annotationScanner.getJpaAnnotatedMembers(compClass, PersistenceContext.class); |
| for (AccessibleObject member : pcMembers) { |
| PersistenceContext pcAnn = member.getAnnotation(PersistenceContext.class); |
| |
| String propName = AnnotationScanner.getName(member); |
| Class<?> iface = AnnotationScanner.getType(member); |
| LOGGER.debug("Injecting {} into prop {} of bean {} with class {}", iface.getSimpleName(), propName, compName, compClass); |
| MutableRefMetadata ref = getServiceRef(cdr, pcAnn.unitName(), iface); |
| compDef.addProperty(propName, ref); |
| |
| MutableRefMetadata emRef = getServiceRef(cdr, pcAnn.unitName(), EntityManager.class); |
| Interceptor interceptor = new JpaInterceptor(container, JPA_COORDINATOR, emRef.getComponentId()); |
| cdr.registerInterceptorWithComponent(compDef, interceptor); |
| } |
| |
| List<AccessibleObject> puMembers = annotationScanner.getJpaAnnotatedMembers(compClass, PersistenceUnit.class); |
| for (AccessibleObject member : puMembers) { |
| PersistenceUnit puAnn = member.getAnnotation(PersistenceUnit.class); |
| String propName = AnnotationScanner.getName(member); |
| Class<?> iface = AnnotationScanner.getType(member); |
| LOGGER.debug("Injecting {} into prop {} of bean {} with class {}", iface.getSimpleName(), propName, compName, compClass); |
| MutableRefMetadata ref = getServiceRef(cdr, puAnn.unitName(), iface); |
| compDef.addProperty(propName, ref); |
| } |
| } |
| |
| private MutableRefMetadata getServiceRef(ComponentDefinitionRegistry cdr, String unitName, Class<?> iface) { |
| ComponentMetadata serviceRef = cdr.getComponentDefinition(getId(unitName, iface)); |
| if (serviceRef == null) { |
| serviceRef = createJPAServiceRef(unitName, iface); |
| cdr.registerComponentDefinition(serviceRef); |
| } |
| MutableRefMetadata ref = pc.createMetadata(MutableRefMetadata.class); |
| ref.setComponentId(serviceRef.getId()); |
| return ref; |
| } |
| |
| private ComponentMetadata createServiceRef(String id, Class<?> iface) { |
| final MutableReferenceMetadata refMeta = pc.createMetadata(MutableReferenceMetadata.class); |
| refMeta.setActivation(getDefaultActivation(pc)); |
| refMeta.setAvailability(ReferenceMetadata.AVAILABILITY_MANDATORY); |
| refMeta.setRuntimeInterface(iface); |
| refMeta.setTimeout(Integer.parseInt(pc.getDefaultTimeout())); |
| List<String> emptyList = Collections.emptyList(); |
| refMeta.setDependsOn(emptyList); |
| refMeta.setId(id); |
| return refMeta; |
| } |
| |
| private ComponentMetadata createJPAServiceRef(String unitName, Class<?> iface) { |
| final MutableReferenceMetadata refMeta = pc.createMetadata(MutableReferenceMetadata.class); |
| refMeta.setActivation(getDefaultActivation(pc)); |
| refMeta.setAvailability(ReferenceMetadata.AVAILABILITY_MANDATORY); |
| refMeta.setRuntimeInterface(iface); |
| refMeta.setFilter(String.format("(%s=%s)", JPA_UNIT_NAME, unitName)); |
| refMeta.setTimeout(Integer.parseInt(pc.getDefaultTimeout())); |
| List<String> emptyList = Collections.emptyList(); |
| refMeta.setDependsOn(emptyList); |
| refMeta.setId(getId(unitName, iface)); |
| return refMeta; |
| } |
| |
| public String getId(String unitName, Class<?> iface) { |
| return unitName + "-" + iface.getSimpleName(); |
| } |
| |
| private static int getDefaultActivation(ParserContext ctx) { |
| return "ACTIVATION_EAGER".equalsIgnoreCase(ctx.getDefaultActivation()) |
| ? ReferenceMetadata.ACTIVATION_EAGER : ReferenceMetadata.ACTIVATION_LAZY; |
| } |
| |
| @SuppressWarnings("unchecked") |
| private static <T>T getComponent(ComponentDefinitionRegistry cdr, String id) { |
| return (T)((PassThroughMetadata) cdr.getComponentDefinition(id)).getObject(); |
| } |
| |
| } |