1 /* Copyright (C) 2004, 2005 Free Software Foundation
3 This file is part of libgcj.
5 This software is copyrighted work licensed under the terms of the
6 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 package gnu
.gcj
.tools
.gcj_dbtool
;
12 import gnu
.gcj
.runtime
.PersistentByteMap
;
14 import java
.nio
.channels
.*;
16 import java
.util
.jar
.*;
17 import java
.security
.MessageDigest
;
21 static private boolean verbose
= false;
23 public static void main (String
[] s
)
25 insist (s
.length
>= 1);
26 if (s
[0].equals("-v") || s
[0].equals("--version"))
28 insist (s
.length
== 1);
29 System
.out
.println("gcj-dbtool ("
30 + System
.getProperty("java.vm.name")
32 + System
.getProperty("java.vm.version"));
34 System
.out
.println("Copyright 2005 Free Software Foundation, Inc.");
35 System
.out
.println("This is free software; see the source for copying conditions. There is NO");
36 System
.out
.println("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
39 if (s
[0].equals("--help"))
45 if (s
[0].equals("-n"))
47 // Create a new database.
48 insist (s
.length
>= 2 && s
.length
<= 3);
54 capacity
= Integer
.parseInt(s
[2]);
66 = PersistentByteMap
.emptyPersistentByteMap(new File(s
[1]),
67 capacity
, capacity
*32);
71 System
.err
.println ("error: could not create "
72 + s
[1] + ": " + e
.toString());
78 if (s
[0].equals("-a"))
80 // Add a jar file to a database, creating it if necessary.
81 // Copies the database, adds the jar file to the copy, and
82 // then renames the new database over the old.
85 insist (s
.length
== 4);
86 File database
= new File(s
[1]);
87 database
= database
.getAbsoluteFile();
88 File jar
= new File(s
[2]);
89 PersistentByteMap map
;
90 if (database
.isFile())
91 map
= new PersistentByteMap(database
,
92 PersistentByteMap
.AccessMode
.READ_ONLY
);
94 map
= PersistentByteMap
.emptyPersistentByteMap(database
,
96 File soFile
= new File(s
[3]);
97 if (! soFile
.isFile())
98 throw new IllegalArgumentException(s
[3] + " is not a file");
99 map
= addJar(jar
, map
, soFile
);
103 System
.err
.println ("error: could not update " + s
[1]
104 + ": " + e
.toString());
110 if (s
[0].equals("-t"))
115 insist (s
.length
== 2);
117 = new PersistentByteMap(new File(s
[1]),
118 PersistentByteMap
.AccessMode
.READ_ONLY
);
119 Iterator iterator
= b
.iterator(PersistentByteMap
.ENTRIES
);
121 while (iterator
.hasNext())
123 PersistentByteMap
.MapEntry entry
124 = (PersistentByteMap
.MapEntry
)iterator
.next();
125 byte[] key
= (byte[])entry
.getKey();
126 byte[] value
= (byte[])b
.get(key
);
127 if (! Arrays
.equals (value
, (byte[])entry
.getValue()))
130 = ("Key " + bytesToString(key
) + " at bucket "
131 + entry
.getBucket());
133 throw new RuntimeException(err
);
145 if (s
[0].equals("-m"))
148 insist (s
.length
>= 3);
151 File database
= new File(s
[1]);
152 database
= database
.getAbsoluteFile();
153 File temp
= File
.createTempFile(database
.getName(), "",
154 database
.getParentFile());
157 int newStringTableSize
= 0;
158 PersistentByteMap
[] sourceMaps
= new PersistentByteMap
[s
.length
- 2];
159 // Scan all the input files, calculating worst case string
160 // table and hash table use.
161 for (int i
= 2; i
< s
.length
; i
++)
164 = new PersistentByteMap(new File(s
[i
]),
165 PersistentByteMap
.AccessMode
.READ_ONLY
);
167 newStringTableSize
+= b
.stringTableSize();
168 sourceMaps
[i
- 2] = b
;
171 newSize
*= 1.5; // Scaling the new size by 1.5 results in
173 PersistentByteMap map
174 = PersistentByteMap
.emptyPersistentByteMap
175 (temp
, newSize
, newStringTableSize
);
177 for (int i
= 0; i
< sourceMaps
.length
; i
++)
180 System
.err
.println("adding " + sourceMaps
[i
].size()
182 + sourceMaps
[i
].getFile());
183 map
.putAll(sourceMaps
[i
]);
186 temp
.renameTo(database
);
196 if (s
[0].equals("-l"))
199 insist (s
.length
== 2);
203 = new PersistentByteMap(new File(s
[1]),
204 PersistentByteMap
.AccessMode
.READ_ONLY
);
206 System
.out
.println ("Capacity: " + b
.capacity());
207 System
.out
.println ("Size: " + b
.size());
208 System
.out
.println ();
210 System
.out
.println ("Elements: ");
211 Iterator iterator
= b
.iterator(PersistentByteMap
.ENTRIES
);
213 while (iterator
.hasNext())
215 PersistentByteMap
.MapEntry entry
216 = (PersistentByteMap
.MapEntry
)iterator
.next();
217 byte[] digest
= (byte[])entry
.getKey();
218 System
.out
.print ("[" + entry
.getBucket() + "] "
219 + bytesToString(digest
)
221 System
.out
.println (new String((byte[])entry
.getValue()));
226 System
.err
.println ("error: could not list "
227 + s
[1] + ": " + e
.toString());
233 if (s
[0].equals("-d"))
235 // For testing only: fill the byte map with random data.
236 insist (s
.length
== 2);
239 MessageDigest md
= MessageDigest
.getInstance("MD5");
241 = new PersistentByteMap(new File(s
[1]),
242 PersistentByteMap
.AccessMode
.READ_WRITE
);
243 int N
= b
.capacity();
244 byte[] bytes
= new byte[1];
245 byte digest
[] = md
.digest(bytes
);
246 for (int i
= 0; i
< N
; i
++)
248 digest
= md
.digest(digest
);
249 b
.put(digest
, digest
);
264 private static void insist(boolean ok
)
273 private static void usage(PrintStream out
)
276 ("gcj-dbtool: Manipulate gcj map database files\n"
279 + " gcj-dbtool -n file.gcjdb [size] - Create a new gcj map database\n"
280 + " gcj-dbtool -a file.gcjdb file.jar file.so\n"
281 + " - Add the contents of file.jar to a new gcj map database\n"
282 + " gcj-dbtool -t file.gcjdb - Test a gcj map database\n"
283 + " gcj-dbtool -l file.gcjdb - List a gcj map database\n"
284 + " gcj-dbtool -m dest.gcjdb [source.gcjdb]...\n"
285 + " - Merge gcj map databases into dest\n"
287 + " To add to dest, include dest in the list of sources");
290 // Add a jar to a map. This copies the map first and returns a
291 // different map that contains the data. The original map is
294 private static PersistentByteMap
295 addJar(File f
, PersistentByteMap b
, File soFile
)
298 MessageDigest md
= MessageDigest
.getInstance("MD5");
300 JarFile jar
= new JarFile (f
);
304 Enumeration entries
= jar
.entries();
305 while (entries
.hasMoreElements())
307 JarEntry classfile
= (JarEntry
)entries
.nextElement();
308 if (classfile
.getName().endsWith(".class"))
314 System
.err
.println("adding " + count
+ " elements from "
315 + f
+ " to " + b
.getFile());
317 // Maybe resize the destination map. We're allowing plenty of
318 // extra space by using a loadFactor of 2.
319 b
= resizeMap(b
, (b
.size() + count
) * 2, true);
321 Enumeration entries
= jar
.entries();
323 byte[] soFileName
= soFile
.getCanonicalPath().getBytes("UTF-8");
324 while (entries
.hasMoreElements())
326 JarEntry classfile
= (JarEntry
)entries
.nextElement();
327 if (classfile
.getName().endsWith(".class"))
329 InputStream str
= jar
.getInputStream(classfile
);
330 long length
= classfile
.getSize();
332 throw new EOFException();
334 byte[] data
= new byte[length
];
336 while (length
- pos
> 0)
338 int len
= str
.read(data
, pos
, (int)(length
- pos
));
340 throw new EOFException("Not enough data reading from: "
341 + classfile
.getName());
344 b
.put(md
.digest(data
), soFileName
);
350 // Resize a map by creating a new one with the same data and
351 // renaming it. If close is true, close the original map.
353 static PersistentByteMap
resizeMap(PersistentByteMap m
, int newCapacity
, boolean close
)
354 throws IOException
, IllegalAccessException
356 newCapacity
= Math
.max(m
.capacity(), newCapacity
);
357 File name
= m
.getFile();
358 File copy
= File
.createTempFile(name
.getName(), "", name
.getParentFile());
361 PersistentByteMap dest
362 = PersistentByteMap
.emptyPersistentByteMap
363 (copy
, newCapacity
, newCapacity
*32);
379 static String
bytesToString(byte[] b
)
381 StringBuffer hexBytes
= new StringBuffer();
382 int length
= b
.length
;
383 for (int i
= 0; i
< length
; ++i
)
384 hexBytes
.append(Integer
.toHexString(b
[i
] & 0xff));
385 return hexBytes
.toString();