/**
* 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.cxf.jca.cxf;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.ResourceBundle;
import javax.jws.WebService;
import javax.resource.NotSupportedException;
import javax.resource.ResourceException;
import javax.resource.spi.ConnectionRequestInfo;
import javax.resource.spi.LocalTransaction;
import javax.resource.spi.ManagedConnectionMetaData;
import javax.security.auth.Subject;
import javax.transaction.xa.XAResource;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.WebServiceException;
import org.apache.cxf.Bus;
import org.apache.cxf.common.i18n.BundleUtils;
import org.apache.cxf.common.i18n.Message;
import org.apache.cxf.connector.Connection;
import org.apache.cxf.frontend.ClientProxyFactoryBean;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.jca.core.resourceadapter.AbstractManagedConnectionImpl;
import org.apache.cxf.jca.core.resourceadapter.ResourceAdapterInternalException;
import org.apache.cxf.jca.cxf.handlers.InvocationHandlerFactory;
public class ManagedConnectionImpl
extends AbstractManagedConnectionImpl
implements CXFManagedConnection, Connection {
private static final ResourceBundle BUNDLE = BundleUtils.getBundle(ConnectionFactoryImpl.class);
private InvocationHandlerFactory handlerFactory;
private Object cxfService;
private boolean connectionHandleActive;
public ManagedConnectionImpl(ManagedConnectionFactoryImpl managedFactory, ConnectionRequestInfo crInfo,
Subject subject) throws ResourceException {
super(managedFactory, crInfo, subject);
}
public void associateConnection(Object connection) throws ResourceException {
try {
CXFInvocationHandler handler =
(CXFInvocationHandler)Proxy.getInvocationHandler(connection);
Object managedConnection = handler.getData().getManagedConnection();
if (managedConnection != this) {
handler.getData().setManagedConnection(this);
((ManagedConnectionImpl)managedConnection).disassociateConnectionHandle(connection);
if (getCXFService() == null) {
// Very unlikely as THIS
// managed connection is
// already involved in a transaction.
cxfService = connection;
connectionHandleActive = true;
}
}
} catch (Exception ex) {
throw new ResourceAdapterInternalException(
new Message("ASSOCIATED_ERROR", BUNDLE).toString(), ex);
}
}
public CXFManagedConnectionFactory getManagedConnectionFactory() {
return (ManagedConnectionFactoryImpl)theManagedConnectionFactory();
}
public Object getCXFService() {
return cxfService;
}
private void initializeCXFConnection(ConnectionRequestInfo crInfo, Subject subject)
throws ResourceException {
this.crinfo = crInfo;
this.subject = subject;
cxfService = getCXFConnection(subject, crInfo);
}
public Object getConnection(Subject subject, ConnectionRequestInfo crInfo) throws ResourceException {
Object connection = null;
if (getCXFService() == null) {
initializeCXFConnection(crInfo, subject);
connection = getCXFService();
} else {
if (!connectionHandleActive && this.crinfo.equals(crInfo)) {
connection = getCXFService();
} else {
connection = getCXFConnection(subject, crInfo);
}
}
connectionHandleActive = true;
return connection;
}
public synchronized Object getCXFConnection(Subject subject, ConnectionRequestInfo crInfo)
throws ResourceException {
CXFConnectionRequestInfo requestInfo = (CXFConnectionRequestInfo)crInfo;
Class<?> serviceInterface = requestInfo.getInterface();
ClassLoader orig = Thread.currentThread().getContextClassLoader();
try {
ClientProxyFactoryBean factoryBean = null;
if (isJaxWsServiceInterface(serviceInterface)) {
factoryBean = new JaxWsProxyFactoryBean();
} else {
factoryBean = new ClientProxyFactoryBean();
}
factoryBean.setServiceClass(serviceInterface);
if (requestInfo.getServiceName() != null) {
factoryBean.getServiceFactory().setServiceName(requestInfo.getServiceName());
}
if (requestInfo.getPortName() != null) {
factoryBean.getServiceFactory().setEndpointName(requestInfo.getPortName());
}
if (requestInfo.getWsdlLocation() != null) {
factoryBean.getServiceFactory().setWsdlURL(requestInfo.getWsdlLocation());
}
if (requestInfo.getAddress() != null) {
factoryBean.setAddress(requestInfo.getAddress());
}
Object obj = factoryBean.create();
setSubject(subject);
return createConnectionProxy(obj, requestInfo, subject);
} catch (WebServiceException wse) {
throw new ResourceAdapterInternalException(new Message("FAILED_TO_GET_CXF_CONNECTION",
BUNDLE, requestInfo).toString(), wse);
} finally {
Thread.currentThread().setContextClassLoader(orig);
}
}
public ManagedConnectionMetaData getMetaData() throws ResourceException {
return new CXFManagedConnectionMetaData();
}
private boolean isJaxWsServiceInterface(Class<?> cls) {
if (cls == null) {
return false;
}
return null != cls.getAnnotation(WebService.class);
}
public boolean isBound() {
return getCXFService() != null;
}
// Compliance: WL9 checks
// implemention of Connection method - never used as real Connection impl is
// a java.lang.Proxy
public void close() throws ResourceException {
//TODO
}
void disassociateConnectionHandle(Object handle) {
if (cxfService == handle) {
connectionHandleActive = false;
cxfService = null;
}
}
private Object createConnectionProxy(Object obj, CXFConnectionRequestInfo cri, Subject subject)
throws ResourceException {
Class<?> classes[] = {Connection.class, BindingProvider.class, cri.getInterface()};
return Proxy.newProxyInstance(cri.getInterface().getClassLoader(), classes,
createInvocationHandler(obj, subject));
}
private InvocationHandler createInvocationHandler(Object obj, Subject subject) throws ResourceException {
return getHandlerFactory().createHandlers(obj, subject);
}
private InvocationHandlerFactory getHandlerFactory() throws ResourceException {
if (handlerFactory == null) {
handlerFactory = new InvocationHandlerFactory(getBus(), this);
}
return handlerFactory;
}
private Bus getBus() {
return ((ManagedConnectionFactoryImpl)getManagedConnectionFactory()).getBus();
}
public void close(Object closingHandle) throws ResourceException {
if (closingHandle == cxfService) {
connectionHandleActive = false;
}
super.close(closingHandle);
}
// beging chucked from the pool
public void destroy() throws ResourceException {
connectionHandleActive = false;
this.cxfService = null;
super.destroy();
}
public CXFTransaction getCXFTransaction() {
//TODO should throw the exception
return null;
}
public XAResource getXAResource() throws ResourceException {
throw new NotSupportedException();
}
public LocalTransaction getLocalTransaction() throws ResourceException {
throw new NotSupportedException();
}
}