blob: 8bda174b07569ab133408e33d74bd758c5e96c2f [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.webbeans.resource.spi.se;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.MessageFormat;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.Bean;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceUnit;
import javax.xml.ws.WebServiceRef;
import org.apache.webbeans.component.ResourceBean;
import org.apache.webbeans.config.OWBLogConst;
import org.apache.webbeans.config.WebBeansContext;
import org.apache.webbeans.exception.WebBeansException;
import org.apache.webbeans.logger.WebBeansLoggerFacade;
import org.apache.webbeans.spi.FailOverService;
import org.apache.webbeans.spi.ResourceInjectionService;
import org.apache.webbeans.spi.api.ResourceReference;
import org.apache.webbeans.util.AnnotationUtil;
public class StandaloneResourceInjectionService implements ResourceInjectionService
{
/**
* When ResourceProxyHandler deserialized, this will instruct owb to create a new actual instance, if
* the actual resource is not serializable.
*/
private static final String DUMMY_STRING = "owb.actual.resource.dummy";
private final StandaloneResourceProcessor processor = StandaloneResourceProcessor.getProcessor();
private static final Logger logger = WebBeansLoggerFacade.getLogger(StandaloneResourceInjectionService.class);
private final WebBeansContext webBeansContext;
/**
* Cache the information if a certain class contains any EE resource at all
*/
private final Map<Class<?>, Boolean> classContainsEEResources = new ConcurrentHashMap<Class<?>, Boolean>();
public StandaloneResourceInjectionService(WebBeansContext webBeansContext)
{
this.webBeansContext = webBeansContext;
}
protected WebBeansContext getWebBeansContext()
{
return webBeansContext;
}
@Override
public <X, T extends Annotation> X getResourceReference(ResourceReference<X, T> resourceReference)
{
if(resourceReference.supports(Resource.class))
{
Resource resource = resourceReference.getAnnotation(Resource.class);
return processor.getResource(resource, resourceReference.getResourceType());
}
if(resourceReference.supports(WebServiceRef.class))
{
WebServiceRef resource = resourceReference.getAnnotation(WebServiceRef.class);
return processor.getWebServiceResource(resource, resourceReference.getResourceType());
}
if(resourceReference.supports(PersistenceContext.class))
{
PersistenceContext persistenceContext = resourceReference.getAnnotation(PersistenceContext.class);
return processor.getEntityManager(persistenceContext, resourceReference.getResourceType());
}
if(resourceReference.supports(PersistenceUnit.class))
{
PersistenceUnit persistenceUnit = resourceReference.getAnnotation(PersistenceUnit.class);
return processor.getEntityManagerFactory(persistenceUnit, resourceReference.getResourceType());
}
return null;
}
@Override
public void injectJavaEEResources(Object managedBeanInstance)
{
Class currentClass = managedBeanInstance.getClass();
Boolean containsEeResource = classContainsEEResources.get(currentClass);
if (containsEeResource != null && !containsEeResource)
{
// nothing to do it seems.
return;
}
while (currentClass != null && !Object.class.getName().equals(currentClass.getName()))
{
Field[] fields = webBeansContext.getSecurityService().doPrivilegedGetDeclaredFields(currentClass);
for(Field field : fields)
{
if(!field.isAnnotationPresent(Produces.class))
{
if(!Modifier.isStatic(field.getModifiers()))
{
Annotation ann = AnnotationUtil.hasOwbInjectableResource(field.getDeclaredAnnotations());
if(ann != null)
{
@SuppressWarnings("unchecked")
ResourceReference<Object, ?> resourceRef = new ResourceReference(field.getDeclaringClass(), field.getName(), field.getType(), ann);
try
{
Object resourceToInject = getResourceReference(resourceRef);
if (resourceToInject != null)
{
if(!field.isAccessible())
{
webBeansContext.getSecurityService().doPrivilegedSetAccessible(field, true);
}
field.set(managedBeanInstance, resourceToInject);
}
containsEeResource = Boolean.TRUE;
}
catch(Exception e)
{
logger.log(Level.SEVERE, WebBeansLoggerFacade.constructMessage(OWBLogConst.ERROR_0025, e, field));
throw new WebBeansException(MessageFormat.format(WebBeansLoggerFacade.getTokenString(OWBLogConst.ERROR_0025), field), e);
}
}
}
}
}
currentClass = currentClass.getSuperclass();
}
if (containsEeResource == null)
{
containsEeResource = Boolean.FALSE;
}
classContainsEEResources.put(managedBeanInstance.getClass(), containsEeResource);
}
@Override
public void clear()
{
processor.clear();
}
/**
* delegation of serialization behavior
*/
@Override
public <T> void writeExternal(Bean<T> bean, T actualResource, ObjectOutput out) throws IOException
{
// try fail over service to serialize the resource object
FailOverService failoverService = webBeansContext.getService(FailOverService.class);
if (failoverService != null)
{
Object ret = failoverService.handleResource(bean, actualResource, null, out);
if (ret != FailOverService.NOT_HANDLED)
{
return;
}
}
// default behavior
if (actualResource instanceof Serializable)
{
// for remote ejb stub and other serializable resources
out.writeObject(actualResource);
}
else
{
// otherwise, write a dummy string.
out.writeObject(DUMMY_STRING);
}
}
/**
* delegation of serialization behavior
*/
@Override
public <T> T readExternal(Bean<T> bean, ObjectInput in) throws IOException,
ClassNotFoundException
{
T actualResource = null;
// try fail over service to serialize the resource object
FailOverService failoverService = webBeansContext.getService(FailOverService.class);
if (failoverService != null)
{
actualResource = (T) failoverService.handleResource(bean, actualResource, in, null);
if (actualResource != FailOverService.NOT_HANDLED)
{
return actualResource;
}
}
// default behavior
actualResource = (T) in.readObject();
if (actualResource instanceof javax.rmi.CORBA.Stub)
{
// for remote ejb stub, reconnect after deserialization.
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(new String[0], null);
((javax.rmi.CORBA.Stub)actualResource).connect(orb);
}
else if (actualResource.equals(DUMMY_STRING))
{
actualResource = (T) ((ResourceBean)bean).getActualInstance();
}
return actualResource;
}
}