/* * (C) Copyright 2006-2010 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Contributors: * bstefanescu */ package org.nuxeo.ecm.automation.jaxrs.io; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Arrays; import java.util.List; import org.codehaus.jackson.JsonEncoding; import org.codehaus.jackson.JsonFactory; import org.codehaus.jackson.JsonGenerator; import org.nuxeo.ecm.automation.AutomationService; import org.nuxeo.ecm.automation.OperationDocumentation; import org.nuxeo.ecm.automation.OperationDocumentation.Param; import org.nuxeo.ecm.automation.OperationException; import org.nuxeo.ecm.automation.core.Constants; import org.nuxeo.ecm.automation.io.services.codec.ObjectCodec; import org.nuxeo.ecm.automation.io.services.codec.ObjectCodecService; import org.nuxeo.ecm.automation.jaxrs.LoginInfo; import org.nuxeo.ecm.automation.jaxrs.io.operations.AutomationInfo; import org.nuxeo.ecm.platform.forms.layout.api.WidgetDefinition; import org.nuxeo.ecm.platform.forms.layout.io.JSONLayoutExporter; import org.nuxeo.ecm.webengine.JsonFactoryManager; import org.nuxeo.ecm.webengine.WebException; import org.nuxeo.runtime.api.Framework; /** * Json writer for operations export. * * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> * @author <a href="mailto:grenard@nuxeo.com">Guillaume Renard</a> */ public class JsonWriter { private static JsonFactory getFactory() { return Framework.getLocalService(JsonFactoryManager.class).getJsonFactory(); } private static JsonGenerator createGenerator(OutputStream out) throws IOException { return getFactory().createJsonGenerator(out, JsonEncoding.UTF8); } public static void writeAutomationInfo(OutputStream out, AutomationInfo info, boolean prettyPrint) throws IOException { writeAutomationInfo(createGenerator(out), info, prettyPrint); } public static void writeAutomationInfo(JsonGenerator jg, AutomationInfo info, boolean prettyPrint) throws IOException { if (prettyPrint) { jg.useDefaultPrettyPrinter(); } jg.writeStartObject(); writePaths(jg); writeCodecs(jg); writeOperations(jg, info); writeChains(jg, info); jg.writeEndObject(); jg.flush(); } private static void writePaths(JsonGenerator jg) throws IOException { jg.writeObjectFieldStart("paths"); jg.writeStringField("login", "login"); jg.writeEndObject(); } private static void writeCodecs(JsonGenerator jg) throws IOException { jg.writeArrayFieldStart("codecs"); ObjectCodecService codecs = Framework.getLocalService(ObjectCodecService.class); for (ObjectCodec<?> codec : codecs.getCodecs()) { if (!codec.isBuiltin()) { jg.writeString(codec.getClass().getName()); } } jg.writeEndArray(); } /** * Used to export operations to studio. */ public static String exportOperations() throws IOException, OperationException { return exportOperations(false); } /** * Used to export operations to studio. * * @param filterNotInStudio if true, operation types not exposed in Studio will be filtered. * @since 5.9.1 */ public static String exportOperations(boolean filterNotInStudio) throws IOException, OperationException { List<OperationDocumentation> ops = Framework.getLocalService(AutomationService.class).getDocumentation(); ByteArrayOutputStream out = new ByteArrayOutputStream(); JsonGenerator jg = getFactory().createJsonGenerator(out); jg.useDefaultPrettyPrinter(); jg.writeStartObject(); jg.writeArrayFieldStart("operations"); for (OperationDocumentation op : ops) { if (filterNotInStudio) { if (op.addToStudio && !Constants.CAT_CHAIN.equals(op.category)) { writeOperation(jg, op); } } else { writeOperation(jg, op); } } jg.writeEndArray(); jg.writeEndObject(); jg.flush(); return out.toString("UTF-8"); } private static void writeOperations(JsonGenerator jg, AutomationInfo info) throws IOException { jg.writeArrayFieldStart("operations"); for (OperationDocumentation op : info.getOperations()) { writeOperation(jg, op); } jg.writeEndArray(); } private static void writeChains(JsonGenerator jg, AutomationInfo info) throws IOException { jg.writeArrayFieldStart("chains"); for (OperationDocumentation op : info.getChains()) { writeOperation(jg, op, Constants.CHAIN_ID_PREFIX + op.id); } jg.writeEndArray(); } public static void writeOperation(OutputStream out, OperationDocumentation op) throws IOException { writeOperation(out, op, false); } /** * @since 5.9.4 */ public static void writeOperation(OutputStream out, OperationDocumentation op, boolean prettyPrint) throws IOException { writeOperation(createGenerator(out), op, prettyPrint); } public static void writeOperation(JsonGenerator jg, OperationDocumentation op) throws IOException { writeOperation(jg, op, false); } /** * @since 5.9.4 */ public static void writeOperation(JsonGenerator jg, OperationDocumentation op, boolean prettyPrint) throws IOException { writeOperation(jg, op, op.url, prettyPrint); } public static void writeOperation(JsonGenerator jg, OperationDocumentation op, String url) throws IOException { writeOperation(jg, op, url, false); } /** * @since 5.9.4 */ public static void writeOperation(JsonGenerator jg, OperationDocumentation op, String url, boolean prettyPrint) throws IOException { if (prettyPrint) { jg.useDefaultPrettyPrinter(); } jg.writeStartObject(); jg.writeStringField("id", op.id); if (op.getAliases() != null && op.getAliases().length > 0) { jg.writeArrayFieldStart("aliases"); for (String alias : op.getAliases()) { jg.writeString(alias); } jg.writeEndArray(); } jg.writeStringField("label", op.label); jg.writeStringField("category", op.category); jg.writeStringField("requires", op.requires); jg.writeStringField("description", op.description); if (op.since != null && op.since.length() > 0) { jg.writeStringField("since", op.since); } jg.writeStringField("url", url); jg.writeArrayFieldStart("signature"); for (String s : op.signature) { jg.writeString(s); } jg.writeEndArray(); writeParams(jg, Arrays.asList(op.params)); if (op.widgetDefinitions != null && op.widgetDefinitions.length > 0) { jg.writeArrayFieldStart("widgets"); for (WidgetDefinition wdef : op.widgetDefinitions) { jg.writeObject(JSONLayoutExporter.exportToJson(wdef, null, null)); } jg.writeEndArray(); } jg.writeEndObject(); jg.flush(); } private static void writeParams(JsonGenerator jg, List<Param> params) throws IOException { jg.writeArrayFieldStart("params"); for (Param p : params) { jg.writeStartObject(); jg.writeStringField("name", p.name); jg.writeStringField("description", p.description); jg.writeStringField("type", p.type); jg.writeBooleanField("required", p.required); jg.writeStringField("widget", p.widget); jg.writeNumberField("order", p.order); jg.writeArrayFieldStart("values"); for (String value : p.values) { jg.writeString(value); } jg.writeEndArray(); jg.writeEndObject(); } jg.writeEndArray(); } public static void writeLogin(OutputStream out, LoginInfo login) throws IOException { writeLogin(createGenerator(out), login); } public static void writeLogin(JsonGenerator jg, LoginInfo login) throws IOException { jg.writeStartObject(); jg.writeStringField("entity-type", "login"); jg.writeStringField("username", login.getUsername()); jg.writeBooleanField("isAdministrator", login.isAdministrator()); jg.writeArrayFieldStart("groups"); for (String group : login.getGroups()) { jg.writeString(group); } jg.writeEndArray(); jg.writeEndObject(); jg.flush(); } public static void writePrimitive(OutputStream out, Object value) throws IOException { writePrimitive(createGenerator(out), value); } public static void writePrimitive(JsonGenerator jg, Object value) throws IOException { jg.writeStartObject(); jg.writeStringField("entity-type", "primitive"); if (value != null) { Class<?> type = value.getClass(); if (type == String.class) { jg.writeStringField("value", (String) value); } else if (type == Boolean.class) { jg.writeBooleanField("value", (Boolean) value); } else if (type == Long.class) { jg.writeNumberField("value", ((Number) value).longValue()); } else if (type == Double.class) { jg.writeNumberField("value", ((Number) value).doubleValue()); } else if (type == Integer.class) { jg.writeNumberField("value", ((Number) value).intValue()); } else if (type == Float.class) { jg.writeNumberField("value", ((Number) value).floatValue()); } } else { jg.writeNullField("value"); } jg.writeEndObject(); jg.flush(); } /** * @deprecated since 6.0 - use * {@link org.nuxeo.ecm.webengine.app .JsonWebengineWriter#writeException(java.io.OutputStream, org.nuxeo.ecm.webengine.WebException)} * instead */ @Deprecated public static void writeException(OutputStream out, WebException eh) throws IOException { writeException(createGenerator(out), eh); } /** * @deprecated since 6.0 - use * {@link org.nuxeo.ecm.webengine.app .JsonWebengineWriter#writeException(org.codehaus.jackson.JsonGenerator, org.nuxeo.ecm.webengine.WebException)} * instead */ @Deprecated public static void writeException(JsonGenerator jg, WebException eh) throws IOException { jg.writeStartObject(); jg.writeStringField("entity-type", "exception"); jg.writeStringField("type", eh.getType()); jg.writeNumberField("status", eh.getStatus()); jg.writeStringField("message", eh.getMessage()); jg.writeStringField("stack", eh.getStackTraceString()); jg.writeObjectField("cause", eh.getCause()); jg.writeEndObject(); jg.flush(); } }