1 /*
   2  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.xml.internal.ws.util.pipe;
  27 
  28 import com.sun.xml.internal.ws.api.message.Packet;
  29 import com.sun.xml.internal.ws.api.pipe.NextAction;
  30 import com.sun.xml.internal.ws.api.pipe.Pipe;
  31 import com.sun.xml.internal.ws.api.pipe.Tube;
  32 import com.sun.xml.internal.ws.api.pipe.TubeCloner;
  33 import com.sun.xml.internal.ws.api.pipe.helper.AbstractFilterTubeImpl;
  34 import com.sun.xml.internal.ws.api.pipe.helper.AbstractTubeImpl;
  35 
  36 import javax.xml.stream.XMLOutputFactory;
  37 import javax.xml.stream.XMLStreamException;
  38 import javax.xml.stream.XMLStreamWriter;
  39 import java.io.PrintStream;
  40 import java.lang.reflect.Constructor;
  41 
  42 /**
  43  * {@link Pipe} that dumps messages that pass through.
  44  *
  45  * @author Kohsuke Kawaguchi
  46  */
  47 public class DumpTube extends AbstractFilterTubeImpl {
  48 
  49     private final String name;
  50 
  51     private final PrintStream out;
  52 
  53     private final XMLOutputFactory staxOut;
  54 
  55     /**
  56      * @param name
  57      *      Specify the name that identifies this {@link DumpTube}
  58      *      instance. This string will be printed when this pipe
  59      *      dumps messages, and allows people to distinguish which
  60      *      pipe instance is dumping a message when multiple
  61      *      {@link DumpTube}s print messages out.
  62      * @param out
  63      *      The output to send dumps to.
  64      * @param next
  65      *      The next {@link Tube} in the pipeline.
  66      */
  67     public DumpTube(String name, PrintStream out, Tube next) {
  68         super(next);
  69         this.name = name;
  70         this.out = out;
  71         this.staxOut = XMLOutputFactory.newInstance();
  72         //staxOut.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES,true);
  73     }
  74 
  75     /**
  76      * Copy constructor.
  77      */
  78     protected DumpTube(DumpTube that, TubeCloner cloner) {
  79         super(that,cloner);
  80         this.name = that.name;
  81         this.out = that.out;
  82         this.staxOut = that.staxOut;
  83     }
  84 
  85     @Override
  86     public NextAction processRequest(Packet request) {
  87         dump("request",request);
  88         return super.processRequest(request);
  89     }
  90 
  91     @Override
  92     public NextAction processResponse(Packet response) {
  93         dump("response",response);
  94         return super.processResponse(response);
  95     }
  96 
  97     protected void dump(String header, Packet packet) {
  98         out.println("====["+name+":"+header+"]====");
  99         if(packet.getMessage()==null)
 100             out.println("(none)");
 101         else
 102             try {
 103                 XMLStreamWriter writer = staxOut.createXMLStreamWriter(new PrintStream(out) {
 104                     @Override
 105                     public void close() {
 106                         // noop
 107                     }
 108                 });
 109                 writer = createIndenter(writer);
 110                 packet.getMessage().copy().writeTo(writer);
 111                 writer.close();
 112             } catch (XMLStreamException e) {
 113                 e.printStackTrace(out);
 114             }
 115         out.println("============");
 116     }
 117 
 118     /**
 119      * Wraps {@link XMLStreamWriter} by an indentation engine if possible.
 120      *
 121      * <p>
 122      * We can do this only when we have <tt>stax-utils.jar</tt> in the classpath.
 123      */
 124     private XMLStreamWriter createIndenter(XMLStreamWriter writer) {
 125         try {
 126             Class clazz = getClass().getClassLoader().loadClass("javanet.staxutils.IndentingXMLStreamWriter");
 127             Constructor c = clazz.getConstructor(XMLStreamWriter.class);
 128             writer = (XMLStreamWriter)c.newInstance(writer);
 129         } catch (Exception e) {
 130             // if stax-utils.jar is not in the classpath, this will fail
 131             // so, we'll just have to do without indentation
 132             if(!warnStaxUtils) {
 133                 warnStaxUtils = true;
 134                 out.println("WARNING: put stax-utils.jar to the classpath to indent the dump output");
 135             }
 136         }
 137         return writer;
 138     }
 139 
 140 
 141     public AbstractTubeImpl copy(TubeCloner cloner) {
 142         return new DumpTube(this,cloner);
 143     }
 144 
 145     private static boolean warnStaxUtils;
 146 }