| Index: third_party/jmake/src/org/pantsbuild/jmake/TextProjectDatabaseWriter.java
|
| diff --git a/third_party/jmake/src/org/pantsbuild/jmake/TextProjectDatabaseWriter.java b/third_party/jmake/src/org/pantsbuild/jmake/TextProjectDatabaseWriter.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ee5c08f5dba6de19713cade8e14629ad05773dd5
|
| --- /dev/null
|
| +++ b/third_party/jmake/src/org/pantsbuild/jmake/TextProjectDatabaseWriter.java
|
| @@ -0,0 +1,144 @@
|
| +/* Copyright (c) 2002-2013 Sun Microsystems, Inc. All rights reserved
|
| + *
|
| + * This program is distributed under the terms of
|
| + * the GNU General Public License Version 2. See the LICENSE file
|
| + * at the top of the source tree.
|
| + */
|
| +package org.pantsbuild.jmake;
|
| +
|
| +import java.io.BufferedWriter;
|
| +import java.io.ByteArrayOutputStream;
|
| +import java.io.File;
|
| +import java.io.FileNotFoundException;
|
| +import java.io.FileOutputStream;
|
| +import java.io.IOException;
|
| +import java.io.ObjectOutputStream;
|
| +import java.io.OutputStreamWriter;
|
| +import java.io.UnsupportedEncodingException;
|
| +import java.io.Writer;
|
| +import java.util.Arrays;
|
| +import java.util.LinkedHashMap;
|
| +import java.util.LinkedHashSet;
|
| +import java.util.Map;
|
| +import java.util.Set;
|
| +
|
| +
|
| +/**
|
| + * This class implements writing a text stream representing a project database.
|
| + *
|
| + * @see TextProjectDatabaseReader for details.
|
| + *
|
| + * @author Benjy Weinberger
|
| + * 13 January 2013
|
| + */
|
| +public class TextProjectDatabaseWriter {
|
| + private static Set<String> primitives = new LinkedHashSet<String>(
|
| + Arrays.asList("boolean", "byte", "char", "double", "float", "int", "long", "short",
|
| + "Z", "B", "C", "D", "F", "I", "J", "S"));
|
| +
|
| + private ByteArrayOutputStream baos = new ByteArrayOutputStream(); // Reusable temp buffer.
|
| +
|
| + public void writeProjectDatabaseToFile(File outfile, Map<String, PCDEntry> pcd) {
|
| + try {
|
| + Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outfile), "UTF-8"));
|
| + try {
|
| + writeProjectDatabase(out, pcd);
|
| + } finally {
|
| + out.close();
|
| + }
|
| + } catch (FileNotFoundException e) {
|
| + throw new PrivateException(e);
|
| + } catch (UnsupportedEncodingException e) {
|
| + throw new PrivateException(e);
|
| + } catch (IOException e) {
|
| + throw new PrivateException(e);
|
| + }
|
| + }
|
| +
|
| + public void writeProjectDatabase(Writer out, Map<String,PCDEntry> pcd) {
|
| + try {
|
| + out.write("pcd entries:\n");
|
| + out.write(Integer.toString(pcd.size()));
|
| + out.write(" items\n");
|
| + Map<String, Set<String>> depsBySource = new LinkedHashMap<String, Set<String>>();
|
| + for (PCDEntry entry : pcd.values()) {
|
| + writePCDEntry(out, entry);
|
| + Set<String> deps = depsBySource.get(entry.javaFileFullPath);
|
| + if (deps == null) {
|
| + deps = new LinkedHashSet<String>();
|
| + depsBySource.put(entry.javaFileFullPath, deps);
|
| + }
|
| + addDepsFromClassInfo(deps, entry.oldClassInfo);
|
| + }
|
| + // Write out dependency information. Note that we don't need to read this back to recreate
|
| + // the PCD. We write it out here just as a convenience, so that external readers of the PDB
|
| + // file don't have to grok our internal ClassInfo structures.
|
| + out.write("dependencies:\n");
|
| + out.write(Integer.toString(depsBySource.size()));
|
| + out.write(" items\n");
|
| + for (Map.Entry<String, Set<String>> item : depsBySource.entrySet()) {
|
| + out.write(item.getKey());
|
| + for (String s : item.getValue()) {
|
| + out.write('\t');
|
| + out.write(s);
|
| + }
|
| + out.write('\n');
|
| + }
|
| + } catch (IOException e) {
|
| + throw new PrivateException(e);
|
| + }
|
| + }
|
| +
|
| + private void addDepsFromClassInfo(Set<String> deps, ClassInfo ci) {
|
| + for (String s : ci.cpoolRefsToClasses) {
|
| + int i = 0;
|
| + int j = s.length();
|
| +
|
| + // Fix some inconsistencies in how we represent types internally:
|
| + // Despite the comment on ci.cpoolRefsToClasses, class names may be
|
| + // representing in it with '['s and with '@', '#' instead of 'L', ';'.
|
| + while (s.charAt(i) == '[') i++;
|
| + if (s.charAt(i) == '@') i++;
|
| + if (s.endsWith("#")) j--;
|
| + int k = s.indexOf('$');
|
| +
|
| + // Take the outer class, on references to nested classes.
|
| + if (k != -1) j = k;
|
| + if (i > 0 || j < s.length())
|
| + s = s.substring(i, j);
|
| +
|
| + // We don't need to record deps on primitive types, or arrays of them.
|
| + if (!primitives.contains(s))
|
| + deps.add(s);
|
| + }
|
| + }
|
| +
|
| + private void writePCDEntry(Writer out, PCDEntry entry) {
|
| + try {
|
| + out.write(entry.className);
|
| + out.write('\t');
|
| + out.write(entry.javaFileFullPath);
|
| + out.write('\t');
|
| + out.write(Long.toString(entry.oldClassFileLastModified));
|
| + out.write('\t');
|
| + out.write(Long.toString(entry.oldClassFileFingerprint));
|
| + out.write('\t');
|
| + out.write(classInfoToBase64(entry.oldClassInfo));
|
| + out.write('\n');
|
| + } catch (IOException e) {
|
| + throw new PrivateException(e);
|
| + }
|
| + }
|
| +
|
| + private char[] classInfoToBase64(ClassInfo ci) {
|
| + baos.reset();
|
| + try {
|
| + ObjectOutputStream oos = new ObjectOutputStream(baos);
|
| + oos.writeObject(ci);
|
| + oos.close();
|
| + } catch (IOException e) {
|
| + throw new PrivateException(e);
|
| + }
|
| + return Base64.encode(baos.toByteArray());
|
| + }
|
| +}
|
|
|