001/* 002 * (C) Copyright 2006-2010 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * bstefanescu 018 */ 019package org.nuxeo.shell.automation.cmds; 020 021import java.io.File; 022import java.io.InputStream; 023import java.text.SimpleDateFormat; 024import java.util.Date; 025 026import org.codehaus.jackson.JsonNode; 027import org.codehaus.jackson.map.ObjectMapper; 028import org.nuxeo.ecm.automation.client.OperationRequest; 029import org.nuxeo.ecm.automation.client.model.Blob; 030import org.nuxeo.ecm.automation.client.model.FileBlob; 031import org.nuxeo.shell.Argument; 032import org.nuxeo.shell.Command; 033import org.nuxeo.shell.Context; 034import org.nuxeo.shell.Parameter; 035import org.nuxeo.shell.ShellConsole; 036import org.nuxeo.shell.ShellException; 037import org.nuxeo.shell.automation.RemoteContext; 038import org.nuxeo.shell.fs.FileCompletor; 039import org.nuxeo.shell.fs.FileSystem; 040import org.nuxeo.shell.utils.StringUtils; 041 042/** 043 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 044 */ 045@Command(name = "audit", help = "Run a query against audit service") 046public class Audit implements Runnable { 047 048 @Context 049 protected RemoteContext ctx; 050 051 @Parameter(name = "-ctx", hasValue = true, help = "Use this to set query variables. Syntax is: \"k1=v1,k1=v2\"") 052 protected String queryVars; 053 054 @Parameter(name = "-s", hasValue = true, help = "Use this to change the separator used in query variables. THe default is ','") 055 protected String sep = ","; 056 057 @Parameter(name = "-f", hasValue = true, completor = FileCompletor.class, help = "Use this to save results in a file. Otherwise results are printed on the screen.") 058 protected File file; 059 060 @Parameter(name = "-max", hasValue = true, help = "The max number of rows to return.") 061 protected int max; 062 063 @Parameter(name = "-page", hasValue = true, help = "The current page to return. To be used in conjunction with -max.") 064 protected int page = 1; 065 066 @Argument(name = "query", index = 0, required = true, help = "The query to run. Query is in JPQL format") 067 protected String query; 068 069 public void run() { 070 try { 071 OperationRequest req = ctx.getSession().newRequest("Audit.Query").set("query", query).set("maxResults", max).set( 072 "pageNo", page); 073 if (queryVars != null) { 074 for (String pair : queryVars.split(sep)) { 075 String[] ar = StringUtils.split(pair, '=', true); 076 req.setContextProperty("audit.query." + ar[0], ar[1]); 077 } 078 } 079 Blob blob = (Blob) req.execute(); 080 String content = null; 081 if (file != null) { 082 ((FileBlob) blob).getFile().renameTo(file); 083 } else { 084 InputStream in = blob.getStream(); 085 try { 086 content = FileSystem.readContent(in); 087 } finally { 088 in.close(); 089 ((FileBlob) blob).getFile().delete(); 090 } 091 print(ctx.getShell().getConsole(), content); 092 } 093 } catch (Exception e) { 094 throw new ShellException("Failed to query audit.", e); 095 } 096 } 097 098 private final void printString(ShellConsole console, JsonNode obj, String key) { 099 JsonNode v = obj.get(key); 100 if (v != null) { 101 String s = v.getTextValue(); 102 if (s != null) { 103 console.print(v.getTextValue()); 104 return; 105 } 106 } 107 console.print("[null]"); 108 } 109 110 private final void printDate(ShellConsole console, JsonNode obj, String key, SimpleDateFormat fmt) { 111 JsonNode v = obj.get(key); 112 if (v != null) { 113 console.print(fmt.format(new Date(v.getValueAsLong()))); 114 } else { 115 console.print("[null]"); 116 } 117 } 118 119 protected void print(ShellConsole console, String content) throws Exception { 120 ObjectMapper mapper = new ObjectMapper(); 121 JsonNode rows = mapper.readTree(content); 122 if (!rows.isArray()) { 123 console.print("Invalid JSON object received:\n" + content); 124 return; 125 } 126 int len = rows.size(); 127 SimpleDateFormat fmt = new SimpleDateFormat(); 128 for (int i = 0; i < len; i++) { 129 JsonNode obj = (JsonNode) rows.get(i); 130 printString(console, obj, "eventId"); 131 console.print("\t"); 132 printString(console, obj, "category"); 133 console.print("\t"); 134 printDate(console, obj, "eventDate", fmt); 135 console.print("\t"); 136 printString(console, obj, "principal"); 137 console.print("\t"); 138 printString(console, obj, "docUUID"); 139 console.print("\t"); 140 printString(console, obj, "docType"); 141 console.print("\t"); 142 printString(console, obj, "docLifeCycle"); 143 console.print("\t"); 144 printString(console, obj, "comment"); 145 console.println(); 146 } 147 } 148}