1   /*
2    * Copyright 2003 - 2013 The eFaps Team
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   * Revision:        $Rev$
17   * Last Changed:    $Date$
18   * Last Changed By: $Author$
19   */
20  
21  package org.efaps.db.transaction;
22  
23  import java.sql.Connection;
24  import java.sql.SQLException;
25  
26  import javax.transaction.xa.XAException;
27  import javax.transaction.xa.Xid;
28  
29  import org.efaps.db.Context;
30  import org.efaps.util.EFapsException;
31  import org.slf4j.Logger;
32  import org.slf4j.LoggerFactory;
33  
34  /**
35   * The class implements the XAResource interface for SQL connections.
36   *
37   * @author The eFaps Team
38   * @version $Id$
39   */
40  public class ConnectionResource
41      extends AbstractResource
42  {
43      /**
44       * Logging instance used in this class.
45       */
46      private static final Logger LOG = LoggerFactory.getLogger(ConnectionResource.class);
47  
48      /**
49       * Stores the SQL connection of this connection resource.
50       */
51      private Connection connection = null;
52  
53      /**
54       * @param _connection   SQL connection
55       * @throws SQLException if auto commit could not be set to <i>false</i>
56       */
57      public ConnectionResource(final Connection _connection)
58          throws SQLException
59      {
60          this.connection = _connection;
61          this.connection.setAutoCommit(false);
62      }
63  
64      /**
65       * This is the getter method for instance variable {@link #connection}.
66       *
67       * @return value of instance variable {@link #connection}
68       * @see #connection
69       */
70      public final Connection getConnection()
71      {
72          return this.connection;
73      }
74  
75      /**
76       * Frees the resource and gives this connection resource back to the
77       * context object.
78       */
79      @Override
80      protected void freeResource()
81      {
82          try {
83              ConnectionResource.LOG.debug("free Resource: {}", this);
84              Context.getThreadContext().returnConnectionResource(this);
85          } catch (final EFapsException e) {
86              ConnectionResource.LOG.error("EFapsException", e);
87          }
88      }
89  
90      /**
91       * Ask the resource manager to prepare for a transaction commit of the
92       * transaction specified in xid (used for 2-phase commits).
93       * @param _xid Xid
94       * @return 0
95       */
96      public int prepare(final Xid _xid)
97      {
98          ConnectionResource.LOG.trace("prepare (xid = {})", _xid);
99          return 0;
100     }
101 
102     /**
103      * Commits the global transaction specified by xid.
104      * @param _xid      Xid
105      * @param _onePhase one phase
106      * @throws XAException on error
107      */
108     public void commit(final Xid _xid,
109                        final boolean _onePhase)
110         throws XAException
111     {
112         ConnectionResource.LOG.trace("commit (xid = {}, one phase = {})", _xid, _onePhase);
113         try  {
114             if (this.connection != null)  {
115                 this.connection.commit();
116             }
117         } catch (final SQLException e)  {
118             final XAException xa = new XAException(XAException.XA_RBCOMMFAIL);
119             xa.initCause(e);
120             throw xa;
121         } finally  {
122             try {
123                 if (this.connection != null)  {
124                     this.connection.close();
125                     this.connection = null;
126                 }
127             } catch (final SQLException e) {
128                 ConnectionResource.LOG.error("SQLException", e);
129             }
130         }
131     }
132 
133     /**
134      * Informs the resource manager to roll back work done on behalf of a
135      * transaction branch.
136      * @param _xid Xid
137      * @throws XAException on error
138      */
139     public void rollback(final Xid _xid)
140         throws XAException
141     {
142         ConnectionResource.LOG.trace("rollback (xid = {})", _xid);
143         try  {
144             if (this.connection != null)  {
145                 this.connection.rollback();
146             }
147         } catch (final SQLException e)  {
148             final XAException xa = new XAException(XAException.XA_RBCOMMFAIL);
149             xa.initCause(e);
150             throw xa;
151         } finally  {
152             try {
153                 if (this.connection != null)  {
154                     this.connection.close();
155                     this.connection = null;
156                 }
157             } catch (final SQLException e) {
158                 ConnectionResource.LOG.error("SQLException", e);
159             }
160         }
161     }
162 
163     /**
164      * Tells the resource manager to forget about a heuristically completed
165      * transaction branch.
166      * @param _xid Xid
167      */
168     public void forget(final Xid _xid)
169     {
170         ConnectionResource.LOG.trace("forget (xid = {})", _xid);
171     }
172 
173     /**
174      * Obtains the current transaction timeout value set for this XAResource
175      * instance.
176      * @return 0
177      */
178     public int getTransactionTimeout()
179     {
180         ConnectionResource.LOG.trace("getTransactionTimeout");
181         return 0;
182     }
183 
184     /**
185      * Obtains a list of prepared transaction branches from a resource manager.
186      * @param _flag flag
187      * @return null
188      */
189     public Xid[] recover(final int _flag)
190     {
191         ConnectionResource.LOG.trace("recover (flag = {})", _flag);
192         return null;
193     }
194 
195     /**
196      * Sets the current transaction timeout value for this XAResource instance.
197      * From this implementation ignored.
198      *
199      * @param _seconds  time out in seconds
200      * @return always <i>true</i>
201      */
202     public boolean setTransactionTimeout(final int _seconds)
203     {
204         ConnectionResource.LOG.debug("setTransactionTimout");
205         return true;
206     }
207 }