001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.camel.model.dataformat; 018 019import javax.xml.bind.annotation.XmlAccessType; 020import javax.xml.bind.annotation.XmlAccessorType; 021import javax.xml.bind.annotation.XmlAttribute; 022import javax.xml.bind.annotation.XmlRootElement; 023import javax.xml.bind.annotation.XmlTransient; 024 025import org.apache.camel.CamelContext; 026import org.apache.camel.model.DataFormatDefinition; 027import org.apache.camel.spi.DataFormat; 028import org.apache.camel.spi.Metadata; 029import org.apache.camel.spi.RouteContext; 030import org.apache.camel.util.CollectionStringBuffer; 031import org.apache.camel.util.ObjectHelper; 032 033/** 034 * Json data format 035 * 036 * @version 037 */ 038@Metadata(label = "dataformat,transformation,json", title = "JSon") 039@XmlRootElement(name = "json") 040@XmlAccessorType(XmlAccessType.FIELD) 041public class JsonDataFormat extends DataFormatDefinition { 042 @XmlAttribute 043 private Boolean prettyPrint; 044 @XmlAttribute @Metadata(defaultValue = "XStream") 045 private JsonLibrary library = JsonLibrary.XStream; 046 @XmlAttribute 047 private String unmarshalTypeName; 048 @XmlTransient 049 private Class<?> unmarshalType; 050 @XmlAttribute 051 private Class<?> jsonView; 052 @XmlAttribute 053 private String include; 054 @XmlAttribute 055 private Boolean allowJmsType; 056 @XmlAttribute 057 private String collectionTypeName; 058 @XmlTransient 059 private Class<?> collectionType; 060 @XmlAttribute 061 private Boolean useList; 062 @XmlAttribute 063 private Boolean enableJaxbAnnotationModule; 064 @XmlAttribute 065 private String moduleClassNames; 066 @XmlAttribute 067 private String moduleRefs; 068 @XmlAttribute 069 private String enableFeatures; 070 @XmlAttribute 071 private String disableFeatures; 072 @XmlAttribute 073 private String permissions; 074 075 public JsonDataFormat() { 076 super("json"); 077 } 078 079 public JsonDataFormat(JsonLibrary library) { 080 this.library = library; 081 } 082 083 public Boolean getPrettyPrint() { 084 return prettyPrint; 085 } 086 087 /** 088 * To enable pretty printing output nicely formatted. 089 * <p/> 090 * Is by default false. 091 */ 092 public void setPrettyPrint(Boolean prettyPrint) { 093 this.prettyPrint = prettyPrint; 094 } 095 096 public String getUnmarshalTypeName() { 097 return unmarshalTypeName; 098 } 099 100 /** 101 * Class name of the java type to use when unarmshalling 102 */ 103 public void setUnmarshalTypeName(String unmarshalTypeName) { 104 this.unmarshalTypeName = unmarshalTypeName; 105 } 106 107 public Class<?> getUnmarshalType() { 108 return unmarshalType; 109 } 110 111 /** 112 * Class of the java type to use when unarmshalling 113 */ 114 public void setUnmarshalType(Class<?> unmarshalType) { 115 this.unmarshalType = unmarshalType; 116 } 117 118 public JsonLibrary getLibrary() { 119 return library; 120 } 121 122 /** 123 * Which json library to use such. 124 * <p/> 125 * Is by default xstream 126 */ 127 public void setLibrary(JsonLibrary library) { 128 this.library = library; 129 } 130 131 public Class<?> getJsonView() { 132 return jsonView; 133 } 134 135 /** 136 * When marshalling a POJO to JSON you might want to exclude certain fields from the JSON output. 137 * With Jackson you can use JSON views to accomplish this. This option is to refer to the class 138 * which has @JsonView annotations 139 */ 140 public void setJsonView(Class<?> jsonView) { 141 this.jsonView = jsonView; 142 } 143 144 public String getInclude() { 145 return include; 146 } 147 148 /** 149 * If you want to marshal a pojo to JSON, and the pojo has some fields with null values. 150 * And you want to skip these null values, you can set this option to <tt>NOT_NULL</tt> 151 */ 152 public void setInclude(String include) { 153 this.include = include; 154 } 155 156 public Boolean getAllowJmsType() { 157 return allowJmsType; 158 } 159 160 /** 161 * Used for JMS users to allow the JMSType header from the JMS spec to specify a FQN classname 162 * to use to unmarshal to. 163 */ 164 public void setAllowJmsType(Boolean allowJmsType) { 165 this.allowJmsType = allowJmsType; 166 } 167 168 public String getCollectionTypeName() { 169 return collectionTypeName; 170 } 171 172 /** 173 * Refers to a custom collection type to lookup in the registry to use. This option should rarely be used, but allows 174 * to use different collection types than java.util.Collection based as default. 175 */ 176 public void setCollectionTypeName(String collectionTypeName) { 177 this.collectionTypeName = collectionTypeName; 178 } 179 180 public Boolean getUseList() { 181 return useList; 182 } 183 184 /** 185 * To unarmshal to a List of Map or a List of Pojo. 186 */ 187 public void setUseList(Boolean useList) { 188 this.useList = useList; 189 } 190 191 public Boolean getEnableJaxbAnnotationModule() { 192 return enableJaxbAnnotationModule; 193 } 194 195 /** 196 * Whether to enable the JAXB annotations module when using jackson. When enabled then JAXB annotations 197 * can be used by Jackson. 198 */ 199 public void setEnableJaxbAnnotationModule(Boolean enableJaxbAnnotationModule) { 200 this.enableJaxbAnnotationModule = enableJaxbAnnotationModule; 201 } 202 203 public String getModuleClassNames() { 204 return moduleClassNames; 205 } 206 207 /** 208 * To use custom Jackson modules com.fasterxml.jackson.databind.Module specified as a String with FQN class names. 209 * Multiple classes can be separated by comma. 210 */ 211 public void setModuleClassNames(String moduleClassNames) { 212 this.moduleClassNames = moduleClassNames; 213 } 214 215 public String getModuleRefs() { 216 return moduleRefs; 217 } 218 219 /** 220 * To use custom Jackson modules referred from the Camel registry. 221 * Multiple modules can be separated by comma. 222 */ 223 public void setModuleRefs(String moduleRefs) { 224 this.moduleRefs = moduleRefs; 225 } 226 227 public String getEnableFeatures() { 228 return enableFeatures; 229 } 230 231 /** 232 * Set of features to enable on the Jackson <tt>com.fasterxml.jackson.databind.ObjectMapper</tt>. 233 * <p/> 234 * The features should be a name that matches a enum from <tt>com.fasterxml.jackson.databind.SerializationFeature</tt>, 235 * <tt>com.fasterxml.jackson.databind.DeserializationFeature</tt>, or <tt>com.fasterxml.jackson.databind.MapperFeature</tt> 236 * <p/> 237 * Multiple features can be separated by comma 238 */ 239 public void setEnableFeatures(String enableFeatures) { 240 this.enableFeatures = enableFeatures; 241 } 242 243 public String getDisableFeatures() { 244 return disableFeatures; 245 } 246 247 /** 248 * Set of features to disable on the Jackson <tt>com.fasterxml.jackson.databind.ObjectMapper</tt>. 249 * <p/> 250 * The features should be a name that matches a enum from <tt>com.fasterxml.jackson.databind.SerializationFeature</tt>, 251 * <tt>com.fasterxml.jackson.databind.DeserializationFeature</tt>, or <tt>com.fasterxml.jackson.databind.MapperFeature</tt> 252 * <p/> 253 * Multiple features can be separated by comma 254 */ 255 public void setDisableFeatures(String disableFeatures) { 256 this.disableFeatures = disableFeatures; 257 } 258 259 public String getPermissions() { 260 return permissions; 261 } 262 263 /** 264 * Adds permissions that controls which Java packages and classes XStream is allowed to use during 265 * unmarshal from xml/json to Java beans. 266 * <p/> 267 * A permission must be configured either here or globally using a JVM system property. The permission 268 * can be specified in a syntax where a plus sign is allow, and minus sign is deny. 269 * <br/> 270 * Wildcards is supported by using <tt>.*</tt> as prefix. For example to allow <tt>com.foo</tt> and all subpackages 271 * then specfy <tt>+com.foo.*</tt>. Multiple permissions can be configured separated by comma, such as 272 * <tt>+com.foo.*,-com.foo.bar.MySecretBean</tt>. 273 * <br/> 274 * The following default permission is always included: <tt>"-*,java.lang.*,java.util.*"</tt> unless 275 * its overridden by specifying a JVM system property with they key <tt>org.apache.camel.xstream.permissions</tt>. 276 */ 277 public void setPermissions(String permissions) { 278 this.permissions = permissions; 279 } 280 281 /** 282 * To add permission for the given pojo classes. 283 * @param type the pojo class(es) xstream should use as allowed permission 284 * @see #setPermissions(String) 285 */ 286 public void setPermissions(Class<?>... type) { 287 CollectionStringBuffer csb = new CollectionStringBuffer(","); 288 for (Class<?> clazz : type) { 289 csb.append("+"); 290 csb.append(clazz.getName()); 291 } 292 setPermissions(csb.toString()); 293 } 294 295 @Override 296 public String getDataFormatName() { 297 // json data format is special as the name can be from different bundles 298 return "json-" + library.name().toLowerCase(); 299 } 300 301 @Override 302 protected DataFormat createDataFormat(RouteContext routeContext) { 303 if (library == JsonLibrary.XStream) { 304 setProperty(routeContext.getCamelContext(), this, "dataFormatName", "json-xstream"); 305 } else if (library == JsonLibrary.Jackson) { 306 setProperty(routeContext.getCamelContext(), this, "dataFormatName", "json-jackson"); 307 } else { 308 setProperty(routeContext.getCamelContext(), this, "dataFormatName", "json-gson"); 309 } 310 311 if (unmarshalType == null && unmarshalTypeName != null) { 312 try { 313 unmarshalType = routeContext.getCamelContext().getClassResolver().resolveMandatoryClass(unmarshalTypeName); 314 } catch (ClassNotFoundException e) { 315 throw ObjectHelper.wrapRuntimeCamelException(e); 316 } 317 } 318 if (collectionType == null && collectionTypeName != null) { 319 try { 320 collectionType = routeContext.getCamelContext().getClassResolver().resolveMandatoryClass(collectionTypeName); 321 } catch (ClassNotFoundException e) { 322 throw ObjectHelper.wrapRuntimeCamelException(e); 323 } 324 } 325 326 return super.createDataFormat(routeContext); 327 } 328 329 @Override 330 protected void configureDataFormat(DataFormat dataFormat, CamelContext camelContext) { 331 if (unmarshalType != null) { 332 setProperty(camelContext, dataFormat, "unmarshalType", unmarshalType); 333 } 334 if (prettyPrint != null) { 335 setProperty(camelContext, dataFormat, "prettyPrint", prettyPrint); 336 } 337 if (jsonView != null) { 338 setProperty(camelContext, dataFormat, "jsonView", jsonView); 339 } 340 if (include != null) { 341 setProperty(camelContext, dataFormat, "include", include); 342 } 343 if (allowJmsType != null) { 344 setProperty(camelContext, dataFormat, "allowJmsType", allowJmsType); 345 } 346 if (collectionType != null) { 347 setProperty(camelContext, dataFormat, "collectionType", collectionType); 348 } 349 if (useList != null) { 350 setProperty(camelContext, dataFormat, "useList", useList); 351 } 352 if (enableJaxbAnnotationModule != null) { 353 setProperty(camelContext, dataFormat, "enableJaxbAnnotationModule", enableJaxbAnnotationModule); 354 } 355 if (moduleClassNames != null) { 356 setProperty(camelContext, dataFormat, "modulesClassNames", moduleClassNames); 357 } 358 if (moduleRefs != null) { 359 setProperty(camelContext, dataFormat, "moduleRefs", moduleRefs); 360 } 361 if (enableFeatures != null) { 362 setProperty(camelContext, dataFormat, "enableFeatures", enableFeatures); 363 } 364 if (disableFeatures != null) { 365 setProperty(camelContext, dataFormat, "disableFeatures", disableFeatures); 366 } 367 if (permissions != null) { 368 setProperty(camelContext, dataFormat, "permissions", permissions); 369 } 370 // if we have the unmarshal type, but no permission set, then use it to be allowed 371 if (permissions == null && unmarshalType != null) { 372 String allow = "+" + unmarshalType.getName(); 373 setProperty(camelContext, dataFormat, "permissions", allow); 374 } 375 } 376 377}