blob: a9f919ca23e9ca2e50533200f5c86dab968a8387 [file] [log] [blame]
/*
* Copyright 2004-2005 The Apache Software Foundation or its licensors,
* as applicable.
*
* Licensed 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.jackrabbit.jca;
import org.apache.jackrabbit.core.RepositoryImpl;
import org.apache.jackrabbit.core.XASession;
import javax.jcr.Repository;
import javax.resource.ResourceException;
import javax.resource.spi.ConnectionEvent;
import javax.resource.spi.ConnectionEventListener;
import javax.resource.spi.ConnectionRequestInfo;
import javax.resource.spi.LocalTransaction;
import javax.resource.spi.ManagedConnection;
import javax.resource.spi.ManagedConnectionMetaData;
import javax.security.auth.Subject;
import javax.transaction.xa.XAResource;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.LinkedList;
/**
* This class implements the managed connection for
* this resource adapter.
*/
public final class JCAManagedConnection
implements ManagedConnection, ManagedConnectionMetaData {
/**
* Managed connection factory.
*/
private final JCAManagedConnectionFactory mcf;
/**
* Connection request info.
*/
private final JCAConnectionRequestInfo cri;
/**
* Session instance.
*/
private final XASession session;
/**
* Listeners.
*/
private final LinkedList listeners;
/**
* Handles.
*/
private final LinkedList handles;
/**
* Log writer.
*/
private PrintWriter logWriter;
/**
* Construct the managed connection.
*/
public JCAManagedConnection(JCAManagedConnectionFactory mcf, JCAConnectionRequestInfo cri, XASession session) {
this.mcf = mcf;
this.cri = cri;
this.session = session;
this.listeners = new LinkedList();
this.handles = new LinkedList();
}
/**
* Return the repository.
*/
private RepositoryImpl getRepository() {
return mcf.getRepository();
}
/**
* Return the managed connection factory.
*/
public JCAManagedConnectionFactory getManagedConnectionFactory() {
return mcf;
}
/**
* Return the connection request info.
*/
public JCAConnectionRequestInfo getConnectionRequestInfo() {
return cri;
}
/**
* Get the log writer.
*/
public PrintWriter getLogWriter() {
return logWriter;
}
/**
* Set the log writer.
*/
public void setLogWriter(PrintWriter logWriter)
throws ResourceException {
this.logWriter = logWriter;
}
/**
* Creates a new connection handle for the underlying physical
* connection represented by the ManagedConnection instance.
*/
public Object getConnection(Subject subject, ConnectionRequestInfo cri)
throws ResourceException {
JCASessionHandle handle = new JCASessionHandle(this);
addHandle(handle);
return handle;
}
/**
* Destroys the physical connection to the underlying resource manager.
*/
public void destroy()
throws ResourceException {
cleanup();
session.logout();
}
/**
* Application server calls this method to force any cleanup on
* the ManagedConnection instance.
*/
public void cleanup()
throws ResourceException {
closeHandles();
}
/**
* Used by the container to change the association of an
* application-level connection handle with a ManagedConneciton instance.
*/
public void associateConnection(Object connection)
throws ResourceException {
JCASessionHandle handle = (JCASessionHandle) connection;
if (handle.getManagedConnection() != this) {
handle.getManagedConnection().removeHandle(handle);
handle.setManagedConnection(this);
addHandle(handle);
}
}
/**
* Returns an javax.transaction.xa.XAresource instance.
*/
public XAResource getXAResource()
throws ResourceException {
return session.getXAResource();
}
/**
* Returns an javax.resource.spi.LocalTransaction instance.
*/
public LocalTransaction getLocalTransaction()
throws ResourceException {
throw new UnsupportedOperationException("Local transaction is not supported");
}
/**
* Gets the metadata information for this connection's underlying
* EIS resource manager instance.
*/
public ManagedConnectionMetaData getMetaData()
throws ResourceException {
return this;
}
/**
* Close the handle.
*/
public void closeHandle(JCASessionHandle handle) {
if (handle != null) {
removeHandle(handle);
sendClosedEvent(handle);
}
}
/**
* Return the session.
*/
public XASession getSession(JCASessionHandle handle) {
synchronized (handles) {
if ((handles.size() > 0) && (handles.get(0) == handle)) {
return session;
} else {
throw new java.lang.IllegalStateException("Inactive logical session handle called");
}
}
}
/**
* Return the product name.
*/
public String getEISProductName()
throws ResourceException {
return getRepository().getDescriptor(Repository.REP_NAME_DESC);
}
/**
* Return the product version.
*/
public String getEISProductVersion()
throws ResourceException {
return getRepository().getDescriptor(Repository.REP_VERSION_DESC);
}
/**
* Return number of max connections.
*/
public int getMaxConnections()
throws ResourceException {
return Integer.MAX_VALUE;
}
/**
* Return the user name.
*/
public String getUserName()
throws ResourceException {
return session.getUserID();
}
/**
* Log a message.
*/
public void log(String message) {
log(message, null);
}
/**
* Log a message.
*/
public void log(String message, Throwable exception) {
if (logWriter != null) {
logWriter.println(message);
if (exception != null) {
exception.printStackTrace(logWriter);
}
}
}
/**
* Adds a listener.
*/
public void addConnectionEventListener(ConnectionEventListener listener) {
synchronized (listeners) {
if (!listeners.contains(listener)) {
listeners.add(listener);
}
}
}
/**
* Remove a listener.
*/
public void removeConnectionEventListener(ConnectionEventListener listener) {
synchronized (listeners) {
listeners.remove(listener);
}
}
/**
* Send event.
*/
private void sendEvent(ConnectionEvent event) {
synchronized (listeners) {
for (Iterator i = listeners.iterator(); i.hasNext();) {
ConnectionEventListener listener = (ConnectionEventListener) i.next();
switch (event.getId()) {
case ConnectionEvent.CONNECTION_CLOSED:
listener.connectionClosed(event);
break;
case ConnectionEvent.CONNECTION_ERROR_OCCURRED:
listener.connectionErrorOccurred(event);
break;
case ConnectionEvent.LOCAL_TRANSACTION_COMMITTED:
listener.localTransactionCommitted(event);
break;
case ConnectionEvent.LOCAL_TRANSACTION_ROLLEDBACK:
listener.localTransactionRolledback(event);
break;
case ConnectionEvent.LOCAL_TRANSACTION_STARTED:
listener.localTransactionStarted(event);
break;
}
}
}
}
/**
* Send event.
*/
private void sendEvent(int type, Object handle, Exception cause) {
ConnectionEvent event = new ConnectionEvent(this, type, cause);
if (handle != null) {
event.setConnectionHandle(handle);
}
sendEvent(event);
}
/**
* Send connection closed event.
*/
private void sendClosedEvent(JCASessionHandle handle) {
sendEvent(ConnectionEvent.CONNECTION_CLOSED, handle, null);
}
/**
* Send connection error event.
*/
public void sendrrorEvent(JCASessionHandle handle, Exception cause) {
sendEvent(ConnectionEvent.CONNECTION_ERROR_OCCURRED, handle, cause);
}
/**
* Send transaction committed event.
*/
public void sendTxCommittedEvent(JCASessionHandle handle) {
sendEvent(ConnectionEvent.LOCAL_TRANSACTION_COMMITTED, handle, null);
}
/**
* Send transaction rolledback event.
*/
public void sendTxRolledbackEvent(JCASessionHandle handle) {
sendEvent(ConnectionEvent.LOCAL_TRANSACTION_ROLLEDBACK, handle, null);
}
/**
* Send transaction started event.
*/
public void sendTxStartedEvent(JCASessionHandle handle) {
sendEvent(ConnectionEvent.LOCAL_TRANSACTION_STARTED, handle, null);
}
/**
* Add a session handle.
*/
private void addHandle(JCASessionHandle handle) {
synchronized (handles) {
handles.addFirst(handle);
}
}
/**
* Remove a session handle.
*/
private void removeHandle(JCASessionHandle handle) {
synchronized (handles) {
handles.remove(handle);
}
}
/**
* Release handles.
*/
private void closeHandles() {
synchronized (handles) {
for (Iterator i = handles.iterator(); i.hasNext();) {
JCASessionHandle handle = (JCASessionHandle) i.next();
closeHandle(handle);
}
handles.clear();
}
}
}