Merge from the pain train
[official-gcc.git] / libjava / gnu / gcj / tools / gcj_dbtool / Main.java
blobea8f35cf3f41cb247491c24609845abde3a70a53
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
7 details. */
9 package gnu.gcj.tools.gcj_dbtool;
12 import gnu.gcj.runtime.PersistentByteMap;
13 import java.io.*;
14 import java.nio.channels.*;
15 import java.util.*;
16 import java.util.jar.*;
17 import java.security.MessageDigest;
19 public class Main
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")
31 + ") "
32 + System.getProperty("java.vm.version"));
33 System.out.println();
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.");
37 return;
39 if (s[0].equals("--help"))
41 usage(System.out);
42 return;
45 if (s[0].equals("-n"))
47 // Create a new database.
48 insist (s.length >= 2 && s.length <= 3);
50 int capacity = 32749;
52 if (s.length == 3)
54 capacity = Integer.parseInt(s[2]);
56 if (capacity <= 2)
58 usage(System.err);
59 System.exit(1);
63 try
65 PersistentByteMap b
66 = PersistentByteMap.emptyPersistentByteMap(new File(s[1]),
67 capacity, capacity*32);
69 catch (Exception e)
71 System.err.println ("error: could not create "
72 + s[1] + ": " + e.toString());
73 System.exit(2);
75 return;
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.
83 try
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);
93 else
94 map = PersistentByteMap.emptyPersistentByteMap(database,
95 100, 100*32);
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);
101 catch (Exception e)
103 System.err.println ("error: could not update " + s[1]
104 + ": " + e.toString());
105 System.exit(2);
107 return;
110 if (s[0].equals("-t"))
112 // Test
115 insist (s.length == 2);
116 PersistentByteMap b
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()))
129 String err
130 = ("Key " + bytesToString(key) + " at bucket "
131 + entry.getBucket());
133 throw new RuntimeException(err);
137 catch (Exception e)
139 e.printStackTrace();
140 System.exit(3);
142 return;
145 if (s[0].equals("-m"))
147 // Merge databases.
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());
156 int newSize = 0;
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++)
163 PersistentByteMap b
164 = new PersistentByteMap(new File(s[i]),
165 PersistentByteMap.AccessMode.READ_ONLY);
166 newSize += b.size();
167 newStringTableSize += b.stringTableSize();
168 sourceMaps[i - 2] = b;
171 newSize *= 1.5; // Scaling the new size by 1.5 results in
172 // fewer collisions.
173 PersistentByteMap map
174 = PersistentByteMap.emptyPersistentByteMap
175 (temp, newSize, newStringTableSize);
177 for (int i = 0; i < sourceMaps.length; i++)
179 if (verbose)
180 System.err.println("adding " + sourceMaps[i].size()
181 + " elements from "
182 + sourceMaps[i].getFile());
183 map.putAll(sourceMaps[i]);
185 map.close();
186 temp.renameTo(database);
188 catch (Exception e)
190 e.printStackTrace();
191 System.exit(3);
193 return;
196 if (s[0].equals("-l"))
198 // List a database.
199 insist (s.length == 2);
202 PersistentByteMap b
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)
220 + " -> ");
221 System.out.println (new String((byte[])entry.getValue()));
224 catch (Exception e)
226 System.err.println ("error: could not list "
227 + s[1] + ": " + e.toString());
228 System.exit(2);
230 return;
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");
240 PersistentByteMap b
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);
252 catch (Exception e)
254 e.printStackTrace();
255 System.exit(3);
257 return;
260 usage(System.err);
261 System.exit(1);
264 private static void insist(boolean ok)
266 if (! ok)
268 usage(System.err);
269 System.exit(1);
273 private static void usage(PrintStream out)
275 out.println
276 ("gcj-dbtool: Manipulate gcj map database files\n"
277 + "\n"
278 + " Usage: \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"
286 + " Replaces 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
292 // closed.
294 private static PersistentByteMap
295 addJar(File f, PersistentByteMap b, File soFile)
296 throws Exception
298 MessageDigest md = MessageDigest.getInstance("MD5");
300 JarFile jar = new JarFile (f);
302 int count = 0;
304 Enumeration entries = jar.entries();
305 while (entries.hasMoreElements())
307 JarEntry classfile = (JarEntry)entries.nextElement();
308 if (classfile.getName().endsWith(".class"))
309 count++;
313 if (verbose)
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();
331 if (length == -1)
332 throw new EOFException();
334 byte[] data = new byte[length];
335 int pos = 0;
336 while (length - pos > 0)
338 int len = str.read(data, pos, (int)(length - pos));
339 if (len == -1)
340 throw new EOFException("Not enough data reading from: "
341 + classfile.getName());
342 pos += len;
344 b.put(md.digest(data), soFileName);
347 return b;
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);
364 dest.putAll(m);
365 dest.force();
366 if (close)
367 m.close();
368 copy.renameTo(name);
369 return dest;
371 catch (Exception e)
373 copy.delete();
375 return null;
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();