1 18 package org.apache.batik.svggen; 19 20 import java.io.ByteArrayOutputStream ; 21 import java.io.File ; 22 import java.io.FileInputStream ; 23 import java.io.FileOutputStream ; 24 import java.io.IOException ; 25 import java.io.OutputStream ; 26 import java.util.Arrays ; 27 import java.util.Hashtable ; 28 import java.util.LinkedList ; 29 import java.util.ListIterator ; 30 import java.util.zip.Adler32 ; 31 import java.util.zip.Checksum ; 32 33 import org.w3c.dom.Document ; 34 import org.w3c.dom.Element ; 35 36 37 43 public abstract class ImageCacher implements SVGSyntax, ErrorConstants { 44 45 DOMTreeManager domTreeManager = null; 46 Hashtable imageCache; 47 Checksum checkSum; 48 49 52 public ImageCacher() { 53 imageCache = new Hashtable (); 54 checkSum = new Adler32 (); 55 } 56 57 62 public ImageCacher(DOMTreeManager domTreeManager) { 63 this(); 64 setDOMTreeManager(domTreeManager); 65 } 66 67 72 public void setDOMTreeManager(DOMTreeManager domTreeManager) { 73 if (domTreeManager == null){ 74 throw new IllegalArgumentException (); 75 } 76 this.domTreeManager = domTreeManager; 77 } 78 79 public DOMTreeManager getDOMTreeManager(){ 80 return domTreeManager; 81 } 82 83 95 public String lookup(ByteArrayOutputStream os, 96 int width, int height, 97 SVGGeneratorContext ctx) 98 throws SVGGraphics2DIOException { 99 int checksum = getChecksum(os.toByteArray()); 104 Integer key = new Integer (checksum); 105 String href = null; 106 107 Object data = getCacheableData(os); 108 109 LinkedList list = (LinkedList ) imageCache.get(key); 110 if(list == null) { 111 list = new LinkedList (); 113 imageCache.put(key, list); 114 } else { 115 for(ListIterator i = list.listIterator(0); i.hasNext(); ) { 117 ImageCacheEntry entry = (ImageCacheEntry) i.next(); 118 if(entry.checksum == checksum && imagesMatch(entry.src, data)) { 119 href = entry.href; 120 break; 121 } 122 } 123 } 124 125 if(href == null) { 126 ImageCacheEntry newEntry = createEntry(checksum, data, 128 width, height, 129 ctx); 130 list.add(newEntry); 131 href = newEntry.href; 132 } 133 134 return href; 135 } 136 137 144 abstract Object getCacheableData(ByteArrayOutputStream os); 145 146 155 abstract boolean imagesMatch(Object o1, Object o2) 156 throws SVGGraphics2DIOException; 157 158 167 abstract ImageCacheEntry createEntry(int checksum, 168 Object data, 169 int width, int height, 170 SVGGeneratorContext ctx) 171 throws SVGGraphics2DIOException; 172 173 176 int getChecksum(byte[] data) { 177 checkSum.reset(); 178 checkSum.update(data, 0, data.length); 179 return (int) checkSum.getValue(); 180 } 181 182 187 private class ImageCacheEntry { 188 189 190 public int checksum; 191 192 193 public Object src; 194 195 196 public String href; 197 198 201 public ImageCacheEntry(int checksum, 202 Object src, 203 String href) { 204 this.checksum = checksum; 205 this.src = src; 206 this.href = href; 207 } 208 } 209 210 213 public static class Embedded extends ImageCacher { 214 215 220 public void setDOMTreeManager(DOMTreeManager domTreeManager) { 221 if(this.domTreeManager != domTreeManager) { 224 this.domTreeManager = domTreeManager; 225 this.imageCache = new Hashtable (); 226 } 227 } 228 229 Object getCacheableData(ByteArrayOutputStream os) { 230 return DATA_PROTOCOL_PNG_PREFIX + os.toString(); 234 } 235 236 boolean imagesMatch(Object o1, Object o2) { 237 return o1.equals(o2); 238 } 239 240 ImageCacheEntry createEntry(int checksum, Object data, 241 int width, int height, 242 SVGGeneratorContext ctx) { 243 244 String id = ctx.idGenerator.generateID(ID_PREFIX_IMAGE); 246 247 addToTree(id, (String ) data, width, height, ctx); 249 250 return new ImageCacheEntry(checksum, data, SIGN_POUND + id); 252 } 253 254 257 private void addToTree(String id, 258 String href, 259 int width, int height, 260 SVGGeneratorContext ctx) { 261 262 Document domFactory = domTreeManager.getDOMFactory(); 263 265 Element imageElement = domFactory.createElementNS(SVG_NAMESPACE_URI, 267 SVG_IMAGE_TAG); 268 imageElement.setAttributeNS(null, SVG_ID_ATTRIBUTE, 269 id); 270 imageElement.setAttributeNS(null, SVG_WIDTH_ATTRIBUTE, 271 Integer.toString(width)); 272 imageElement.setAttributeNS(null, SVG_HEIGHT_ATTRIBUTE, 273 Integer.toString(height)); 274 imageElement.setAttributeNS(DefaultImageHandler.XLINK_NAMESPACE_URI, 275 ATTR_XLINK_HREF, 276 href); 277 domTreeManager.addOtherDef(imageElement); 279 } 280 281 282 290 303 } 304 305 308 public static class External extends ImageCacher { 309 310 private String imageDir; 311 private String prefix; 312 private String suffix; 313 314 public External(String imageDir, String prefix, String suffix) { 315 super(); 316 this.imageDir = imageDir; 317 this.prefix = prefix; 318 this.suffix = suffix; 319 } 320 321 Object getCacheableData(ByteArrayOutputStream os) { 322 return os; 323 } 324 325 boolean imagesMatch(Object o1, Object o2) 326 throws SVGGraphics2DIOException { 327 boolean match = false; 328 try { 329 FileInputStream imageStream = 330 new FileInputStream ((File ) o1); 331 int imageLen = imageStream.available(); 332 byte[] imageBytes = new byte[imageLen]; 333 byte[] candidateBytes = 334 ((ByteArrayOutputStream ) o2).toByteArray(); 335 336 int bytesRead = 0; 337 while (bytesRead != imageLen) { 338 bytesRead += imageStream.read 339 (imageBytes, bytesRead, imageLen-bytesRead); 340 } 341 342 match = Arrays.equals(imageBytes, candidateBytes); 343 } catch(IOException e) { 344 throw new SVGGraphics2DIOException( 345 ERR_READ+((File ) o1).getName()); 346 } 347 return match; 348 } 349 350 ImageCacheEntry createEntry(int checksum, Object data, 351 int width, int height, 352 SVGGeneratorContext ctx) 353 throws SVGGraphics2DIOException { 354 355 File imageFile = null; 357 358 try { 359 while (imageFile == null) { 362 String fileId = ctx.idGenerator.generateID(prefix); 363 imageFile = new File (imageDir, fileId + suffix); 364 if (imageFile.exists()) 365 imageFile = null; 366 } 367 368 OutputStream outputStream = new FileOutputStream (imageFile); 370 ((ByteArrayOutputStream ) data).writeTo(outputStream); 371 ((ByteArrayOutputStream ) data).close(); 372 } catch(IOException e) { 373 throw new SVGGraphics2DIOException(ERR_WRITE+imageFile.getName()); 374 } 375 376 return new ImageCacheEntry(checksum, imageFile, imageFile.getName()); 378 } 379 380 } 381 382 } 383 384 385 | Popular Tags |