1090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson/* 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2008 The Guava Authors 3090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 4090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 5090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * you may not use this file except in compliance with the License. 6090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * You may obtain a copy of the License at 7090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 8090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 9090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 10090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Unless required by applicable law or agreed to in writing, software 11090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 12090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * See the License for the specific language governing permissions and 14090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * limitations under the License. 15090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 16090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 17090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonpackage com.google.common.collect; 18090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 19090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.io.IOException; 20090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.io.ObjectInputStream; 21090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.io.ObjectOutputStream; 22090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.lang.reflect.Field; 23090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.util.Collection; 24090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.util.Map; 25090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 26090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson/** 27090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Provides static methods for serializing collection classes. 28090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 29090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * <p>This class assists the implementation of collection classes. Do not use 30090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * this class to serialize collections that are defined elsewhere. 31090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 32090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @author Jared Levy 33090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 34090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonfinal class Serialization { 35090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private Serialization() {} 36090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 37090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** 38090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Reads a count corresponding to a serialized map, multiset, or multimap. It 39090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * returns the size of a map serialized by {@link 40090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * #writeMap(Map, ObjectOutputStream)}, the number of distinct elements in a 41090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * multiset serialized by {@link 42090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * #writeMultiset(Multiset, ObjectOutputStream)}, or the number of distinct 43090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * keys in a multimap serialized by {@link 44090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * #writeMultimap(Multimap, ObjectOutputStream)}. 45090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 46090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * <p>The returned count may be used to construct an empty collection of the 47090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * appropriate capacity before calling any of the {@code populate} methods. 48090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert static int readCount(ObjectInputStream stream) throws IOException { 50090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return stream.readInt(); 51090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 52090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 53090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** 54090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Stores the contents of a map in an output stream, as part of serialization. 55090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * It does not support concurrent maps whose content may change while the 56090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * method is running. 57090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 58090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * <p>The serialized output consists of the number of entries, first key, 59090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * first value, second key, second value, and so on. 60090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert static <K, V> void writeMap(Map<K, V> map, ObjectOutputStream stream) 62090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson throws IOException { 63090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson stream.writeInt(map.size()); 64090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson for (Map.Entry<K, V> entry : map.entrySet()) { 65090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson stream.writeObject(entry.getKey()); 66090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson stream.writeObject(entry.getValue()); 67090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 68090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 69090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 70090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** 71090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Populates a map by reading an input stream, as part of deserialization. 72090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * See {@link #writeMap} for the data format. 73090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert static <K, V> void populateMap(Map<K, V> map, ObjectInputStream stream) 75090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson throws IOException, ClassNotFoundException { 76090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson int size = stream.readInt(); 77090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson populateMap(map, stream, size); 78090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 79090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 80090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** 81090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Populates a map by reading an input stream, as part of deserialization. 82090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * See {@link #writeMap} for the data format. The size is determined by a 83090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * prior call to {@link #readCount}. 84090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert static <K, V> void populateMap(Map<K, V> map, ObjectInputStream stream, 86090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson int size) throws IOException, ClassNotFoundException { 87090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson for (int i = 0; i < size; i++) { 88090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @SuppressWarnings("unchecked") // reading data stored by writeMap 89090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson K key = (K) stream.readObject(); 90090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @SuppressWarnings("unchecked") // reading data stored by writeMap 91090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson V value = (V) stream.readObject(); 92090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson map.put(key, value); 93090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 94090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 95090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 96090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** 97090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Stores the contents of a multiset in an output stream, as part of 98090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * serialization. It does not support concurrent multisets whose content may 99090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * change while the method is running. 100090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 101090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * <p>The serialized output consists of the number of distinct elements, the 102090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * first element, its count, the second element, its count, and so on. 103090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert static <E> void writeMultiset( 105090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Multiset<E> multiset, ObjectOutputStream stream) throws IOException { 106090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson int entryCount = multiset.entrySet().size(); 107090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson stream.writeInt(entryCount); 108090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson for (Multiset.Entry<E> entry : multiset.entrySet()) { 109090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson stream.writeObject(entry.getElement()); 110090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson stream.writeInt(entry.getCount()); 111090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 112090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 113090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 114090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** 115090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Populates a multiset by reading an input stream, as part of 116090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * deserialization. See {@link #writeMultiset} for the data format. 117090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert static <E> void populateMultiset( 119090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Multiset<E> multiset, ObjectInputStream stream) 120090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson throws IOException, ClassNotFoundException { 121090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson int distinctElements = stream.readInt(); 122090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson populateMultiset(multiset, stream, distinctElements); 123090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 124090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 125090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** 126090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Populates a multiset by reading an input stream, as part of 127090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * deserialization. See {@link #writeMultiset} for the data format. The number 128090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * of distinct elements is determined by a prior call to {@link #readCount}. 129090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert static <E> void populateMultiset( 131090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Multiset<E> multiset, ObjectInputStream stream, int distinctElements) 132090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson throws IOException, ClassNotFoundException { 133090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson for (int i = 0; i < distinctElements; i++) { 134090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @SuppressWarnings("unchecked") // reading data stored by writeMultiset 135090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson E element = (E) stream.readObject(); 136090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson int count = stream.readInt(); 137090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson multiset.add(element, count); 138090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 139090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 140090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 141090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** 142090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Stores the contents of a multimap in an output stream, as part of 143090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * serialization. It does not support concurrent multimaps whose content may 144090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * change while the method is running. The {@link Multimap#asMap} view 145090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * determines the ordering in which data is written to the stream. 146090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 147090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * <p>The serialized output consists of the number of distinct keys, and then 148090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * for each distinct key: the key, the number of values for that key, and the 149090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * key's values. 150090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert static <K, V> void writeMultimap( 152090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Multimap<K, V> multimap, ObjectOutputStream stream) throws IOException { 153090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson stream.writeInt(multimap.asMap().size()); 154090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson for (Map.Entry<K, Collection<V>> entry : multimap.asMap().entrySet()) { 155090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson stream.writeObject(entry.getKey()); 156090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson stream.writeInt(entry.getValue().size()); 157090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson for (V value : entry.getValue()) { 158090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson stream.writeObject(value); 159090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 160090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 161090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 162090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 163090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** 164090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Populates a multimap by reading an input stream, as part of 165090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * deserialization. See {@link #writeMultimap} for the data format. 166090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert static <K, V> void populateMultimap( 168090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Multimap<K, V> multimap, ObjectInputStream stream) 169090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson throws IOException, ClassNotFoundException { 170090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson int distinctKeys = stream.readInt(); 171090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson populateMultimap(multimap, stream, distinctKeys); 172090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 173090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 174090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** 175090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Populates a multimap by reading an input stream, as part of 176090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * deserialization. See {@link #writeMultimap} for the data format. The number 177090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * of distinct keys is determined by a prior call to {@link #readCount}. 178090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert static <K, V> void populateMultimap( 180090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Multimap<K, V> multimap, ObjectInputStream stream, int distinctKeys) 181090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson throws IOException, ClassNotFoundException { 182090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson for (int i = 0; i < distinctKeys; i++) { 183090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @SuppressWarnings("unchecked") // reading data stored by writeMultimap 184090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson K key = (K) stream.readObject(); 185090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Collection<V> values = multimap.get(key); 186090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson int valueCount = stream.readInt(); 187090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson for (int j = 0; j < valueCount; j++) { 188090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @SuppressWarnings("unchecked") // reading data stored by writeMultimap 189090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson V value = (V) stream.readObject(); 190090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson values.add(value); 191090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 192090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 193090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 194090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 195090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson // Secret sauce for setting final fields; don't make it public. 196090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson static <T> FieldSetter<T> getFieldSetter( 197090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson final Class<T> clazz, String fieldName) { 198090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson try { 199090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Field field = clazz.getDeclaredField(fieldName); 200090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return new FieldSetter<T>(field); 201090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } catch (NoSuchFieldException e) { 202090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson throw new AssertionError(e); // programmer error 203090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 204090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 205090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 206090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson // Secret sauce for setting final fields; don't make it public. 207090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson static final class FieldSetter<T> { 208090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private final Field field; 209090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 210090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private FieldSetter(Field field) { 211090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson this.field = field; 212090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson field.setAccessible(true); 213090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 214090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 215090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson void set(T instance, Object value) { 216090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson try { 217090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson field.set(instance, value); 218090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } catch (IllegalAccessException impossible) { 219090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson throw new AssertionError(impossible); 220090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 221090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 222090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 223090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson void set(T instance, int value) { 224090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson try { 225090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson field.set(instance, value); 226090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } catch (IllegalAccessException impossible) { 227090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson throw new AssertionError(impossible); 228090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 229090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 230090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 231090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson} 232