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.ecm.automation.jaxrs.io; 020 021import java.io.ByteArrayOutputStream; 022import java.io.IOException; 023import java.io.OutputStream; 024import java.util.Arrays; 025import java.util.List; 026 027import org.codehaus.jackson.JsonEncoding; 028import org.codehaus.jackson.JsonFactory; 029import org.codehaus.jackson.JsonGenerator; 030import org.nuxeo.ecm.automation.AutomationService; 031import org.nuxeo.ecm.automation.OperationDocumentation; 032import org.nuxeo.ecm.automation.OperationDocumentation.Param; 033import org.nuxeo.ecm.automation.OperationException; 034import org.nuxeo.ecm.automation.core.Constants; 035import org.nuxeo.ecm.automation.io.services.codec.ObjectCodec; 036import org.nuxeo.ecm.automation.io.services.codec.ObjectCodecService; 037import org.nuxeo.ecm.automation.jaxrs.LoginInfo; 038import org.nuxeo.ecm.automation.jaxrs.io.operations.AutomationInfo; 039import org.nuxeo.ecm.platform.forms.layout.api.WidgetDefinition; 040import org.nuxeo.ecm.platform.forms.layout.io.JSONLayoutExporter; 041import org.nuxeo.ecm.webengine.JsonFactoryManager; 042import org.nuxeo.runtime.api.Framework; 043 044/** 045 * Json writer for operations export. 046 * 047 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 048 * @author <a href="mailto:grenard@nuxeo.com">Guillaume Renard</a> 049 */ 050public class JsonWriter { 051 052 private static JsonFactory getFactory() { 053 return Framework.getService(JsonFactoryManager.class).getJsonFactory(); 054 } 055 056 private static JsonGenerator createGenerator(OutputStream out) throws IOException { 057 return getFactory().createJsonGenerator(out, JsonEncoding.UTF8); 058 } 059 060 public static void writeAutomationInfo(OutputStream out, AutomationInfo info, boolean prettyPrint) 061 throws IOException { 062 writeAutomationInfo(createGenerator(out), info, prettyPrint); 063 } 064 065 public static void writeAutomationInfo(JsonGenerator jg, AutomationInfo info, boolean prettyPrint) 066 throws IOException { 067 if (prettyPrint) { 068 jg.useDefaultPrettyPrinter(); 069 } 070 jg.writeStartObject(); 071 writePaths(jg); 072 writeCodecs(jg); 073 writeOperations(jg, info); 074 writeChains(jg, info); 075 jg.writeEndObject(); 076 jg.flush(); 077 } 078 079 private static void writePaths(JsonGenerator jg) throws IOException { 080 jg.writeObjectFieldStart("paths"); 081 jg.writeStringField("login", "login"); 082 jg.writeEndObject(); 083 } 084 085 private static void writeCodecs(JsonGenerator jg) throws IOException { 086 jg.writeArrayFieldStart("codecs"); 087 ObjectCodecService codecs = Framework.getService(ObjectCodecService.class); 088 for (ObjectCodec<?> codec : codecs.getCodecs()) { 089 if (!codec.isBuiltin()) { 090 jg.writeString(codec.getClass().getName()); 091 } 092 } 093 jg.writeEndArray(); 094 } 095 096 /** 097 * Used to export operations to studio. 098 */ 099 public static String exportOperations() throws IOException, OperationException { 100 return exportOperations(false); 101 } 102 103 /** 104 * Used to export operations to studio. 105 * 106 * @param filterNotInStudio if true, operation types not exposed in Studio will be filtered. 107 * @since 5.9.1 108 */ 109 public static String exportOperations(boolean filterNotInStudio) throws IOException, OperationException { 110 List<OperationDocumentation> ops = Framework.getService(AutomationService.class).getDocumentation(); 111 ByteArrayOutputStream out = new ByteArrayOutputStream(); 112 JsonGenerator jg = getFactory().createJsonGenerator(out); 113 jg.useDefaultPrettyPrinter(); 114 jg.writeStartObject(); 115 jg.writeArrayFieldStart("operations"); 116 for (OperationDocumentation op : ops) { 117 if (filterNotInStudio) { 118 if (op.addToStudio && !Constants.CAT_CHAIN.equals(op.category)) { 119 writeOperation(jg, op); 120 } 121 } else { 122 writeOperation(jg, op); 123 } 124 } 125 jg.writeEndArray(); 126 jg.writeEndObject(); 127 jg.flush(); 128 return out.toString("UTF-8"); 129 } 130 131 private static void writeOperations(JsonGenerator jg, AutomationInfo info) throws IOException { 132 jg.writeArrayFieldStart("operations"); 133 for (OperationDocumentation op : info.getOperations()) { 134 writeOperation(jg, op); 135 } 136 jg.writeEndArray(); 137 } 138 139 private static void writeChains(JsonGenerator jg, AutomationInfo info) throws IOException { 140 jg.writeArrayFieldStart("chains"); 141 for (OperationDocumentation op : info.getChains()) { 142 writeOperation(jg, op, Constants.CHAIN_ID_PREFIX + op.id); 143 } 144 jg.writeEndArray(); 145 } 146 147 public static void writeOperation(OutputStream out, OperationDocumentation op) throws IOException { 148 writeOperation(out, op, false); 149 } 150 151 /** 152 * @since 5.9.4 153 */ 154 public static void writeOperation(OutputStream out, OperationDocumentation op, boolean prettyPrint) 155 throws IOException { 156 writeOperation(createGenerator(out), op, prettyPrint); 157 } 158 159 public static void writeOperation(JsonGenerator jg, OperationDocumentation op) throws IOException { 160 writeOperation(jg, op, false); 161 } 162 163 /** 164 * @since 5.9.4 165 */ 166 public static void writeOperation(JsonGenerator jg, OperationDocumentation op, boolean prettyPrint) 167 throws IOException { 168 writeOperation(jg, op, op.url, prettyPrint); 169 } 170 171 public static void writeOperation(JsonGenerator jg, OperationDocumentation op, String url) throws IOException { 172 writeOperation(jg, op, url, false); 173 } 174 175 /** 176 * @since 5.9.4 177 */ 178 public static void writeOperation(JsonGenerator jg, OperationDocumentation op, String url, boolean prettyPrint) 179 throws IOException { 180 if (prettyPrint) { 181 jg.useDefaultPrettyPrinter(); 182 } 183 jg.writeStartObject(); 184 jg.writeStringField("id", op.id); 185 if (op.getAliases() != null && op.getAliases().length > 0) { 186 jg.writeArrayFieldStart("aliases"); 187 for (String alias : op.getAliases()) { 188 jg.writeString(alias); 189 } 190 jg.writeEndArray(); 191 } 192 jg.writeStringField("label", op.label); 193 jg.writeStringField("category", op.category); 194 jg.writeStringField("requires", op.requires); 195 jg.writeStringField("description", op.description); 196 if (op.since != null && op.since.length() > 0) { 197 jg.writeStringField("since", op.since); 198 } 199 jg.writeStringField("url", url); 200 jg.writeArrayFieldStart("signature"); 201 for (String s : op.signature) { 202 jg.writeString(s); 203 } 204 jg.writeEndArray(); 205 writeParams(jg, Arrays.asList(op.params)); 206 if (op.widgetDefinitions != null && op.widgetDefinitions.length > 0) { 207 jg.writeArrayFieldStart("widgets"); 208 for (WidgetDefinition wdef : op.widgetDefinitions) { 209 jg.writeObject(JSONLayoutExporter.exportToJson(wdef, null, null)); 210 } 211 jg.writeEndArray(); 212 } 213 jg.writeEndObject(); 214 jg.flush(); 215 } 216 217 private static void writeParams(JsonGenerator jg, List<Param> params) throws IOException { 218 jg.writeArrayFieldStart("params"); 219 for (Param p : params) { 220 jg.writeStartObject(); 221 jg.writeStringField("name", p.name); 222 jg.writeStringField("description", p.description); 223 jg.writeStringField("type", p.type); 224 jg.writeBooleanField("required", p.required); 225 226 jg.writeStringField("widget", p.widget); 227 jg.writeNumberField("order", p.order); 228 jg.writeArrayFieldStart("values"); 229 for (String value : p.values) { 230 jg.writeString(value); 231 } 232 jg.writeEndArray(); 233 jg.writeEndObject(); 234 } 235 jg.writeEndArray(); 236 } 237 238 public static void writeLogin(OutputStream out, LoginInfo login) throws IOException { 239 writeLogin(createGenerator(out), login); 240 } 241 242 public static void writeLogin(JsonGenerator jg, LoginInfo login) throws IOException { 243 jg.writeStartObject(); 244 jg.writeStringField("entity-type", "login"); 245 jg.writeStringField("username", login.getUsername()); 246 jg.writeBooleanField("isAdministrator", login.isAdministrator()); 247 jg.writeArrayFieldStart("groups"); 248 for (String group : login.getGroups()) { 249 jg.writeString(group); 250 } 251 jg.writeEndArray(); 252 jg.writeEndObject(); 253 jg.flush(); 254 } 255 256 public static void writePrimitive(OutputStream out, Object value) throws IOException { 257 writePrimitive(createGenerator(out), value); 258 } 259 260 public static void writePrimitive(JsonGenerator jg, Object value) throws IOException { 261 jg.writeStartObject(); 262 jg.writeStringField("entity-type", "primitive"); 263 if (value != null) { 264 Class<?> type = value.getClass(); 265 if (type == String.class) { 266 jg.writeStringField("value", (String) value); 267 } else if (type == Boolean.class) { 268 jg.writeBooleanField("value", (Boolean) value); 269 } else if (type == Long.class) { 270 jg.writeNumberField("value", ((Number) value).longValue()); 271 } else if (type == Double.class) { 272 jg.writeNumberField("value", ((Number) value).doubleValue()); 273 } else if (type == Integer.class) { 274 jg.writeNumberField("value", ((Number) value).intValue()); 275 } else if (type == Float.class) { 276 jg.writeNumberField("value", ((Number) value).floatValue()); 277 } 278 } else { 279 jg.writeNullField("value"); 280 } 281 jg.writeEndObject(); 282 jg.flush(); 283 } 284 285}