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 /** 050 * Constructs a SimpleMsg with an XML tag, an optional name attribute, and a payload. 051 * 052 * @param tagName XML tag name 053 * @param msgName optional name attribute, or {@code null} 054 * @param msgContent message payload (rendered specially for byte arrays, collections, throwables, and loggeables) 055 */ 056 public SimpleMsg(String tagName, String msgName, Object msgContent) { 057 this.tagName = tagName; 058 this.msgName = msgName; 059 if (msgContent instanceof byte[]) 060 this.msgContent = ISOUtil.hexString((byte[]) msgContent); 061 else 062 this.msgContent = msgContent; 063 } 064 065 /** 066 * Constructs a SimpleMsg with no name attribute. 067 * 068 * @param tagName XML tag name 069 * @param msgContent message payload 070 */ 071 public SimpleMsg(String tagName, Object msgContent) { 072 this(tagName, null, msgContent); 073 } 074 075 /** 076 * dumps message 077 * 078 * @param p a PrintStream usually supplied by Logger 079 * @param indent indention string, usually suppiled by Logger 080 * @see org.jpos.util.Loggeable 081 */ 082 @Override 083 public void dump(PrintStream p, String indent) { 084 String inner = indent + " "; 085 p.print(indent + "<" + tagName); 086 if (msgName != null) 087 p.print(" name=\"" + msgName + "\""); 088 089 Collection cl = null; 090 if (msgContent instanceof Object[]) 091 cl = Arrays.asList((Object[]) msgContent); 092 else if (msgContent instanceof Collection) 093 cl = (Collection) msgContent; 094 else if (msgContent instanceof Loggeable) 095 cl = Arrays.asList(msgContent); 096 else if (msgContent instanceof Throwable) 097 cl = Arrays.asList(msgContent); 098 else if (msgName != null && msgContent == null) { 099 p.println("/>"); 100 return; 101 } else if (msgName != null) 102 cl = Arrays.asList(msgContent); 103 else if (msgContent != null) 104 p.print(">" + msgContent); 105 else { 106 p.println("/>"); 107 return; 108 } 109 110 if (cl != null) { 111 p.println(">"); 112 for (Object o : cl) { 113 if (o instanceof Loggeable) 114 ((Loggeable) o).dump(p, inner); 115 else if (o instanceof Throwable) 116 p.print(formatThrowable(indent, (Throwable) o)); 117 else 118 p.println(inner + o); 119 } 120 p.print(indent); 121 } 122 123 p.println("</" + tagName + ">"); 124 } 125 126 private String formatThrowable(String indent, Throwable t) { 127 String inde = indent + STACKTRACE_EXTRA_INDENT; 128 try ( 129 OutputStream os = new ByteArrayOutputStream(); 130 PrintStream ps = new PrintStream(os); 131 ) { 132 // indent stack trace first line 133 ps.print(inde); 134 t.printStackTrace(ps); 135 136 String res = os.toString(); 137 res = res.replace("\n\t", "\n" + inde + STACKTRACE_TAB_REPLACE); 138 res = res.replace("\nCaused by:", "\n" + inde + "Caused by:"); 139 return res; 140 } catch (IOException ex) { 141 return ""; // it should never occur for ByteArrayOutputStream 142 } 143 } 144 145 /** 146 * Replaces the message payload. 147 * 148 * @param msgContent new payload 149 */ 150 public void setMsgContent(Object msgContent) { 151 this.msgContent = msgContent; 152 } 153 154 /** 155 * Returns the current message payload. 156 * 157 * @return the payload (may be {@code null}) 158 */ 159 public Object getMsgContent() { 160 return msgContent; 161 } 162}