Interface Externalizable

All Known Implementing Classes:
AccessToken, CachedData, Cookie, Receipt

public interface Externalizable

Externalizable is similar to the Java SE Externalizable interface this interface. Notice that due to the lack of reflection and use of obfuscation these objects must be registered with the Util class.

Also notice that all externalizable objects must have a default public constructor.

Built-In Object types

The externalization process supports serializing these types and considers them to be Externalizable. E.g. you can just write Storage.getInstance().writeObject(new Object[] {"Str1", "Str2");} and it will work as expected.

Notice that while these objects can be written, the process doesn't guarantee they will be read with the same object type. E.g. if you write a java.util.LinkedList you could get back a java.util.ArrayList as both implement java.util.Collection:

java.lang.String, java.util.Collection, java.util.Map, java.util.ArrayList, java.util.HashMap, java.util.Vector, java.util.Hashtable, java.lang.Integer, java.lang.Double, java.lang.Float, java.lang.Byte, java.lang.Short, java.lang.Long, java.lang.Character, java.lang.Boolean, Object[], byte[], int[], float[], long[], double[].

The sample below demonstrates the usage and registration of the Externalizable interface:

// File: Main.java
public Main {
  public void init(Object o) {
    theme = UIManager.initFirstTheme("/theme");

    // IMPORTANT: Notice we don't use MyClass.class.getName()! This won't work due to obfuscation!
    Util.register("MyClass", MyClass.class);
  }

  public void start() {
    //...
  }

  public void stop() {
    //...
  }

  public void destroy() {
    //...
  }
}
// File: MyClass.java
public MyClass implements Externalizable {
  // allows us to manipulate the version, in this case we are demonstrating a data change between the initial release
  // and the current state of object data
  private static final int VERSION = 2;

  private String name;
  private Map data;

  // this field was added after version 1
  private Date startedAt;

  public int getVersion() {
    return VERSION;
  }

  public void externalize(DataOutputStream out) throws IOException {
    Util.writeUTF(name, out);
    Util.writeObject(data, out);
    if(startedAt != null) {
        out.writeBoolean(true);
        out.writeLong(startedAt.getTime());
    } else {
        out.writeBoolean(false);
    }
  }
  public void internalize(int version, DataInputStream in) throws IOException {
    name = Util.readUTF(in);
    data = (Map)Util.readObject(in);
    if(version > 1) {
        boolean hasDate = in.readBoolean();
        if(hasDate) {
            startedAt = new Date(in.readLong());
        }
    }
  }
  public String getObjectId() {
    // IMPORTANT: Notice we don't use getClass().getName()! This won't work due to obfuscation!
    return "MyClass";
  }
}
// File: ReadAndWrite.java
// will read the file or return null if failed
MyClass object = (MyClass)Storage.getInstance().readObject("NameOfFile");

// write the object back to storage
Storage.getInstance().writeObject("NameOfFile", object);

WARNING: The externalization process caches objects so the app will seem to work and only fail on restart!

  • Method Summary

    Modifier and Type
    Method
    Description
    void
    Allows us to store an object state, this method must be implemented in order to save the state of an object
    The object id must be unique, it is used to identify the object when loaded even when it is obfuscated.
    int
    Returns the version for the current persistance code, the version will be pased to internalized thus allowing the internalize method to recognize classes persisted in older revisions
    void
    internalize(int version, DataInputStream in)
    Loads the object from the input stream and allows deserialization
  • Method Details

    • getVersion

      int getVersion()

      Returns the version for the current persistance code, the version will be pased to internalized thus allowing the internalize method to recognize classes persisted in older revisions

      Returns

      version number for the persistant code

    • externalize

      void externalize(DataOutputStream out) throws IOException

      Allows us to store an object state, this method must be implemented in order to save the state of an object

      Parameters
      • out: the stream into which the object must be serialized
      Throws
      • java.io.IOException: the method may throw an exception
      Throws:
      IOException
    • internalize

      void internalize(int version, DataInputStream in) throws IOException

      Loads the object from the input stream and allows deserialization

      Parameters
      • version: the version the class returned during the externalization processs

      • in: the input stream used to load the class

      Throws
      • java.io.IOException: the method may throw an exception
      Throws:
      IOException
    • getObjectId

      String getObjectId()

      The object id must be unique, it is used to identify the object when loaded even when it is obfuscated.

      Returns

      a unique id