Coverage Summary for Class: Serialization (com.google.common.collect)

Class Method, % Line, %
Serialization 0% (0/12) 0% (0/46)
Serialization$FieldSetter 0% (0/4) 0% (0/12)
Total 0% (0/16) 0% (0/58)


1 /* 2  * Copyright (C) 2008 The Guava Authors 3  * 4  * Licensed under the Apache License, Version 2.0 (the "License"); 5  * you may not use this file except in compliance with the License. 6  * You may obtain a copy of the License at 7  * 8  * http://www.apache.org/licenses/LICENSE-2.0 9  * 10  * Unless required by applicable law or agreed to in writing, software 11  * distributed under the License is distributed on an "AS IS" BASIS, 12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13  * See the License for the specific language governing permissions and 14  * limitations under the License. 15  */ 16  17 package com.google.common.collect; 18  19 import com.google.common.annotations.GwtIncompatible; 20 import java.io.IOException; 21 import java.io.ObjectInputStream; 22 import java.io.ObjectOutputStream; 23 import java.lang.reflect.Field; 24 import java.util.Collection; 25 import java.util.Map; 26  27 /** 28  * Provides static methods for serializing collection classes. 29  * 30  * <p>This class assists the implementation of collection classes. Do not use this class to 31  * serialize collections that are defined elsewhere. 32  * 33  * @author Jared Levy 34  */ 35 @GwtIncompatible 36 final class Serialization { 37  private Serialization() {} 38  39  /** 40  * Reads a count corresponding to a serialized map, multiset, or multimap. It returns the size of 41  * a map serialized by {@link #writeMap(Map, ObjectOutputStream)}, the number of distinct elements 42  * in a multiset serialized by {@link #writeMultiset(Multiset, ObjectOutputStream)}, or the number 43  * of distinct keys in a multimap serialized by {@link #writeMultimap(Multimap, 44  * ObjectOutputStream)}. 45  */ 46  static int readCount(ObjectInputStream stream) throws IOException { 47  return stream.readInt(); 48  } 49  50  /** 51  * Stores the contents of a map in an output stream, as part of serialization. It does not support 52  * concurrent maps whose content may change while the method is running. 53  * 54  * <p>The serialized output consists of the number of entries, first key, first value, second key, 55  * second value, and so on. 56  */ 57  static <K, V> void writeMap(Map<K, V> map, ObjectOutputStream stream) throws IOException { 58  stream.writeInt(map.size()); 59  for (Map.Entry<K, V> entry : map.entrySet()) { 60  stream.writeObject(entry.getKey()); 61  stream.writeObject(entry.getValue()); 62  } 63  } 64  65  /** 66  * Populates a map by reading an input stream, as part of deserialization. See {@link #writeMap} 67  * for the data format. 68  */ 69  static <K, V> void populateMap(Map<K, V> map, ObjectInputStream stream) 70  throws IOException, ClassNotFoundException { 71  int size = stream.readInt(); 72  populateMap(map, stream, size); 73  } 74  75  /** 76  * Populates a map by reading an input stream, as part of deserialization. See {@link #writeMap} 77  * for the data format. The size is determined by a prior call to {@link #readCount}. 78  */ 79  static <K, V> void populateMap(Map<K, V> map, ObjectInputStream stream, int size) 80  throws IOException, ClassNotFoundException { 81  for (int i = 0; i < size; i++) { 82  @SuppressWarnings("unchecked") // reading data stored by writeMap 83  K key = (K) stream.readObject(); 84  @SuppressWarnings("unchecked") // reading data stored by writeMap 85  V value = (V) stream.readObject(); 86  map.put(key, value); 87  } 88  } 89  90  /** 91  * Stores the contents of a multiset in an output stream, as part of serialization. It does not 92  * support concurrent multisets whose content may change while the method is running. 93  * 94  * <p>The serialized output consists of the number of distinct elements, the first element, its 95  * count, the second element, its count, and so on. 96  */ 97  static <E> void writeMultiset(Multiset<E> multiset, ObjectOutputStream stream) 98  throws IOException { 99  int entryCount = multiset.entrySet().size(); 100  stream.writeInt(entryCount); 101  for (Multiset.Entry<E> entry : multiset.entrySet()) { 102  stream.writeObject(entry.getElement()); 103  stream.writeInt(entry.getCount()); 104  } 105  } 106  107  /** 108  * Populates a multiset by reading an input stream, as part of deserialization. See {@link 109  * #writeMultiset} for the data format. 110  */ 111  static <E> void populateMultiset(Multiset<E> multiset, ObjectInputStream stream) 112  throws IOException, ClassNotFoundException { 113  int distinctElements = stream.readInt(); 114  populateMultiset(multiset, stream, distinctElements); 115  } 116  117  /** 118  * Populates a multiset by reading an input stream, as part of deserialization. See {@link 119  * #writeMultiset} for the data format. The number of distinct elements is determined by a prior 120  * call to {@link #readCount}. 121  */ 122  static <E> void populateMultiset( 123  Multiset<E> multiset, ObjectInputStream stream, int distinctElements) 124  throws IOException, ClassNotFoundException { 125  for (int i = 0; i < distinctElements; i++) { 126  @SuppressWarnings("unchecked") // reading data stored by writeMultiset 127  E element = (E) stream.readObject(); 128  int count = stream.readInt(); 129  multiset.add(element, count); 130  } 131  } 132  133  /** 134  * Stores the contents of a multimap in an output stream, as part of serialization. It does not 135  * support concurrent multimaps whose content may change while the method is running. The {@link 136  * Multimap#asMap} view determines the ordering in which data is written to the stream. 137  * 138  * <p>The serialized output consists of the number of distinct keys, and then for each distinct 139  * key: the key, the number of values for that key, and the key's values. 140  */ 141  static <K, V> void writeMultimap(Multimap<K, V> multimap, ObjectOutputStream stream) 142  throws IOException { 143  stream.writeInt(multimap.asMap().size()); 144  for (Map.Entry<K, Collection<V>> entry : multimap.asMap().entrySet()) { 145  stream.writeObject(entry.getKey()); 146  stream.writeInt(entry.getValue().size()); 147  for (V value : entry.getValue()) { 148  stream.writeObject(value); 149  } 150  } 151  } 152  153  /** 154  * Populates a multimap by reading an input stream, as part of deserialization. See {@link 155  * #writeMultimap} for the data format. 156  */ 157  static <K, V> void populateMultimap(Multimap<K, V> multimap, ObjectInputStream stream) 158  throws IOException, ClassNotFoundException { 159  int distinctKeys = stream.readInt(); 160  populateMultimap(multimap, stream, distinctKeys); 161  } 162  163  /** 164  * Populates a multimap by reading an input stream, as part of deserialization. See {@link 165  * #writeMultimap} for the data format. The number of distinct keys is determined by a prior call 166  * to {@link #readCount}. 167  */ 168  static <K, V> void populateMultimap( 169  Multimap<K, V> multimap, ObjectInputStream stream, int distinctKeys) 170  throws IOException, ClassNotFoundException { 171  for (int i = 0; i < distinctKeys; i++) { 172  @SuppressWarnings("unchecked") // reading data stored by writeMultimap 173  K key = (K) stream.readObject(); 174  Collection<V> values = multimap.get(key); 175  int valueCount = stream.readInt(); 176  for (int j = 0; j < valueCount; j++) { 177  @SuppressWarnings("unchecked") // reading data stored by writeMultimap 178  V value = (V) stream.readObject(); 179  values.add(value); 180  } 181  } 182  } 183  184  // Secret sauce for setting final fields; don't make it public. 185  static <T> FieldSetter<T> getFieldSetter(final Class<T> clazz, String fieldName) { 186  try { 187  Field field = clazz.getDeclaredField(fieldName); 188  return new FieldSetter<T>(field); 189  } catch (NoSuchFieldException e) { 190  throw new AssertionError(e); // programmer error 191  } 192  } 193  194  // Secret sauce for setting final fields; don't make it public. 195  static final class FieldSetter<T> { 196  private final Field field; 197  198  private FieldSetter(Field field) { 199  this.field = field; 200  field.setAccessible(true); 201  } 202  203  void set(T instance, Object value) { 204  try { 205  field.set(instance, value); 206  } catch (IllegalAccessException impossible) { 207  throw new AssertionError(impossible); 208  } 209  } 210  211  void set(T instance, int value) { 212  try { 213  field.set(instance, value); 214  } catch (IllegalAccessException impossible) { 215  throw new AssertionError(impossible); 216  } 217  } 218  } 219 }