001: /*
002: * @(#) OTSInterceptor.java 1.0 02/07/15
003: *
004: * JOTM: Java Open Transaction Manager
005: *
006: * This module was originally developed by
007: * - INRIA inside the ObjectWeb Consortium(http://www.objectweb.org)
008: *
009: * The original code and portions created by INRIA are
010: * Copyright (C) 2002 - INRIA (www.inria.fr)
011: * All rights reserved.
012: *
013: * Redistribution and use in source and binary forms, with or without
014: * modification, are permitted provided that the following conditions are met:
015: *
016: * -Redistributions of source code must retain the above copyright notice, this
017: * list of conditions and the following disclaimer.
018: *
019: * -Redistributions in binary form must reproduce the above copyright notice,
020: * this list of conditions and the following disclaimer in the documentation
021: * and/or other materials provided with the distribution.
022: *
023: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
024: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
025: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
026: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
027: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
028: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
029: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
030: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
031: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
032: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
033: * POSSIBILITY OF SUCH DAMAGE.
034: *
035: * --------------------------------------------------------------------------
036: * $Id: OTSInterceptor.java,v 1.7 2004/12/15 22:52:40 tonyortiz Exp $
037: * --------------------------------------------------------------------------
038: */
039: package org.objectweb.jotm.ots;
040:
041: import javax.rmi.PortableRemoteObject;
042: import javax.transaction.xa.Xid;
043:
044: import org.omg.CORBA.Any;
045: import org.omg.CORBA.LocalObject;
046: import org.omg.CORBA.ORB;
047: import org.omg.CORBA.TCKind;
048: import org.omg.CosTransactions.PropagationContext;
049: import org.omg.CosTransactions.PropagationContextHelper;
050: import org.omg.CosTransactions.TransIdentity;
051: import org.omg.CosTransactions.otid_t;
052: import org.omg.DynamicAny.DynAnyFactory;
053: import org.omg.DynamicAny.DynAnyFactoryHelper;
054: import org.omg.IOP.Codec;
055: import org.omg.IOP.ServiceContext;
056: import org.omg.PortableInterceptor.ForwardRequest;
057: import org.omg.PortableInterceptor.ORBInitInfo;
058: import org.omg.PortableInterceptor.ORBInitInfoPackage.InvalidName;
059:
060: import org.objectweb.jotm.Coordinator;
061: import org.objectweb.jotm.InternalTransactionContext;
062: import org.objectweb.jotm.Terminator;
063: import org.objectweb.jotm.TransactionContext;
064: import org.objectweb.jotm.XidImpl;
065:
066: public abstract class OTSInterceptor extends LocalObject {
067:
068: // Used to encode/decode the call
069: protected Codec codec;
070:
071: // for identifying client or server.
072: protected DynAnyFactory dynAnyFactoryS_;
073:
074: // Service context identifier
075: protected final int TX_CTX_ID = org.omg.IOP.TransactionService.value; //100;
076:
077: // ORB instance
078: protected static ORB orb = null;
079:
080: /**
081: * constructor
082: */
083:
084: public OTSInterceptor(ORBInitInfo info) {
085:
086: // Get the codec factory
087: org.omg.IOP.CodecFactory factory = info.codec_factory();
088: if (factory == null)
089: throw new RuntimeException();
090:
091: // Create codec
092: org.omg.IOP.Encoding how = new org.omg.IOP.Encoding();
093: how.major_version = 1;
094: how.minor_version = 0;
095: how.format = org.omg.IOP.ENCODING_CDR_ENCAPS.value;
096:
097: try {
098: codec = factory.create_codec(how);
099: } catch (org.omg.IOP.CodecFactoryPackage.UnknownEncoding ex) {
100: throw new RuntimeException();
101: }
102:
103: if (codec == null)
104: throw new RuntimeException();
105:
106: //
107: // Get the dynamic any factory
108: //
109: DynAnyFactory dynAnyFactory = null;
110: try {
111: org.omg.CORBA.Object obj = info
112: .resolve_initial_references("DynAnyFactory");
113: dynAnyFactory = DynAnyFactoryHelper.narrow(obj);
114: } catch (InvalidName ex) {
115: throw new RuntimeException();
116: } catch (org.omg.CORBA.BAD_PARAM ex) {
117: throw new RuntimeException();
118: }
119:
120: dynAnyFactoryS_ = dynAnyFactory;
121:
122: } // end constructor
123:
124: protected Any create_any()
125: throws org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode {
126: org.omg.DynamicAny.DynAny dynAny = dynAnyFactoryS_
127: .create_dyn_any_from_type_code(PropagationContextHelper
128: .type());
129: return dynAny.to_any();
130: }
131:
132: /**
133: * Build and returns the CORBA PropagationContext (JTS)
134: */
135: protected ServiceContext buildCorbaPropagationContext(
136: TransactionContext txCtx) throws ForwardRequest {
137: try {
138:
139: // Build a new CORBA Propagation context
140: // For the moment, JOTM does not implement tx interoperability EJB2.1 ?19.6 and
141: // so the fields CosTransactions:Coordinator and CosTransactions:Terminator are set
142: // to null in order to generate a 'null transaction ctx'
143: // The coordinator/terminator are propagated in the 'implementation_specific_data' field.
144:
145: // Get Information of TransactionContext
146: Xid xid = txCtx.getXid();
147: int timeout = txCtx.getTimeout();
148: Coordinator coord = txCtx.getCoordinator();
149:
150: // Xid is coded in the otid_t
151: byte[] gtrid = xid.getGlobalTransactionId();
152: byte[] bqual = xid.getBranchQualifier();
153: byte[] tid = new byte[gtrid.length + bqual.length];
154: System.arraycopy(bqual, 0, tid, 0, bqual.length);
155: System.arraycopy(gtrid, 0, tid, bqual.length, gtrid.length);
156: otid_t otid = new otid_t(xid.getFormatId(), bqual.length,
157: tid);
158:
159: // current holds only otid_t
160: TransIdentity curr = new TransIdentity(null, null, otid);
161:
162: // Create the PropagationContext
163: PropagationContext pctx = new PropagationContext(timeout,
164: curr, new TransIdentity[0], null);
165:
166: // In JOTM, the Coordinator and the terminator interface are implemented
167: // by the same class : ControlImpl. The stub is propagated to others JOnAS
168: // instances in the implementation_specific_data field. It is coded in an Any
169: // field
170: if (orb == null) {
171: // Get ORB instance
172: orb = ORB.init(new String[] {}, null);
173: }
174:
175: Any specific = orb.create_any();
176: if (coord != null) {
177: // Set the JOTM's coordinator in the 'specific' field
178: specific
179: .insert_Object((javax.rmi.CORBA.Stub) PortableRemoteObject
180: .toStub(coord));
181: pctx.implementation_specific_data = specific;
182: } else {
183: // If the coordinator is unknown, set a 'JONAS' pattern
184: // to allow the other side to recognize a
185: // JOTM context
186: specific.insert_string("JOnAS");
187: pctx.implementation_specific_data = specific;
188: }
189:
190: Any pAny = create_any();
191: PropagationContextHelper.insert(pAny, pctx);
192:
193: // encode the PropagationContext in a service context
194: byte[] propagationContextData = codec.encode_value(pAny);
195: return new ServiceContext(TX_CTX_ID, propagationContextData);
196:
197: } catch (Exception e) {
198: throw new ForwardRequest();
199: }
200: }
201:
202: /**
203: * decode the Corba Propagation Context and build an internal transaction context
204: * @param sCtx ServiceContext
205: */
206: protected TransactionContext decodeCorbaPropagationContext(
207: ServiceContext sCtx) {
208:
209: if (sCtx == null) { // no tx ctx
210:
211: return null;
212: }
213: Xid xid = null;
214: int timeout;
215: Any specific = null;
216:
217: // try to decode the corba tx context
218: try {
219: // unmarshall the Propagation Context
220: Any pctxAny = codec.decode_value(sCtx.context_data,
221: PropagationContextHelper.type());
222: PropagationContext pctx = PropagationContextHelper
223: .extract(pctxAny);
224:
225: // get the propagation context values
226: specific = pctx.implementation_specific_data;
227: otid_t otid = pctx.current.otid;
228: timeout = pctx.timeout;
229: xid = new XidImpl(otid.formatID, otid.bqual_length,
230: otid.tid);
231:
232: } catch (Exception e) { // invalid tx ctx
233:
234: return null;
235: }
236:
237: // JOTM don't be able to detect whether the context is a valid or a null ctx
238: // If it isn't a JOTM's context (fail during decoding), it considers it's a null ctx
239: boolean isJotmCtx = false;
240: Coordinator coord = null;
241: Terminator term = null;
242:
243: try {
244: if ((specific == null)
245: || (specific.type().kind() == TCKind.tk_null)
246: || (specific.type().kind() == TCKind.tk_octet)) {
247: // null ctx or valid ctx but sent from another app server
248: // isJotmCtx=false ;
249: } else if (specific.type().kind() == TCKind.tk_string) {
250: String pattern = specific.extract_string();
251: // Here, maybe we have received a JOTM context with an unknown coordinator
252: // In this case, a JONAS pattern has been set
253: if (pattern.compareTo("JOnAS") == 0) {
254: isJotmCtx = true;
255: }
256:
257: } else {
258: // Last try, it should be a typical JOTM context with the coordinator set in 'specific' field
259: coord = (Coordinator) PortableRemoteObject.narrow(
260: (java.rmi.Remote) specific.extract_Object(),
261: Coordinator.class);
262: term = (Terminator) PortableRemoteObject.narrow(
263: (java.rmi.Remote) specific.extract_Object(),
264: Terminator.class);
265: isJotmCtx = true;
266:
267: }
268: } catch (Exception e) {
269: // null ctx or valid ctx but sent from another app server
270: // isJotmCtx=false ;
271: }
272:
273: TransactionContext tCtx = new InternalTransactionContext(
274: timeout, coord, term, xid);
275: if (isJotmCtx == false) {
276: // flag the internal context to indicate the ctx comes from
277: // another vendor
278: tCtx.setNotJotmCtx();
279: }
280: return tCtx;
281: }
282: }
|