/**
* 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.net.URL;
//import java.util.Iterator;
import java.util.logging.Logger;
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.wsdl.Port;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceException;
import org.apache.cxf.Bus;
import org.apache.cxf.connector.Connection;
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 Logger LOG = Logger.getLogger(ManagedConnectionImpl.class.getName());
private InvocationHandlerFactory handlerFactory;
private Object cxfService;
private boolean connectionHandleActive;
public ManagedConnectionImpl(ManagedConnectionFactoryImpl managedFactory, ConnectionRequestInfo crInfo,
Subject subject) throws ResourceException {
super(managedFactory, crInfo, subject);
LOG.fine("ManagedConnection created with hash: " + hashCode() + "." + toString());
}
public void associateConnection(Object arg0) throws ResourceException {
try {
CXFInvocationHandler handler = (CXFInvocationHandler)Proxy
.getInvocationHandler((Proxy)arg0);
Object managedConnection = handler.getData().getManagedConnection();
LOG.fine("previously associated managed connection: " + managedConnection.hashCode());
if (managedConnection != this) {
LOG.fine("associate handle " + arg0 + " with managed connection " + this
+ " with hashcode: " + hashCode());
handler.getData().setManagedConnection(this);
((ManagedConnectionImpl)managedConnection).disassociateConnectionHandle(arg0);
if (getCXFService() == null) {
// Very unlikely as THIS
// managed connection is
// already involved in a transaction.
cxfService = arg0;
connectionHandleActive = true;
}
}
} catch (Exception ex) {
throw new ResourceAdapterInternalException("Error associating handle " + arg0
+ " with managed connection " + this, ex);
}
}
public CXFManagedConnectionFactory getManagedConnectionFactory() {
return (ManagedConnectionFactoryImpl)theManagedConnectionFactory();
}
final Object getCXFService() {
return cxfService;
}
final void initialiseCXFService(ConnectionRequestInfo crInfo, Subject subject)
throws ResourceException {
LOG.fine("initialiseCXFService, this=" + this + ", info=" + crInfo + ", subject=" + subject);
this.crinfo = crInfo;
this.subject = subject;
cxfService = getCXFServiceFromBus(subject, crInfo);
}
public Object getConnection(Subject subject, ConnectionRequestInfo crInfo) throws ResourceException {
LOG.fine("getConnection: this=" + this + ", info=" + crInfo + ", subject=" + subject);
Object connection = null;
if (getCXFService() == null) {
initialiseCXFService(crInfo, subject);
connection = getCXFService();
} else {
if (!connectionHandleActive && this.crinfo.equals(crInfo)) {
connection = getCXFService();
} else {
connection = getCXFServiceFromBus(subject, crInfo);
}
}
connectionHandleActive = true;
return connection;
}
public synchronized Object getCXFServiceFromBus(Subject subject, ConnectionRequestInfo crInfo)
throws ResourceException {
CXFConnectionRequestInfo arReqInfo = (CXFConnectionRequestInfo)crInfo;
ClassLoader orig = Thread.currentThread().getContextClassLoader();
// Bus bus = getBus();
//Thread.currentThread().setContextClassLoader(bus.getClass().getClassLoader());
QName serviceName = arReqInfo.getServiceQName();
URL wsdlLocationUrl = arReqInfo.getWsdlLocationUrl();
if (wsdlLocationUrl == null) {
// if the wsdlLocationUrl is null, set the default wsdl
try {
Object obj = null;
Service service = Service.create(serviceName);
QName port = arReqInfo.getPortQName();
if (port == null) {
obj = service.getPort(arReqInfo.getInterface());
} else {
obj = service.getPort(arReqInfo.getPortQName(), arReqInfo.getInterface());
}
setSubject(subject);
return createConnectionProxy(obj, arReqInfo, subject);
} catch (WebServiceException wse) {
throw new ResourceAdapterInternalException("Failed to create proxy client for service "
+ crInfo, wse);
} finally {
// Thread.currentThread().setContextClassLoader(orig);
}
}
try {
Object obj = null;
Service service = Service.create(wsdlLocationUrl, serviceName);
if (arReqInfo.getPortQName() != null) {
obj = service.getPort(arReqInfo.getPortQName(), arReqInfo.getInterface());
} else {
obj = service.getPort(arReqInfo.getInterface());
}
setSubject(subject);
return createConnectionProxy(obj, arReqInfo, subject);
} catch (WebServiceException wse) {
throw new ResourceAdapterInternalException("Failed to getPort for " + crInfo, wse);
} finally {
Thread.currentThread().setContextClassLoader(orig);
}
}
public ManagedConnectionMetaData getMetaData() throws ResourceException {
throw new NotSupportedException("Not Supported");
}
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, 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();
}
}