/* * Bibliothek - DockingFrames * Library built on Java/Swing, allows the user to "drag and drop" * panels containing any Swing-Component the developer likes to add. * * Copyright (C) 2007 Benjamin Sigg * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Benjamin Sigg * benjamin_sigg@gmx.ch * CH - Switzerland */ package bibliothek.gui.dock.support.util; import java.io.*; import java.util.HashMap; import java.util.Map; import java.util.prefs.Preferences; import bibliothek.util.Version; import bibliothek.util.xml.XElement; /** * Manages a set of {@link ApplicationResource}s, can load and store the * resources at any time.<br> * The {@link ApplicationResource}s are organized in a {@link Map}. Each * resource is associated with a unique key. This key is used to determine, which * stream of bytes belongs to which resource. If data is loaded, the byte-streams * for missing resources will be stored in a buffer that is read as soon as * a missing resource is registered. Additional resources are ignored.<br> * Note that there is no order how the resources are stored in the file. * @author Benjamin Sigg * */ public class ApplicationResourceManager { /** the map of all resources known to this manager */ private Map<String, ApplicationResource> resources = new HashMap<String, ApplicationResource>(); /** buffer for streams which are not yet read */ private Map<String, Object> buffer = new HashMap<String, Object>(); /** * Stores a resource that might be read or written at any time. If a stream * was already read by this manager, and if there was an entry in that stream * that equals <code>name</code>, then <code>resource</code> will immediately * be asked to read the stream. * @param name the unique identifier of the resource * @param resource the new resource * @throws NullPointerException if <code>name</code> of <code>resource</code> * is <code>null</code> * @throws IOException if the buffered stream can't be read. The resource * will be stored in this manager even if an exception occurs */ public void put( String name, ApplicationResource resource ) throws IOException{ if( name == null ) throw new NullPointerException( "name must not be null" ); if( resource == null ) throw new NullPointerException( "resource must not be null" ); resources.put( name, resource ); Object buffered = buffer.get( name ); if( buffered != null ){ if( buffered instanceof byte[] ){ ByteArrayInputStream in = new ByteArrayInputStream( (byte[])buffered ); DataInputStream data = new DataInputStream( in ); resource.read( data ); data.close(); } if( buffered instanceof XElement ){ resource.readXML( (XElement)buffered ); } } } /** * Removes a resources that was earlier added to this manager. * @param name the name of the resource to remove */ public void remove( String name ){ resources.remove( name ); } /** * Writes all currently known {@link ApplicationResource}s into * <code>out</code>. * @param out the stream to write into * @throws IOException if the operation can't be completed */ public void writeStream( DataOutputStream out ) throws IOException{ // version Version.write( out, Version.VERSION_1_0_4 ); // number of elements out.writeInt( resources.size() ); // elements for( Map.Entry<String, ApplicationResource> resource : resources.entrySet() ){ out.writeUTF( resource.getKey() ); ByteArrayOutputStream array = new ByteArrayOutputStream(); DataOutputStream data = new DataOutputStream( array ); resource.getValue().write( data ); data.close(); // write out the array out.writeInt( array.size() ); array.writeTo( out ); } } /** * Lets all {@link ApplicationResource}s read from <code>in</code>. * @param in the stream to read from * @throws IOException if the operation can't be completed */ public void readStream( DataInputStream in ) throws IOException{ Version version = Version.read( in ); version.checkCurrent(); int size = in.readInt(); for( int i = 0; i < size; i++ ){ String key = in.readUTF(); int length = in.readInt(); byte[] input = new byte[ length ]; in.readFully( input ); ApplicationResource resource = resources.get( key ); if( resource != null ){ ByteArrayInputStream array = new ByteArrayInputStream( input ); DataInputStream data = new DataInputStream( array ); resource.read( data ); data.close(); } else buffer.put( key, input ); } } /** * Writes the content of this manager in xml format. * @param element the element to write into, the attributes of this * element will not be changed. */ public void writeXML( XElement element ){ for( Map.Entry<String, ApplicationResource> resource : resources.entrySet() ){ XElement xresource = element.addElement( "resource" ); xresource.addString( "name", resource.getKey() ); resource.getValue().writeXML( xresource ); } } /** * Reads the contents of this manager from a xml element. * @param element the element to read */ public void readXML( XElement element ){ for( XElement xresource : element.getElements( "resource" )){ String name = xresource.getString( "name" ); ApplicationResource resource = resources.get( name ); if( resource != null ){ resource.readXML( xresource ); } else buffer.put( name, xresource ); } } /** * Writes the contents of this manager into <code>file</code>. * @param file the file to write into * @throws IOException if the operation can't be completed */ public void writeFile( File file ) throws IOException{ DataOutputStream out = new DataOutputStream( new BufferedOutputStream( new FileOutputStream( file ))); try{ writeStream( out ); } finally{ out.close(); } } /** * Reads the contents of this manager from <code>file</code>. * @param file the file to read * @throws IOException if the operation can't be completed */ public void readFile( File file ) throws IOException{ DataInputStream in = new DataInputStream( new BufferedInputStream( new FileInputStream( file ))); try{ readStream( in ); } finally{ in.close(); } } /** * Writes the contents of this manager into an array of bytes. * @return the contents as stream of bytes * @throws IOException if the operation can't be completed */ public byte[] writeArray() throws IOException{ ByteArrayOutputStream out = new ByteArrayOutputStream(); DataOutputStream data = new DataOutputStream( out ); writeStream( data ); data.close(); return out.toByteArray(); } /** * Reads the contents of this manager from an array of bytes. * @param array the content as stream of bytes * @throws IOException if the operation can't be completed */ public void readArray( byte[] array ) throws IOException{ ByteArrayInputStream in = new ByteArrayInputStream( array ); DataInputStream data = new DataInputStream( in ); readStream( data ); data.close(); } /** * Writes the contents of this manager into the {@link Preferences} which * represent the package of {@link ApplicationResourceManager}. * @throws IOException if the operation can't be completed */ public void writePreferences() throws IOException{ Preferences preference = Preferences.userNodeForPackage( ApplicationResourceManager.class ); preference.putByteArray( "content", writeArray() ); } /** * Reads the content of this manager from the {@link Preferences} that * represent the package of {@link ApplicationResourceManager}. * @throws IOException if the operation can't be completed */ public void readPreferences() throws IOException{ Preferences preference = Preferences.userNodeForPackage( ApplicationResourceManager.class ); byte[] array = preference.getByteArray( "content", null ); if( array != null ) readArray( array ); } }