001    /*
002     * Common usable utilities
003     *
004     * Copyright (c) 2006 Petr Hadraba <hadrabap@gmail.com>
005     *
006     * Author: Petr Hadraba
007     *
008     * --
009     *
010     * XML Utilities
011     */
012    
013    package global.sandbox.xmlutilities;
014    
015    import java.io.ByteArrayOutputStream;
016    import java.io.OutputStreamWriter;
017    import java.io.PrintStream;
018    import java.io.PrintWriter;
019    import java.nio.charset.Charset;
020    import java.util.Iterator;
021    import java.util.List;
022    import java.util.concurrent.CopyOnWriteArrayList;
023    
024    /**
025     * Common exception related to XML Utilities.
026     *
027     * @author Petr Hadraba
028     *
029     * @since 1.2
030     */
031    public class XmlUtilitiesException extends Exception implements Iterable<Throwable> {
032    
033        private static final long serialVersionUID = 1L;
034    
035        /**
036         * Consequent exception; usually finally block.
037         */
038        private final List<Throwable> consequents = new CopyOnWriteArrayList<Throwable>();
039    
040        public XmlUtilitiesException() {
041        }
042    
043        public XmlUtilitiesException(String message) {
044            super(message);
045        }
046    
047        public XmlUtilitiesException(Throwable cause) {
048            super(cause);
049        }
050    
051        public XmlUtilitiesException(String message, Throwable cause) {
052            super(message, cause);
053        }
054    
055        private static final Throwable[] EMPTY_THROWABLE_ARRAY = new Throwable[] {};
056    
057        public Throwable[] getConsequent() {
058            return consequents.toArray(EMPTY_THROWABLE_ARRAY);
059        }
060    
061        public void addConsequent(Throwable consequent) {
062            this.consequents.add(consequent);
063        }
064    
065        private static final String INTERNAL_ENCODING = "UTF-8";
066    
067        private static final Charset INTERNAL_CHARSET;
068    
069        static {
070            INTERNAL_CHARSET = Charset.forName(INTERNAL_ENCODING);
071        }
072    
073        private static final String CONSEQUENT_CAPTION = "By consequent: ";
074    
075        @Override
076        public void printStackTrace(PrintStream s) {
077            printStackTrace(new WrappedPrintStream(s));
078        }
079    
080        @Override
081        public void printStackTrace(PrintWriter s) {
082            printStackTrace(new WrappedPrintWriter(s));
083        }
084    
085        @Override
086        public void printStackTrace() {
087            printStackTrace(System.err);
088        }
089    
090        @Override
091        public Iterator<Throwable> iterator() {
092            return consequents.iterator();
093        }
094    
095        private void printStackTrace(PrintStreamOrWriter s) {
096            ByteArrayOutputStream baos = new ByteArrayOutputStream();
097            OutputStreamWriter osw = new OutputStreamWriter(baos, INTERNAL_CHARSET);
098            PrintWriter pw = new PrintWriter(osw);
099            super.printStackTrace(pw);
100            pw.flush();
101            s.print(new String(baos.toByteArray(), INTERNAL_CHARSET));
102    
103            for (Throwable consequent : consequents) {
104                s.print(CONSEQUENT_CAPTION);
105                s.printStackTrace(consequent);
106            }
107            s.flush();
108        }
109    
110        private static interface PrintStreamOrWriter {
111    
112            abstract void print(String text);
113    
114            abstract void println(String text);
115    
116            abstract void flush();
117    
118            abstract void printStackTrace(Throwable t);
119    
120        }
121    
122        private static class WrappedPrintWriter implements PrintStreamOrWriter {
123    
124            private final PrintWriter printWriter;
125    
126            WrappedPrintWriter(PrintWriter printWriter) {
127                this.printWriter = printWriter;
128            }
129    
130            @Override
131            public void print(String text) {
132                printWriter.print(text);
133            }
134    
135            @Override
136            public void println(String text) {
137                printWriter.println(text);
138            }
139    
140            @Override
141            public void flush() {
142                printWriter.flush();
143            }
144    
145            @Override
146            public void printStackTrace(Throwable t) {
147                t.printStackTrace(printWriter);
148            }
149    
150        }
151    
152        private static class WrappedPrintStream implements PrintStreamOrWriter {
153    
154            private final PrintStream printStream;
155    
156            WrappedPrintStream(PrintStream printStream) {
157                this.printStream = printStream;
158            }
159    
160            @Override
161            public void print(String text) {
162                printStream.print(text);
163            }
164    
165            @Override
166            public void println(String text) {
167                printStream.println(text);
168            }
169    
170            @Override
171            public void flush() {
172                printStream.flush();
173            }
174    
175            @Override
176            public void printStackTrace(Throwable t) {
177                t.printStackTrace(printStream);
178            }
179    
180        }
181    
182    }