org.apache.axis2.rpc.receivers.ejb.EJB3Util Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of axis2-adb Show documentation
Show all versions of axis2-adb Show documentation
Axis2 Data Binding module
/*
* 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.axis2.rpc.receivers.ejb;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.util.threadpool.DefaultThreadFactory;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Properties;
import java.util.concurrent.*;
/**
* Utility class that provides EJB3 specific features.
*
* @since 1.7.0
*/
public class EJB3Util {
public static final String EJB_JNDI_NAME = "beanJndiName";
public static final String EJB_REMOTE_INTERFACE_NAME = "remoteInterfaceName";
public static final String EJB_LOCAL_INTERFACE_NAME = "localInterfaceName";
public static final String EJB_INITIAL_CONTEXT_FACTORY = "jndiContextClass";
public static final String EJB_PROVIDER_URL = "providerUrl";
public static final String EJB_JNDI_USERNAME = "jndiUser";
public static final String EJB_JNDI_PASSWORD = "jndiPassword";
private static ExecutorService workerPool = null;
static {
workerPool = new ThreadPoolExecutor(1, 50, 150L, TimeUnit.SECONDS,
new LinkedBlockingQueue(), new DefaultThreadFactory(new ThreadGroup(
"EJB provider thread group"), "EJBProvider"));
}
/**
* Return a object which implements the service.
*
* @param msgContext
* the message context
* @return an object that implements the service
* @throws org.apache.axis2.AxisFault
* if fails
*/
protected static Object makeNewServiceObject(MessageContext msgContext) throws AxisFault {
CountDownLatch startLatch = new CountDownLatch(1);
CountDownLatch stopLatch = new CountDownLatch(1);
EJBClientWorker worker = new EJBClientWorker(msgContext, startLatch, stopLatch);
workerPool.execute(worker);
startLatch.countDown();
try {
stopLatch.await();
} catch (InterruptedException e) {
throw AxisFault.makeFault(e);
}
if (worker.getException() != null) {
throw AxisFault.makeFault(worker.getException());
}
return worker.getReturnedValue();
}
private static class EJBClientWorker implements Runnable {
private MessageContext msgContext = null;
private CountDownLatch startLatch = null;
private CountDownLatch stopLatch = null;
// protected static final Class[] empty_class_array = new Class[0];
// protected static final Object[] empty_object_array = new Object[0];
private static InitialContext cached_context = null;
private Exception exception = null;
private Object returnedValue = null;
public EJBClientWorker(MessageContext msgContext, CountDownLatch startLatch,
CountDownLatch stopLatch) {
this.msgContext = msgContext;
this.startLatch = startLatch;
this.stopLatch = stopLatch;
}
public void run() {
try {
startLatch.await();
final AxisService service = msgContext.getAxisService();
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
Thread.currentThread().setContextClassLoader(service.getClassLoader());
return null;
}
});
Parameter remoteName = service.getParameter(EJB_REMOTE_INTERFACE_NAME);
Parameter localName = service.getParameter(EJB_LOCAL_INTERFACE_NAME);
Parameter jndiName = service.getParameter(EJB_JNDI_NAME);
Parameter interfaceName = (remoteName != null ? remoteName : localName);
if (jndiName == null || jndiName.getValue() == null) {
throw new AxisFault("jndi name is not specified");
} else if (interfaceName == null || interfaceName.getValue() == null) {
// cannot find both ejb remote and local interfaces
// todo - in ejb 3.1 this is also not required!
throw new AxisFault("ejb remote/local home class name is not specified");
}
// we create either the ejb using either the RemoteHome or
// LocalHome object
if (remoteName != null) {
returnedValue = createRemoteEJB(msgContext,
((String) jndiName.getValue()).trim(),
((String) interfaceName.getValue()).trim());
} else {
returnedValue = createLocalEJB(msgContext,
((String) jndiName.getValue()).trim(),
((String) interfaceName.getValue()).trim());
}
} catch (Exception e) {
e.printStackTrace();
exception = e;
} finally {
stopLatch.countDown();
}
}
/**
* Create an EJB using a ejb remote object
*
* @param msgContext
* the message context
* @param beanJndiName
* The JNDI name of the EJB remote class
* @param interfaceName
* the name of the interface class
* @return an EJB
* @throws Exception
* If fails
*/
private Object createRemoteEJB(MessageContext msgContext, String beanJndiName,
String interfaceName) throws Exception {
Class cls = getContextClassLoader().loadClass(interfaceName);
// Get the EJB Remote object from JNDI
Object ejbRemote = getEJBInterface(msgContext.getAxisService(), beanJndiName);
return cls.cast(ejbRemote);
}
/**
* Create an EJB using a local home object
*
* @param msgContext
* the message context
* @param beanJndiName
* The JNDI name of the EJB local interface class
* @param interfaceName
* the name of the local interface class
* @return an EJB
* @throws Exception
* if fails
*/
private Object createLocalEJB(MessageContext msgContext, String beanJndiName,
String interfaceName) throws Exception {
Class cls = getContextClassLoader().loadClass(interfaceName);
// Get the EJB local interface object from JNDI
Object ejbLocal = getEJBInterface(msgContext.getAxisService(), beanJndiName);
return cls.cast(ejbLocal);
}
/**
* Common routine to do the JNDI lookup on the remote/local interface
* object username and password for jndi lookup are got from the
* configuration or from the messageContext if not found in the
* configuration
*
* @param service
* AxisService object
* @param beanJndiName
* JNDI name of the EJB remote/local object
* @return EJB remote/local object
* @throws org.apache.axis2.AxisFault
* If fails
*/
private Object getEJBInterface(AxisService service, String beanJndiName) throws AxisFault {
Object ejbRemote = null;
// Set up an InitialContext and use it get the beanJndiName from
// JNDI
try {
Properties properties = null;
// collect all the properties we need to access JNDI:
// username, password, factoryclass, contextUrl
// username
Parameter username = service.getParameter(EJB_JNDI_USERNAME);
if (username != null) {
if (properties == null)
properties = new Properties();
properties.setProperty(Context.SECURITY_PRINCIPAL,
((String) username.getValue()).trim());
}
// password
Parameter password = service.getParameter(EJB_JNDI_PASSWORD);
if (password != null) {
if (properties == null)
properties = new Properties();
properties.setProperty(Context.SECURITY_CREDENTIALS,
((String) password.getValue()).trim());
}
// factory class
Parameter factoryClass = service.getParameter(EJB_INITIAL_CONTEXT_FACTORY);
if (factoryClass != null) {
if (properties == null)
properties = new Properties();
properties.setProperty(Context.INITIAL_CONTEXT_FACTORY,
((String) factoryClass.getValue()).trim());
}
// contextUrl
Parameter contextUrl = service.getParameter(EJB_PROVIDER_URL);
if (contextUrl != null) {
if (properties == null)
properties = new Properties();
properties.setProperty(Context.PROVIDER_URL,
((String) contextUrl.getValue()).trim());
}
// get context using these properties
InitialContext context = getContext(properties);
// if we didn't get a context, fail
if (context == null)
throw new AxisFault("cannot create initial context");
try {
ejbRemote = lookUpEJBInterface(context, beanJndiName);
} catch (Exception e) {
ejbRemote = lookUpEJBInterface(context, beanJndiName); // Retry
// for
// the
// 2nd
// time
// to
// overcome
// issues
// related
// to
// cahing
}
if (ejbRemote == null)
throw new AxisFault("cannot find jndi home");
} catch (Exception exception) {
throw AxisFault.makeFault(exception);
}
return ejbRemote;
}
private InitialContext getCachedContext() throws NamingException {
if (cached_context == null)
cached_context = new InitialContext();
return cached_context;
}
private InitialContext getContext(Properties properties) throws AxisFault, NamingException {
return ((properties == null) ? getCachedContext() : new InitialContext(properties));
}
private Object lookUpEJBInterface(InitialContext context, String beanJndiName)
throws AxisFault, NamingException {
return context.lookup(beanJndiName);
}
private ClassLoader getContextClassLoader() {
return (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return Thread.currentThread().getContextClassLoader();
}
});
}
public Exception getException() {
return exception;
}
public Object getReturnedValue() {
return returnedValue;
}
}
}