001/* 002 * (C) Copyright 2014 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 * dmetzler 018 * Vladimir Pasquir <[email protected]> 019 */ 020package org.nuxeo.ecm.webengine; 021 022import java.io.IOException; 023 024import org.nuxeo.runtime.api.Framework; 025 026import com.fasterxml.jackson.core.JsonFactory; 027import com.fasterxml.jackson.core.JsonGenerationException; 028import com.fasterxml.jackson.core.JsonGenerator; 029import com.fasterxml.jackson.core.Version; 030import com.fasterxml.jackson.databind.BeanDescription; 031import com.fasterxml.jackson.databind.JsonSerializer; 032import com.fasterxml.jackson.databind.ObjectMapper; 033import com.fasterxml.jackson.databind.SerializationConfig; 034import com.fasterxml.jackson.databind.SerializerProvider; 035import com.fasterxml.jackson.databind.module.SimpleModule; 036import com.fasterxml.jackson.databind.ser.BeanSerializer; 037import com.fasterxml.jackson.databind.ser.BeanSerializerModifier; 038 039/** 040 * @since 6.0 041 */ 042public class JsonFactoryManagerImpl implements JsonFactoryManager { 043 044 public static final String REST_STACK_DISPLAY = "org.nuxeo.rest.stack" + ".enable"; 045 046 protected boolean stackDisplay; 047 048 public JsonFactoryManagerImpl() { 049 stackDisplay = Framework.isBooleanPropertyTrue(REST_STACK_DISPLAY); 050 } 051 052 private static class ThrowableSerializer extends BeanSerializer { 053 054 public ThrowableSerializer(BeanSerializer src) { 055 super(src); 056 } 057 058 @Override 059 protected void serializeFields(Object bean, JsonGenerator jgen, SerializerProvider provider) 060 throws IOException, JsonGenerationException { 061 serializeClassName(bean, jgen, provider); 062 super.serializeFields(bean, jgen, provider); 063 } 064 065 @Override 066 protected void serializeFieldsFiltered(Object bean, JsonGenerator jgen, SerializerProvider provider) 067 throws IOException, JsonGenerationException { 068 serializeClassName(bean, jgen, provider); 069 super.serializeFieldsFiltered(bean, jgen, provider); 070 } 071 072 protected void serializeClassName(Object bean, JsonGenerator jgen, SerializerProvider provider) 073 throws JsonGenerationException, IOException { 074 jgen.writeFieldName("className"); 075 jgen.writeString(bean.getClass().getName()); 076 } 077 } 078 079 private JsonFactory factory; 080 081 @Override 082 public JsonFactory getJsonFactory() { 083 if (factory == null) { 084 factory = createFactory(); 085 } 086 return factory; 087 } 088 089 @Override 090 public JsonFactory createFactory() { 091 JsonFactory factory = new JsonFactory(); 092 final ObjectMapper oc = new ObjectMapper(factory); 093 final SimpleModule module = new SimpleModule("webengine", Version.unknownVersion()) { 094 095 @Override 096 public void setupModule(SetupContext context) { 097 super.setupModule(context); 098 099 context.addBeanSerializerModifier(new BeanSerializerModifier() { 100 101 @Override 102 public JsonSerializer<?> modifySerializer(SerializationConfig config, 103 BeanDescription beanDesc, JsonSerializer<?> serializer) { 104 if (!Throwable.class.isAssignableFrom(beanDesc.getBeanClass())) { 105 return super.modifySerializer(config, beanDesc, serializer); 106 } 107 return new ThrowableSerializer((BeanSerializer) serializer); 108 } 109 }); 110 } 111 }; 112 oc.registerModule(module); 113 factory.setCodec(oc); 114 return factory; 115 } 116 117 @Override 118 public boolean toggleStackDisplay() { 119 return stackDisplay = !stackDisplay; 120 } 121 122 public boolean isStackDisplay() { 123 return stackDisplay; 124 } 125}