1 /* gnuRuntime.java -- 2 Copyright (C) 2005 Free Software Foundation, Inc. 3 4 This file is part of GNU Classpath. 5 6 GNU Classpath is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GNU Classpath is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU Classpath; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301 USA. 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 38 39 package gnu.CORBA.CDR; 40 41 import gnu.CORBA.Minor; 42 43 import gnu.java.lang.CPStringBuilder; 44 45 import org.omg.CORBA.LocalObject; 46 import org.omg.CORBA.MARSHAL; 47 48 import java.io.Serializable; 49 import java.util.Comparator; 50 import java.util.HashMap; 51 import java.util.IdentityHashMap; 52 import java.util.Iterator; 53 import java.util.Map; 54 import java.util.TreeMap; 55 import java.util.TreeSet; 56 57 /** 58 * Our implementation of the sending context runtime. 59 * 60 * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) 61 */ 62 public class gnuRuntime 63 extends LocalObject 64 implements org.omg.SendingContext.RunTime 65 { 66 /** 67 * The data entry about the object that was written. 68 */ 69 static class Entry 70 { 71 /** 72 * The stream position, where the object was written. 73 */ 74 int at; 75 76 /** 77 * The object that was written. 78 */ 79 Object object; 80 toString()81 public String toString() 82 { 83 return object + "[" + at + "] "+object.getClass().getName(); 84 } 85 } 86 87 /** 88 * The instruction that the actual object is stored at different location. 89 * Used when processing chunked data where positions shifts due removing the 90 * chunking tags. 91 */ 92 static class Redirection 93 extends Entry 94 { toString()95 public String toString() 96 { 97 return "->" + at; 98 } 99 } 100 101 /** 102 * Use serialVersionUID for interoperability. 103 */ 104 private static final long serialVersionUID = 1; 105 106 /** 107 * The history of the written objects, maps object to records. The different 108 * objects must be treated as different regardless that .equals returns. 109 */ 110 private Map sh_objects = new IdentityHashMap(); 111 112 /** 113 * The written repository Ids that can be shared. 114 */ 115 private Map sh_ids = new TreeMap(new Comparator() 116 { 117 public int compare(Object a, Object b) 118 { 119 if (a instanceof String && b instanceof String) 120 // Comparing string with string. 121 return ((String) a).compareTo((String) b); 122 else if (a instanceof String[] && b instanceof String[]) 123 { 124 // Comparing array with array. 125 String[] sa = (String[]) a; 126 String[] sb = (String[]) b; 127 128 if (sa.length != sb.length) 129 return sa.length - sb.length; 130 else 131 { 132 int c; 133 for (int i = 0; i < sa.length; i++) 134 { 135 c = sa[i].compareTo(sb[i]); 136 if (c != 0) 137 return c; 138 } 139 return 0; 140 } 141 } 142 else 143 // Comparing string with array. 144 return a instanceof String ? 1 : -1; 145 } 146 }); 147 148 /** 149 * The history of the written objects, maps positions to records. The 150 * different objects must be treated as different regardless that .equals 151 * returns. 152 */ 153 private Map positions = new HashMap(); 154 155 /** 156 * The Codebase. 157 */ 158 private String codebase; 159 160 /** 161 * The pre-created instance of the object being written (avoid 162 * re-instantiation). 163 */ 164 public Serializable target; 165 166 /** 167 * Create Runtime. 168 * 169 * @param a_id a repository Id, if only one Id was specified in the stream. 170 * @param a_ids a repository Ids, if the multiple Ids were specified in te 171 * stream. 172 * @param a_codebase a codebase, if it was specified in the stream. 173 */ gnuRuntime(String a_codebase, Object a_target)174 public gnuRuntime(String a_codebase, Object a_target) 175 { 176 if (a_target instanceof Serializable) 177 target = (Serializable) a_target; 178 179 codebase = a_codebase; 180 } 181 182 /** 183 * Mark the given object as written at the given position. 184 */ objectWritten(Object object, int at)185 public void objectWritten(Object object, int at) 186 { 187 if (object == null || at < 0) 188 return; // No positional information provided. 189 if (sh_objects.containsKey(object)) 190 throw new AssertionError("Repetetive writing of the same object " 191 + object + " at " + at + dump()); 192 193 Entry e = new Entry(); 194 e.at = at; 195 e.object = object; 196 197 sh_objects.put(object, e); 198 positions.put(new Integer(at), e); 199 } 200 201 /** 202 * Check if the object is already written. 203 * 204 * @return the position, at that the object is allready written or -1 if it is 205 * not yet written. 206 */ isWrittenAt(Object x)207 public int isWrittenAt(Object x) 208 { 209 Entry e = (Entry) sh_objects.get(x); 210 return e == null ? -1 : e.at; 211 } 212 213 /** 214 * Set redirection, indicating that the object, searched at the p_searched 215 * position can be actually found at the p_present position. 216 */ redirect(int p_searched, int p_present)217 public void redirect(int p_searched, int p_present) 218 { 219 Redirection redirection = new Redirection(); 220 redirection.at = p_present; 221 positions.put(new Integer(p_searched), redirection); 222 } 223 224 /** 225 * Get the object, written at the given position. This returs both shared 226 * objects and repository Ids. 227 * 228 * @return the position, at that the object is allready written. 229 * 230 * @throws MARSHAL if there is no object written at that position. 231 */ isObjectWrittenAt(int x, int offset)232 public Object isObjectWrittenAt(int x, int offset) 233 { 234 Entry e = (Entry) positions.get(new Integer(x)); 235 if (e instanceof Redirection) 236 return isObjectWrittenAt(e.at, offset); 237 else if (e != null) 238 return e.object; 239 else 240 { 241 MARSHAL m = new MARSHAL("No object was written at " + x + 242 " (offset " + offset + ") r " + this + dump()); 243 m.minor = Minor.Graph; 244 throw m; 245 } 246 } 247 248 /** 249 * Mark the given object as written at the given position. 250 */ singleIdWritten(String id, int at)251 public void singleIdWritten(String id, int at) 252 { 253 if (sh_ids.containsKey(id)) 254 throw new InternalError("Repetetive writing of the same string " + 255 id + dump()); 256 257 Entry e = new Entry(); 258 e.at = at; 259 e.object = id; 260 261 sh_ids.put(id, e); 262 positions.put(new Integer(at), e); 263 } 264 265 /** 266 * Mark the given object as written at the given position. 267 */ multipleIdsWritten(String[] ids, int at)268 public void multipleIdsWritten(String[] ids, int at) 269 { 270 if (sh_ids.containsKey(ids)) 271 throw new InternalError("Repetetive writing of the same string " + 272 ids + dump()); 273 274 Entry e = new Entry(); 275 e.at = at; 276 e.object = ids; 277 278 sh_ids.put(ids, e); 279 positions.put(new Integer(at), e); 280 } 281 282 /** 283 * Check if the object is already written. 284 * 285 * @return the position, at that the object is allready written or -1 if it is 286 * not yet written. 287 */ idWrittenAt(Object x)288 public int idWrittenAt(Object x) 289 { 290 Entry e = (Entry) sh_ids.get(x); 291 return e == null ? -1 : e.at; 292 } 293 294 /** 295 * Get the codebase. 296 */ getCodeBase()297 public String getCodeBase() 298 { 299 return codebase; 300 } 301 302 /** 303 * Set the codebase, preserving the old value if the passed parameter is null 304 * and forming the space delimited list if both new and old values are not 305 * null. 306 */ addCodeBase(String base)307 public void addCodeBase(String base) 308 { 309 if (base != null) 310 { 311 if (codebase == null) 312 codebase = base; 313 else 314 codebase = codebase + " " + base; 315 } 316 } 317 318 /** 319 * Dump all objects that are currently stored. 320 */ dump()321 public String dump() 322 { 323 CPStringBuilder b = new CPStringBuilder(" Stream content: \n"); 324 325 // Sort by position. 326 TreeSet t = new TreeSet(positions.keySet()); 327 Iterator p = t.iterator(); 328 329 while (p.hasNext()) 330 { 331 Object k = p.next(); 332 b.append(" " + k + ": " + ((Entry) positions.get(k)).toString() 333 + "\n"); 334 } 335 return b.toString(); 336 } 337 338 } 339