/core-avl/src/main/java/org/apache/directory/server/core/avltree/ArrayMarshaller.java

https://bitbucket.org/mirror/apache-directory-server · Java · 203 lines · 103 code · 35 blank · 65 comment · 20 complexity · 626e552478102f124bbabf55fa3325a7 MD5 · raw file

  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. *
  19. */
  20. package org.apache.directory.server.core.avltree;
  21. import java.io.ByteArrayInputStream;
  22. import java.io.ByteArrayOutputStream;
  23. import java.io.DataInputStream;
  24. import java.io.DataOutputStream;
  25. import java.io.IOException;
  26. import java.util.Comparator;
  27. import org.apache.directory.api.util.Strings;
  28. import org.apache.directory.server.i18n.I18n;
  29. /**
  30. * Class to serialize the Array data.
  31. *
  32. * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  33. */
  34. @SuppressWarnings("unchecked")
  35. public class ArrayMarshaller<E> implements Marshaller<ArrayTree<E>>
  36. {
  37. /** used for serialized form of an empty AvlTree */
  38. private static final byte[] EMPTY_TREE = new byte[1];
  39. /** marshaller to be used for marshalling the keys */
  40. private Marshaller<E> keyMarshaller;
  41. /** key Comparator for the AvlTree */
  42. private Comparator<E> comparator;
  43. /**
  44. * Creates a new instance of AvlTreeMarshaller with a custom key
  45. * Marshaller.
  46. *
  47. * @param comparator Comparator to be used for key comparision
  48. * @param keyMarshaller marshaller for keys
  49. */
  50. public ArrayMarshaller( Comparator<E> comparator, Marshaller<E> keyMarshaller )
  51. {
  52. this.comparator = comparator;
  53. this.keyMarshaller = keyMarshaller;
  54. }
  55. /**
  56. * Creates a new instance of AvlTreeMarshaller with the default key
  57. * Marshaller which uses Java Serialization.
  58. *
  59. * @param comparator Comparator to be used for key comparision
  60. */
  61. public ArrayMarshaller( Comparator<E> comparator )
  62. {
  63. this.comparator = comparator;
  64. this.keyMarshaller = ( Marshaller<E> ) DefaultMarshaller.INSTANCE;
  65. }
  66. /**
  67. * Marshals the given tree to bytes
  68. * @param tree the tree to be marshalled
  69. */
  70. public byte[] serialize( ArrayTree<E> tree )
  71. {
  72. if ( ( tree == null ) || ( tree.size() == 0 ) )
  73. {
  74. return EMPTY_TREE;
  75. }
  76. ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
  77. DataOutputStream out = new DataOutputStream( byteStream );
  78. byte[] data = null;
  79. try
  80. {
  81. out.writeByte( 0 ); // represents the start of an Array byte stream
  82. out.writeInt( tree.size() );
  83. for ( int position = 0; position < tree.size(); position++ )
  84. {
  85. E value = tree.get( position );
  86. byte[] bytes = keyMarshaller.serialize( value );
  87. // Write the key length
  88. out.writeInt( bytes.length );
  89. // Write the key if its length is not null
  90. if ( bytes.length != 0 )
  91. {
  92. out.write( bytes );
  93. }
  94. }
  95. out.flush();
  96. data = byteStream.toByteArray();
  97. // Try to deserialize, just to see
  98. /*
  99. try
  100. {
  101. deserialize( data );
  102. }
  103. catch ( NullPointerException npe )
  104. {
  105. System.out.println( I18n.err( I18n.ERR_438, Strings.dumpBytes( data ) ) );
  106. throw npe;
  107. }
  108. */
  109. out.close();
  110. }
  111. catch ( IOException e )
  112. {
  113. e.printStackTrace();
  114. }
  115. return data;
  116. }
  117. /**
  118. * Creates an Array from given bytes of data.
  119. *
  120. * @param data byte array to be converted into an array
  121. */
  122. public ArrayTree<E> deserialize( byte[] data ) throws IOException
  123. {
  124. //LOG.debug( "Deserializing the tree, called by {}", Reflection.getCallerClass( 2 ).getSimpleName() );
  125. try
  126. {
  127. if ( ( data == null ) || ( data.length == 0 ) )
  128. {
  129. throw new IOException( I18n.err( I18n.ERR_439 ) );
  130. }
  131. if ( ( data.length == 1 ) && ( data[0] == 0 ) )
  132. {
  133. E[] array = ( E[] ) new Object[]
  134. {};
  135. ArrayTree<E> tree = new ArrayTree<E>( comparator, array );
  136. return tree;
  137. }
  138. ByteArrayInputStream bin = new ByteArrayInputStream( data );
  139. DataInputStream din = new DataInputStream( bin );
  140. byte startByte = din.readByte();
  141. if ( startByte != 0 )
  142. {
  143. throw new IOException( I18n.err( I18n.ERR_440 ) );
  144. }
  145. int size = din.readInt();
  146. E[] nodes = ( E[] ) new Object[size];
  147. for ( int i = 0; i < size; i++ )
  148. {
  149. // Read the object's size
  150. int dataSize = din.readInt();
  151. if ( dataSize != 0 )
  152. {
  153. byte[] bytes = new byte[dataSize];
  154. din.readFully( bytes );
  155. E key = keyMarshaller.deserialize( bytes );
  156. nodes[i] = key;
  157. }
  158. }
  159. ArrayTree<E> arrayTree = new ArrayTree<E>( comparator, nodes );
  160. return arrayTree;
  161. }
  162. catch ( NullPointerException npe )
  163. {
  164. System.out.println( I18n.err( I18n.ERR_441, Strings.dumpBytes( data ) ) );
  165. throw npe;
  166. }
  167. }
  168. }