1 /* PersistentMap.java -- The persistent object naming map
2 Copyright (C) 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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)
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.
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
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
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. */
39 package gnu
.classpath
.tools
.orbd
;
41 import gnu
.CORBA
.NamingService
.NamingMap
;
43 import java
.io
.BufferedOutputStream
;
44 import java
.io
.BufferedReader
;
46 import java
.io
.FileInputStream
;
47 import java
.io
.FileOutputStream
;
48 import java
.io
.IOException
;
49 import java
.io
.InputStreamReader
;
50 import java
.io
.OutputStream
;
51 import java
.util
.Iterator
;
54 import org
.omg
.CORBA
.ORB
;
55 import org
.omg
.CosNaming
.NameComponent
;
56 import org
.omg
.CosNaming
.NamingContextPackage
.AlreadyBound
;
57 import org
.omg
.CosNaming
.NamingContextPackage
.InvalidName
;
60 * The persistent object naming map for the persistent naming service. The
61 * inherited (super.) naming map implementation is transient and is used as a
62 * cache. During the normal work, the naming map does not read from the disk,
63 * just stores the changes there. Map only reads from the disk when it starts.
65 * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
67 public class PersistentMap
73 public static class Entry
82 * Get the name component node.
84 public NameComponent
getComponent()
86 return new NameComponent(id
, kind
);
90 * Write the naming map entry to the output stream.
92 public void write(OutputStream out
) throws IOException
94 // Format: id.kind <eoln> ior <eoln><eoln>
95 out
.write(getKey(id
, kind
).getBytes());
97 out
.write(ior
.getBytes());
103 * Read the name component from the input stream
105 public boolean read(BufferedReader in
) throws IOException
107 String key
= in
.readLine();
108 String xior
= in
.readLine();
110 if (key
!= null && xior
!= null)
112 if (key
.length() < 2)
114 // A single char key cannot have the kind part.
120 // Search for the id/kind splitter, dot:
122 for (int i
= 1; i
< key
.length(); i
++)
124 if (key
.charAt(i
) == '.')
125 // The id is separated from kind by dot, unless preceeded by
127 // escape character, \.
128 if (key
.charAt(i
- 1) != '\\')
135 // May also end by dot, if the kind field is missing.
141 else if (iks
== key
.length() - 1)
143 id
= key
.substring(0, key
.length() - 1);
148 id
= key
.substring(0, iks
);
149 kind
= key
.substring(iks
+ 1);
160 * Get the key value from the name component.
162 * @param id the component id
163 * @param kind the component kind
164 * @return the key value
166 public String
getKey(String id
, String kind
)
168 StringBuilder b
= new StringBuilder(id
.length() + 8);
171 if (kind
!= null && kind
.length() > 0)
172 appEscaping(b
, kind
);
177 * Append the contents of the string to this string buffer, inserting the
178 * escape sequences, where required.
180 * @param b a buffer to append the contents to.
181 * @param s a string to append.
183 void appEscaping(StringBuilder b
, String s
)
186 for (int i
= 0; i
< s
.length(); i
++)
207 * The file, where the persistent naming map stores the information. The
208 * format of this file is n*(id LF kind LF ior LFLF).
210 public final File file
;
213 * The naming service ORB, used to obtain and produce the object stringified
219 * If true, all existing data on the file system are discarded.
224 * Create the persistent map that stores information in the given file.
226 * @param an_orb the naming service ORB, used to obtain and produce the object
227 * stringified references.
228 * @param mapFile the file, where the persistent information is stored.
229 * @param a_reset if true, the previous naming data are discarded. If false
230 * (normally expected), they are loaded from the persistent memory to
231 * provide the persistence.
233 public PersistentMap(ORB an_orb
, File mapFile
, boolean a_reset
)
240 // Initialise the persistent map with existing data.
241 if (file
.exists() && ! reset
)
247 FileInputStream fin
= new FileInputStream(file
);
248 in
= new BufferedReader(new InputStreamReader(fin
));
249 Entry e
= new Entry();
254 org
.omg
.CORBA
.Object object
= string_to_object(e
.ior
);
256 map
.put(e
.getComponent(), object
);
261 InternalError ierr
= new InternalError(file
.getAbsolutePath());
269 * Restore object from its string description.
271 * @param description the string, describing the object
273 * @return the object.
275 protected org
.omg
.CORBA
.Object
string_to_object(String description
)
277 return orb
.string_to_object(description
);
281 * Convert the object to its string description
283 * @param object the object to convert
284 * @return the string description of the object
286 protected String
object_to_string(org
.omg
.CORBA
.Object object
)
288 return orb
.object_to_string(object
);
292 * Put the given GIOP object, specifying the given name as a key. If the entry
293 * with the given name already exists, or if the given object is already
294 * mapped under another name, the {@link AlreadyBound} exception will be
297 * @param name the name
298 * @param object the object
300 public void bind(NameComponent name
, org
.omg
.CORBA
.Object object
)
301 throws AlreadyBound
, InvalidName
303 if (!containsKey(name
))
305 super.bind(name
, object
);
306 register(name
, object
);
309 throw new AlreadyBound(name
.id
+ "." + name
.kind
);
313 * Put the given CORBA object, specifying the given name as a key. Remove all
314 * pre - existing mappings for the given name and object.
316 * @param name the name.
317 * @param object the object
319 public void rebind(NameComponent name
, org
.omg
.CORBA
.Object object
)
322 if (containsKey(name
))
324 org
.omg
.CORBA
.Object existing
= get(name
);
325 String ior
= object_to_string(object
);
326 String xior
= object_to_string(existing
);
328 // Same name and same ior - nothing to do.
329 if (ior
.equals(xior
))
335 Iterator iter
= entries().iterator();
338 // Remove the existing mapping for the given object, if present.
339 while (iter
.hasNext())
341 item
= (Map
.Entry
) iter
.next();
342 if (item
.getValue().equals(object
))
346 map
.put(name
, object
);
347 register(name
, object
);
351 * Removes the given name, if present.
353 * @param name a name to remove.
355 public void remove(NameComponent name
)
362 * Register this name - object pair in the persistent storage.
364 * @param name the name.
365 * @param object the object
367 public void register(NameComponent name
, org
.omg
.CORBA
.Object object
)
369 // If this key is already known, and this is the same object,
370 // then return without action.
371 String ior
= object_to_string(object
);
377 FileOutputStream fou
;
380 fou
= new FileOutputStream(file
);
382 fou
= new FileOutputStream(file
, true);
384 Entry e
= new Entry();
393 InternalError ierr
= new InternalError(file
.getAbsolutePath());
401 * Remove this name from the persistent storage.
403 * @param name the name to remove
405 public void unregister(NameComponent name
)
411 File nf
= new File(file
.getParent(), file
.getName() + "_t");
412 FileInputStream fin
= new FileInputStream(file
);
413 FileOutputStream fou
= new FileOutputStream(nf
);
414 BufferedOutputStream ou
= new BufferedOutputStream(fou
);
416 BufferedReader in
= new BufferedReader(new InputStreamReader(fin
));
418 String nk
= name
.kind
;
422 Entry e
= new Entry();
426 if (e
.id
.equals(name
.id
) && e
.kind
.equals(nk
))
428 // Do nothing - skip.
436 File deleteIt
= new File(file
.getParent(), file
.getName() + "_d");
437 if (deleteIt
.exists())
440 if (! file
.renameTo(deleteIt
))
441 throw new IOException(file
.getAbsolutePath() + " rename failed");
443 if (! nf
.renameTo(file
))
444 throw new IOException(file
.getAbsolutePath() + " rename failed");
448 InternalError ierr
= new InternalError(file
.getAbsolutePath());