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