OLD | NEW |
(Empty) | |
| 1 /* Copyright (c) 2002-2013 Sun Microsystems, Inc. All rights reserved |
| 2 * |
| 3 * This program is distributed under the terms of |
| 4 * the GNU General Public License Version 2. See the LICENSE file |
| 5 * at the top of the source tree. |
| 6 */ |
| 7 package org.pantsbuild.jmake; |
| 8 |
| 9 import java.io.BufferedWriter; |
| 10 import java.io.ByteArrayOutputStream; |
| 11 import java.io.File; |
| 12 import java.io.FileNotFoundException; |
| 13 import java.io.FileOutputStream; |
| 14 import java.io.IOException; |
| 15 import java.io.ObjectOutputStream; |
| 16 import java.io.OutputStreamWriter; |
| 17 import java.io.UnsupportedEncodingException; |
| 18 import java.io.Writer; |
| 19 import java.util.Arrays; |
| 20 import java.util.LinkedHashMap; |
| 21 import java.util.LinkedHashSet; |
| 22 import java.util.Map; |
| 23 import java.util.Set; |
| 24 |
| 25 |
| 26 /** |
| 27 * This class implements writing a text stream representing a project database. |
| 28 * |
| 29 * @see TextProjectDatabaseReader for details. |
| 30 * |
| 31 * @author Benjy Weinberger |
| 32 * 13 January 2013 |
| 33 */ |
| 34 public class TextProjectDatabaseWriter { |
| 35 private static Set<String> primitives = new LinkedHashSet<String>( |
| 36 Arrays.asList("boolean", "byte", "char", "double", "float", "int", "long
", "short", |
| 37 "Z", "B", "C", "D", "F", "I", "J", "S")); |
| 38 |
| 39 private ByteArrayOutputStream baos = new ByteArrayOutputStream(); // Reusab
le temp buffer. |
| 40 |
| 41 public void writeProjectDatabaseToFile(File outfile, Map<String, PCDEntry> p
cd) { |
| 42 try { |
| 43 Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutpu
tStream(outfile), "UTF-8")); |
| 44 try { |
| 45 writeProjectDatabase(out, pcd); |
| 46 } finally { |
| 47 out.close(); |
| 48 } |
| 49 } catch (FileNotFoundException e) { |
| 50 throw new PrivateException(e); |
| 51 } catch (UnsupportedEncodingException e) { |
| 52 throw new PrivateException(e); |
| 53 } catch (IOException e) { |
| 54 throw new PrivateException(e); |
| 55 } |
| 56 } |
| 57 |
| 58 public void writeProjectDatabase(Writer out, Map<String,PCDEntry> pcd) { |
| 59 try { |
| 60 out.write("pcd entries:\n"); |
| 61 out.write(Integer.toString(pcd.size())); |
| 62 out.write(" items\n"); |
| 63 Map<String, Set<String>> depsBySource = new LinkedHashMap<String, Se
t<String>>(); |
| 64 for (PCDEntry entry : pcd.values()) { |
| 65 writePCDEntry(out, entry); |
| 66 Set<String> deps = depsBySource.get(entry.javaFileFullPath); |
| 67 if (deps == null) { |
| 68 deps = new LinkedHashSet<String>(); |
| 69 depsBySource.put(entry.javaFileFullPath, deps); |
| 70 } |
| 71 addDepsFromClassInfo(deps, entry.oldClassInfo); |
| 72 } |
| 73 // Write out dependency information. Note that we don't need to read
this back to recreate |
| 74 // the PCD. We write it out here just as a convenience, so that exte
rnal readers of the PDB |
| 75 // file don't have to grok our internal ClassInfo structures. |
| 76 out.write("dependencies:\n"); |
| 77 out.write(Integer.toString(depsBySource.size())); |
| 78 out.write(" items\n"); |
| 79 for (Map.Entry<String, Set<String>> item : depsBySource.entrySet())
{ |
| 80 out.write(item.getKey()); |
| 81 for (String s : item.getValue()) { |
| 82 out.write('\t'); |
| 83 out.write(s); |
| 84 } |
| 85 out.write('\n'); |
| 86 } |
| 87 } catch (IOException e) { |
| 88 throw new PrivateException(e); |
| 89 } |
| 90 } |
| 91 |
| 92 private void addDepsFromClassInfo(Set<String> deps, ClassInfo ci) { |
| 93 for (String s : ci.cpoolRefsToClasses) { |
| 94 int i = 0; |
| 95 int j = s.length(); |
| 96 |
| 97 // Fix some inconsistencies in how we represent types internally: |
| 98 // Despite the comment on ci.cpoolRefsToClasses, class names may be |
| 99 // representing in it with '['s and with '@', '#' instead of 'L', ';
'. |
| 100 while (s.charAt(i) == '[') i++; |
| 101 if (s.charAt(i) == '@') i++; |
| 102 if (s.endsWith("#")) j--; |
| 103 int k = s.indexOf('$'); |
| 104 |
| 105 // Take the outer class, on references to nested classes. |
| 106 if (k != -1) j = k; |
| 107 if (i > 0 || j < s.length()) |
| 108 s = s.substring(i, j); |
| 109 |
| 110 // We don't need to record deps on primitive types, or arrays of the
m. |
| 111 if (!primitives.contains(s)) |
| 112 deps.add(s); |
| 113 } |
| 114 } |
| 115 |
| 116 private void writePCDEntry(Writer out, PCDEntry entry) { |
| 117 try { |
| 118 out.write(entry.className); |
| 119 out.write('\t'); |
| 120 out.write(entry.javaFileFullPath); |
| 121 out.write('\t'); |
| 122 out.write(Long.toString(entry.oldClassFileLastModified)); |
| 123 out.write('\t'); |
| 124 out.write(Long.toString(entry.oldClassFileFingerprint)); |
| 125 out.write('\t'); |
| 126 out.write(classInfoToBase64(entry.oldClassInfo)); |
| 127 out.write('\n'); |
| 128 } catch (IOException e) { |
| 129 throw new PrivateException(e); |
| 130 } |
| 131 } |
| 132 |
| 133 private char[] classInfoToBase64(ClassInfo ci) { |
| 134 baos.reset(); |
| 135 try { |
| 136 ObjectOutputStream oos = new ObjectOutputStream(baos); |
| 137 oos.writeObject(ci); |
| 138 oos.close(); |
| 139 } catch (IOException e) { |
| 140 throw new PrivateException(e); |
| 141 } |
| 142 return Base64.encode(baos.toByteArray()); |
| 143 } |
| 144 } |
OLD | NEW |