/* * JBoss, Home of Professional Open Source * Copyright 2010, Red Hat Middleware LLC, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed 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.jboss.arquillian.container.openejb.embedded_3_1; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import javax.annotation.Resource; import javax.naming.Binding; import javax.naming.Context; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.resource.spi.ResourceAdapter; import javax.sql.DataSource; import javax.transaction.UserTransaction; import org.jboss.arquillian.spi.TestEnricher; import org.jboss.arquillian.spi.core.Instance; import org.jboss.arquillian.spi.core.annotation.Inject; import org.jboss.arquillian.testenricher.resource.ResourceInjectionEnricher; /** * {@link TestEnricher} implementation specific to the OpenEJB * Container for injecting <code>@Resource</code> annotated * fields and method parameters. * * @author David Allen * */ public class OpenEJBResourceInjectionEnricher extends ResourceInjectionEnricher { private static final String RESOURCE_ADAPTER_LOOKUP_PREFIX = "openejb/Resource"; @Inject private Instance<Context> contextInstance; @Override protected Context getContainerContext() throws NamingException { return contextInstance.get(); } @Override protected Object resolveResource(AnnotatedElement element) throws Exception { Object resolvedResource = null; Class<?> resourceType = null; if (Field.class.isAssignableFrom(element.getClass())) { resourceType = ((Field) element).getType(); } else if (Method.class.isAssignableFrom(element.getClass())) { resourceType = ((Method) element).getParameterTypes()[0]; } if (resourceType == null) { throw new IllegalStateException("No type found for resource injection target " + element); } // If the element type is a resource adapter, then apply special rules // for looking it up in JNDI if (ResourceAdapter.class.isAssignableFrom(resourceType) || DataSource.class.isAssignableFrom(resourceType)) { Resource resourceAnnotation = element.getAnnotation(Resource.class); if (!resourceAnnotation.name().equals("")) { resolvedResource = lookup(RESOURCE_ADAPTER_LOOKUP_PREFIX + "/" + resourceAnnotation.name()); } else if (!resourceAnnotation.mappedName().equals("")) { resolvedResource = lookup(resourceAnnotation.mappedName()); } else { resolvedResource = findResourceByType(resourceType); } } else if (UserTransaction.class.isAssignableFrom(resourceType)) { resolvedResource = lookup("java:comp/UserTransaction"); } return resolvedResource; } private Object findResourceByType(Class<?> resourceType) throws NamingException { NamingEnumeration<Binding> namingEnumeration = null; try { namingEnumeration = getContainerContext().listBindings(RESOURCE_ADAPTER_LOOKUP_PREFIX); } catch (NamingException ignore) { // No resource adapters exist, so we don't find anything here } List<Object> resourceMatches = new ArrayList<Object>(); while ((namingEnumeration != null) && (namingEnumeration.hasMoreElements())) { Binding binding = namingEnumeration.next(); Object boundResource = binding.getObject(); if (resourceType.isAssignableFrom(boundResource.getClass())) { resourceMatches.add(boundResource); } } if (resourceMatches.size() == 1) { return resourceMatches.get(0); } else if (resourceMatches.size() > 1) { // Throw some ambiguous matches exception perhaps? return resourceMatches.get(0); } throw new RuntimeException("Could not inject resource of type " + resourceType); } }