1/* 2 * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25/* 26 * Licensed Materials - Property of IBM 27 * RMI-IIOP v1.0 28 * Copyright IBM Corp. 1998 1999 All Rights Reserved 29 * 30 */ 31 32package com.sun.corba.se.impl.ior; 33 34import java.io.ObjectInputStream ; 35import java.io.ObjectOutputStream ; 36import java.io.IOException ; 37import java.io.StringWriter ; 38 39import org.omg.CORBA.ORB ; 40 41import org.omg.CORBA.portable.Delegate ; 42import org.omg.CORBA.portable.InputStream ; 43import org.omg.CORBA.portable.OutputStream ; 44 45// Be very careful: com.sun.corba imports must not depend on 46// PEORB internal classes in ways that prevent portability to 47// other vendor's ORBs. 48import com.sun.corba.se.spi.presentation.rmi.StubAdapter ; 49import com.sun.corba.se.impl.orbutil.HexOutputStream ; 50 51/** 52 * This class implements a very simply IOR representation 53 * which must be completely ORBImpl free so that this class 54 * can be used in the implementation of a portable StubDelegateImpl. 55 */ 56public class StubIORImpl 57{ 58 // cached hash code 59 private int hashCode; 60 61 // IOR components 62 private byte[] typeData; 63 private int[] profileTags; 64 private byte[][] profileData; 65 66 public StubIORImpl() 67 { 68 hashCode = 0 ; 69 typeData = null ; 70 profileTags = null ; 71 profileData = null ; 72 } 73 74 public String getRepositoryId() 75 { 76 if (typeData == null) 77 return null ; 78 79 return new String( typeData ) ; 80 } 81 82 public StubIORImpl( org.omg.CORBA.Object obj ) 83 { 84 // write the IOR to an OutputStream and get an InputStream 85 OutputStream ostr = StubAdapter.getORB( obj ).create_output_stream(); 86 ostr.write_Object(obj); 87 InputStream istr = ostr.create_input_stream(); 88 89 // read the IOR components back from the stream 90 int typeLength = istr.read_long(); 91 typeData = new byte[typeLength]; 92 istr.read_octet_array(typeData, 0, typeLength); 93 int numProfiles = istr.read_long(); 94 profileTags = new int[numProfiles]; 95 profileData = new byte[numProfiles][]; 96 for (int i = 0; i < numProfiles; i++) { 97 profileTags[i] = istr.read_long(); 98 profileData[i] = new byte[istr.read_long()]; 99 istr.read_octet_array(profileData[i], 0, profileData[i].length); 100 } 101 } 102 103 public Delegate getDelegate( ORB orb ) 104 { 105 // write the IOR components to an org.omg.CORBA.portable.OutputStream 106 OutputStream ostr = orb.create_output_stream(); 107 ostr.write_long(typeData.length); 108 ostr.write_octet_array(typeData, 0, typeData.length); 109 ostr.write_long(profileTags.length); 110 for (int i = 0; i < profileTags.length; i++) { 111 ostr.write_long(profileTags[i]); 112 ostr.write_long(profileData[i].length); 113 ostr.write_octet_array(profileData[i], 0, profileData[i].length); 114 } 115 116 InputStream istr = ostr.create_input_stream() ; 117 118 // read the IOR back from the stream 119 org.omg.CORBA.Object obj = (org.omg.CORBA.Object)istr.read_Object(); 120 return StubAdapter.getDelegate( obj ) ; 121 } 122 123 public void doRead( java.io.ObjectInputStream stream ) 124 throws IOException, ClassNotFoundException 125 { 126 // read the IOR from the ObjectInputStream 127 int typeLength = stream.readInt(); 128 typeData = new byte[typeLength]; 129 stream.readFully(typeData); 130 int numProfiles = stream.readInt(); 131 profileTags = new int[numProfiles]; 132 profileData = new byte[numProfiles][]; 133 for (int i = 0; i < numProfiles; i++) { 134 profileTags[i] = stream.readInt(); 135 profileData[i] = new byte[stream.readInt()]; 136 stream.readFully(profileData[i]); 137 } 138 } 139 140 public void doWrite( ObjectOutputStream stream ) 141 throws IOException 142 { 143 // write the IOR to the ObjectOutputStream 144 stream.writeInt(typeData.length); 145 stream.write(typeData); 146 stream.writeInt(profileTags.length); 147 for (int i = 0; i < profileTags.length; i++) { 148 stream.writeInt(profileTags[i]); 149 stream.writeInt(profileData[i].length); 150 stream.write(profileData[i]); 151 } 152 } 153 154 /** 155 * Returns a hash code value for the object which is the same for all stubs 156 * that represent the same remote object. 157 * @return the hash code value. 158 */ 159 public synchronized int hashCode() 160 { 161 if (hashCode == 0) { 162 163 // compute the hash code 164 for (int i = 0; i < typeData.length; i++) { 165 hashCode = hashCode * 37 + typeData[i]; 166 } 167 168 for (int i = 0; i < profileTags.length; i++) { 169 hashCode = hashCode * 37 + profileTags[i]; 170 for (int j = 0; j < profileData[i].length; j++) { 171 hashCode = hashCode * 37 + profileData[i][j]; 172 } 173 } 174 } 175 176 return hashCode; 177 } 178 179 private boolean equalArrays( int[] data1, int[] data2 ) 180 { 181 if (data1.length != data2.length) 182 return false ; 183 184 for (int ctr=0; ctr<data1.length; ctr++) { 185 if (data1[ctr] != data2[ctr]) 186 return false ; 187 } 188 189 return true ; 190 } 191 192 private boolean equalArrays( byte[] data1, byte[] data2 ) 193 { 194 if (data1.length != data2.length) 195 return false ; 196 197 for (int ctr=0; ctr<data1.length; ctr++) { 198 if (data1[ctr] != data2[ctr]) 199 return false ; 200 } 201 202 return true ; 203 } 204 205 private boolean equalArrays( byte[][] data1, byte[][] data2 ) 206 { 207 if (data1.length != data2.length) 208 return false ; 209 210 for (int ctr=0; ctr<data1.length; ctr++) { 211 if (!equalArrays( data1[ctr], data2[ctr] )) 212 return false ; 213 } 214 215 return true ; 216 } 217 218 public boolean equals(java.lang.Object obj) 219 { 220 if (this == obj) { 221 return true; 222 } 223 224 if (!(obj instanceof StubIORImpl)) { 225 return false; 226 } 227 228 StubIORImpl other = (StubIORImpl) obj; 229 if (other.hashCode() != this.hashCode()) { 230 return false; 231 } 232 233 return equalArrays( typeData, other.typeData ) && 234 equalArrays( profileTags, other.profileTags ) && 235 equalArrays( profileData, other.profileData ) ; 236 } 237 238 private void appendByteArray( StringBuffer result, byte[] data ) 239 { 240 for ( int ctr=0; ctr<data.length; ctr++ ) { 241 result.append( Integer.toHexString( data[ctr] ) ) ; 242 } 243 } 244 245 /** 246 * Returns a string representation of this stub. Returns the same string 247 * for all stubs that represent the same remote object. 248 * {@code "SimpleIORImpl[<typeName>,[<profileID>]data, ...]"} 249 * @return a string representation of this stub. 250 */ 251 public String toString() 252 { 253 StringBuffer result = new StringBuffer() ; 254 result.append( "SimpleIORImpl[" ) ; 255 String repositoryId = new String( typeData ) ; 256 result.append( repositoryId ) ; 257 for (int ctr=0; ctr<profileTags.length; ctr++) { 258 result.append( ",(" ) ; 259 result.append( profileTags[ctr] ) ; 260 result.append( ")" ) ; 261 appendByteArray( result, profileData[ctr] ) ; 262 } 263 264 result.append( "]" ) ; 265 return result.toString() ; 266 } 267} 268