| /* |
| * 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(); |
| } |
| } |
| } |