1:
9:
10: package ;
11:
12:
13: import ;
14: import ;
15: import ;
16: import ;
17: import ;
18: import ;
19:
20: public class Main
21: {
22: static private boolean verbose = false;
23:
24: public static void main (String[] s)
25: {
26: boolean fileListFromStdin = false;
27: char filenameSeparator = ' ';
28:
29: insist (s.length >= 1);
30:
31: if (s[0].equals("-") ||
32: s[0].equals("-0"))
33: {
34: if (s[0].equals("-0"))
35: filenameSeparator = (char)0;
36: fileListFromStdin = true;
37: String[] newArgs = new String[s.length - 1];
38: System.arraycopy(s, 1, newArgs, 0, s.length - 1);
39: s = newArgs;
40: }
41:
42: if (s[0].equals("-v") || s[0].equals("--version"))
43: {
44: insist (s.length == 1);
45: System.out.println("gcj-dbtool ("
46: + System.getProperty("java.vm.name")
47: + ") "
48: + System.getProperty("java.vm.version"));
49: System.out.println();
50: System.out.println("Copyright 2012 Free Software Foundation, Inc.");
51: System.out.println("This is free software; see the source for copying conditions. There is NO");
52: System.out.println("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
53: return;
54: }
55: if (s[0].equals("--help"))
56: {
57: usage(System.out);
58: return;
59: }
60:
61: if (s[0].equals("-n"))
62: {
63:
64: insist (s.length >= 2 && s.length <= 3);
65:
66: int capacity = 32749;
67:
68: if (s.length == 3)
69: {
70: capacity = Integer.parseInt(s[2]);
71:
72: if (capacity <= 2)
73: {
74: usage(System.err);
75: System.exit(1);
76: }
77: }
78:
79: try
80: {
81: PersistentByteMap b
82: = PersistentByteMap.emptyPersistentByteMap(new File(s[1]),
83: capacity, capacity*32);
84: }
85: catch (Exception e)
86: {
87: System.err.println ("error: could not create "
88: + s[1] + ": " + e.toString());
89: System.exit(2);
90: }
91: return;
92: }
93:
94: if (s[0].equals("-a") || s[0].equals("-f"))
95: {
96:
97:
98:
99: try
100: {
101: insist (s.length == 4);
102: File database = new File(s[1]);
103: database = database.getAbsoluteFile();
104: File jar = new File(s[2]);
105: PersistentByteMap map;
106: if (database.isFile())
107: map = new PersistentByteMap(database,
108: PersistentByteMap.AccessMode.READ_ONLY);
109: else
110: map = PersistentByteMap.emptyPersistentByteMap(database,
111: 100, 100*32);
112: File soFile = new File(s[3]);
113: if (! s[0].equals("-f") && ! soFile.isFile())
114: throw new IllegalArgumentException(s[3] + " is not a file");
115: map = addJar(jar, map, soFile);
116: }
117: catch (Exception e)
118: {
119: System.err.println ("error: could not update " + s[1]
120: + ": " + e.toString());
121: System.exit(2);
122: }
123: return;
124: }
125:
126: if (s[0].equals("-t"))
127: {
128:
129: try
130: {
131: insist (s.length == 2);
132: PersistentByteMap b
133: = new PersistentByteMap(new File(s[1]),
134: PersistentByteMap.AccessMode.READ_ONLY);
135: Iterator iterator = b.iterator(PersistentByteMap.ENTRIES);
136:
137: while (iterator.hasNext())
138: {
139: PersistentByteMap.MapEntry entry
140: = (PersistentByteMap.MapEntry)iterator.next();
141: byte[] key = (byte[])entry.getKey();
142: byte[] value = (byte[])b.get(key);
143: if (! Arrays.equals (value, (byte[])entry.getValue()))
144: {
145: String err
146: = ("Key " + bytesToString(key) + " at bucket "
147: + entry.getBucket());
148:
149: throw new RuntimeException(err);
150: }
151: }
152: }
153: catch (Exception e)
154: {
155: e.printStackTrace();
156: System.exit(3);
157: }
158: return;
159: }
160:
161: if (s[0].equals("-m"))
162: {
163:
164: insist (s.length >= 3
165: || fileListFromStdin && s.length == 2);
166: try
167: {
168: File database = new File(s[1]);
169: database = database.getAbsoluteFile();
170: File temp = File.createTempFile(database.getName(), "",
171: database.getParentFile());
172:
173: int newSize = 0;
174: int newStringTableSize = 0;
175: Fileset files = getFiles(s, 2, fileListFromStdin,
176: filenameSeparator);
177: PersistentByteMap[] sourceMaps
178: = new PersistentByteMap[files.size()];
179:
180:
181:
182: {
183: Iterator it = files.iterator();
184: int i = 0;
185: while (it.hasNext())
186: {
187: PersistentByteMap b
188: = new PersistentByteMap((File)it.next(),
189: PersistentByteMap.AccessMode.READ_ONLY);
190: newSize += b.size();
191: newStringTableSize += b.stringTableSize();
192: sourceMaps[i++] = b;
193: }
194: }
195:
196: newSize *= 1.5;
197:
198: PersistentByteMap map
199: = PersistentByteMap.emptyPersistentByteMap
200: (temp, newSize, newStringTableSize);
201:
202: for (int i = 0; i < sourceMaps.length; i++)
203: {
204: if (verbose)
205: System.err.println("adding " + sourceMaps[i].size()
206: + " elements from "
207: + sourceMaps[i].getFile());
208: map.putAll(sourceMaps[i]);
209: }
210: map.close();
211: temp.renameTo(database);
212: }
213: catch (Exception e)
214: {
215: e.printStackTrace();
216: System.exit(3);
217: }
218: return;
219: }
220:
221: if (s[0].equals("-l"))
222: {
223:
224: insist (s.length == 2);
225: try
226: {
227: PersistentByteMap b
228: = new PersistentByteMap(new File(s[1]),
229: PersistentByteMap.AccessMode.READ_ONLY);
230:
231: System.out.println ("Capacity: " + b.capacity());
232: System.out.println ("Size: " + b.size());
233: System.out.println ();
234:
235: System.out.println ("Elements: ");
236: Iterator iterator = b.iterator(PersistentByteMap.ENTRIES);
237:
238: while (iterator.hasNext())
239: {
240: PersistentByteMap.MapEntry entry
241: = (PersistentByteMap.MapEntry)iterator.next();
242: byte[] digest = (byte[])entry.getKey();
243: System.out.print ("[" + entry.getBucket() + "] "
244: + bytesToString(digest)
245: + " -> ");
246: System.out.println (new String((byte[])entry.getValue()));
247: }
248: }
249: catch (Exception e)
250: {
251: System.err.println ("error: could not list "
252: + s[1] + ": " + e.toString());
253: System.exit(2);
254: }
255: return;
256: }
257:
258: if (s[0].equals("-d"))
259: {
260:
261: insist (s.length == 2);
262: try
263: {
264: MessageDigest md = MessageDigest.getInstance("MD5");
265: PersistentByteMap b
266: = new PersistentByteMap(new File(s[1]),
267: PersistentByteMap.AccessMode.READ_WRITE);
268: int N = b.capacity();
269: byte[] bytes = new byte[1];
270: byte digest[] = md.digest(bytes);
271: for (int i = 0; i < N; i++)
272: {
273: digest = md.digest(digest);
274: b.put(digest, digest);
275: }
276: }
277: catch (Exception e)
278: {
279: e.printStackTrace();
280: System.exit(3);
281: }
282: return;
283: }
284:
285: if (s[0].equals("-p"))
286: {
287: insist (s.length == 1 || s.length == 2);
288: String result;
289:
290: if (s.length == 1)
291: result = System.getProperty("gnu.gcj.precompiled.db.path", "");
292: else
293: result = (s[1]
294: + (s[1].endsWith(File.separator) ? "" : File.separator)
295: + getDbPathTail ());
296:
297: System.out.println (result);
298: return;
299: }
300:
301: usage(System.err);
302: System.exit(1);
303: }
304:
305: private static native String getDbPathTail ();
306:
307: private static void insist(boolean ok)
308: {
309: if (! ok)
310: {
311: usage(System.err);
312: System.exit(1);
313: }
314: }
315:
316: private static void usage(PrintStream out)
317: {
318: out.println
319: ("gcj-dbtool: Manipulate gcj map database files\n"
320: + "\n"
321: + " Usage: \n"
322: + " gcj-dbtool -n file.gcjdb [size] - Create a new gcj map database\n"
323: + " gcj-dbtool -a file.gcjdb file.jar file.so\n"
324: + " - Add the contents of file.jar to a gcj map database\n"
325: + " gcj-dbtool -f file.gcjdb file.jar file.so\n"
326: + " - Add the contents of file.jar to a gcj map database\n"
327: + " gcj-dbtool -t file.gcjdb - Test a gcj map database\n"
328: + " gcj-dbtool -l file.gcjdb - List a gcj map database\n"
329: + " gcj-dbtool [-][-0] -m dest.gcjdb [source.gcjdb]...\n"
330: + " - Merge gcj map databases into dest\n"
331: + " Replaces dest\n"
332: + " To add to dest, include dest in the list of sources\n"
333: + " If the first arg is -, read the list from stdin\n"
334: + " If the first arg is -0, filenames separated by nul\n"
335: + " gcj-dbtool -p [LIBDIR] - Print default database name"
336: );
337: }
338:
339:
340:
341:
342:
343: private static PersistentByteMap
344: addJar(File f, PersistentByteMap b, File soFile)
345: throws Exception
346: {
347: MessageDigest md = MessageDigest.getInstance("MD5");
348:
349: JarFile jar = new JarFile (f);
350:
351: int count = 0;
352: {
353: Enumeration entries = jar.entries();
354: while (entries.hasMoreElements())
355: {
356: JarEntry classfile = (JarEntry)entries.nextElement();
357: if (classfile.getName().endsWith(".class"))
358: count++;
359: }
360: }
361:
362: if (verbose)
363: System.err.println("adding " + count + " elements from "
364: + f + " to " + b.getFile());
365:
366:
367:
368: b = resizeMap(b, (b.size() + count) * 2, true);
369:
370: Enumeration entries = jar.entries();
371:
372: byte[] soFileName = soFile.getCanonicalPath().getBytes("UTF-8");
373: while (entries.hasMoreElements())
374: {
375: JarEntry classfile = (JarEntry)entries.nextElement();
376: if (classfile.getName().endsWith(".class"))
377: {
378: InputStream str = jar.getInputStream(classfile);
379: int length = (int) classfile.getSize();
380: if (length == -1)
381: throw new EOFException();
382:
383: byte[] data = new byte[length];
384: int pos = 0;
385: while (length - pos > 0)
386: {
387: int len = str.read(data, pos, length - pos);
388: if (len == -1)
389: throw new EOFException("Not enough data reading from: "
390: + classfile.getName());
391: pos += len;
392: }
393: b.put(md.digest(data), soFileName);
394: }
395: }
396: return b;
397: }
398:
399:
400:
401:
402: static PersistentByteMap resizeMap(PersistentByteMap m, int newCapacity, boolean close)
403: throws IOException, IllegalAccessException
404: {
405: newCapacity = Math.max(m.capacity(), newCapacity);
406: File name = m.getFile();
407: File copy = File.createTempFile(name.getName(), "", name.getParentFile());
408: try
409: {
410: PersistentByteMap dest
411: = PersistentByteMap.emptyPersistentByteMap
412: (copy, newCapacity, newCapacity*32);
413: dest.putAll(m);
414: dest.force();
415: if (close)
416: m.close();
417: copy.renameTo(name);
418: return dest;
419: }
420: catch (Exception e)
421: {
422: copy.delete();
423: }
424: return null;
425: }
426:
427:
428: static String bytesToString(byte[] b)
429: {
430: StringBuffer hexBytes = new StringBuffer();
431: int length = b.length;
432: for (int i = 0; i < length; ++i)
433: {
434: int v = b[i] & 0xff;
435: if (v < 16)
436: hexBytes.append('0');
437: hexBytes.append(Integer.toHexString(v));
438: }
439: return hexBytes.toString();
440: }
441:
442:
443:
444:
445: private static final Fileset getFiles(String[] s, int startPos,
446: boolean fileListFromStdin,
447: char separator)
448: {
449: if (fileListFromStdin)
450: return new Fileset(System.in, separator);
451: else
452: return new Fileset(s, startPos, s.length);
453: }
454: }
455:
456:
457:
458: class Tokenizer
459: {
460: final Reader r;
461: final char separator;
462:
463: Tokenizer(Reader r, char separator)
464: {
465: this.r = r;
466: this.separator = separator;
467: }
468:
469: boolean isSeparator(int c)
470: {
471: if (Character.isWhitespace(separator))
472: return Character.isWhitespace((char)c);
473: else
474: return c == separator;
475: }
476:
477:
478:
479: String nextToken ()
480: {
481: StringBuffer buf = new StringBuffer();
482: int c;
483: try
484: {
485: while ((c = r.read()) != -1)
486: {
487: if (! isSeparator(c))
488: {
489: buf.append((char)c);
490: break;
491: }
492: }
493: while ((c = r.read()) != -1)
494: {
495: if (isSeparator(c))
496: break;
497: else
498: buf.append((char)c);
499: }
500: }
501: catch (java.io.IOException e)
502: {
503: }
504: return buf.toString();
505: }
506: }
507:
508:
509:
510:
511: class Fileset
512: {
513: LinkedHashSet files = new LinkedHashSet();
514:
515: Fileset (String[] s, int start, int end)
516: {
517: for (int i = start; i < end; i++)
518: {
519: files.add(new File(s[i]));
520: }
521: }
522:
523: Fileset (InputStream is, char separator)
524: {
525: Reader r = new BufferedReader(new InputStreamReader(is));
526: Tokenizer st = new Tokenizer(r, separator);
527: String name;
528: while (! "".equals(name = st.nextToken()))
529: files.add(new File(name));
530: }
531:
532: Iterator iterator()
533: {
534: return files.iterator();
535: }
536:
537: int size()
538: {
539: return files.size();
540: }
541: }