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 java.util.ArrayList; 020import java.util.LinkedHashMap; 021import java.util.List; 022import java.util.Map; 023 024import javax.xml.bind.annotation.XmlAccessType; 025import javax.xml.bind.annotation.XmlAccessorType; 026import javax.xml.bind.annotation.XmlAttribute; 027import javax.xml.bind.annotation.XmlElement; 028import javax.xml.bind.annotation.XmlRootElement; 029 030import org.apache.camel.model.DataFormatDefinition; 031import org.apache.camel.model.PropertyDefinition; 032import org.apache.camel.spi.Metadata; 033import org.apache.camel.util.CollectionStringBuffer; 034 035/** 036 * Marshal and unmarshal POJOs to/from XML using <a href="https://x-stream.github.io/">XStream</a> library. 037 */ 038@Metadata(firstVersion = "1.3.0", label = "dataformat,transformation,xml,json", title = "XStream") 039@XmlRootElement(name = "xstream") 040@XmlAccessorType(XmlAccessType.NONE) 041public class XStreamDataFormat extends DataFormatDefinition { 042 @XmlAttribute 043 private String permissions; 044 @XmlAttribute 045 private String encoding; 046 @XmlAttribute 047 private String driver; 048 @XmlAttribute 049 private String driverRef; 050 @XmlAttribute 051 private String mode; 052 053 @XmlElement(name = "converters") 054 private List<PropertyDefinition> converters; 055 @XmlElement(name = "aliases") 056 private List<PropertyDefinition> aliases; 057 @XmlElement(name = "omitFields") 058 private List<PropertyDefinition> omitFields; 059 @XmlElement(name = "implicitCollections") 060 private List<PropertyDefinition> implicitCollections; 061 062 public XStreamDataFormat() { 063 super("xstream"); 064 } 065 066 public XStreamDataFormat(String encoding) { 067 this(); 068 setEncoding(encoding); 069 } 070 071 @Override 072 public String getDataFormatName() { 073 return "json".equals(driver) ? "json-xstream" : "xstream"; 074 } 075 076 public String getEncoding() { 077 return encoding; 078 } 079 080 /** 081 * Sets the encoding to use 082 */ 083 public void setEncoding(String encoding) { 084 this.encoding = encoding; 085 } 086 087 public String getDriver() { 088 return driver; 089 } 090 091 /** 092 * To use a custom XStream driver. The instance must be of type 093 * com.thoughtworks.xstream.io.HierarchicalStreamDriver 094 */ 095 public void setDriver(String driver) { 096 this.driver = driver; 097 } 098 099 public String getDriverRef() { 100 return driverRef; 101 } 102 103 /** 104 * To refer to a custom XStream driver to lookup in the registry. The 105 * instance must be of type 106 * com.thoughtworks.xstream.io.HierarchicalStreamDriver 107 */ 108 public void setDriverRef(String driverRef) { 109 this.driverRef = driverRef; 110 } 111 112 public String getMode() { 113 return mode; 114 } 115 116 /** 117 * Mode for dealing with duplicate references The possible values are: 118 * <ul> 119 * <li>NO_REFERENCES</li> 120 * <li>ID_REFERENCES</li> 121 * <li>XPATH_RELATIVE_REFERENCES</li> 122 * <li>XPATH_ABSOLUTE_REFERENCES</li> 123 * <li>SINGLE_NODE_XPATH_RELATIVE_REFERENCES</li> 124 * <li>SINGLE_NODE_XPATH_ABSOLUTE_REFERENCES</li> 125 * </ul> 126 */ 127 public void setMode(String mode) { 128 this.mode = mode; 129 } 130 131 public List<PropertyDefinition> getConverters() { 132 return converters; 133 } 134 135 public Map<String, String> getConvertersAsMap() { 136 if (converters == null || converters.isEmpty()) { 137 return null; 138 } 139 Map<String, String> answer = new LinkedHashMap<>(); 140 for (PropertyDefinition def : converters) { 141 answer.put(def.getKey(), def.getValue()); 142 } 143 return answer; 144 } 145 146 /** 147 * List of class names for using custom XStream converters. The classes must 148 * be of type com.thoughtworks.xstream.converters.Converter 149 */ 150 public void setConverters(List<PropertyDefinition> converters) { 151 this.converters = converters; 152 } 153 154 public void setConverters(Map<String, String> converters) { 155 this.converters = new ArrayList<>(); 156 converters.forEach((k, v) -> this.converters.add(new PropertyDefinition(k, v))); 157 } 158 159 public List<PropertyDefinition> getAliases() { 160 return aliases; 161 } 162 163 public Map<String, String> getAliasesAsMap() { 164 if (aliases == null || aliases.isEmpty()) { 165 return null; 166 } 167 Map<String, String> answer = new LinkedHashMap<>(); 168 for (PropertyDefinition def : aliases) { 169 answer.put(def.getKey(), def.getValue()); 170 } 171 return answer; 172 } 173 174 /** 175 * Alias a Class to a shorter name to be used in XML elements. 176 */ 177 public void setAliases(List<PropertyDefinition> aliases) { 178 this.aliases = aliases; 179 } 180 181 public void setAliases(Map<String, String> aliases) { 182 this.aliases = new ArrayList<>(); 183 aliases.forEach((k, v) -> this.aliases.add(new PropertyDefinition(k, v))); 184 } 185 186 public List<PropertyDefinition> getOmitFields() { 187 return omitFields; 188 } 189 190 /** 191 * Prevents a field from being serialized. To omit a field you must always 192 * provide the declaring type and not necessarily the type that is 193 * converted. Multiple values can be separated by comma. 194 */ 195 public void setOmitFields(List<PropertyDefinition> omitFields) { 196 this.omitFields = omitFields; 197 } 198 199 public void setOmitFields(Map<String, String> aliases) { 200 this.omitFields = new ArrayList<>(); 201 aliases.forEach((k, v) -> this.omitFields.add(new PropertyDefinition(k, v))); 202 } 203 204 public Map<String, String> getOmitFieldsAsMap() { 205 if (omitFields == null || omitFields.isEmpty()) { 206 return null; 207 } 208 Map<String, String> answer = new LinkedHashMap<>(); 209 for (PropertyDefinition def : omitFields) { 210 answer.put(def.getKey(), def.getValue()); 211 } 212 return answer; 213 } 214 215 public List<PropertyDefinition> getImplicitCollections() { 216 return implicitCollections; 217 } 218 219 /** 220 * Adds a default implicit collection which is used for any unmapped XML tag. 221 * Multiple values can be separated by comma. 222 */ 223 public void setImplicitCollections(List<PropertyDefinition> implicitCollections) { 224 this.implicitCollections = implicitCollections; 225 } 226 227 public void setImplicitCollections(Map<String, String> implicitCollections) { 228 this.implicitCollections = new ArrayList<>(); 229 implicitCollections.forEach((k, v) -> this.implicitCollections.add(new PropertyDefinition(k, v))); 230 } 231 232 public Map<String, String> getImplicitCollectionsAsMap() { 233 if (implicitCollections == null || implicitCollections.isEmpty()) { 234 return null; 235 } 236 Map<String, String> answer = new LinkedHashMap<>(); 237 for (PropertyDefinition def : implicitCollections) { 238 answer.put(def.getKey(), def.getValue()); 239 } 240 return answer; 241 } 242 243 public String getPermissions() { 244 return permissions; 245 } 246 247 /** 248 * Adds permissions that controls which Java packages and classes XStream is 249 * allowed to use during unmarshal from xml/json to Java beans. 250 * <p/> 251 * A permission must be configured either here or globally using a JVM 252 * system property. The permission can be specified in a syntax where a plus 253 * sign is allow, and minus sign is deny. <br/> 254 * Wildcards is supported by using <tt>.*</tt> as prefix. For example to 255 * allow <tt>com.foo</tt> and all subpackages then specify 256 * <tt>+com.foo.*</tt>. Multiple permissions can be configured separated by 257 * comma, such as <tt>+com.foo.*,-com.foo.bar.MySecretBean</tt>. <br/> 258 * The following default permission is always included: 259 * <tt>"-*,java.lang.*,java.util.*"</tt> unless its overridden by specifying 260 * a JVM system property with they key 261 * <tt>org.apache.camel.xstream.permissions</tt>. 262 */ 263 public void setPermissions(String permissions) { 264 this.permissions = permissions; 265 } 266 267 /** 268 * To add permission for the given pojo classes. 269 * 270 * @param type the pojo class(es) xstream should use as allowed permission 271 * @see #setPermissions(String) 272 */ 273 public void setPermissions(Class<?>... type) { 274 CollectionStringBuffer csb = new CollectionStringBuffer(","); 275 for (Class<?> clazz : type) { 276 csb.append("+"); 277 csb.append(clazz.getName()); 278 } 279 setPermissions(csb.toString()); 280 } 281 282}