blob: 9c1a384c7ad390cbca9c0d6843fd37ec0d1c3ccc [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.tuscany.sca.binding.jms.provider;
import java.util.Properties;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Session;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.resource.spi.ActivationSpec;
import org.apache.tuscany.sca.binding.jms.JMSBindingException;
/**
* Abstracts away any JMS provide specific feature from the JMS binding
*
* @version $Rev$ $Date$
*/
public class JMSResourceFactoryImpl implements JMSResourceFactory {
protected String initialContextFactoryName;
protected String connectionFactoryName = "ConnectionFactory";
protected String jndiURL;
protected Connection connection;
protected Context context;
protected boolean isConnectionStarted;
private Connection responseConnection;
private String responseConnectionFactoryName;
public JMSResourceFactoryImpl(String connectionFactoryName, String responseConnectionFactoryName, String initialContextFactoryName, String jndiURL) {
if (connectionFactoryName != null && connectionFactoryName.trim().length() > 0) {
this.connectionFactoryName = connectionFactoryName.trim();
}
if (responseConnectionFactoryName != null && responseConnectionFactoryName.trim().length() > 0) {
this.responseConnectionFactoryName = responseConnectionFactoryName.trim();
}
if (initialContextFactoryName != null && initialContextFactoryName.trim().length() > 0) {
this.initialContextFactoryName = initialContextFactoryName.trim();
}
if (jndiURL != null) {
this.jndiURL = jndiURL.trim();
}
}
/*
* This is a simple implementation where a connection is created per binding Ideally the resource factory should be
* able to leverage the host environment to provide connection pooling if it can. E.g. if Tuscany is running inside
* an AppServer Then we could leverage the JMS resources it provides
*
* @see org.apache.tuscany.sca.binding.jms.provider.JMSResourceFactory#getConnection()
*/
public Connection getConnection() throws NamingException, JMSException {
if (connection == null) {
createConnection();
}
return connection;
}
/*
* (non-Javadoc)
*
* @see org.apache.tuscany.sca.binding.jms.provider.JMSResourceFactory#createSession()
*/
public Session createSession() throws JMSException, NamingException {
return getConnection().createSession(false, Session.AUTO_ACKNOWLEDGE);
}
/*
* (non-Javadoc)
*
* @see org.apache.tuscany.sca.binding.jms.provider.JMSResourceFactory#closeSession(javax.jms.Session)
*/
public void closeSession(Session session) throws JMSException {
session.close();
}
/*
* (non-Javadoc)
*
* @see org.apache.tuscany.sca.binding.jms.provider.JMSResourceFactory#startConnection()
*/
public void startConnection() throws JMSException, NamingException {
if (!isConnectionStarted) {
getConnection().start();
isConnectionStarted = true;
}
}
/*
* (non-Javadoc)
*
* @see org.apache.tuscany.sca.binding.jms.provider.JMSResourceFactory#closeConnection()
*/
public void closeConnection() throws JMSException {
if (connection != null) {
try {
connection.close();
} catch (JMSException e) {
// if using an embedded broker then when shutting down Tuscany the broker may get closed
// before this stop method is called. I can't see how to detect that so for now just
// ignore the exception if the message is that the transport is already disposed
if (!e.getMessage().contains("disposed")) {
throw e;
}
}
}
}
protected void createConnection() throws NamingException, JMSException {
Object o = jndiLookUp(connectionFactoryName);
if (o == null) {
throw new JMSBindingException("connection factory not found: " + connectionFactoryName);
}
if (!(o instanceof ConnectionFactory)) {
throw new JMSBindingException("JNDI resource '" + connectionFactoryName +"' is not a JMS ConnectionFactory");
}
ConnectionFactory connectionFactory = (ConnectionFactory)o;
connection = connectionFactory.createConnection();
}
protected synchronized Context getInitialContext() throws NamingException {
if (context == null) {
Properties props = new Properties();
if (initialContextFactoryName != null) {
props.setProperty(Context.INITIAL_CONTEXT_FACTORY, initialContextFactoryName);
}
if (jndiURL != null) {
props.setProperty(Context.PROVIDER_URL, jndiURL);
}
initJREEnvironment(props);
context = new InitialContext(props);
}
return context;
}
/**
* If using the WAS JMS Client with a non-IBM JRE then an additional
* environment property needs to be set to initialize the ORB correctly.
* See: http://www-1.ibm.com/support/docview.wss?uid=swg24012804
*/
protected void initJREEnvironment(Properties props) {
if ("com.ibm.websphere.naming.WsnInitialContextFactory".equals(props.get(Context.INITIAL_CONTEXT_FACTORY))) {
String vendor = System.getProperty("java.vendor");
if (vendor == null || !vendor.contains("IBM")) {
props.setProperty("com.ibm.CORBA.ORBInit", "com.ibm.ws.sib.client.ORB");
}
}
}
/* (non-Javadoc)
* @see org.apache.tuscany.sca.binding.jms.provider.JMSResourceFactory#lookupDestination(java.lang.String)
*/
public Destination lookupDestination(String destName) throws NamingException {
if (destName == null) {
return null;
}
Destination dest = (Destination)jndiLookUp(destName);
if (dest == null) {
dest = lookupPhysical(destName);
}
return dest;
}
protected Destination lookupPhysical(String jndiName) {
// TODO: the SCA JMS spec says a destination name may be a non-jndi plain destination name
// Session session = null;
// try {
//
// Destination dest;
// session = createSession();
// dest = session.createQueue(jndiName);
// return dest;
//
// } catch (JMSException e) {
// throw new JMSBindingException(e);
// } catch (NamingException e) {
// throw new JMSBindingException(e);
// } finally {
// if (session != null) {
// try {
// session.close();
// } catch (JMSException e) {
// throw new JMSBindingException(e);
// }
// }
// }
return null;
}
/* (non-Javadoc)
* @see org.apache.tuscany.sca.binding.jms.provider.JMSResourceFactory#createDestination(java.lang.String)
*/
public Destination createDestination(String jndiName) throws NamingException {
if ( jndiName == null )
return null;
return lookupDestination("dynamicQueues/" + jndiName);
}
protected Object jndiLookUp(String name) {
Object o = null;
try {
o = getInitialContext().lookup("java:comp/env/" + name);
} catch (Exception ex) {
// ignore
}
if (o == null) {
try {
o = getInitialContext().lookup(name);
} catch (NamingException ex) {
// ignore
}
}
return o;
}
public Session createResponseSession() throws JMSException, NamingException {
return getResponseConnection().createSession(false, Session.AUTO_ACKNOWLEDGE);
}
public void closeResponseSession(Session session) throws JMSException {
session.close();
}
public Connection getResponseConnection() throws NamingException, JMSException {
if (responseConnection == null) {
if (responseConnectionFactoryName != null) {
ConnectionFactory connectionFactory = (ConnectionFactory)jndiLookUp(responseConnectionFactoryName);
if (connectionFactory == null) {
throw new JMSBindingException("connection factory not found: " + responseConnectionFactoryName);
}
responseConnection = connectionFactory.createConnection();
} else {
// if no response connection is defined in the SCDL use the request connection
responseConnection = getConnection();
}
}
return responseConnection;
}
public void closeResponseConnection() throws JMSException {
if (responseConnection != null && !responseConnection.equals(connection)) {
try {
responseConnection.close();
} catch (JMSException e) {
// if using an embedded broker then when shutting down Tuscany the broker may get closed
// before this stop method is called. I can't see how to detect that so for now just
// ignore the exception if the message is that the transport is already disposed
if (!e.getMessage().contains("disposed")) {
throw e;
}
}
}
}
public boolean isConnectionClosedAfterUse() {
// It is assumed this resource factory is used in an environment
// where the connection can be held for the life of the binding.
return false;
}
public ActivationSpec lookupActivationSpec(String activationSpecName) {
Object o = jndiLookUp(activationSpecName);
if ( o == null )
return null;
else if (o instanceof ActivationSpec)
return (ActivationSpec) o;
throw new JMSBindingException("Incorrect resource type for ActivationSpec: " + o.getClass().getName());
}
}