/* * JBoss, Home of Professional Open Source. * Copyright 2012, Red Hat, Inc., and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.as.controller.audit; import org.jboss.as.controller.OperationContext.ResultAction; import org.jboss.as.controller.audit.AuditLogItem.JmxAccessAuditLogItem; import org.jboss.as.controller.audit.AuditLogItem.ModelControllerAuditLogItem; import org.jboss.dmr.ModelNode; /** * All methods on this class should be called with {@link ManagedAuditLoggerImpl}'s lock taken. * * @author <a href="kabir.khan@jboss.com">Kabir Khan</a> */ public class JsonAuditLogItemFormatter extends AuditLogItemFormatter { private static final ModelNode UNDEFINED = new ModelNode(); static { UNDEFINED.protect(); } public static final String TYPE = "type"; public static final String READ_ONLY = "r/o"; public static final String BOOTING = "booting"; public static final String AS_VERSION = "version"; public static final String USER_ID = "user"; public static final String DOMAIN_UUID = "domainUUID"; public static final String ACCESS_MECHANISM = "access"; public static final String REMOTE_ADDRESS = "remote-address"; public static final String OPERATIONS = "ops"; public static final String SUCCESS = "success"; public static final String METHOD_NAME = "method"; public static final String METHOD_SIGNATURE = "sig"; public static final String METHOD_PARAMETERS = "params"; public static final String ERROR = "error"; private volatile boolean compactJson; private volatile boolean escapeNewLine; private volatile boolean escapeControlCharacters; public JsonAuditLogItemFormatter(String name, boolean includeDate, String dateSeparator, String dateFormat, boolean compactJson, boolean escapeNewLine, boolean escapeControlCharacters) { super(name, includeDate, dateSeparator, dateFormat); this.compactJson = compactJson; this.escapeNewLine = escapeNewLine; this.escapeControlCharacters = escapeControlCharacters; } public boolean isCompactJson() { return compactJson; } public void setCompactJson(boolean compactJson) { this.compactJson = compactJson; } public void setEscapeNewLine(boolean escapeNewLine) { this.escapeNewLine = escapeNewLine; } public void setEscapeControlCharacters(boolean escapeControlCharacters) { this.escapeControlCharacters = escapeControlCharacters; } @Override public String formatAuditLogItem(ModelControllerAuditLogItem item) { String formattedString = getCachedString(); if (formattedString != null) { return formattedString; } ModelNode formatted = new ModelNode(); formatted.get(TYPE).set(TYPE_CORE); addCommonFields(item, formatted); formatted.get(SUCCESS).set(item.getResultAction() == ResultAction.KEEP); formatted.get(OPERATIONS).set(item.getOperations()); return cacheString(createRecordText(item, formatted)); } @Override public String formatAuditLogItem(JmxAccessAuditLogItem item) { String formattedString = getCachedString(); if (formattedString != null) { return formattedString; } ModelNode formatted = new ModelNode(); formatted.get(TYPE).set(TYPE_JMX); addCommonFields(item, formatted); formatted.get(METHOD_NAME).set(item.getMethodName()); formatted.get(METHOD_SIGNATURE); for (String sig : item.getMethodSignature()) { formatted.get(METHOD_SIGNATURE).add(sig); } formatted.get(METHOD_PARAMETERS); for (Object param : item.getMethodParams()) { //TODO handle arrays better formatted.get(METHOD_PARAMETERS).add(param == null ? UNDEFINED : new ModelNode(param.toString())); } final Throwable throwable = item.getError(); if (throwable != null) { //TODO include stack trace? formatted.get(ERROR).set(throwable.getMessage()); } return cacheString(createRecordText(item, formatted)); } private String createRecordText(AuditLogItem item, ModelNode formatted) { StringBuilder sb = new StringBuilder(); appendDate(sb, item); sb.append(formatted.toJSONString(compactJson)); String formattedString; if (escapeNewLine && !escapeControlCharacters) { //Escape all instances of "\n" with "#012" formattedString = sb.toString().replace("\n", "#012"); } else if (escapeControlCharacters) { StringBuilder escaped = new StringBuilder(); for (int i = 0 ; i < sb.length() ; i++) { char c = sb.charAt(i); if (c >= 0 && c < 32) { escaped.append('#'); if (c < 8) { escaped.append('0').append('0').append((int) c); } else { escaped.append('0').append(c >> 3).append(c & 0x07); } } else { escaped.append(c); } } formattedString = escaped.toString(); } else { formattedString = sb.toString(); } return formattedString; } private void addCommonFields(AuditLogItem item, ModelNode formatted) { formatted.get(READ_ONLY).set(item.isReadOnly()); formatted.get(BOOTING).set(item.isBooting()); formatted.get(AS_VERSION).set(item.getAsVersion()); formatted.get(USER_ID); if (item.getUserId() != null) { formatted.get(USER_ID).set(item.getUserId()); } formatted.get(DOMAIN_UUID); if (item.getDomainUUID() != null) { formatted.get(DOMAIN_UUID).set(item.getDomainUUID()); } formatted.get(ACCESS_MECHANISM); if (item.getAccessMechanism() != null) { formatted.get(ACCESS_MECHANISM).set(item.getAccessMechanism().toString()); } formatted.get(REMOTE_ADDRESS); if (item.getRemoteAddress() != null) { formatted.get(REMOTE_ADDRESS).set(item.getRemoteAddress().toString()); } } public static void getJsonFormatter(String nameFromAddress) { } }