001: /*
002: * JacORB - a free Java ORB
003: *
004: * Copyright (C) 1999-2004 Gerald Brose
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Library General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Library General Public License for more details.
015: *
016: * You should have received a copy of the GNU Library General Public
017: * License along with this library; if not, write to the Free
018: * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
019: *
020: */
021:
022: package org.jacorb.orb.etf;
023:
024: import org.apache.avalon.framework.configuration.*;
025:
026: import org.jacorb.orb.CDROutputStream;
027: import org.jacorb.orb.CDRInputStream;
028: import org.jacorb.orb.TaggedComponentList;
029:
030: import org.omg.CORBA.BAD_PARAM;
031: import org.omg.CORBA.MARSHAL;
032: import org.omg.ETF.*;
033: import org.omg.IOP.*;
034:
035: /**
036: * @author Andre Spiegel
037: * @version $Id: ProfileBase.java,v 1.6 2007/02/14 09:07:23 andre.spiegel Exp $
038: */
039: public abstract class ProfileBase extends _ProfileLocalBase implements
040: Cloneable, Configurable {
041: protected org.omg.GIOP.Version version = null;
042: protected byte[] objectKey = null;
043: protected TaggedComponentList components = null;
044:
045: protected org.jacorb.config.Configuration configuration;
046: protected String corbalocStr = null;
047:
048: /**
049: * ETF defined operation to set the object key on this profile.
050: */
051: public void set_object_key(byte[] key) {
052: this .objectKey = key;
053: }
054:
055: /**
056: * ETF defined operation to get the object key from this profile.
057: */
058: public byte[] get_object_key() {
059: return objectKey;
060: }
061:
062: /**
063: * ETF defined read-only accessor for the GIOP version.
064: */
065: public org.omg.GIOP.Version version() {
066: return version;
067: }
068:
069: /**
070: * ETF defined read-only accessor for the GIOP tag.
071: */
072: public abstract int tag();
073:
074: /**
075: * Profiles use this method for taking alternative address values
076: * for replacement, such as when an IOR proxy or IMR is in use.
077: * This is a concrete method here to not break existing profiles
078: * that may not be interested in this behavior.
079: */
080: public void patchPrimaryAddress(ProtocolAddressBase replacement) {
081: // nothing to do
082: }
083:
084: /**
085: * ETF defined function to marshal the appropriate information for this
086: * transport into the tagged profile. ORBs will typically need
087: * to call the IOR interception points before calling marshal().
088: * <p>
089: * This particular implementation *should* work for any IOP
090: * type protocol that encodes its profile_data as a CDR encapsulated
091: * octet array as long as you have correctly implemented
092: * the {@link #encapsulation()}, {@link #writeAddressProfile(CDROutputStream)}, and
093: * {@link #readAddressProfile(CDRInputStream)} methods. But, feel free to override
094: * it for the purpose of optimisation or whatever. It should however,
095: * remain consistent with your implementation
096: * of the above mentioned methods.
097: */
098: public void marshal(final TaggedProfileHolder tagged_profile,
099: final TaggedComponentSeqHolder componentSequence) {
100: TaggedComponentSeqHolder compSeq = componentSequence;
101:
102: if (encapsulation() != 0) {
103: // You're going to have to define your own marshal operation
104: // for littleEndian profiles.
105: // The CDROutputStream only does big endian currently.
106: throw new BAD_PARAM(
107: "We can only marshal big endian stylee profiles !!");
108: }
109:
110: // Start a CDR encapsulation for the profile_data
111: CDROutputStream profileDataStream = new CDROutputStream();
112: try {
113: profileDataStream.beginEncapsulatedArray();
114:
115: // Write the opaque AddressProfile bytes for this profile...
116: writeAddressProfile(profileDataStream);
117:
118: // ... then the object key
119: profileDataStream.write_long(objectKey.length);
120: profileDataStream.write_octet_array(objectKey, 0,
121: objectKey.length);
122:
123: switch (version.minor) {
124: case 0:
125: // For GIOP 1.0 there were no tagged components
126: break;
127: default:
128: // Assume minor != 0 means 1.1 onwards and encode the TaggedComponents
129: if (compSeq == null) {
130: compSeq = new TaggedComponentSeqHolder(
131: new TaggedComponent[0]);
132: }
133: // Write the length of the TaggedProfile sequence.
134: profileDataStream.write_long(this .components.size()
135: + compSeq.value.length);
136:
137: // Write the TaggedProfiles (ours first, then the ORB's)
138: for (int i = 0; i < this .components.asArray().length; i++) {
139: TaggedComponentHelper.write(profileDataStream,
140: this .components.asArray()[i]);
141: }
142: for (int i = 0; i < compSeq.value.length; i++) {
143: TaggedComponentHelper.write(profileDataStream,
144: compSeq.value[i]);
145: }
146: }
147:
148: // Populate the TaggedProfile for return.
149: tagged_profile.value = new TaggedProfile(this .tag(),
150: profileDataStream.getBufferCopy());
151: } finally {
152: profileDataStream.close();
153: }
154: }
155:
156: /**
157: * Method to mirror the marshal method.
158: */
159: public void demarshal(TaggedProfileHolder tagged_profile,
160: TaggedComponentSeqHolder components) {
161: if (tagged_profile.value.tag != this .tag()) {
162: throw new org.omg.CORBA.BAD_PARAM(
163: "Wrong tag for Transport, tag: "
164: + tagged_profile.value.tag);
165: }
166: initFromProfileData(tagged_profile.value.profile_data);
167: components.value = getComponents().asArray();
168: }
169:
170: /**
171: * Indicates the encapsulation that will be used by this profile
172: * when encoding its AddressProfile bytes, and which should subsequently
173: * be used when marshalling all the rest of the TaggedProfile.profile_data.
174: * Using the default CDROutputStream for a transport profile encapsulation
175: * this should always be 0.
176: */
177: public short encapsulation() {
178: return 0; // i.e. Big endian TAG_INTERNET_IOP style
179: }
180:
181: /**
182: * Write the AddressProfile to the supplied stream.
183: * Implementors can assume an encapsulation is already open.
184: */
185: public abstract void writeAddressProfile(CDROutputStream stream);
186:
187: /**
188: * Read the ETF::AddressProfile from the supplied stream.
189: */
190: public abstract void readAddressProfile(CDRInputStream stream);
191:
192: /**
193: * Accessor for the TaggedComponents of the Profile.
194: */
195: public TaggedComponentList getComponents() {
196: return components;
197: }
198:
199: public Object getComponent(int tag, Class helper) {
200: return components.getComponent(tag, helper);
201: }
202:
203: public void addComponent(int tag, Object data, Class helper) {
204: components.addComponent(tag, data, helper);
205: }
206:
207: public void addComponent(int tag, byte[] data) {
208: components.addComponent(tag, data);
209: }
210:
211: public TaggedProfile asTaggedProfile() {
212: TaggedProfileHolder result = new TaggedProfileHolder();
213: this .marshal(result, null);
214: return result.value;
215: }
216:
217: /**
218: * This function shall return an equivalent, deep-copy of the profile
219: * on the free store.
220: */
221: public Profile copy() {
222: try {
223: return (Profile) this .clone();
224: } catch (CloneNotSupportedException e) {
225: throw new RuntimeException("error cloning profile: " + e); // NOPMD
226: }
227: }
228:
229: /**
230: * Used from the byte[] constructor and the demarshal method. Relies
231: * on subclasses having satisfactorily implemented the
232: * {@link #readAddressProfile(CDRInputStream)} method.
233: */
234: protected void initFromProfileData(byte[] data) {
235: final CDRInputStream in = new CDRInputStream(null, data);
236:
237: try {
238: in.openEncapsulatedArray();
239:
240: readAddressProfile(in);
241:
242: int length = in.read_ulong();
243:
244: if (in.available() < length) {
245: throw new MARSHAL("Unable to extract object key. Only "
246: + in.available()
247: + " available and trying to assign " + length);
248: }
249:
250: objectKey = new byte[length];
251: in.read_octet_array(objectKey, 0, length);
252:
253: components = (version != null && version.minor > 0) ? new TaggedComponentList(
254: in)
255: : new TaggedComponentList();
256: } finally {
257: in.close();
258: }
259: }
260: }
|