blob: 8751463fc55fcb71b44c6f5ee1063701da1654c6 [file] [log] [blame]
/*
* Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package com.sun.enterprise.v3.common;
import org.jvnet.hk2.annotations.Service;
import org.glassfish.hk2.api.PerLookup;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
/**
* Writes command output to a json stream
*
* @author Ludovic Champenois
*/
@Service(name = "json")
@PerLookup
public class JsonActionReporter extends ActionReporter {
/*
top is true only for the first toplevel message to emit more data like
* command name and exit_code of the command
*
*/
private boolean top = true;
/** Creates a new instance of JsonActionReporter */
public JsonActionReporter() {
}
@Override
public void writeReport(OutputStream os) throws IOException {
PrintWriter writer = new PrintWriter(os);
write(topMessage, writer);
if (exception != null) {
writer.println("Exception raised during operation : <br>");
exception.printStackTrace(writer);
}
if (subActions.size() > 0) {
writer.println(quote(", number_subactions") + ":" + quote("" + subActions.size()));
}
writer.flush();
}
private void write(MessagePart part, PrintWriter writer) {
writer.println("{ " + quote("name") + ":" + quote(part.getMessage()));
if (top) {
writer.println(", " + quote("command") + ":" + quote(actionDescription));
writer.println(", " + quote("exit_code") + ":" + quote("" + this.exitCode));
top = false;
}
writeProperties(part.getProps(), writer);
boolean first = true;
for (MessagePart child : part.getChildren()) {
if (first == true) {
writer.println(", " + quote("result") + " : [");
} else {
writer.println(",");
}
first = false;
write(child, writer);
}
if (first == false) { //close the array
writer.println("]");
}
writer.println("}");
}
private void writeProperties(Properties props, PrintWriter writer) {
if (props == null || props.size() == 0) {
return;
}
StringBuilder result = new StringBuilder(",");
result.append(quote("properties")).append(" : {");
String sep = "";
for (Map.Entry entry : props.entrySet()) {
String line = quote("" + entry.getKey()) + " : ";
Object value = entry.getValue();
if (value instanceof List) {
line += encodeList((List)value);
} else if (value instanceof Map) {
line += encodeMap((Map)value);
} else {
line += quote("" + value.toString());
}
result.append(sep).append(line);
sep = ",";
}
writer.println(result.append("}").toString());
}
private String encodeList (List list) {
StringBuilder result = new StringBuilder("[");
String sep = "";
for (Object entry : list) {
if (entry instanceof List) {
result.append(sep).append(encodeList((List)entry));
} else if (entry instanceof Map) {
result.append(sep).append(encodeMap((Map)entry));
} else {
result.append(sep).append(quote (entry.toString()));
}
sep = ",";
}
return result.append("]").toString();
}
private String encodeMap (Map map) {
StringBuilder result = new StringBuilder("{");
String sep = "";
for (Map.Entry entry : (Set<Map.Entry>)map.entrySet()) {
String key = entry.getKey().toString();
Object value = entry.getValue();
result.append(sep).append(quote(key)).append(":");
if (value instanceof List) {
result.append(encodeList((List) value));
} else if (value instanceof Map) {
result.append(encodeMap((Map) value));
} else {
result.append(quote(value.toString()));
}
sep = ",";
}
return result.append("}").toString();
}
/**
* Produce a string in double quotes with backslash sequences in all the
* right places.
*/
private String quote(String string) {
if (string == null || string.length() == 0) {
return "\"\"";
}
char b;
char c = 0;
int i;
int len = string.length();
StringBuilder sb = new StringBuilder(len + 4);
String t;
sb.append('"');
for (i = 0; i < len; i += 1) {
b = c;
c = string.charAt(i);
switch (c) {
case '\\':
case '"':
sb.append('\\');
sb.append(c);
break;
case '/':
if (b == '<') {
sb.append('\\');
}
sb.append(c);
break;
case '\b':
sb.append("\\b");
break;
case '\t':
sb.append("\\t");
break;
case '\n':
sb.append("\\n");
break;
case '\f':
sb.append("\\f");
break;
case '\r':
sb.append("\\r");
break;
default:
if (c < ' ') {
t = "000" + Integer.toHexString(c);
sb.append("\\u" + t.substring(t.length() - 4));
} else {
sb.append(c);
}
}
}
sb.append('"');
return sb.toString();
}
}