Skip to content

Commit

Permalink
CAMEL-10575: snakeyaml: add an option to filter classes the yaml pars…
Browse files Browse the repository at this point in the history
…er can construct

(cherry picked from commit 20e2622)
  • Loading branch information
lburgazzoli committed Dec 9, 2016
1 parent 6c2db21 commit 2f19ce5
Show file tree
Hide file tree
Showing 22 changed files with 1,120 additions and 125 deletions.
Expand Up @@ -16,9 +16,12 @@
*/
package org.apache.camel.model.dataformat;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

Expand Down Expand Up @@ -58,6 +61,10 @@ public class YAMLDataFormat extends DataFormatDefinition {
private Boolean useApplicationContextClassLoader = true;
@XmlAttribute @Metadata(defaultValue = "false")
private Boolean prettyFlow = false;
@XmlAttribute @Metadata(defaultValue = "false")
private Boolean allowAnyType = false;
@XmlElement(name = "typeFilter")
private List<YAMLTypeFilterDefinition> typeFilters;

public YAMLDataFormat() {
this(YAMLLibrary.SnakeYAML);
Expand Down Expand Up @@ -188,6 +195,28 @@ public void setPrettyFlow(boolean prettyFlow) {
this.prettyFlow = prettyFlow;
}

public boolean isAllowAnyType() {
return allowAnyType;
}

/**
* Allow any class to be un-marshaled
*/
public void setAllowAnyType(boolean allowAnyType) {
this.allowAnyType = allowAnyType;
}

public List<YAMLTypeFilterDefinition> getTypeFilters() {
return typeFilters;
}

/**
* Set the types SnakeYAML is allowed to un-marshall
*/
public void setTypeFilters(List<YAMLTypeFilterDefinition> typeFilters) {
this.typeFilters = typeFilters;
}

@Override
protected DataFormat createDataFormat(RouteContext routeContext) {
if (library == YAMLLibrary.SnakeYAML) {
Expand Down Expand Up @@ -218,6 +247,27 @@ protected void configureSnakeDataFormat(DataFormat dataFormat, CamelContext came
setProperty(dataFormat, camelContext, "classLoader", classLoader);
setProperty(dataFormat, camelContext, "useApplicationContextClassLoader", useApplicationContextClassLoader);
setProperty(dataFormat, camelContext, "prettyFlow", prettyFlow);
setProperty(dataFormat, camelContext, "allowAnyType", allowAnyType);

if (typeFilters != null && !typeFilters.isEmpty()) {
List<String> typeFilterDefinitions = new ArrayList<>(typeFilters.size());
for (YAMLTypeFilterDefinition definition : typeFilters) {
String value = definition.getValue();

if (!value.startsWith("type") && !value.startsWith("regexp")) {
YAMLTypeFilterType type = definition.getType();
if (type == null) {
type = YAMLTypeFilterType.type;
}

value = type.name() + ":" + value;
}

typeFilterDefinitions.add(value);
}

setProperty(dataFormat, camelContext, "typeFilterDefinitions", typeFilterDefinitions);
}

setPropertyRef(dataFormat, camelContext, "constructor", constructor);
setPropertyRef(dataFormat, camelContext, "representer", representer);
Expand All @@ -238,4 +288,5 @@ protected void setPropertyRef(DataFormat dataFormat, CamelContext camelContext,
setProperty(camelContext, dataFormat, propertyName, ref);
}
}

}
@@ -0,0 +1,47 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
package org.apache.camel.model.dataformat;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "typeFilter")
@XmlAccessorType(XmlAccessType.FIELD)
public final class YAMLTypeFilterDefinition {
@XmlAttribute
private String value;
@XmlAttribute
private YAMLTypeFilterType type;

public String getValue() {
return value;
}

public void setValue(String value) {
this.value = value;
}

public YAMLTypeFilterType getType() {
return type;
}

public void setType(YAMLTypeFilterType type) {
this.type = type;
}
}
@@ -0,0 +1,26 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/

package org.apache.camel.model.dataformat;

import javax.xml.bind.annotation.XmlEnum;

@XmlEnum
public enum YAMLTypeFilterType {
type,
regexp
}
6 changes: 5 additions & 1 deletion components/camel-snakeyaml/pom.xml
Expand Up @@ -45,13 +45,17 @@
<artifactId>snakeyaml</artifactId>
<version>${snakeyaml-version}</version>
</dependency>

<!-- testing -->
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-test-spring</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-test-blueprint</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
Expand Down
Expand Up @@ -14,34 +14,12 @@ Every library requires adding the special camel component (see
"Dependency..." paragraphs further down). By default Camel uses the
SnakeYAML library.

[[YAMLDataFormat-UsingYAMLdataformatwiththeSnakeYAMLlibrary]]
Using YAML data format with the SnakeYAML library
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

[source,java]
------------------------------------------------------------
// lets turn Object messages into yaml then send to MQSeries
from("activemq:My.Queue")
.marshal().yaml()
.to("mqseries:Another.Queue");
------------------------------------------------------------

[source,java]
------------------------------------------------------------
// lets turn Object messages into yaml then send to MQSeries
from("activemq:My.Queue")
.marshal().yaml(YAMLLibrary.SnakeYAML)
.to("mqseries:Another.Queue");
------------------------------------------------------------

[[YAML-Options]]
YAML Options
^^^^^^^^^^^^



// dataformat options: START
The YAML SnakeYAML dataformat supports 8 options which are listed below.
The YAML SnakeYAML dataformat supports 10 options which are listed below.



Expand All @@ -57,11 +35,48 @@ The YAML SnakeYAML dataformat supports 8 options which are listed below.
| resolver | | String | Resolver to detect implicit type
| useApplicationContextClassLoader | true | Boolean | Use ApplicationContextClassLoader as custom ClassLoader
| prettyFlow | false | Boolean | Force the emitter to produce a pretty YAML document when using the flow style.
| allowAnyType | false | Boolean | Allow any class to be un-marshaled
| typeFilter | | List | Set the types SnakeYAML is allowed to un-marshall
|=======================================================================
{% endraw %}
// dataformat options: END

WARNING: SnakeYAML can load any class from YAML definition which may lead to security breach so by default, SnakeYAML DataForma restrict the object it can load to standard Java objects like List or Long. If you want to load custom POJOs you need to add theirs type to SnakeYAML DataFormat type filter list. If your source is trusted, you can set the property allowAnyType to true so SnakeYAML DataForma won't perform any filter on the types.

[[YAMLDataFormat-UsingYAMLdataformatwiththeSnakeYAMLlibrary]]
Using YAML data format with the SnakeYAML library
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

- Turn Object messages into yaml then send to MQSeries
+
[source,java]
------------------------------------------------------------
from("activemq:My.Queue")
.marshal().yaml()
.to("mqseries:Another.Queue");
------------------------------------------------------------
+
[source,java]
------------------------------------------------------------
from("activemq:My.Queue")
.marshal().yaml(YAMLLibrary.SnakeYAML)
.to("mqseries:Another.Queue");
------------------------------------------------------------
- Restrict classes to be loaded from YAML
+
[source,java]
------------------------------------------------------------
// Creat a SnakeYAMLDataFormat instance
SnakeYAMLDataFormat yaml = new SnakeYAMLDataFormat();
// Restrict classes to be loaded from YAML
yaml.addTypeFilters(TypeFilters.types(MyPojo.class, MyOtherPojo.class));

from("activemq:My.Queue")
.unmarshal(yaml)
.to("mqseries:Another.Queue");
------------------------------------------------------------

[[YAMLDataFormat-UsingYAMLinSpringDSL]]
Using YAML in Spring DSL
Expand All @@ -72,56 +87,50 @@ declare the data formats first. This is done in the *DataFormats* XML
tag.

[source,xml]
----------------------------------------------------------------------------------------------------------------------------------
<dataFormats>
<!-- here we define a YAML data format with the id snak and that it should use the TestPojo as the class type when
doing unmarshal. The unmarshalTypeName is optional, if not provided Camel will use a Object.class as the type -->
<yaml id="snake" library="SnakeYAML" unmarshalTypeName="org.apache.camel.component.yaml.model.TestPojo"/>
</dataFormats>
----------------------------------------------------------------------------------------------------------------------------------

And then you can refer to this id in the route:
--------------------------------------------------------------------------------
<dataFormats>
<!--
here we define a YAML data format with the id snake and that it should use
the TestPojo as the class type when doing unmarshal. The unmarshalTypeName
is optional
-->
<yaml
id="snake"
library="SnakeYAML"
unmarshalTypeName="org.apache.camel.component.yaml.model.TestPojo"/>
<!--
here we define a YAML data format with the id snake-safe which restricts the
classes to be loaded from YAML to TestPojo and those belonging to package
com.mycompany
-->
<yaml id="snake-safe">
<typeFilter value="org.apache.camel.component.yaml.model.TestPojo"/>
<typeFilter value="com.mycompany\..*" type="regexp"/>
</yaml>
</dataFormats>
--------------------------------------------------------------------------------

And then you can refer to those ids in the route:

[source,xml]
-------------------------------------
<route>
<from uri="direct:back"/>
<unmarshal ref="snake"/>
<to uri="mock:reverse"/>
</route>
<route>
<from uri="direct:unmarshal"/>
<unmarshal>
<custom ref="snake"/>
</unmarshal>
<to uri="mock:unmarshal"/>
</route>
<route>
<from uri="direct:unmarshal-safe"/>
<unmarshal>
<custom ref="snake-safe"/>
</unmarshal>
<to uri="mock:unmarshal-safe"/>
</route>
-------------------------------------



[[YAMLDataFormat-OptionsforSnakeYAMLDataFormat]]
Options for SnakeYAML Data Format
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

[width="100%",cols="<25%,<25%,<25%,<25%",options="header",]
|=======================================================================
|Name |Type |Default |Description
|unmarshalType |`Class` |`Object.class` |Class of the object to be created

|classLoader |ClassLoader |null |The classloader to use to
instantiate objects

|constructor |String |null |A reference to an
org.yaml.snakeyaml.constructor.BaseConstructor instance in the registry

|representer |String |null |A reference to an
org.yaml.snakeyaml.representer.Representer instance in the registry

|dumperOptions |String |null |A reference to an
org.yaml.snakeyaml.DumperOptions instance in the registry

|resolver |String |null |A reference to an
org.yaml.snakeyaml.resolver.Resolver instance in the registry

|useApplicationContextClassLoader | Boolean |true  |To use CamelContext's ApplicationContextClassLoader if no custom class loader is set and
ApplicationContextClassLoader is provided

|prettyFlow | Boolean |false  |Force the emitter to produce a pretty YAML document when using the flow style
|=======================================================================

[[YAMLDataFormat-DependenciesforSnakeYAML]]
Dependencies for SnakeYAML
Expand Down

0 comments on commit 2f19ce5

Please sign in to comment.