001: /*
002: * All content copyright (c) 2003-2007 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.net.groups;
006:
007: import com.tc.io.TCByteBufferInput;
008: import com.tc.io.TCByteBufferOutput;
009: import com.tc.io.TCSerializable;
010: import com.tc.io.serializer.TCObjectInputStream;
011: import com.tc.io.serializer.TCObjectOutputStream;
012:
013: import java.io.ByteArrayInputStream;
014: import java.io.ByteArrayOutputStream;
015: import java.io.IOException;
016: import java.io.ObjectInput;
017: import java.io.ObjectOutput;
018:
019: /**
020: * This is a helper class to hide the serialization and deserialization of NodeID implementations from external world.
021: * Having it here makes it easy to abstract the differences from everywhere else. The downside is that when a new
022: * implementation comes around this class needs to be updated.
023: */
024: public class NodeIDSerializer implements TCSerializable {
025:
026: private static final byte CLIENT_ID = 0x01;
027: private static final byte NODE_ID_IMPL = 0x02;
028:
029: private NodeID nodeID;
030:
031: public NodeIDSerializer() {
032: // NOP
033: }
034:
035: public NodeIDSerializer(NodeID nodeID) {
036: this .nodeID = nodeID;
037: }
038:
039: public NodeID getNodeID() {
040: return nodeID;
041: }
042:
043: public static void writeNodeID(NodeID n, ObjectOutput out)
044: throws IOException {
045: byte type = getType(n);
046: out.writeByte(type);
047: n.writeExternal(out);
048: }
049:
050: private static byte getType(NodeID nodeID) {
051: if (nodeID instanceof ClientID) {
052: return CLIENT_ID;
053: } else if (nodeID instanceof NodeIDImpl) {
054: return NODE_ID_IMPL;
055: } else {
056: throw new AssertionError("Unknown type : "
057: + nodeID.getClass().getName() + " : " + nodeID);
058: }
059: }
060:
061: public static NodeID readNodeID(ObjectInput in) throws IOException,
062: ClassNotFoundException {
063: byte type = in.readByte();
064: NodeID n = getImpl(type);
065: n.readExternal(in);
066: return n;
067: }
068:
069: private static NodeID getImpl(byte type) {
070: switch (type) {
071: case CLIENT_ID:
072: return new ClientID();
073: case NODE_ID_IMPL:
074: return new NodeIDImpl();
075: default:
076: throw new AssertionError("Unknown type : " + type);
077: }
078: }
079:
080: // XXX:: These are not very efficient ways to serialize and deserialize NodeIDs, this is here coz it is used by two
081: // different stack implementation
082: public byte[] getBytes(NodeID n) {
083: try {
084: ByteArrayOutputStream bao = new ByteArrayOutputStream(64);
085: // XXX::NOTE:: We are using TCObjectOutputStream which can only serialize known types. @see writeObject()
086: TCObjectOutputStream tos = new TCObjectOutputStream(bao);
087: writeNodeID(n, tos);
088: tos.close();
089: return bao.toByteArray();
090: } catch (IOException ioe) {
091: throw new AssertionError(ioe);
092: }
093: }
094:
095: // XXX:: These are not very efficient ways to serialize and deserialize NodeIDs, this is here coz it is used by two
096: // different stack implementation
097: public NodeID createFrom(byte[] data) {
098: try {
099: ByteArrayInputStream bais = new ByteArrayInputStream(data);
100: TCObjectInputStream tci = new TCObjectInputStream(bais);
101: return readNodeID(tci);
102: } catch (Exception e) {
103: throw new AssertionError(e);
104: }
105: }
106:
107: public Object deserializeFrom(TCByteBufferInput serialInput)
108: throws IOException {
109: byte type = serialInput.readByte();
110: this .nodeID = getImpl(type);
111: this .nodeID.deserializeFrom(serialInput);
112: return this ;
113: }
114:
115: public void serializeTo(TCByteBufferOutput serialOutput) {
116: serialOutput.writeByte(getType(this.nodeID));
117: this.nodeID.serializeTo(serialOutput);
118: }
119:
120: }
|