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");
	}
}

 

Ads help maintain this website.