com.moss.rpcutil.proxy.jaxws.JAXWSProxyProvider.java Source code

Java tutorial

Introduction

Here is the source code for com.moss.rpcutil.proxy.jaxws.JAXWSProxyProvider.java

Source

/**
 * Copyright (C) 2013, Moss Computing Inc.
 *
 * This file is part of rpcutil.
 *
 * rpcutil is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * rpcutil is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with rpcutil; see the file COPYING.  If not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA.
 *
 * Linking this library statically or dynamically with other modules is
 * making a combined work based on this library.  Thus, the terms and
 * conditions of the GNU General Public License cover the whole
 * combination.
 *
 * As a special exception, the copyright holders of this library give you
 * permission to link this library with independent modules to produce an
 * executable, regardless of the license terms of these independent
 * modules, and to copy and distribute the resulting executable under
 * terms of your choice, provided that you also meet, for each linked
 * independent module, the terms and conditions of the license of that
 * module.  An independent module is a module which is not derived from
 * or based on this library.  If you modify this library, you may extend
 * this exception to your version of the library, but you are not
 * obligated to do so.  If you do not wish to do so, delete this
 * exception statement from your version.
 */
package com.moss.rpcutil.proxy.jaxws;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.Service;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.HandlerResolver;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.PortInfo;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.moss.jaxbhelper.JAXBHelper;
import com.moss.rpcutil.proxy.ProxyProvider;

public final class JAXWSProxyProvider implements ProxyProvider {

    private final Log log;
    private final Map<Class, QName> registry;
    private final Map<String, Object> cache;

    public JAXWSProxyProvider() {
        this.log = LogFactory.getLog(this.getClass());
        registry = new HashMap<Class, QName>();
        cache = new HashMap<String, Object>();
    }

    public synchronized JAXWSProxyProvider register(Class iface, QName type) {
        registry.put(iface, type);
        return this;
    }

    public synchronized <T> T getProxy(Class<T> iface, String url) {

        QName type = registry.get(iface);

        if (type == null) {
            throw new RuntimeException("Service type not registered: " + iface);
        }

        T proxy = (T) cache.get(url);
        if (proxy == null) {

            Service service;
            try {
                String wsdlLocation = url;
                if (!wsdlLocation.endsWith("?wsdl")) {
                    wsdlLocation += "?wsdl";
                }
                service = Service.create(new URL(wsdlLocation), type);
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }

            if (log.isDebugEnabled()) {
                // SOAP LOGGING STUFF
                service.setHandlerResolver(new HandlerResolver() {
                    public List<Handler> getHandlerChain(PortInfo arg0) {
                        List<Handler> handlers = new LinkedList<Handler>();
                        handlers.add(new SOAPLoggingHandler(log));
                        return handlers;
                    }
                });
            }

            proxy = service.getPort(iface);

            //         BindingProvider bp = (BindingProvider) proxy;
            //         
            //         bp.getRequestContext().put(
            //            MessageContext.HTTP_REQUEST_HEADERS, 
            //            Collections.singletonMap("Content-Type", Arrays.asList(new String[]{"application/soap+xml", "charset=utf-8"}))
            //         );

            cache.put(url, proxy);
        }

        return proxy;
    }

    /*
     * This simple SOAPHandler will output the contents of incoming
     * and outgoing messages.
     */
    public class SOAPLoggingHandler implements SOAPHandler<SOAPMessageContext> {

        private Log log;

        public SOAPLoggingHandler(Log log) {
            super();
            this.log = log;
        }

        public Set<QName> getHeaders() {
            return null;
        }

        public boolean handleMessage(SOAPMessageContext smc) {
            logToSystemOut(smc);
            return true;
        }

        public boolean handleFault(SOAPMessageContext smc) {
            logToSystemOut(smc);
            return true;
        }

        // nothing to clean up
        public void close(MessageContext messageContext) {
        }

        /*
         * Check the MESSAGE_OUTBOUND_PROPERTY in the context
         * to see if this is an outgoing or incoming message.
         * Write a brief message to the print stream and
         * output the message. The writeTo() method can throw
         * SOAPException or IOException
         */
        private void logToSystemOut(SOAPMessageContext smc) {
            if (!log.isDebugEnabled())
                return;

            try {
                final Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
                final ByteArrayOutputStream messageBytes = new ByteArrayOutputStream();
                SOAPMessage message = smc.getMessage();
                message.writeTo(messageBytes);
                messageBytes.close();

                new Thread() {
                    @Override
                    public void run() {
                        try {

                            if (outboundProperty.booleanValue()) {
                                log.debug("\nOutbound message:");
                            } else {
                                log.debug("\nInbound message:");
                            }

                            ByteArrayOutputStream formattedBytes = new ByteArrayOutputStream();
                            setPriority(MIN_PRIORITY);
                            JAXBHelper.beautify(new ByteArrayInputStream(messageBytes.toByteArray()),
                                    formattedBytes);
                            formattedBytes.close();
                            log.debug(new String(formattedBytes.toByteArray()));
                            log.debug("");
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    }
                }.start();

                // just to add a newline
            } catch (Exception e) {
                log.debug("Exception in handler: " + e);
            }
        }
    }
}