org.apache.openejb.cdi.CdiResourceInjectionService Maven / Gradle / Ivy
/*
* 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.openejb.cdi;
import org.apache.openejb.AppContext;
import org.apache.openejb.BeanContext;
import org.apache.openejb.Injection;
import org.apache.openejb.InjectionProcessor;
import org.apache.openejb.core.WebContext;
import org.apache.openejb.core.ivm.naming.Reference;
import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Logger;
import org.apache.openejb.util.PassthroughFactory;
import org.apache.webbeans.component.ResourceBean;
import org.apache.webbeans.config.WebBeansContext;
import org.apache.webbeans.spi.ResourceInjectionService;
import org.apache.webbeans.spi.api.ResourceReference;
import org.apache.xbean.recipe.ObjectRecipe;
import org.apache.xbean.recipe.Option;
import javax.enterprise.inject.spi.Bean;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class CdiResourceInjectionService implements ResourceInjectionService {
private final Logger logger = Logger.getInstance(LogCategory.OPENEJB.createChild("cdi"), CdiResourceInjectionService.class);
private final CdiPlugin ejbPlugin;
private final List compContexts = new ArrayList();
private volatile AppContext appCtx;
private volatile boolean ear;
public CdiResourceInjectionService(final WebBeansContext context) {
ejbPlugin = CdiPlugin.class.cast(context.getPluginLoader().getEjbPlugin());
}
public void setAppContext(final AppContext appModule, final Collection ejbs) {
compContexts.clear();
ear = false;
for (final BeanContext beanContext : appModule.getBeanContexts()) {
if (!ear) {
ear = beanContext.getEjbName().contains("ear-scoped-cdi-beans_");
}
if (beanContext.getBeanClass().equals(BeanContext.Comp.class)
&& (ejbs == null || ear || ejbs.contains(beanContext))) {
compContexts.add(beanContext);
}
}
this.appCtx = appModule;
}
@Override
public X getResourceReference(final ResourceReference resourceReference) {
final Class type = resourceReference.getResourceType();
final String name = resourceReference.getJndiName();
try {
return type.cast(new InitialContext().lookup(name));
} catch (final NamingException e) {
// no-op: try next
}
final String noJavaPrefix = name.replace("java:", "");
for (final BeanContext beanContext : compContexts) {
try {
return type.cast(beanContext.getJndiContext().lookup(noJavaPrefix));
} catch (final NamingException e1) {
// fine for now
}
}
if (appCtx != null) { // depending envrt bindings can be missing from InitialContext (embedded for instance)
for (final WebContext w : appCtx.getWebContexts()) {
final Object instance = w.getBindings().get(noJavaPrefix);
if (instance != null) {
if (Reference.class.isInstance(instance)) {
try {
return type.cast(Reference.class.cast(instance).getObject());
} catch (final NamingException e) {
// no-op: try next
}
}
if (type.isInstance(instance)) {
return type.cast(instance);
}
// else a javax.naming.Reference we don't handle yet surely
}
}
}
return null;
}
@Override
public void injectJavaEEResources(final Object managedBeanInstance) {
if (managedBeanInstance == null) {
return;
}
final Class> managedBeanInstanceClass = managedBeanInstance.getClass();
if (ejbPlugin.isSessionBean(managedBeanInstanceClass)) { // already done
return;
}
final ObjectRecipe receipe = PassthroughFactory.recipe(managedBeanInstance);
receipe.allow(Option.FIELD_INJECTION);
receipe.allow(Option.PRIVATE_PROPERTIES);
receipe.allow(Option.IGNORE_MISSING_PROPERTIES);
receipe.allow(Option.NAMED_PARAMETERS);
fillInjectionProperties(receipe, managedBeanInstance);
receipe.create();
}
@SuppressWarnings("unchecked")
private void fillInjectionProperties(final ObjectRecipe objectRecipe, final Object managedBeanInstance) {
final boolean usePrefix = true;
final Class> clazz = managedBeanInstance.getClass();
Collection comps;
WebBeansContext webBeansContext = null;
if (ear) { // let it be contextual, ie use webapp context (env-entries...) to create ear libs interceptors...
try {
webBeansContext = WebBeansContext.currentInstance();
comps = CdiResourceInjectionService.class.cast(webBeansContext.getService(ResourceInjectionService.class)).compContexts;
} catch (final Exception e) {
comps = compContexts;
}
} else {
comps = compContexts;
}
for (final BeanContext beanContext : comps) {
for (final Injection injection : beanContext.getInjections()) {
if (injection.getTarget() == null) {
continue;
}
if (!injection.getTarget().isAssignableFrom(clazz)) {
continue;
}
final String prefix;
if (usePrefix) {
prefix = injection.getTarget().getName() + "/";
} else {
prefix = "";
}
try {
final Object value = lookup(beanContext, injection);
objectRecipe.setProperty(prefix + injection.getName(), value);
} catch (final NamingException e) {
boolean found = false;
if (webBeansContext != null) {
for (final WebContext w : appCtx.getWebContexts()) {
if (w.getWebBeansContext() == webBeansContext) {
final Object value = w.getBindings().get(injection.getJndiName());
if (value != null) {
objectRecipe.setProperty(prefix + injection.getName(), value);
found = true;
}
break;
}
}
}
if (!found) {
logger.warning("Injection data not found in JNDI context: jndiName='" + injection.getJndiName() + "', target=" + injection.getTarget().getName() + "/" + injection.getName());
}
}
}
}
}
private Object lookup(final BeanContext beanContext, final Injection injection) throws NamingException {
String jndiName = injection.getJndiName();
try {
return beanContext.getJndiContext().lookup(jndiName);
} catch (final NamingException e) {
if (!jndiName.startsWith("java:")) {
jndiName = "java:" + jndiName;
}
Object value;
try {
value = InjectionProcessor.unwrap(beanContext.getJndiContext()).lookup(jndiName);
} catch (final NamingException e1) {
// Fallback and try the Context on the current thread
//
// We attempt to create a Context instance for each
// individual CDI bean. This isn't really accurate
// however, and in a webapp all the beans will share
// the same JNDI Context. This fallback will cover
// the situation where we did not accurately create
// a Context for each bean and instead the Context
// on the thread (the webapp context) has the data
// we need to lookup.
try {
value = new InitialContext().lookup(jndiName);
} catch (final NamingException e2) {
throw e;
}
}
return value;
}
}
@Override
public void clear() {
compContexts.clear();
}
/**
* delegation of serialization behavior
*/
public void writeExternal(final Bean bean, final T actualResource, final ObjectOutput out) throws IOException {
//do nothing
}
/**
* delegation of serialization behavior
*/
public T readExternal(final Bean bean, final ObjectInput out) throws IOException,
ClassNotFoundException {
return (T) ((ResourceBean) bean).getActualInstance();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy