1 15 package org.apache.tapestry.record; 16 17 import java.io.BufferedInputStream ; 18 import java.io.BufferedOutputStream ; 19 import java.io.ByteArrayInputStream ; 20 import java.io.ByteArrayOutputStream ; 21 import java.io.IOException ; 22 import java.io.InputStream ; 23 import java.io.ObjectInputStream ; 24 import java.io.ObjectOutputStream ; 25 import java.util.ArrayList ; 26 import java.util.Collections ; 27 import java.util.Iterator ; 28 import java.util.List ; 29 import java.util.zip.GZIPInputStream ; 30 import java.util.zip.GZIPOutputStream ; 31 32 import org.apache.commons.codec.binary.Base64; 33 import org.apache.hivemind.ApplicationRuntimeException; 34 import org.apache.hivemind.HiveMind; 35 import org.apache.hivemind.util.Defense; 36 import org.apache.tapestry.util.io.TeeOutputStream; 37 38 49 public class PersistentPropertyDataEncoderImpl implements PersistentPropertyDataEncoder 50 { 51 54 55 public static final String BYTESTREAM_PREFIX = "B"; 56 57 60 61 public static final String GZIP_BYTESTREAM_PREFIX = "Z"; 62 63 public String encodePageChanges(List changes) 64 { 65 Defense.notNull(changes, "changes"); 66 67 if (changes.isEmpty()) 68 return ""; 69 70 try 71 { 72 ByteArrayOutputStream bosPlain = new ByteArrayOutputStream (); 73 ByteArrayOutputStream bosCompressed = new ByteArrayOutputStream (); 74 75 GZIPOutputStream gos = new GZIPOutputStream (bosCompressed); 76 77 TeeOutputStream tos = new TeeOutputStream(bosPlain, gos); 78 79 ObjectOutputStream oos = new ObjectOutputStream (new BufferedOutputStream (tos)); 80 81 writeChangesToStream(changes, oos); 82 83 oos.close(); 84 85 boolean useCompressed = bosCompressed.size() < bosPlain.size(); 86 87 byte[] data = useCompressed ? bosCompressed.toByteArray() : bosPlain.toByteArray(); 88 89 byte[] encoded = Base64.encodeBase64(data); 90 91 String prefix = useCompressed ? GZIP_BYTESTREAM_PREFIX : BYTESTREAM_PREFIX; 92 93 return prefix + new String (encoded); 94 } 95 catch (Exception ex) 96 { 97 throw new ApplicationRuntimeException(RecordMessages.encodeFailure(ex), ex); 98 } 99 } 100 101 public List decodePageChanges(String encoded) 102 { 103 if (HiveMind.isBlank(encoded)) 104 return Collections.EMPTY_LIST; 105 106 String prefix = encoded.substring(0, 1); 107 108 if (!(prefix.equals(BYTESTREAM_PREFIX) || prefix.equals(GZIP_BYTESTREAM_PREFIX))) 109 throw new ApplicationRuntimeException(RecordMessages.unknownPrefix(prefix)); 110 111 try 112 { 113 115 byte[] decoded = Base64.decodeBase64(encoded.substring(1).getBytes()); 116 117 InputStream is = new ByteArrayInputStream (decoded); 118 119 if (prefix.equals(GZIP_BYTESTREAM_PREFIX)) 120 is = new GZIPInputStream (is); 121 122 127 ObjectInputStream ois = new ObjectInputStream (new BufferedInputStream (is)); 128 129 List result = readChangesFromStream(ois); 130 131 ois.close(); 132 133 return result; 134 } 135 catch (Exception ex) 136 { 137 throw new ApplicationRuntimeException(RecordMessages.decodeFailure(ex), ex); 138 } 139 } 140 141 private void writeChangesToStream(List changes, ObjectOutputStream oos) throws IOException 142 { 143 oos.writeInt(changes.size()); 144 145 Iterator i = changes.iterator(); 146 while (i.hasNext()) 147 { 148 PropertyChange pc = (PropertyChange) i.next(); 149 150 String componentPath = pc.getComponentPath(); 151 String propertyName = pc.getPropertyName(); 152 Object value = pc.getNewValue(); 153 154 oos.writeBoolean(componentPath != null); 155 156 if (componentPath != null) 157 oos.writeUTF(componentPath); 158 159 oos.writeUTF(propertyName); 160 oos.writeObject(value); 161 } 162 } 163 164 private List readChangesFromStream(ObjectInputStream ois) throws IOException , 165 ClassNotFoundException 166 { 167 List result = new ArrayList (); 168 169 int count = ois.readInt(); 170 171 for (int i = 0; i < count; i++) 172 { 173 boolean hasPath = ois.readBoolean(); 174 String componentPath = hasPath ? ois.readUTF() : null; 175 String propertyName = ois.readUTF(); 176 Object value = ois.readObject(); 177 178 PropertyChangeImpl pc = new PropertyChangeImpl(componentPath, propertyName, value); 179 180 result.add(pc); 181 } 182 183 return result; 184 } 185 } | Popular Tags |