All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.internal.io.stream.StreamDatabase Maven / Gradle / Ivy

The newest version!
/**
 * 
 */
package com.adobe.internal.io.stream;

import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import com.adobe.internal.io.ByteReader;
import com.adobe.internal.io.ByteWriter;

/**
 * @author sgill
 *
 */
class StreamDatabase
{
	private static class StreamData
	{
		private long references;
		private long maxReferences;
		private String stackTrace;

		public StreamData()
		{
			if (false)
			{
				try {
					throw new RuntimeException();
				} catch (RuntimeException e) {
					Writer writer = new CharArrayWriter();
					PrintWriter printWriter = new PrintWriter(writer);
					e.printStackTrace(printWriter);
					printWriter.close();
					this.stackTrace = writer.toString();
				}
			}
		}

		public long getReferences()
		{
			return this.references;
		}

		public long getMaxReferences()
		{
			return this.maxReferences;
		}

		public void addReference()
		{
			this.references++;
			this.maxReferences++;
		}

		public boolean removeReference()
		{
			this.references--;
			if (this.references < 0)
			{
				throw new RuntimeException("Stream closed and not removed from stream database.");
			}
			return this.references == 0;
		}

		public String toString()
		{
			StringBuilder buffer = new StringBuilder("Number of open references = ");

			buffer.append(this.getReferences()).append("\n").
					append("Number of max references = ").append(this.getMaxReferences()).append("\n").			
					append("Originally created = \n").append(this.stackTrace).append("\n");		
			return buffer.toString();
		}
	}

	private Map inputStreamData;
	private Map outputStreamData;
	private ByteReader masterByteReader;
	//private long maxOBS;
	private boolean lenientMasterByteReader = false;
	private boolean ignoreRemoveOnNonexistentReader = false;
	private boolean ignoreRemoveOnNonexistentWriter = false;

	/**
	 * 
	 */
	/*package protected*/ StreamDatabase(ByteReader masterByteReader, boolean lenientMasterByteReader,
			boolean ignoreRemoveOnNonexistentReader, boolean ignoreRemoveOnNonexistentWriter)
			{
		super();
		this.inputStreamData = new HashMap();
		this.outputStreamData = new HashMap();
		this.lenientMasterByteReader = lenientMasterByteReader;
		this.ignoreRemoveOnNonexistentReader = ignoreRemoveOnNonexistentReader;
		this.ignoreRemoveOnNonexistentWriter = ignoreRemoveOnNonexistentWriter;
		this.initMasterByteReader(masterByteReader);
			}

	/*package protected*/ ByteReader resetMasterByteReader(ByteReader masterByteReader) 
	throws IOException
	{
		ByteReader oldMasterByteReader = this.masterByteReader;
		StreamData oldBRData = (StreamData) this.inputStreamData.get(this.masterByteReader);

		// what to do with open references?
		if (oldBRData != null)
		{
			if (oldBRData.getReferences() != 0)
			{
				// TODO - stop being nice
				// are we're gonna be nice?
				if (!this.lenientMasterByteReader)
				{
					throw new RuntimeException("Closing master ByteReader with open streams.");
				} 
			}
		}

		// force the old master bytereader down
		if (oldMasterByteReader != null)
		{
			this.inputStreamData.remove(oldMasterByteReader);
			try
			{
				oldMasterByteReader.close();
			} catch (IOException e) {
				IOException ioe = new IOException("Unable to close master ByteReader: " + oldMasterByteReader);
				ioe.initCause(e);
				throw ioe;
			}
		}

		// finally, reset the master bytereader
		this.initMasterByteReader(masterByteReader);
		return oldMasterByteReader;
	}

	private void initMasterByteReader(ByteReader masterByteReader)
	{
		this.masterByteReader = masterByteReader;
		if (this.masterByteReader != null)
		{
			StreamData newBRData = new StreamData();
			this.inputStreamData.put(this.masterByteReader, newBRData);
		}
	}

	/*package protected*/ boolean addIBS(InputByteStream ibs, ByteReader br)
	{
		boolean ibsFirstTime = false;
		StreamData data = (StreamData) this.inputStreamData.get(br);
		if (data == null)
		{
			data = new StreamData();
			this.inputStreamData.put(br, data);
			ibsFirstTime = true;
		}
		data.addReference();

		return ibsFirstTime;
	}

	/*package protected*/ boolean removeIBS(InputByteStream ibs, ByteReader br)
	{
		boolean lastReference = true;
		StreamData data = (StreamData) this.inputStreamData.get(br);
		if (data == null)
		{
			if (!this.ignoreRemoveOnNonexistentReader)
			{
				throw new RuntimeException("Closing an InputByteStream that isn't in the stream database.");
			}
		} else {
			lastReference = data.removeReference();
			if (lastReference)
			{
				this.inputStreamData.remove(br);
			}
		}
		return lastReference;
	}

	/*package protected*/ boolean addOBS(OutputByteStream obs, ByteWriter bw)
	{
		boolean obsFirstTime = false;
		StreamData data = (StreamData) this.outputStreamData.get(bw);
		if (data == null)
		{
			data = new StreamData();
			this.outputStreamData.put(bw, data);
			obsFirstTime = true;
			//this.maxOBS++;
		}
		data.addReference();

		return obsFirstTime;
	}

	/*package protected*/ boolean removeOBS(OutputByteStream obs, ByteWriter bw)
	{
		boolean lastReference = true;
		StreamData data = (StreamData) this.outputStreamData.get(bw);
		if (data == null)
		{
			if (!this.ignoreRemoveOnNonexistentWriter)
			{
				throw new RuntimeException("Closing an OutputByteStream that isn't in the stream database.");
			}
		} else {
			lastReference = data.removeReference();
			if (lastReference)
			{
				this.outputStreamData.remove(bw);
			}
		}
		return lastReference & !this.inputStreamData.containsKey(bw);
	}

	/*package protected*/ boolean isOutputEmpty()
	{
		return this.outputStreamData.isEmpty();
	}

	/*package protected*/ boolean isInputEmpty()
	{
		return this.inputStreamData.isEmpty();
	}

	/*package protected*/ boolean isEmpty()
	{
		return this.isInputEmpty() && this.isOutputEmpty();
	}

//	/*package protected*/ boolean isEmptyExceptForMasterByteReader()
//	{
//		// must be both empty OR the output is empty and the only thing in the input is the master
//		boolean output = this.isOutputEmpty();
//		boolean input = this.isInputEmpty();
//		boolean onlyMaster = (this.getInputCount() == 1) && this.inputStreamData.containsKey(this.masterByteReader);
//		boolean empty = output && (input || (!input && onlyMaster));
//		return empty;
//	}

	/*package protected*/ int getOutputCount()
	{
		return this.outputStreamData.size();
	}

	/*package protected*/ int getInputCount()
	{
		return this.inputStreamData.size();
	}

	/*package protected*/ int getCount()
	{
		return this.getOutputCount() + this.getInputCount();
	}

	public String toString()
	{
		StringBuilder buffer = new StringBuilder("Open ByteReader = ");
		buffer.append(this.getInputCount()).append("\n").append("Open ByteWriter = ").append(this.getOutputCount()).append("\n").
														append("======== ByteReaders\n");
		Iterator iter = this.inputStreamData.keySet().iterator();
		while (iter.hasNext())
		{
			Object key = iter.next();
			buffer.append("ByteReader = ").append(key.toString()).append("\n");
			StreamData data = (StreamData) this.inputStreamData.get(key);
			buffer.append(data.toString());
		}

		buffer.append("======== ByteWriters\n");
		iter = this.outputStreamData.keySet().iterator();
		while (iter.hasNext())
		{
			Object key = iter.next();
			buffer.append("ByteWriter = ").append(key.toString()).append("\n");
			StreamData data = (StreamData) this.outputStreamData.get(key);
			buffer.append(data.toString());
		}
		return buffer.toString();
	}

	/*package protected*/ int closeAllOpen(boolean ignoreMaster) 
	throws IOException
	{
		int numberOpen = closeAllOpenReaders(ignoreMaster);
		numberOpen += closeAllOpenWriters(ignoreMaster);

		return numberOpen;
	}

	private int closeAllOpenReaders(boolean ignoreMaster) 
	throws IOException
	{
		int numberOpen = 0;

		// close the readers
		Set openReaderSet = this.inputStreamData.keySet();
		numberOpen += openReaderSet.size();
		Iterator readerIter = openReaderSet.iterator();
		while (readerIter.hasNext())
		{
			ByteReader openReader = (ByteReader) readerIter.next();
			if (ignoreMaster && openReader == this.masterByteReader)
			{
				continue;
			}
			try {
				openReader.close();
			} catch (IOException e) {
				IOException ioe = new IOException("Unable to close ByteReader: " + openReader);
				ioe.initCause(e);
				throw ioe;
			}
		}
		this.inputStreamData.clear();

		return numberOpen;
	}

	private int closeAllOpenWriters(boolean ignoreMaster) 
	throws IOException
	{
		int numberOpen = 0;

		// close the writers
		Set openWriterSet = this.outputStreamData.keySet();
		numberOpen += openWriterSet.size();
		Iterator writerIter = openWriterSet.iterator();
		while (writerIter.hasNext())
		{
			ByteWriter openWriter = (ByteWriter) writerIter.next();
			if (ignoreMaster && openWriter == this.masterByteReader)
			{
				continue;
			}
			try {
				openWriter.close();
			} catch (IOException e) {
				IOException ioe = new IOException("Unable to close  ByteWriter: " + openWriter);
				ioe.initCause(e);
				throw ioe;
			}
		}
		this.outputStreamData.clear();

		return numberOpen;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy