FileDocCategorySizeDatePackage
SVGImageLoader.javaAPI DocphoneME MR2 API (J2ME)12932Wed May 02 18:00:36 BST 2007com.sun.perseus.model

SVGImageLoader

public class SVGImageLoader extends DefaultImageLoader
JSR 226 implementation of the ImageLoader interface.
author
Kevin Wong
version
$Id: SVGImageLoader.java,v 1.14 2006/06/29 10:47:34 ln156897 Exp $

Fields Summary
protected static final String
IMAGE_REQUESTED
Constant used to indicate that an image has been requested to the ExternalResourceHandler but that the handler has not delivered the result yet.
protected javax.microedition.m2g.ExternalResourceHandler
handler
Handles any external resource referenced in the image document.
protected SVGImageImpl
svgImage
The SVGImage associated to this SVGImageLoader
protected Hashtable
rasterImageConsumerTable
Simple hashtable used to track ImageNode objects.
protected com.sun.perseus.j2d.ImageLoaderUtil
loaderUtil
ImageLoaderUtil contains helper methods which make this implementation easier.
protected boolean
documentLoaded
Set to true once the associated DocumentNode has fully loaded.
protected Vector
pendingNeedsURI
Keeps track of pending absoluteURI requests.
Constructors Summary
public SVGImageLoader(SVGImageImpl svgImage, javax.microedition.m2g.ExternalResourceHandler handler)
Constructor

param
svgImage the associated SVGImage, should not be null.
param
handler the ExternalResourceHandler which will get the images data.


                                     
       
                            
        if (svgImage == null || handler == null) {
            throw new NullPointerException();
        }

        this.svgImage = svgImage;
        this.handler = handler;
    
Methods Summary
public voidaddRasterImageConsumer(java.lang.String absoluteURI, RasterImageConsumer imageNode)
In cases where the ImageLoader may update the images associated to a URI, RasterImageConsumer interested in updates need to register their interest throught this method.

param
absoluteURI the URI the RasterImageConsumer is interested in.
param
imageNode the RasterImageConsumer interested in the URI.

        if (absoluteURI == null) {
            return;
        }

        synchronized (rasterImageConsumerTable) {
            Vector v = (Vector) rasterImageConsumerTable.get(absoluteURI);
            if (v == null) {
                v = new Vector(1);
                v.addElement(imageNode);
                rasterImageConsumerTable.put(absoluteURI, v);
            } else {
                if (!v.contains(imageNode)) {
                    v.addElement(imageNode);
                }
            }
        }
    
voidaddToCache(java.lang.String uri, java.lang.Object image)
Adds image to the Image cache.

param
uri the key for the Image cache.
param
image the Image to store.

        synchronized (cache) {
            cache.put(uri, image);
        }
    
public booleanallowsRelativeURI()
Determines whether this ImageLoader can handle relative uri's

return
true if this ImageLoader can handle relative uri's; false otherwise.

        return true;
    
public voiddocumentLoaded(DocumentNode doc)
Some ImageLoader implementations may wish to wait until the end of the Document load to start retrieving resources. This method notifies the implementation that the DocumentNode completed loading successfully.

param
doc the DocumentNode which just finised loading.

        // Place a needsURIDocumentLoaded call for each entry in the 
        // pendingNeedsURI vector. See the needsURI method.
        documentLoaded = true;
        int n = pendingNeedsURI.size();
        for (int i = 0; i < n; i++) {
            needsURIDocumentLoaded((String) pendingNeedsURI.elementAt(i));
        }

        // Empty pending requests
        pendingNeedsURI.removeAllElements();
    
public com.sun.perseus.j2d.RasterImagegetImageAndWait(java.lang.String uri)
Requests the given image. This call blocks until an image is returned.

param
uri the requested URI.
return
the loaded image or the same image as returned by a getBrokenImage call if the image could not be loaded.

        // If we are dealing with a data URI, decode the image
        // now. Data URIs do not go in the cache.
        if (loaderUtil.isDataURI(uri)) {
            return loaderUtil.getEmbededImage(uri);
        }

        Object img;

        // We are dealing with a regular URI which requires IO.
        // The image might already be in the loading queue from
        // a call in needsURI. 
        synchronized (cache) {
            img = cache.get(uri);
        }

        if ((img != null) && (img != IMAGE_REQUESTED)) {
            return (RasterImage) img;
        }

        // Make the sure the image is requested
        if (img == null) {
            needsURI(uri);
        }

        // The URI has not been retrieved yet...
        img = ((SVGImageImpl) svgImage).waitOnRequestCompleted(uri);

        return (RasterImage) img;
    
public com.sun.perseus.j2d.RasterImagegetImageFromCache(java.lang.String uri)
Returns the Image that was previously loaded.

param
uri the key for the Image cache.
return
the Image associated with the key.

        Object img;
        synchronized (cache) {
            img = cache.get(uri);
            if (IMAGE_REQUESTED == img) {
                img = null;
            }
        }
        return (RasterImage) img;
    
public voidgetImageLater(java.lang.String uri, RasterImageConsumer rasterImageConsumer)
Requests the given image. This call returns immediately and the image is set on the input ImageNode when the image becomes available.

param
uri the requested URI.
param
rasterImageConsumer the RasterImageConsumer whose image member should be set as a result of loading the image.

        // Only load later images which have not been loaded yet
        // and which are not data URIs.
        if (loaderUtil.isDataURI(uri)) {
            rasterImageConsumer.setImage(loaderUtil.getEmbededImage(uri), uri);
            return;
        }

        Object img = null;
        synchronized (cache) {
            img = cache.get(uri);
        }

        if ((img != null) && (img != IMAGE_REQUESTED)) {
            rasterImageConsumer.setImage((RasterImage) img, uri);
            return;
        }

        // Save ImageNode associated with the uri for use with SVGImage's
        // requestCompleted().
        addRasterImageConsumer(uri, rasterImageConsumer);
    
public voidneedsURI(java.lang.String absoluteURI)
Notifies the URILoader that the given uri will be needed.

param
absoluteURI the requested URI content.

        // SVGImageLoader waits until the document has loaded before actually
        // requesting any image from the ResourceHandler.
        if (documentLoaded) {
            needsURIDocumentLoaded(absoluteURI);
        } else {
            if (!loaderUtil.isDataURI(absoluteURI) && 
                !pendingNeedsURI.contains(absoluteURI)) {
                // Cache the request for future use (see documentLoaded method)
                pendingNeedsURI.addElement(absoluteURI);
            }
        }
    
protected voidneedsURIDocumentLoaded(java.lang.String absoluteURI)
In SVGImageLoader, we wait until the document has been loaded before acting on required raster images.

param
absoluteURI the requested URI content.

        // Do not load base64 images as we do not want to 
        // store the base64 string in the cache, because it
        // might be huge.
        //
        // Correct content should not have the same base64 
        // string duplicated. Rather, the same image element
        // can be referenced by a use element.
        if (!loaderUtil.isDataURI(absoluteURI)) {
            boolean isRequested = true;
            synchronized (cache) {
                // First check if the image is already available (implies that
                // images has been requested and obtained successfully)
                Object imgObj = cache.get(absoluteURI);
                if (null == imgObj) {
                    // The image has not been requested yet
                    isRequested  = false;
                    addToCache(absoluteURI, IMAGE_REQUESTED);
                } else if (IMAGE_REQUESTED != imgObj) {
                    // The image has been requested and retrieved
                    setRasterImageConsumerImage(absoluteURI, 
                                                (RasterImage) imgObj);
                    return;
                }
            }

            // requestResource() called outside of synchronized block
            // so that the cache is not unnecessarily locked.  handler is an
            // external implementation and the behavior is unpredictable.
            if (!isRequested) {
                System.err.println("handler.requestResource: " + absoluteURI);
                handler.requestResource(svgImage, absoluteURI);
            }
        }
    
public voidremoveRasterImageConsumer(java.lang.String absoluteURI, RasterImageConsumer imageNode)
In cases where the ImageLoader may update the images associated to a URI, RasterImageConsumer interested in updates need to de-register their interest throught this method.

param
absoluteURI the URI the RasterImageConsumer is interested in.
param
imageNode the RasterImageConsumer interested in the URI.

        if (absoluteURI != null) {
            synchronized (rasterImageConsumerTable) {
                Vector v = (Vector) rasterImageConsumerTable.get(absoluteURI);
                if (v != null) {
                    v.removeElement(imageNode);
                }
            }
        }
    
voidsetRasterImageConsumerImage(java.lang.String uri, com.sun.perseus.j2d.RasterImage image)
Implementation helper.

param
uri the uri identifying the image resource.
param
image the RasterImage to send to the consumers.

        ((DocumentNode) svgImage.getDocument()).safeInvokeAndWait(
                new Runnable() {
                    public void run() {
                        synchronized (rasterImageConsumerTable) {
                            Vector v = 
                                (Vector) rasterImageConsumerTable.get(uri);
                            if (v != null) {
                                int n = v.size();
                                for (int i = 0; i < n; i++) {
                                    final RasterImageConsumer in 
                                        = (RasterImageConsumer) v.elementAt(i);
                                    in.setImage(image, uri);
                                }
                            }
                        }
                    }
                });