001/*
002 * jPOS Project [http://jpos.org]
003 * Copyright (C) 2000-2026 jPOS Software SRL
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.jpos.util;
020
021import java.io.ByteArrayOutputStream;
022import java.io.IOException;
023import java.io.OutputStream;
024
025import org.jpos.iso.ISOUtil;
026
027import java.io.PrintStream;
028import java.util.Arrays;
029import java.util.Collection;
030
031/**
032 * <p>
033 * A simple general purpose loggeable message.
034 * </p>
035 *
036 * @author Hani S. Kirollos
037 * @version $Revision$ $Date$
038 */
039public class SimpleMsg implements Loggeable {
040
041    static final String STACKTRACE_EXTRA_INDENT = "    ";
042
043    static final String STACKTRACE_TAB_REPLACE = STACKTRACE_EXTRA_INDENT + STACKTRACE_EXTRA_INDENT;
044
045    String tagName;
046    String msgName;
047    Object msgContent;
048
049    public SimpleMsg(String tagName, String msgName, Object msgContent) {
050        this.tagName = tagName;
051        this.msgName = msgName;
052        if (msgContent instanceof byte[])
053            this.msgContent = ISOUtil.hexString((byte[]) msgContent);
054        else
055            this.msgContent = msgContent;
056    }
057
058    public SimpleMsg(String tagName, Object msgContent) {
059        this(tagName, null, msgContent);
060    }
061
062    /**
063     * dumps message
064     *
065     * @param p      a PrintStream usually supplied by Logger
066     * @param indent indention string, usually suppiled by Logger
067     * @see org.jpos.util.Loggeable
068     */
069    @Override
070    public void dump(PrintStream p, String indent) {
071        String inner = indent + "  ";
072        p.print(indent + "<" + tagName);
073        if (msgName != null)
074            p.print(" name=\"" + msgName + "\"");
075
076        Collection cl = null;
077        if (msgContent instanceof Object[])
078            cl = Arrays.asList((Object[]) msgContent);
079        else if (msgContent instanceof Collection)
080            cl = (Collection) msgContent;
081        else if (msgContent instanceof Loggeable)
082            cl = Arrays.asList(msgContent);
083        else if (msgContent instanceof Throwable)
084            cl = Arrays.asList(msgContent);
085        else if (msgName != null && msgContent == null) {
086            p.println("/>");
087            return;
088        } else if (msgName != null)
089            cl = Arrays.asList(msgContent);
090        else if (msgContent != null)
091            p.print(">" + msgContent);
092        else {
093            p.println("/>");
094            return;
095        }
096
097        if (cl != null) {
098            p.println(">");
099            for (Object o : cl) {
100                if (o instanceof Loggeable)
101                    ((Loggeable) o).dump(p, inner);
102                else if (o instanceof Throwable)
103                    p.print(formatThrowable(indent, (Throwable) o));
104                else
105                    p.println(inner + o);
106            }
107            p.print(indent);
108        }
109
110        p.println("</" + tagName + ">");
111    }
112
113    private String formatThrowable(String indent, Throwable t) {
114        String inde = indent + STACKTRACE_EXTRA_INDENT;
115        try (
116                OutputStream os = new ByteArrayOutputStream();
117                PrintStream ps = new PrintStream(os);
118        ) {
119            // indent stack trace first line
120            ps.print(inde);
121            t.printStackTrace(ps);
122
123            String res = os.toString();
124            res = res.replace("\n\t", "\n" + inde + STACKTRACE_TAB_REPLACE);
125            res = res.replace("\nCaused by:", "\n" + inde + "Caused by:");
126            return res;
127        } catch (IOException ex) {
128            return ""; // it should never occur for ByteArrayOutputStream
129        }
130    }
131
132    public void setMsgContent(Object msgContent) {
133        this.msgContent = msgContent;
134    }
135
136    public Object getMsgContent() {
137        return msgContent;
138    }
139}