/*
* JBoss, Home of Professional Open Source.
* Copyright 2011, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.as.webservices.invocation;
import java.lang.reflect.Method;
import java.util.Collection;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.WebServiceException;
import org.jboss.as.ee.component.Component;
import org.jboss.as.ee.component.ComponentView;
import org.jboss.as.ee.component.ComponentViewInstance;
import org.jboss.as.webservices.util.ASHelper;
import org.jboss.invocation.InterceptorContext;
import org.jboss.ws.common.injection.ThreadLocalAwareWebServiceContext;
import org.jboss.ws.common.invocation.AbstractInvocationHandler;
import org.jboss.wsf.spi.SPIProvider;
import org.jboss.wsf.spi.SPIProviderResolver;
import org.jboss.wsf.spi.deployment.Endpoint;
import org.jboss.wsf.spi.invocation.Invocation;
import org.jboss.wsf.spi.invocation.InvocationContext;
import org.jboss.wsf.spi.ioc.IoCContainerProxy;
import org.jboss.wsf.spi.ioc.IoCContainerProxyFactory;
/**
* Handles invocations on EJB3 endpoints.
*
* @author <a href="mailto:ropalka@redhat.com">Richard Opalka</a>
*/
final class InvocationHandlerEJB3 extends AbstractInvocationHandler {
/** EJB3 JNDI context. */
private static final String EJB3_JNDI_PREFIX = "java:env/";
/** MC kernel controller. */
private final IoCContainerProxy iocContainer;
/** EJB3 container name. */
private String ejbName;
/** EJB3 container. */
private volatile ComponentViewInstance ejbComponentViewInstance;
/**
* Constructor.
*/
InvocationHandlerEJB3() {
final SPIProvider spiProvider = SPIProviderResolver.getInstance().getProvider();
final IoCContainerProxyFactory iocContainerFactory = spiProvider.getSPI(IoCContainerProxyFactory.class);
iocContainer = iocContainerFactory.getContainer();
}
/**
* Initializes EJB3 container name.
*
* @param endpoint web service endpoint
*/
public void init(final Endpoint endpoint) {
ejbName = (String) endpoint.getProperty(ASHelper.CONTAINER_NAME);
if (ejbName == null) {
throw new IllegalArgumentException("Container name cannot be null");
}
}
/**
* Gets EJB 3 container lazily.
*
* @return EJB3 container
*/
private ComponentViewInstance getComponentViewInstance() {
if (ejbComponentViewInstance == null) {
synchronized(this) {
if (ejbComponentViewInstance == null) {
final ComponentView ejbView = iocContainer.getBean(ejbName, ComponentView.class);
if (ejbView == null) {
throw new WebServiceException("Cannot find ejb: " + ejbName);
}
ejbComponentViewInstance = ejbView.createInstance();
}
}
}
return ejbComponentViewInstance;
}
/**
* Invokes EJB 3 endpoint.
*
* @param endpoint EJB 3 endpoint
* @param wsInvocation web service invocation
* @throws Exception if any error occurs
*/
public void invoke(final Endpoint endpoint, final Invocation wsInvocation) throws Exception {
try {
// prepare for invocation
onBeforeInvocation(wsInvocation);
// prepare invocation data
final ComponentViewInstance componentViewInstance = getComponentViewInstance();
final Method method = getEJBMethod(wsInvocation.getJavaMethod(), componentViewInstance.allowedMethods());
final InterceptorContext context = new InterceptorContext();
context.setMethod(method);
context.setContextData(getWebServiceContext(wsInvocation).getMessageContext());
context.setParameters(wsInvocation.getArgs());
context.setTarget(componentViewInstance.createProxy());
context.putPrivateData(Component.class, componentViewInstance.getComponent());
context.putPrivateData(ComponentViewInstance.class, componentViewInstance);
// invoke method
final Object retObj = componentViewInstance.getEntryPoint(method).processInvocation(context);
// set return value
wsInvocation.setReturnValue(retObj);
}
catch (Throwable t) {
log.error("Method invocation failed with exception: " + t.getMessage(), t);
handleInvocationException(t);
}
finally {
onAfterInvocation(wsInvocation);
}
}
private Method getEJBMethod(final Method seiMethod, final Collection<Method> methods) {
for (final Method method : methods) {
if (seiMethod.equals(method)) {
return method;
}
}
throw new IllegalStateException();
}
public Context getJNDIContext(final Endpoint ep) throws NamingException {
return null; // TODO: implement
// final EJBContainer ejb3Container = (EJBContainer) getComponentViewInstance();
// return (Context) ejb3Container.getEnc().lookup(EJB3_JNDI_PREFIX);
}
/**
* Injects webservice context on target bean.
*
* @param invocation current invocation
*/
@Override
public void onBeforeInvocation(final Invocation invocation) {
final WebServiceContext wsContext = getWebServiceContext(invocation);
ThreadLocalAwareWebServiceContext.getInstance().setMessageContext(wsContext);
}
/**
* Cleanups injected webservice context on target bean.
*
* @param invocation current invocation
*/
@Override
public void onAfterInvocation(final Invocation invocation) {
ThreadLocalAwareWebServiceContext.getInstance().setMessageContext(null);
}
/**
* Returns WebServiceContext associated with this invocation.
*
* @param invocation current invocation
* @return web service context or null if not available
*/
private WebServiceContext getWebServiceContext(final Invocation invocation) {
final InvocationContext invocationContext = invocation.getInvocationContext();
return invocationContext.getAttachment(WebServiceContext.class);
}
}