package net.sourceforge.plantuml.preproc; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.ref.SoftReference; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import net.sourceforge.plantuml.Log; import net.sourceforge.plantuml.brotli.BrotliInputStream; public class StdlibOld { static private final Map all = new ConcurrentHashMap(); static class Portion { int position; int length; Portion(int position, int length) { this.position = position; this.length = length; } public byte[] of(DataInputStream is) throws IOException { is.skipBytes(position); final byte result[] = new byte[length]; is.readFully(result); is.close(); return result; } } private final Map data = new HashMap(); private final Map> cache = new ConcurrentHashMap>(); private final String name; private final Map info = new HashMap(); public static InputStream getResourceAsStream(String fullname) { fullname = fullname.toLowerCase().replace(".puml", ""); final int last = fullname.indexOf('/'); if (last == -1) { return null; } try { final StdlibOld folder = retrieve(fullname.substring(0, last)); if (folder == null) { return null; } final byte[] data = folder.getData(fullname.substring(last + 1)); if (data == null) { return null; } return new ByteArrayInputStream(data); } catch (IOException e) { e.printStackTrace(); return null; } } private static InputStream getInternalInputStream(String fullname, String extension) { final String res = "/stdlib/" + fullname + extension; return StdlibOld.class.getResourceAsStream(res); } private static StdlibOld retrieve(final String name) throws IOException { StdlibOld result = all.get(name); if (result == null) { result = new StdlibOld(name); all.put(name, result); } return result; } private StdlibOld(String name) throws IOException { this.name = name; Log.info("Opening archive " + name); int pos = 0; final DataInputStream is = getDataIndex(); fillMap(is.readUTF()); while (true) { final String filename = is.readUTF(); if (filename.length() == 0) { break; } final int len = is.readInt(); this.data.put(filename.toLowerCase(), new Portion(pos, len)); pos += len; } is.close(); } private void fillMap(String infoString) { for (String s : infoString.split("\n")) { if (s.contains("=")) { final String data[] = s.split("="); this.info.put(data[0], data[1]); } } } private DataInputStream getDataIndex() { final InputStream raw = getInternalInputStream(name, "-idx.repx"); if (raw == null) { return null; } return new DataInputStream(raw); } private DataInputStream getFullTexts() throws IOException { final InputStream raw = getInternalInputStream(name, "-dat.repx"); if (raw == null) { return null; } return new DataInputStream(new BrotliInputStream(raw)); } private byte[] getData(String filename) throws IOException { final SoftReference ref = cache.get(filename); byte[] result = ref == null ? null : ref.get(); final String full = name + "/" + filename + ".puml"; if (result == null) { result = getDataSlow(filename); cache.put(filename, new SoftReference(result)); Log.info("Reading " + full); } else { Log.info("Retrieving " + full); } return result; } private byte[] getDataSlow(String filename) throws IOException { final Portion portion = data.get(filename); return portion.of(getFullTexts()); } public static void extractStdLib() throws IOException { for (String name : getAll()) { final StdlibOld folder = new StdlibOld(name); folder.extractMeFull(new File("stdlib", name)); } } private static List getAll() throws IOException { final List result = new ArrayList(); final InputStream home = getInternalInputStream("home", ".repx"); final BufferedReader br = new BufferedReader(new InputStreamReader(home)); String name; while ((name = br.readLine()) != null) { result.add(name); } return Collections.unmodifiableList(result); } private void extractMeFull(File dir) throws IOException { final DataInputStream idx = getDataIndex(); final DataInputStream txt = getFullTexts(); final String infoString = idx.readUTF(); while (true) { final String filename = idx.readUTF(); if (filename.length() == 0) { idx.close(); txt.close(); return; } final int len = idx.readInt(); final File f = new File("stdlib/" + name + "/" + filename + ".puml"); f.getParentFile().mkdirs(); final FileOutputStream fos = new FileOutputStream(f); final byte data[] = new byte[len]; txt.readFully(data); fos.write(data); fos.close(); } } public static void addInfoVersion(List strings) { try { for (String name : getAll()) { final StdlibOld folder = new StdlibOld(name); strings.add("* " + name + " (Version " + folder.getVersion() + ")"); } } catch (IOException e) { e.printStackTrace(); } } private String getVersion() { return info.get("VERSION"); } }