001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.tm.iiop;
023:
024: import javax.naming.Context;
025: import javax.naming.InitialContext;
026: import javax.naming.NamingException;
027: import javax.transaction.Transaction;
028:
029: import org.omg.CORBA.Any;
030: import org.omg.CORBA.BAD_PARAM;
031: import org.omg.CORBA.TCKind;
032: import org.omg.CORBA.LocalObject;
033: import org.omg.CosTransactions.PropagationContext;
034: import org.omg.CosTransactions.PropagationContextHelper;
035: import org.omg.CosTransactions.otid_t;
036: import org.omg.IOP.Codec;
037: import org.omg.IOP.CodecPackage.FormatMismatch;
038: import org.omg.IOP.CodecPackage.TypeMismatch;
039: import org.omg.IOP.ServiceContext;
040: import org.omg.PortableInterceptor.InvalidSlot;
041: import org.omg.PortableInterceptor.ServerRequestInfo;
042: import org.omg.PortableInterceptor.ServerRequestInterceptor;
043:
044: import org.jboss.proxy.ejb.ForeignTransaction;
045: import org.jboss.tm.GlobalId;
046: import org.jboss.tm.TransactionPropagationContextImporter;
047:
048: /**
049: * This implementation of
050: * <code>org.omg.PortableInterceptor.ServerRequestInterceptor</code>
051: * retrieves the transactional context from incoming IIOP requests and
052: * makes it available to the servant methods that handle the requests,
053: * through the static method <code>getCurrentTransaction</code).
054: *
055: * @author <a href="mailto:reverbel@ime.usp.br">Francisco Reverbel</a>
056: * @version $Revision: 57194 $
057: */
058: public class TxServerInterceptor extends LocalObject implements
059: ServerRequestInterceptor {
060: /** @since 4.0.1 */
061: static final long serialVersionUID = 7474707114565659371L;
062:
063: // Static fields -------------------------------------------------
064:
065: private static final int txContextId = org.omg.IOP.TransactionService.value;
066: private static int slotId;
067: private static Codec codec;
068: private static org.omg.PortableInterceptor.Current piCurrent = null;
069: private static TransactionPropagationContextImporter tpcImporter = null;
070:
071: // Static methods ------------------------------------------------
072:
073: /**
074: * Called by <code>TxServerInterceptorInitializer</code>
075: * at ORB initialization time.
076: */
077: static void init(int slotId, Codec codec,
078: org.omg.PortableInterceptor.Current piCurrent) {
079: TxServerInterceptor.slotId = slotId;
080: TxServerInterceptor.codec = codec;
081: TxServerInterceptor.piCurrent = piCurrent;
082: }
083:
084: /**
085: * Returns the transaction associated with the transaction propagation
086: * context that arrived in the current IIOP request.
087: */
088: public static Transaction getCurrentTransaction() {
089: Transaction tx = null;
090: if (piCurrent != null) {
091: // A non-null piCurrent means that a TxServerInterceptor was
092: // installed: check if there is a transaction propagation context
093: try {
094: Any any = piCurrent.get_slot(slotId);
095: if (any.type().kind().value() != TCKind._tk_null) {
096: // Yes, there is a TPC
097: PropagationContext pc = PropagationContextHelper
098: .extract(any);
099: if (pc.current.coord == null)
100: tx = ForeignTransaction.instance;
101: otid_t otid = pc.current.otid;
102: // Build a GlobalId with info taken from the TPC
103: GlobalId globalId = new GlobalId(otid.formatID,
104: otid.bqual_length, otid.tid);
105: // Get transaction by GlobalId
106: tx = getTPCImporter()
107: .importTransactionPropagationContext(
108: globalId);
109: // No transaction propagation (add the marker)
110: if (tx == null)
111: tx = ForeignTransaction.instance;
112: }
113: } catch (InvalidSlot e) {
114: throw new RuntimeException("Exception getting slot in "
115: + "TxServerInterceptor: " + e);
116: }
117:
118: }
119: return tx;
120: }
121:
122: /**
123: * Get a reference to the transaction importer.
124: */
125: private static TransactionPropagationContextImporter getTPCImporter() {
126: if (tpcImporter == null) {
127: try {
128: Context ctx = new InitialContext();
129: tpcImporter = (TransactionPropagationContextImporter) ctx
130: .lookup("java:/TransactionPropagationContextImporter");
131: } catch (NamingException e) {
132: throw new RuntimeException(
133: "java:/TransactionPropagationContextImporter lookup failed",
134: e);
135: }
136: }
137: return tpcImporter;
138: }
139:
140: // Constructor ---------------------------------------------------
141:
142: public TxServerInterceptor() {
143: // do nothing
144: }
145:
146: // org.omg.PortableInterceptor.Interceptor operations ------------
147:
148: public String name() {
149: return "TxServerInterceptor";
150: }
151:
152: public void destroy() {
153: // do nothing
154: }
155:
156: // ServerRequestInterceptor operations ---------------------------
157:
158: public void receive_request_service_contexts(ServerRequestInfo ri) {
159: try {
160: ServiceContext sc = ri
161: .get_request_service_context(txContextId);
162: Any any = codec.decode_value(sc.context_data,
163: PropagationContextHelper.type());
164: ri.set_slot(slotId, any);
165: } catch (BAD_PARAM e) {
166: // no service context with txContextId: do nothing
167: } catch (FormatMismatch e) {
168: throw new RuntimeException(
169: "Exception decoding context data in "
170: + "TxServerInterceptor: " + e);
171: } catch (TypeMismatch e) {
172: throw new RuntimeException(
173: "Exception decoding context data in "
174: + "TxServerInterceptor: " + e);
175: } catch (InvalidSlot e) {
176: throw new RuntimeException("Exception setting slot in "
177: + "TxServerInterceptor: " + e);
178: }
179: }
180:
181: public void receive_request(ServerRequestInfo ri) {
182: // do nothing
183: }
184:
185: public void send_reply(ServerRequestInfo ri) {
186: // do nothing
187: }
188:
189: public void send_exception(ServerRequestInfo ri) {
190: // do nothing
191: }
192:
193: public void send_other(ServerRequestInfo ri) {
194: // do nothing
195: }
196: }
|