Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

Pickle.d

Go to the documentation of this file.
00001 /*******************************************************************************
00002 
00003         @file Pickle.d
00004 
00005         This is a distillation of the relevant Mango.io portions, combined
00006         for the purposes of readability. The original files include:
00007 
00008         IWriter.d
00009         IReader.d
00010         IPickle.d
00011         PickleRegistry.d
00012         Exception.d
00013 
00014         Copyright (C) 2004 Kris Bell
00015 
00016         This software is provided 'as-is', without any express or implied
00017         warranty. In no event will the authors be held liable for damages
00018         of any kind arising from the use of this software.
00019 
00020         Permission is hereby granted to anyone to use this software for any 
00021         purpose, including commercial applications, and to alter it and/or 
00022         redistribute it freely, subject to the following restrictions:
00023 
00024         1. The origin of this software must not be misrepresented; you must 
00025            not claim that you wrote the original software. If you use this 
00026            software in a product, an acknowledgment within documentation of 
00027            said product would be appreciated but is not required.
00028 
00029         2. Altered source versions must be plainly marked as such, and must 
00030            not be misrepresented as being the original software.
00031 
00032         3. This notice may not be removed or altered from any distribution
00033            of the source.
00034 
00035 
00036                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00037 
00038 
00039         @version        Initial version, November 2004      
00040         @author         Kris
00041 
00042 *******************************************************************************/
00043 
00044 
00045 
00046 /*******************************************************************************
00047 
00048         Any class implementing IReadable becomes part of the Reader framework
00049 
00050 *******************************************************************************/
00051 
00052 interface IReadable
00053 {
00054         void read (IReader r);
00055 }
00056 
00057 /*******************************************************************************
00058 
00059         Interface to make any class compatible with any IWriter.
00060 
00061 *******************************************************************************/
00062 
00063 interface IWritable
00064 {
00065         void write (IWriter w);
00066 }
00067 
00068 /*******************************************************************************
00069 
00070         Interface for all serializable classes. Such classes are intended
00071         to be transported over a network, or be frozen in a file for later
00072         reconstruction. 
00073 
00074 *******************************************************************************/
00075 
00076 interface IPickle : IWritable, IReadable
00077 {
00078         /***********************************************************************
00079 
00080                 Identify this serializable class via a char[]. This should
00081                 be (per class) unique within the domain. Use version numbers 
00082                 or similar mechanism to isolate different implementations of
00083                 the same class.
00084 
00085         ***********************************************************************/
00086 
00087         char[] getGuid ();
00088 }
00089 
00090 
00091 /*******************************************************************************
00092 
00093         Interface for all deserializable classes. Such classes either 
00094         implement the full concrete class instance or they act as a
00095         proxy of sorts, creating the true instance only when called 
00096         upon to do so. An IPickleProxy could perhaps take alternative 
00097         action when called upon to create an "old" or "unsupported" 
00098         class guid. The default behaviour is to throw an exception
00099         when an unknown guid is seen.
00100 
00101 *******************************************************************************/
00102 
00103 interface IPickleFactory
00104 {
00105         /***********************************************************************
00106 
00107                 Identify this serializable class via a char[]. This should
00108                 be (per class) unique within the domain. Use version numbers 
00109                 or similar mechanism to isolate different implementations of
00110                 the same class.
00111 
00112         ***********************************************************************/
00113 
00114         char[] getGuid ();
00115 
00116         /***********************************************************************
00117 
00118                 This defines the factory method. Each IPickleProxy object
00119                 provides a factory for creating a deserialized instance.
00120                 The factory is registered along with the appropriate guid.
00121 
00122         ***********************************************************************/
00123 
00124         Object create (IReader reader);
00125 }
00126 
00127 
00128 /*******************************************************************************
00129 
00130         PickleException is thrown when the PickleRegistry encounters a 
00131         problem during proxy registration, or when it sees an unregistered
00132         guid.
00133 
00134 *******************************************************************************/
00135 
00136 class PickleException : IOException
00137 {
00138         /***********************************************************************
00139 
00140                 Construct exception with the provided text string
00141 
00142         ***********************************************************************/
00143 
00144         this (char[] msg)
00145         {
00146                 super (msg);
00147         }        
00148 }
00149 
00150 /*******************************************************************************
00151 
00152         Bare framework for registering and creating serializable objects.
00153         Such objects are intended to be transported across a local network
00154         and re-instantiated at some destination node. 
00155 
00156         Each IPickle exposes the means to write, or freeze, its content. An
00157         IPickleFactory provides the means to create a new instance of itself
00158         populated with thawed data. Frozen objects are uniquely identified 
00159         by a guid exposed via the interface. Responsibility of maintaining
00160         uniqueness across said identifiers lies in the hands of the developer.
00161 
00162         See PickleReader for an example of how this is expected to operate.
00163 
00164 *******************************************************************************/
00165 
00166 class PickleRegistry
00167 {
00168         private static Proxy[char[]] registry;
00169 
00170         /***********************************************************************
00171 
00172                 This is a singleton: the constructor should not be exposed
00173 
00174         ***********************************************************************/
00175 
00176         private this ()
00177         {
00178         }
00179 
00180         /***********************************************************************
00181         
00182                 IPickleFactory registrar entry
00183 
00184         ***********************************************************************/
00185 
00186         private class Proxy
00187         {
00188                 IPickleFactory factory;
00189 
00190                 /***************************************************************
00191         
00192                 ***************************************************************/
00193               
00194                 this (IPickleFactory factory)
00195                 {
00196                         this.factory = factory;
00197                 }
00198 
00199                 /***************************************************************
00200         
00201                 ***************************************************************/
00202               
00203                 Object create (IReader reader)
00204                 {       
00205                         return factory.create (reader);
00206                 }
00207         }
00208 
00209         /***********************************************************************
00210         
00211                 Add the provided object to the registry. Note that one
00212                 cannot change a registration once it is placed. Neither
00213                 can one remove registered item. This is done to avoid 
00214                 major issues when trying to synchronize servers across
00215                 a farm, which may still have live instances of "old"
00216                 objects waiting to be passed around the cluster. New
00217                 versions of an object should be given a distinct guid
00218                 from the prior version; appending an incremental number 
00219                 may well be sufficient for your needs.
00220 
00221         ***********************************************************************/
00222 
00223         static void enroll (IPickleFactory object)
00224         {
00225                 char[] guid = object.getGuid;
00226 
00227                 synchronized {
00228                              if (guid in registry)
00229                                  throw new PickleException ("Invalid attempt to re-register a guid");
00230 
00231                              registry[guid] = new Proxy (object);
00232                              }
00233         }
00234 
00235         /***********************************************************************
00236         
00237                 Create a new instance of a registered class from the content
00238                 made available via the given reader. The factory is located
00239                 using the provided guid, which must match an enrolled class.
00240 
00241         ***********************************************************************/
00242 
00243         static Object create (IReader reader, char[] guid)
00244         {
00245                 // locate the appropriate Proxy.
00246                 synchronized {
00247                              if (guid in registry)
00248                                  return registry[guid].create(reader);
00249                              }
00250 
00251                 throw new PickleException ("Attempt to unpickle via unregistered guid '"~guid~"'");
00252         }
00253 }
00254 

Generated on Tue Jan 25 21:18:22 2005 for Mango by doxygen 1.3.6