/* * 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.annotation.Annotation; import java.lang.reflect.Field; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.List; import javax.inject.Inject; import javax.naming.Binding; import javax.naming.InitialContext; import javax.naming.NamingEnumeration; import org.apache.openejb.assembler.classic.AppInfo; import org.jboss.arquillian.prototyping.context.api.ArquillianContext; import org.jboss.arquillian.prototyping.context.api.Properties; import org.jboss.arquillian.prototyping.context.api.Property; import org.jboss.arquillian.prototyping.context.impl.PropertiesImpl; import org.jboss.arquillian.prototyping.context.impl.openejb.OpenEJBArquillianContextImpl; import org.jboss.arquillian.spi.TestEnricher; import org.jboss.arquillian.spi.core.Instance; import org.jboss.arquillian.testenricher.ejb.EJBInjectionEnricher; /** * {@link TestEnricher} implementation specific to the OpenEJB * Container * * @author <a href="mailto:andrew.rubinger@jboss.org">ALR</a> * @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a> * @version $Revision: $ */ public class OpenEJBTestEnricher extends EJBInjectionEnricher { @org.jboss.arquillian.spi.core.annotation.Inject private Instance<AppInfo> appInfo; private ArquillianContext arquillianContext = null; /** * {@inheritDoc} * @see org.jboss.arquillian.testenricher.ejb.EJBInjectionEnricher#enrich(org.jboss.arquillian.spi.Context, java.lang.Object) */ @Override public void enrich(Object testCase) { // Call the super implementation to handle @EJB super.enrich(testCase); // Handle Typesafe @Inject (ie. ask Arquillian for a an instance of the field type with no additional context properties) final Class<? extends Annotation> inject = (Class<? extends Annotation>) Inject.class; List<Field> fieldsWithInject = this.getFieldsWithAnnotation(testCase.getClass(), inject); for (final Field field : fieldsWithInject) { // Set accessible if it's not if (!field.isAccessible()) { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { field.setAccessible(true); // Return return null; } }); } try { /* * Resolve (based on contextual properties if specified) */ final Object resolvedVaue; final ArquillianContext arquillianContext = this.getArquillianContext(); final Class<?> type = field.getType(); // If Properties are defined if (field.isAnnotationPresent(Properties.class)) { final Properties properties = field.getAnnotation(Properties.class); resolvedVaue = arquillianContext.get(type, properties); } // If just one property is defined else if (field.isAnnotationPresent(Property.class)) { final Property property = field.getAnnotation(Property.class); final Properties properties = new PropertiesImpl(new Property[] {property}); resolvedVaue = arquillianContext.get(type, properties); } // No properties defined; do type-based resolution only else { resolvedVaue = arquillianContext.get(type); } // Inject field.set(testCase, resolvedVaue); } catch (final IllegalAccessException e) { throw new RuntimeException("Could not inject into " + field.getName() + " of test case: " + testCase, e); } } } protected ArquillianContext getArquillianContext() { if (arquillianContext == null) { // Make a context final AppInfo deployment = appInfo.get(); arquillianContext = new OpenEJBArquillianContextImpl(deployment); } return arquillianContext; } @Override protected InitialContext createContext() throws Exception { return this.getArquillianContext().get(InitialContext.class); } @Override protected Object lookupEJB(Class<?> fieldType, String mappedName) throws Exception { // InjectionBuilder injectionBuilder = new InjectionBuilder(Thread.currentThread().getContextClassLoader()); // // List<Injection> injections = new ArrayList<Injections>(); // for(EjbJarInfo info : appInfo.get().ejbJars) // { // for(EnterpriseBeanInfo ejb : info.enterpriseBeans) // { // = injectionBuilder.buildInjections(ejb.jndiEnc); // // } // } InitialContext initcontext = createContext(); if(mappedName != null && !mappedName.equals("")) { return initcontext.lookup(mappedName); } return lookupRecursive(fieldType, initcontext, initcontext.listBindings("/")); } //TODO No, no no: we must look up a known location from metadata, not search for a matching type in the whole JNDI tree protected Object lookupRecursive(Class<?> fieldType, javax.naming.Context context, NamingEnumeration<Binding> contextNames) throws Exception { while (contextNames.hasMore()) { Binding contextName = contextNames.nextElement(); Object value = contextName.getObject(); if (javax.naming.Context.class.isInstance(value)) { javax.naming.Context subContext = (javax.naming.Context) value; return lookupRecursive(fieldType, subContext, subContext.listBindings("/")); } else { value = context.lookup(contextName.getName()); if (fieldType.isInstance(value)) { return value; } } } throw new RuntimeException("Could not lookup EJB reference for: " + fieldType); } }