1 17 18 19 20 package org.apache.fop.image; 21 22 import java.io.InputStream ; 24 import java.lang.ref.Reference ; 25 import java.lang.ref.ReferenceQueue ; 26 import java.lang.ref.SoftReference ; 27 import java.lang.reflect.Constructor ; 28 import java.util.ArrayList ; 29 import java.util.Map ; 30 import java.util.Set ; 31 import java.util.Collections ; 32 import java.util.HashMap ; 33 import java.util.Iterator ; 34 import java.util.List ; 35 import java.util.Map.Entry; 36 37 import javax.xml.transform.Source ; 38 import javax.xml.transform.stream.StreamSource ; 39 40 import org.apache.commons.logging.Log; 41 import org.apache.commons.logging.LogFactory; 42 43 import org.apache.fop.image.analyser.ImageReaderFactory; 45 import org.apache.fop.apps.FOUserAgent; 46 import org.apache.fop.datatypes.URISpecification; 47 48 52 public final class ImageFactory { 53 54 57 protected static Log log = LogFactory.getLog(FopImage.class); 58 59 private HashMap imageMimeTypes = new HashMap (); 60 61 private ImageCache cache = new ContextImageCache(true); 62 63 66 public ImageFactory() { 67 70 ImageProvider jaiImage = new ImageProvider("JAIImage", "org.apache.fop.image.JAIImage"); 71 ImageProvider jimiImage = new ImageProvider("JIMIImage", "org.apache.fop.image.JimiImage"); 72 ImageProvider imageIoImage = new ImageProvider( 73 "ImageIOImage", "org.apache.fop.image.ImageIOImage"); 74 ImageProvider gifImage = new ImageProvider("GIFImage", "org.apache.fop.image.GifImage"); 75 ImageProvider jpegImage = new ImageProvider("JPEGImage", "org.apache.fop.image.JpegImage"); 76 ImageProvider jpegImageIOImage = new ImageProvider( 77 "JPEGImage", "org.apache.fop.image.JpegImageIOImage"); 78 ImageProvider bmpImage = new ImageProvider("BMPImage", "org.apache.fop.image.BmpImage"); 79 ImageProvider epsImage = new ImageProvider("EPSImage", "org.apache.fop.image.EPSImage"); 80 ImageProvider pngImage = new ImageProvider("PNGImage", "org.apache.fop.image.PNGImage"); 81 ImageProvider tiffImage = new ImageProvider("TIFFImage", "org.apache.fop.image.TIFFImage"); 82 ImageProvider xmlImage = new ImageProvider("XMLImage", "org.apache.fop.image.XMLImage"); 83 ImageProvider emfImage = new ImageProvider("EMFImage", "org.apache.fop.image.EmfImage"); 84 85 ImageMimeType imt = new ImageMimeType("image/gif"); 86 imageMimeTypes.put(imt.getMimeType(), imt); 87 imt.addProvider(imageIoImage); 88 imt.addProvider(jaiImage); 89 imt.addProvider(jimiImage); 90 imt.addProvider(gifImage); 91 92 imt = new ImageMimeType("image/jpeg"); 93 imageMimeTypes.put(imt.getMimeType(), imt); 94 imt.addProvider(jpegImageIOImage); 95 imt.addProvider(jpegImage); 96 97 imt = new ImageMimeType("image/bmp"); 98 imageMimeTypes.put(imt.getMimeType(), imt); 99 imt.addProvider(bmpImage); 100 101 imt = new ImageMimeType("image/eps"); 102 imageMimeTypes.put(imt.getMimeType(), imt); 103 imt.addProvider(epsImage); 104 105 imt = new ImageMimeType("image/png"); 106 imageMimeTypes.put(imt.getMimeType(), imt); 107 imt.addProvider(pngImage); 108 imt.addProvider(imageIoImage); 110 111 imt = new ImageMimeType("image/tga"); 112 imageMimeTypes.put(imt.getMimeType(), imt); 113 imt.addProvider(jaiImage); 114 imt.addProvider(imageIoImage); 115 imt.addProvider(jimiImage); 116 117 imt = new ImageMimeType("image/tiff"); 118 imageMimeTypes.put(imt.getMimeType(), imt); 119 imt.addProvider(tiffImage); imt.addProvider(imageIoImage); imt.addProvider(jaiImage); 123 imt = new ImageMimeType("image/svg+xml"); 124 imageMimeTypes.put(imt.getMimeType(), imt); 125 imt.addProvider(xmlImage); 126 127 imt = new ImageMimeType("text/xml"); 128 imageMimeTypes.put(imt.getMimeType(), imt); 129 imt.addProvider(xmlImage); 130 131 imt = new ImageMimeType("image/emf"); 132 imageMimeTypes.put(imt.getMimeType(), imt); 133 imt.addProvider(emfImage); 134 } 135 136 142 public static String getURL(String href) { 143 return URISpecification.getURL(href); 144 } 145 146 156 public FopImage getImage(String url, FOUserAgent context) { 157 return cache.getImage(url, context); 158 } 159 160 169 public void releaseImage(String url, FOUserAgent context) { 170 cache.releaseImage(url, context); 171 } 172 173 178 public void removeContext(FOUserAgent context) { 179 cache.removeContext(context); 180 } 181 182 188 public FopImage loadImage(String href, FOUserAgent ua) { 189 190 Source source = ua.resolveURI(href); 191 if (source == null) { 192 return null; 193 } 194 195 InputStream in = null; 197 if (source instanceof StreamSource ) { 198 in = ((StreamSource )source).getInputStream(); 199 } 200 if (in == null) { 201 try { 202 in = new java.net.URL (source.getSystemId()).openStream(); 203 } catch (Exception ex) { 204 log.error("Unable to obtain stream from id '" 205 + source.getSystemId() + "'"); 206 } 207 } 208 if (in == null) { 209 return null; 210 } 211 212 if (!(in instanceof java.io.BufferedInputStream )) { 214 in = new java.io.BufferedInputStream (in); 215 } 216 217 FopImage.ImageInfo imgInfo = null; 219 try { 220 imgInfo = ImageReaderFactory.make(source.getSystemId(), in, ua); 221 } catch (Exception e) { 222 log.error("Error while recovering image information (" 223 + href + ") : " + e.getMessage(), e); 224 return null; 225 } 226 if (imgInfo == null) { 227 try { 228 in.close(); 229 in = null; 230 } catch (Exception e) { 231 log.debug("Error closing the InputStream for the image", e); 232 } 233 log.error("No ImageReader for this type of image (" + href + ")"); 234 return null; 235 } 236 String imgMimeType = imgInfo.mimeType; 238 Class imageClass = getImageClass(imgMimeType); 239 if (imageClass == null) { 240 log.error("Unsupported image type (" + href + "): " + imgMimeType); 241 return null; 242 } else { 243 if (log.isDebugEnabled()) { 244 log.debug("Loading " + imgMimeType + " with " + imageClass.getName() 245 + ": " + href); 246 } 247 } 248 249 Object imageInstance = null; 252 try { 253 Class [] imageConstructorParameters = new Class [1]; 254 imageConstructorParameters[0] = org.apache.fop.image.FopImage.ImageInfo.class; 255 Constructor imageConstructor = imageClass.getDeclaredConstructor( 256 imageConstructorParameters); 257 Object [] initArgs = new Object [1]; 258 initArgs[0] = imgInfo; 259 imageInstance = imageConstructor.newInstance(initArgs); 260 } catch (java.lang.reflect.InvocationTargetException ex) { 261 Throwable t = ex.getTargetException(); 262 String msg; 263 if (t != null) { 264 msg = t.getMessage(); 265 } else { 266 msg = ex.getMessage(); 267 } 268 log.error("Error creating FopImage object (" 269 + href + "): " + msg, (t == null) ? ex : t); 270 return null; 271 } catch (InstantiationException ie) { 272 log.error("Error creating FopImage object (" 273 + href + "): Could not instantiate " + imageClass.getName() + " instance"); 274 return null; 275 } catch (Exception ex) { 276 log.error("Error creating FopImage object (" 277 + href + "): " + ex.getMessage(), ex); 278 return null; 279 } 280 if (!(imageInstance instanceof org.apache.fop.image.FopImage)) { 281 log.error("Error creating FopImage object (" + href + "): " + "class " 282 + imageClass.getName() 283 + " doesn't implement org.apache.fop.image.FopImage interface"); 284 return null; 285 } 286 return (FopImage) imageInstance; 287 } 288 289 private Class getImageClass(String imgMimeType) { 290 ImageMimeType imt = (ImageMimeType)imageMimeTypes.get(imgMimeType); 291 if (imt == null) { 292 return null; 293 } 294 return imt.getFirstImplementingClass(); 295 } 296 297 304 public void clearCaches() { 305 cache.clearAll(); 306 } 307 } 308 309 313 class BasicImageCache implements ImageCache { 314 315 private Set invalid = Collections.synchronizedSet(new java.util.HashSet ()); 316 318 public FopImage getImage(String url, FOUserAgent context) { 319 if (invalid.contains(url)) { 320 return null; 321 } 322 return null; 324 } 325 326 public void releaseImage(String url, FOUserAgent context) { 327 } 329 330 public void invalidateImage(String url, FOUserAgent context) { 331 if (invalid.size() > 100) { 333 invalid.clear(); 334 } 335 invalid.add(url); 336 } 337 338 public void removeContext(FOUserAgent context) { 339 } 341 342 343 public void clearAll() { 344 invalid.clear(); 345 } 346 347 } 348 349 359 class ContextImageCache implements ImageCache { 360 361 private boolean collective; 366 private Map contextStore = Collections.synchronizedMap(new java.util.HashMap ()); 367 private Set invalid = null; 368 private Map refStore = null; 369 private ReferenceQueue refQueue = new ReferenceQueue (); 370 371 public ContextImageCache(boolean col) { 372 collective = col; 373 if (collective) { 374 refStore = Collections.synchronizedMap(new java.util.HashMap ()); 375 invalid = Collections.synchronizedSet(new java.util.HashSet ()); 376 } 377 } 378 379 public FopImage getImage(String url, FOUserAgent context) { 382 ImageLoader im = null; 383 synchronized (this) { 386 if (collective && invalid.contains(url)) { 387 return null; 388 } 389 Context con = (Context) contextStore.get(context); 390 if (con == null) { 391 con = new Context(context, collective); 392 contextStore.put(context, con); 393 } else { 394 if (con.invalid(url)) { 395 return null; 396 } 397 im = con.getImage(url); 398 } 399 if (im == null && collective) { 400 Iterator i = contextStore.values().iterator(); 401 while (i.hasNext()) { 402 Context c = (Context)i.next(); 403 if (c != con) { 404 im = c.getImage(url); 405 if (im != null) { 406 break; 407 } 408 } 409 } 410 if (im == null) { 411 Reference ref = (Reference )refStore.get(url); 412 if (ref != null) { 413 im = (ImageLoader) ref.get(); 414 if (im == null) { 415 refStore.remove(url); 417 } 418 } 419 } 420 } 421 422 if (im != null) { 423 con.putImage(url, im); 424 } else { 425 im = con.getImage(url, this); 426 } 427 } 428 429 if (im != null) { 432 return im.loadImage(); 433 } 434 return null; 435 } 436 437 public void releaseImage(String url, FOUserAgent context) { 438 Context con = (Context) contextStore.get(context); 439 if (con != null) { 440 if (collective) { 441 ImageLoader im = con.getImage(url); 442 refStore.put(url, wrapInReference(im, url)); 443 } 444 con.releaseImage(url); 445 } 446 } 447 448 public void invalidateImage(String url, FOUserAgent context) { 449 if (collective) { 450 if (invalid.size() > 100) { 452 invalid.clear(); 453 } 454 invalid.add(url); 455 } 456 Context con = (Context) contextStore.get(context); 457 if (con != null) { 458 con.invalidateImage(url); 459 } 460 } 461 462 private Reference wrapInReference(Object obj, Object key) { 463 return new SoftReferenceWithKey(obj, key, refQueue); 464 } 465 466 private static class SoftReferenceWithKey extends SoftReference { 467 468 private Object key; 469 470 public SoftReferenceWithKey(Object referent, Object key, ReferenceQueue q) { 471 super(referent, q); 472 this.key = key; 473 } 474 } 475 476 public void removeContext(FOUserAgent context) { 477 Context con = (Context) contextStore.get(context); 478 if (con != null) { 479 if (collective) { 480 Map images = con.getImages(); 481 Iterator iter = images.entrySet().iterator(); 482 while (iter.hasNext()) { 483 Entry entry = (Entry)iter.next(); 484 refStore.put(entry.getKey(), 485 wrapInReference(entry.getValue(), entry.getKey())); 486 } 487 } 488 contextStore.remove(context); 489 } 490 checkReferenceQueue(); 492 } 493 494 498 private void checkReferenceQueue() { 499 SoftReferenceWithKey ref; 500 while ((ref = (SoftReferenceWithKey)refQueue.poll()) != null) { 501 refStore.remove(ref.key); 502 } 503 } 504 505 class Context { 506 private Map images = Collections.synchronizedMap(new java.util.HashMap ()); 507 private Set invalid = null; 508 private FOUserAgent userAgent; 509 510 public Context(FOUserAgent ua, boolean inv) { 511 userAgent = ua; 512 if (inv) { 513 invalid = Collections.synchronizedSet(new java.util.HashSet ()); 514 } 515 } 516 517 public ImageLoader getImage(String url, ImageCache c) { 518 if (images.containsKey(url)) { 519 return (ImageLoader) images.get(url); 520 } 521 ImageLoader loader = new ImageLoader(url, c, userAgent); 522 images.put(url, loader); 523 return loader; 524 } 525 526 public void putImage(String url, ImageLoader image) { 527 images.put(url, image); 528 } 529 530 public ImageLoader getImage(String url) { 531 return (ImageLoader) images.get(url); 532 } 533 534 public void releaseImage(String url) { 535 images.remove(url); 536 } 537 538 public Map getImages() { 539 return images; 540 } 541 542 public void invalidateImage(String url) { 543 invalid.add(url); 544 } 545 546 public boolean invalid(String url) { 547 return invalid.contains(url); 548 } 549 550 } 551 552 553 public void clearAll() { 554 this.refStore.clear(); 555 this.invalid.clear(); 556 } 561 562 } 563 564 568 class ImageProvider { 569 570 private String name = null; 571 572 private String className = null; 573 574 private boolean checked = false; 575 576 private Class clazz = null; 577 578 585 public ImageProvider(String name, String className) { 586 setName(name); 587 setClassName(className); 588 } 589 590 594 public String getName() { 595 return name; 596 } 597 598 private void setName(String name) { 599 this.name = name; 600 } 601 602 606 public String getClassName() { 607 return className; 608 } 609 610 private void setClassName(String className) { 611 this.className = className; 612 } 613 614 618 public Class getImplementingClass() { 619 if (!checked) { 620 try { 621 clazz = Class.forName(getClassName()); 622 } catch (ClassNotFoundException cnfe) { 623 } catch (LinkageError le) { 625 ImageFactory.log.debug("Image support provider " + getName() 630 + " could not be loaded. If " + getName() + " should be" 631 + " available please make sure all required external libraries" 632 + " are on the classpath."); 633 } 634 checked = true; 635 } 636 return clazz; 637 } 638 } 639 640 644 class ImageMimeType { 645 646 private String mimeType = null; 647 648 private List providers = null; 649 650 654 public ImageMimeType(String mimeType) { 655 setMimeType(mimeType); 656 } 657 658 662 public String getMimeType() { 663 return mimeType; 664 } 665 666 private void setMimeType(String mimeType) { 667 this.mimeType = mimeType; 668 } 669 670 674 public Class getFirstImplementingClass() { 675 if (providers == null) { 676 return null; 677 } 678 for (Iterator it = providers.iterator(); it.hasNext();) { 679 ImageProvider ip = (ImageProvider)it.next(); 680 Class clazz = ip.getImplementingClass(); 681 if (clazz != null) { 682 return clazz; 683 } 684 } 685 return null; 686 } 687 688 693 public void addProvider(ImageProvider provider) { 694 if (providers == null) { 695 providers = new ArrayList (4); } 697 if (!providers.contains(provider)) { 698 providers.add(provider); 699 } 700 } 701 } 702 703 | Popular Tags |