org.apache.fop.fo.flow.ExternalGraphic catches and logs ImageException I want to handle myself

216 views Asked by At

I am transforming an Image into pdf for test purposes.

To ensure that the Image is compatible with the printing process later on, I'm running a quick test print during the upload.

I'm creating a simple Test-PDF with a transformer. When I try to print an image with an incompatible format, the ImageManager of the transformer throws an ImageException, starting in the preloadImage() function:

  public ImageInfo preloadImage(String uri, Source src)
            throws ImageException, IOException {
        Iterator iter = registry.getPreloaderIterator();
        while (iter.hasNext()) {
            ImagePreloader preloader = (ImagePreloader)iter.next();
            ImageInfo info = preloader.preloadImage(uri, src, imageContext);
            if (info != null) {
                return info;
            }
        }
        throw new ImageException("The file format is not supported. No ImagePreloader found for "
                + uri);
    }

throwing it to:

   public ImageInfo needImageInfo(String uri, ImageSessionContext session, ImageManager manager)
                throws ImageException, IOException {
            //Fetch unique version of the URI and use it for synchronization so we have some sort of
            //"row-level" locking instead of "table-level" locking (to use a database analogy).
            //The fine locking strategy is necessary since preloading an image is a potentially long
            //operation.
            if (isInvalidURI(uri)) {
                throw new FileNotFoundException("Image not found: " + uri);
            }
            String lockURI = uri.intern();
            synchronized (lockURI) {
                ImageInfo info = getImageInfo(uri);
                if (info == null) {
                    try {
                        Source src = session.needSource(uri);
                        if (src == null) {
                            registerInvalidURI(uri);
                            throw new FileNotFoundException("Image not found: " + uri);
                        }
                        info = manager.preloadImage(uri, src);
                        session.returnSource(uri, src);
                    } catch (IOException ioe) {
                        registerInvalidURI(uri);
                        throw ioe;
                    } catch (ImageException e) {
                        registerInvalidURI(uri);
                        throw e;
                    }
                    putImageInfo(info);
                }
                return info;
            }
        }

throwing it to :

public ImageInfo getImageInfo(String uri, ImageSessionContext session)
                throws ImageException, IOException {
        if (getCache() != null) {
            return getCache().needImageInfo(uri, session, this);
        } else {
            return preloadImage(uri, session);
        }
    }

Finally it gets caught and logged in the ExternalGraphic.class:

 /** {@inheritDoc} */
    public void bind(PropertyList pList) throws FOPException {
        super.bind(pList);
        src = pList.get(PR_SRC).getString();

        //Additional processing: obtain the image's intrinsic size and baseline information
        url = URISpecification.getURL(src);
        FOUserAgent userAgent = getUserAgent();
        ImageManager manager = userAgent.getFactory().getImageManager();
        ImageInfo info = null;
        try {
            info = manager.getImageInfo(url, userAgent.getImageSessionContext());
        } catch (ImageException e) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageError(this, url, e, getLocator());
        } catch (FileNotFoundException fnfe) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageNotFound(this, url, fnfe, getLocator());
        } catch (IOException ioe) {
            ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
                    getUserAgent().getEventBroadcaster());
            eventProducer.imageIOError(this, url, ioe, getLocator());
        }
        if (info != null) {
            this.intrinsicWidth = info.getSize().getWidthMpt();
            this.intrinsicHeight = info.getSize().getHeightMpt();
            int baseline = info.getSize().getBaselinePositionFromBottom();
            if (baseline != 0) {
                this.intrinsicAlignmentAdjust
                    = FixedLength.getInstance(-baseline);
            }
        }
    }

That way it isn't accessible for me in my code that uses the transformer.

I tried to use a custom ErrorListener, but the transformer only registers fatalErrors to the ErrorListener.

Is there any way to access the Exception and handle it myself without changing the code of the library?

1

There are 1 answers

0
Adoptivkind1904 On BEST ANSWER

It was easier than I thought. Before I call the transformation I register a costum EventListener to the User Agent of the Fop I'm using. This Listener just stores the Information what kind of Event was triggered, so I can throw an Exception if it's an ImageError.

My Listener:

import org.apache.fop.events.Event;
import org.apache.fop.events.EventListener;

public class ImageErrorListener implements EventListener
{

       private String eventKey = "";
private boolean imageError = false;

@Override
public void processEvent(Event event)
{
eventKey = event.getEventKey();
if(eventKey.equals("imageError")) {
    imageError = true;
}
}


public String getEventKey()
{
    return eventKey;
}


public void setEventKey(String eventKey)
{
    this.eventKey = eventKey;
}


public boolean isImageError()
{
    return imageError;
}


public void setImageError(boolean imageError)
{
    this.imageError = imageError;
}    
}

Use of the Listener:

// Start XSLT transformation and FOP processing
    ImageErrorListener imageListener = new ImageErrorListener();

    fop.getUserAgent().getEventBroadcaster().addEventListener(imageListener);
    if (res != null)
    {

        transformer.transform(xmlDomStreamSource, res);
    }

    if(imageListener.isImageError()) {
        throw new ImageException("");
    }

fop is of the type Fop ,xmlDomStreamSource ist the xml-Source I want to transform and res is my SAXResult.