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.nuxeo.ecm.automation.client.OperationRequest; 027import org.nuxeo.ecm.automation.client.model.Blob; 028import org.nuxeo.ecm.automation.client.model.FileBlob; 029import org.nuxeo.shell.Argument; 030import org.nuxeo.shell.Command; 031import org.nuxeo.shell.Context; 032import org.nuxeo.shell.Parameter; 033import org.nuxeo.shell.ShellConsole; 034import org.nuxeo.shell.ShellException; 035import org.nuxeo.shell.automation.RemoteContext; 036import org.nuxeo.shell.fs.FileCompletor; 037import org.nuxeo.shell.fs.FileSystem; 038import org.nuxeo.shell.utils.StringUtils; 039 040import com.fasterxml.jackson.databind.JsonNode; 041import com.fasterxml.jackson.databind.ObjectMapper; 042 043/** 044 * @author <a href="mailto:[email protected]">Bogdan Stefanescu</a> 045 */ 046@Command(name = "audit", help = "Run a query against audit service") 047public class Audit implements Runnable { 048 049 @Context 050 protected RemoteContext ctx; 051 052 @Parameter(name = "-ctx", hasValue = true, help = "Use this to set query variables. Syntax is: \"k1=v1,k1=v2\"") 053 protected String queryVars; 054 055 @Parameter(name = "-s", hasValue = true, help = "Use this to change the separator used in query variables. THe default is ','") 056 protected String sep = ","; 057 058 @Parameter(name = "-f", hasValue = true, completor = FileCompletor.class, help = "Use this to save results in a file. Otherwise results are printed on the screen.") 059 protected File file; 060 061 @Parameter(name = "-max", hasValue = true, help = "The max number of rows to return.") 062 protected int max; 063 064 @Parameter(name = "-page", hasValue = true, help = "The current page to return. To be used in conjunction with -max.") 065 protected int page = 1; 066 067 @Argument(name = "query", index = 0, required = true, help = "The query to run. Query is in JPQL format") 068 protected String query; 069 070 public void run() { 071 try { 072 OperationRequest req = ctx.getSession().newRequest("Audit.Query").set("query", query).set("maxResults", max).set( 073 "pageNo", page); 074 if (queryVars != null) { 075 for (String pair : queryVars.split(sep)) { 076 String[] ar = StringUtils.split(pair, '=', true); 077 req.setContextProperty("audit.query." + ar[0], ar[1]); 078 } 079 } 080 Blob blob = (Blob) req.execute(); 081 String content = null; 082 if (file != null) { 083 ((FileBlob) blob).getFile().renameTo(file); 084 } else { 085 InputStream in = blob.getStream(); 086 try { 087 content = FileSystem.readContent(in); 088 } finally { 089 in.close(); 090 ((FileBlob) blob).getFile().delete(); 091 } 092 print(ctx.getShell().getConsole(), content); 093 } 094 } catch (Exception e) { 095 throw new ShellException("Failed to query audit.", e); 096 } 097 } 098 099 private final void printString(ShellConsole console, JsonNode obj, String key) { 100 JsonNode v = obj.get(key); 101 if (v != null) { 102 String s = v.textValue(); 103 if (s != null) { 104 console.print(v.textValue()); 105 return; 106 } 107 } 108 console.print("[null]"); 109 } 110 111 private final void printDate(ShellConsole console, JsonNode obj, String key, SimpleDateFormat fmt) { 112 JsonNode v = obj.get(key); 113 if (v != null) { 114 console.print(fmt.format(new Date(v.asLong()))); 115 } else { 116 console.print("[null]"); 117 } 118 } 119 120 protected void print(ShellConsole console, String content) throws Exception { 121 ObjectMapper mapper = new ObjectMapper(); 122 JsonNode rows = mapper.readTree(content); 123 if (!rows.isArray()) { 124 console.print("Invalid JSON object received:\n" + content); 125 return; 126 } 127 int len = rows.size(); 128 SimpleDateFormat fmt = new SimpleDateFormat(); 129 for (int i = 0; i < len; i++) { 130 JsonNode obj = (JsonNode) rows.get(i); 131 printString(console, obj, "eventId"); 132 console.print("\t"); 133 printString(console, obj, "category"); 134 console.print("\t"); 135 printDate(console, obj, "eventDate", fmt); 136 console.print("\t"); 137 printString(console, obj, "principal"); 138 console.print("\t"); 139 printString(console, obj, "docUUID"); 140 console.print("\t"); 141 printString(console, obj, "docType"); 142 console.print("\t"); 143 printString(console, obj, "docLifeCycle"); 144 console.print("\t"); 145 printString(console, obj, "comment"); 146 console.println(); 147 } 148 } 149}