001/*-------------------------------------------------------------------------+ 002| | 003| Copyright 2005-2011 the ConQAT Project | 004| | 005| Licensed under the Apache License, Version 2.0 (the "License"); | 006| you may not use this file except in compliance with the License. | 007| You may obtain a copy of the License at | 008| | 009| http://www.apache.org/licenses/LICENSE-2.0 | 010| | 011| Unless required by applicable law or agreed to in writing, software | 012| distributed under the License is distributed on an "AS IS" BASIS, | 013| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 014| See the License for the specific language governing permissions and | 015| limitations under the License. | 016+-------------------------------------------------------------------------*/ 017package org.conqat.lib.commons.serialization.classes; 018 019import java.io.DataInputStream; 020import java.io.DataOutputStream; 021import java.io.IOException; 022import java.io.ObjectStreamConstants; 023import java.util.ArrayList; 024import java.util.List; 025 026import org.conqat.lib.commons.serialization.SerializedEntityBase; 027import org.conqat.lib.commons.serialization.SerializedEntityParser; 028import org.conqat.lib.commons.serialization.SerializedEntityPool; 029import org.conqat.lib.commons.serialization.SerializedEntitySerializer; 030 031/** 032 * Base class for all serialized classes. 033 */ 034public abstract class SerializedClassBase extends SerializedEntityBase { 035 036 /** Handle to the super class (or null handle). */ 037 protected int superClassHandle = SerializedEntityPool.NULL_HANDLE; 038 039 /** 040 * Class annotations. These are either byte arrays for block data, or integer 041 * values representing handles. 042 */ 043 private final List<Object> classAnnotations = new ArrayList<>(); 044 045 /** Constructor for parsing. */ 046 protected SerializedClassBase(DataInputStream din, SerializedEntityPool pool, SerializedEntityParser parser) 047 throws IOException { 048 super(pool); 049 050 parseClass(din, pool, parser); 051 052 readClassAnnotation(din, parser); 053 readSuperClassDescription(parser); 054 } 055 056 /** Direct constructor. */ 057 protected SerializedClassBase(SerializedEntityPool pool) { 058 super(pool); 059 } 060 061 /** 062 * Parses the class content. This is called from the constructor, so fields of 063 * sub classes might not be initialized. 064 */ 065 protected abstract void parseClass(DataInputStream din, SerializedEntityPool pool, SerializedEntityParser parser) 066 throws IOException; 067 068 /** Reads the description of the super class. */ 069 private void readSuperClassDescription(SerializedEntityParser parser) throws IOException { 070 this.superClassHandle = parser.parseClassDesc(); 071 } 072 073 /** Reads the <code>classAnnotation</code> part of a class description. */ 074 private void readClassAnnotation(DataInputStream din, SerializedEntityParser parser) throws IOException { 075 while (true) { 076 din.mark(1); 077 078 byte next = din.readByte(); 079 switch (next) { 080 case ObjectStreamConstants.TC_ENDBLOCKDATA: 081 return; 082 case ObjectStreamConstants.TC_BLOCKDATA: 083 classAnnotations.add(readBlockData(din, din.readUnsignedByte())); 084 break; 085 case ObjectStreamConstants.TC_BLOCKDATALONG: 086 classAnnotations.add(readBlockData(din, din.readInt())); 087 break; 088 default: 089 din.reset(); 090 classAnnotations.add(parser.parseContent()); 091 break; 092 } 093 } 094 } 095 096 /** Reads block data. */ 097 private static byte[] readBlockData(DataInputStream din, int length) throws IOException { 098 byte[] result = new byte[length]; 099 din.readFully(result); 100 return result; 101 } 102 103 /** {@inheritDoc} */ 104 @Override 105 protected final void serializeContent(DataOutputStream dos, SerializedEntitySerializer serializer) 106 throws IOException { 107 serializer.registerHandle(this); 108 109 serializeClass(dos, serializer); 110 111 serializeClassAnnotation(dos, serializer); 112 serializeSuperClass(dos, serializer); 113 } 114 115 /** Serializes the class part of this entity. */ 116 protected abstract void serializeClass(DataOutputStream dos, SerializedEntitySerializer serializer) 117 throws IOException; 118 119 /** Serializes the super class. */ 120 private void serializeSuperClass(DataOutputStream dos, SerializedEntitySerializer serializer) throws IOException { 121 SerializedEntitySerializer.serializeObject(superClassHandle, SerializedClassBase.class, pool, dos, serializer); 122 } 123 124 /** Serializes the class annotation part. */ 125 private void serializeClassAnnotation(DataOutputStream dos, SerializedEntitySerializer serializer) 126 throws IOException { 127 serializer.serializeAnnotationList(classAnnotations, pool); 128 129 // end of class annotation always signaled via endBlockData 130 dos.writeByte(ObjectStreamConstants.TC_ENDBLOCKDATA); 131 } 132 133 /** Returns the handle of the super class. */ 134 public int getSuperClassHandle() { 135 return superClassHandle; 136 } 137}