FileDocCategorySizeDatePackage
BookImageClient.javaAPI DocExample15562Wed Dec 18 11:09:22 GMT 2002ora.jwsnut.chapter3.client

BookImageClient.java

package ora.jwsnut.chapter3.client;

import java.awt.BorderLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JPanel;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeader;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.Name;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;

/**
 * SAAJ client that receives images from a web service.
 */
public class BookImageClient {
    
    // The XML Schema namespace
    private static final String XMLSCHEMA_URI = "http://www.w3.org/2001/XMLSchema";
    
    // The XML Schema instance namespace
    private static final String XMLSCHEMA_INSTANCE_URI = 
                                        "http://www.w3.org/2001/XMLSchema-instance";

    // Namespace prefix for XML Schema
    private static final String XMLSCHEMA_PREFIX = "xsd";

    // Namespace prefix for XML Schema instance
    private static final String XMLSCHEMA_INSTANCE_PREFIX = "xsi";    
    
    // The namespace prefix used for SOAP encoding
    private static final String SOAP_ENC_PREFIX = "SOAP-ENC";
    
    // The URI used to qualify elements for this service
    private static final String SERVICE_URI = "urn:jwsnut.bookimageservice";
    
    // The namespace prefix used in elements for this service
    private static final String SERVICE_PREFIX = "tns";
    
    // MessageFactory for replies from this service
    private static MessageFactory messageFactory;
     
    // SOAPFactory for message pieces
    private static SOAPFactory soapFactory;
    
    // SOAPConnection used to call the server
    private static SOAPConnection conn;
    
    // The name of the element used to request a book name list
    private static Name BOOK_LIST_NAME;
    
    // The name of the element used to reply to a book name list request
    private static Name BOOK_TITLES_NAME;
    
    // The name of the element used to request a book image
    private static Name BOOK_IMAGE_REQUEST_NAME;
    
    // The name of the element used to respond to a book image request
    private static Name BOOK_IMAGES_NAME;
  
    // The name of the attribute used to hold the image encoding
    private static Name IMAGE_TYPE_ATTRIBUTE;
    
    // The name of the href attribute
    private static Name HREF_ATTRIBUTE;
    
    // Server address
    private static String serverAddress;
    
    // Debug required flag
    private static boolean debug;
      
    public static void main(String[] args) {
        // Ignore hostname verification failures
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });        
        
        if (args.length != 1) {
            usage();
        }
        serverAddress = args[0];
        
        // Determine whether debug messages are required
        debug = System.getProperty("DEBUG_MESSAGE") != null;

        try {        
            // Create all static data 
            messageFactory = MessageFactory.newInstance();
            soapFactory = SOAPFactory.newInstance();
            BOOK_LIST_NAME = soapFactory.createName("BookList", SERVICE_PREFIX, SERVICE_URI);
            BOOK_TITLES_NAME = soapFactory.createName("BookTitles", SERVICE_PREFIX, SERVICE_URI);
            BOOK_IMAGE_REQUEST_NAME = 
                        soapFactory.createName("BookImageRequest", SERVICE_PREFIX, SERVICE_URI);
            BOOK_IMAGES_NAME = soapFactory.createName("BookImages", SERVICE_PREFIX, SERVICE_URI);
            IMAGE_TYPE_ATTRIBUTE = soapFactory.createName("imageType", SERVICE_PREFIX, SERVICE_URI);
            HREF_ATTRIBUTE = soapFactory.createName("href");
           
            // Get a SOAPConnection        
            SOAPConnectionFactory connFactory = SOAPConnectionFactory.newInstance();
            conn = connFactory.createConnection();
            
            // Get the book titles from the server
            String[] titles = getBookTitles();
            Arrays.sort(titles);

            // Build the user interface
            showGui(titles);
        } catch (Exception ex) {
            System.out.println(ex);
        }
    }
    
    public static void usage() {
        System.err.println("Usage: java BookImageClient address");
        System.exit(1);
    }
    
    /**
     * Builds the message used to request the book titles,
     * sends it and extracts the titles from the reply.
     */
    private static String[] getBookTitles() throws SOAPException, IOException {
            
        // Build the message
        SOAPMessage message = messageFactory.createMessage();

        // Remove the message header
        SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
        envelope.getHeader().detachNode();

        // Set up the namespace declaration
        envelope.addNamespaceDeclaration(SERVICE_PREFIX, SERVICE_URI);

        // Add the element for the book list request
        SOAPBody soapBody = envelope.getBody();
        soapBody.addBodyElement(BOOK_LIST_NAME);

        // Print the message.
        printMessage(message);
        
        SOAPMessage reply = conn.call(message, serverAddress);
        
        // Print the reply
        printMessage(reply);
        SOAPBody replyBody = reply.getSOAPPart().getEnvelope().getBody();
        if (replyBody.hasFault()) {
            SOAPFault fault = replyBody.getFault();
            throw new SOAPException("Fault when getting book titles: " + fault.getFaultString());
        }
        
        // The body contains a "BookTitles" element with a nested
        // element for each book title.
        Iterator iter = replyBody.getChildElements(BOOK_TITLES_NAME);
        if (iter.hasNext()) {
            ArrayList list = new ArrayList();
            SOAPElement bookTitles = (SOAPElement)iter.next();
            iter = bookTitles.getChildElements();
            while (iter.hasNext()) {
                list.add(((SOAPElement)iter.next()).getValue());
            }
            int size = list.size();
            String[] titles = new String[size];
            list.toArray(titles);
            return titles;            
        } else {
            // No BookTitles element was found
            throw new SOAPException("No BookTitles element in returned message");
        }
    }
    
    /**
     * Gets the images for the books with the supplied titles.
     */
    private static Image[] getImages(Object[] titles, boolean gif) throws SOAPException, IOException {
            
        // Build the message
        SOAPMessage message = messageFactory.createMessage();

        // Remove the message header
        SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
        envelope.getHeader().detachNode();

        // Set up the namespaces and the encoding style
        envelope.addNamespaceDeclaration(SERVICE_PREFIX, SERVICE_URI);
        envelope.addNamespaceDeclaration(SOAP_ENC_PREFIX, 
                                            SOAPConstants.URI_NS_SOAP_ENCODING);
        envelope.addNamespaceDeclaration(XMLSCHEMA_PREFIX, XMLSCHEMA_URI);
        envelope.addNamespaceDeclaration(XMLSCHEMA_INSTANCE_PREFIX, 
                                                        XMLSCHEMA_INSTANCE_URI);        
        envelope.setEncodingStyle(SOAPConstants.URI_NS_SOAP_ENCODING);

        // Add the element for the book image request
        SOAPBody soapBody = envelope.getBody();
        SOAPBodyElement bodyElement = soapBody.addBodyElement(BOOK_IMAGE_REQUEST_NAME);
        
        // Add 'xsi:type = "SOAP-ENC:Array"'
        bodyElement.addAttribute(
            soapFactory.createName("type", XMLSCHEMA_INSTANCE_PREFIX, XMLSCHEMA_INSTANCE_URI),
                                    SOAP_ENC_PREFIX + ":Array");
        
        // Add 'SOAP-ENC:arrayType = "xsd:string[]"
        bodyElement.addAttribute(
            soapFactory.createName("arrayType", SOAP_ENC_PREFIX, SOAPConstants.URI_NS_SOAP_ENCODING),
                                    XMLSCHEMA_PREFIX + ":string[]");
        
        // Add the image type attribute
        bodyElement.addAttribute(IMAGE_TYPE_ATTRIBUTE, gif ? "image/gif" : "image/jpeg");

        // Add an array entry for each book 
        for (int i = 0; i < titles.length; i++) {
            SOAPElement titleElement = bodyElement.addChildElement("item");
            titleElement.addTextNode(titles[i].toString());
        }        

        // Print the message.
        printMessage(message);
        
        SOAPMessage reply = conn.call(message, serverAddress);
        
        // Print the reply
        printMessage(reply);
        SOAPBody replyBody = reply.getSOAPPart().getEnvelope().getBody();
        if (replyBody.hasFault()) {
            SOAPFault fault = replyBody.getFault();
            throw new SOAPException("Fault when getting book images: " + fault.getFaultString() +
                            ", actor is [" + fault.getFaultActor() + "]");
        }
        
        // The body contains a "BookImages" element with a nested
        // element for each book title.
        Iterator iter = replyBody.getChildElements(BOOK_IMAGES_NAME);
        if (iter.hasNext()) {
            ArrayList list = new ArrayList();
            MimeHeaders headers = new MimeHeaders();
            SOAPElement bookImages = (SOAPElement)iter.next();
            iter = bookImages.getChildElements();
            while (iter.hasNext()) {
                SOAPElement element = (SOAPElement)iter.next();
                String imageRef = element.getAttributeValue(HREF_ATTRIBUTE);
                if (imageRef != null) {
                    // Get the attachment using the Content-Id, having
                    // first removed the "cid:" prefix
                    imageRef = imageRef.substring(4);
                    headers.setHeader("Content-Id", imageRef);
                    Iterator attachIter = reply.getAttachments(headers);
                    if (attachIter.hasNext()) {
                        AttachmentPart attach = (AttachmentPart)attachIter.next();
                        Object content = attach.getContent();
                        if (content instanceof Image) {
                            list.add(content);
                        } 
                    }
                }
            }
            int size = list.size();
            Image[] images = new Image[size];
            list.toArray(images);
            return images;            
        } else {
            // No BookTitles element was found
            throw new SOAPException("No BookImages element in returned message");
        }
    }
    
    
    /* -- User interface -- */
    private static void showGui(String[] titles) throws SOAPException {
        JFrame frame = new JFrame("SAAJ Example");
        JPanel mainPanel = new JPanel(new BorderLayout());
        
        // Add an unknown title to the book list
        String[] fullTitles = new String[titles.length + 1];
        System.arraycopy(titles, 0, fullTitles, 0, titles.length);
        fullTitles[titles.length] = "No Such Book";
        final JList titleList = new JList(fullTitles);
        
        final JPanel imagePanel = new JPanel();
        mainPanel.add(new JScrollPane(imagePanel), BorderLayout.CENTER);
        JPanel controls = new JPanel();
        controls.setLayout(new BoxLayout(controls, BoxLayout.X_AXIS));
        mainPanel.add(controls, BorderLayout.SOUTH);
        final JCheckBox isGif = new JCheckBox("Use GIF images");
        JButton fetchButton = new JButton("Fetch");
        controls.add(isGif);
        controls.add(Box.createHorizontalGlue());
        controls.add(fetchButton);
        
        frame.getRootPane().setDefaultButton(fetchButton);
        frame.getContentPane().add(new JScrollPane(titleList), BorderLayout.WEST);
        frame.getContentPane().add(mainPanel, BorderLayout.CENTER);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosed(WindowEvent evt) {
                System.exit(0);
            }
        });
        
        fetchButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                Object[] selections = titleList.getSelectedValues();
                imagePanel.removeAll();
                imagePanel.validate();
                if (selections.length > 0) {
                    try {
                        Image[] images = getImages(selections, isGif.isSelected());
                        for (int i = 0; i < images.length; i++) {
                            imagePanel.add(new JLabel(new ImageIcon(images[i])));
                        }
                        imagePanel.revalidate();
                        imagePanel.repaint();
                    } catch (Exception ex) {
                        System.out.println(ex);
                    }
                }
            }
        });
        frame.setSize(640, 300);
        frame.setVisible(true);        
    }
    
    /* -- Debug methods -- */
    private static void printMessage(SOAPMessage message) throws IOException, SOAPException {
        if (debug && message != null) {
            // Get the MIME headers and print them
            System.out.println("Headers:");
            if (message.saveRequired()) {
                message.saveChanges();
            }
            MimeHeaders headers = message.getMimeHeaders();
            printHeaders(headers);
            
            // Print the message itself
            System.out.println("\nMessage:");
            message.writeTo(System.out);
            System.out.println();
        }
    }
    
    private static void printHeaders(MimeHeaders headers) {
        if (debug) {
            printHeaders(headers.getAllHeaders());
        }
    }
    
    private static void printHeaders(Iterator iter) {
        if (debug) {
            while (iter.hasNext()) {
                MimeHeader header = (MimeHeader)iter.next();
                System.out.println("\t" + header.getName() + ": " + header.getValue());
            }
        }
    }
}