Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JBPM-9558] KIE using XStream does not complain on unknown fields #2369

Merged
merged 1 commit into from
Jan 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,23 @@ public interface Marshaller {

static String MARSHALLER_PARAMETER_STRICT = "strict";

public default String marshall(Object input, Map<String, Object> parameters) {
default String marshall(Object input, Map<String, Object> parameters) {
return marshall(input);
}

public String marshall(Object input);
String marshall(Object input);

public <T> T unmarshall(String input, Class<T> type);
<T> T unmarshall(String input, Class<T> type);

public void dispose();
default <T> T unmarshall(String input, Class<T> type, Map<String, Object> parameters) {
return unmarshall(input, type);
}

void dispose();

public MarshallingFormat getFormat();
MarshallingFormat getFormat();

public void setClassLoader(ClassLoader classloader);
void setClassLoader(ClassLoader classloader);

public ClassLoader getClassLoader();
ClassLoader getClassLoader();
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider;
import com.thoughtworks.xstream.mapper.ElementIgnoringMapper;
import com.thoughtworks.xstream.mapper.Mapper;
import com.thoughtworks.xstream.mapper.MapperWrapper;
import org.drools.core.runtime.help.impl.XStreamXML;
import org.kie.server.api.commands.CallContainerCommand;
Expand Down Expand Up @@ -81,10 +83,13 @@

public class XStreamMarshaller implements Marshaller {

public static final String XSTREAM_IGNORE_UNKNOWN = "ignore-unknown-elements";
private static final Logger logger = LoggerFactory.getLogger(XStreamMarshaller.class);
protected XStream xstream;
protected ClassLoader classLoader;
protected Map<String, Class> classNames = new HashMap<String, Class>();
protected Map<String, Class<?>> classNames = new HashMap<>();

private ThreadLocal<XStreamContext> xstreamContext = ThreadLocal.withInitial(XStreamContext::new);

// Optional marshaller extensions to handle new types / configure custom behavior
private static final List<XStreamMarshallerExtension> EXTENSIONS;
Expand Down Expand Up @@ -113,16 +118,42 @@ public XStreamMarshaller(Set<Class<?>> classes,
EXTENSIONS.forEach(ext -> ext.extend(this));
}

private static class XStreamContext {

private boolean ignoreUnknownElements;

public boolean isIgnoreUnknownElements() {
return ignoreUnknownElements;
}

public void setIgnoreUnknownElements(boolean ignoreUnknownElements) {
this.ignoreUnknownElements = ignoreUnknownElements;
}
}

protected class CustomElementIgnore extends ElementIgnoringMapper {

public CustomElementIgnore(Mapper wrapped) {
super(wrapped);
}

@Override
public boolean isIgnoredElement(String name) {
return xstreamContext.get().isIgnoreUnknownElements();
}
}

protected void buildMarshaller(Set<Class<?>> classes,
final ClassLoader classLoader) {
this.xstream = XStreamXML.newXStreamMarshaller(createNonTrustingXStream(
new PureJavaReflectionProvider(),
next -> {
return new MapperWrapper(chainMapperWrappers(new ArrayList<>(EXTENSIONS),
next)) {
public Class realClass(String elementName) {
new CustomElementIgnore(next))) {

Class customClass = classNames.get(elementName);
@Override
public Class<?> realClass(String elementName) {
Class<?> customClass = classNames.get(elementName);
if (customClass != null) {
return customClass;
}
Expand Down Expand Up @@ -151,7 +182,7 @@ protected void configureMarshaller(Set<Class<?>> classes,
this.xstream.denyTypes(voidDeny);

this.xstream.addPermission(new KieServerTypePermission(classes));
String classWildcards[] = {"org.kie.api.pmml.*", "org.kie.pmml.pmml_4_2.model.*"};
String[] classWildcards = {"org.kie.api.pmml.*", "org.kie.pmml.pmml_4_2.model.*"};
this.xstream.allowTypesByWildcard(classWildcards);

AbstractScoreXStreamConverter.registerScoreConverters(xstream);
Expand Down Expand Up @@ -220,12 +251,24 @@ public String marshall(Object objectInput) {
@Override
public <T> T unmarshall(String input,
Class<T> type) {
return (T) xstream.fromXML(input);
return unmarshall(input, type, Collections.singletonMap(XSTREAM_IGNORE_UNKNOWN, false));
}

@Override
public <T> T unmarshall(String input, Class<T> type, Map<String, Object> parameters) {
Object ignoreString = parameters.get(XSTREAM_IGNORE_UNKNOWN);
xstreamContext.get().setIgnoreUnknownElements(ignoreString != null && Boolean.parseBoolean(ignoreString
.toString()));
try {
return (T) xstream.fromXML(input);
} finally {
xstreamContext.get().setIgnoreUnknownElements(false);
}
}

@Override
public void dispose() {
// nothing to do
xstreamContext.remove();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ public Marshaller build(Set<Class<?>> classes, MarshallingFormat format, ClassLo
return new XStreamMarshaller(classes, classLoader) {
@Override
protected void buildMarshaller(Set<Class<?>> classes, ClassLoader classLoader) {
xstream = XStreamUtils.createNonTrustingXStream(new PureJavaReflectionProvider(), new DomDriver("UTF-8", new XmlFriendlyNameCoder("_-", "_")));
xstream = XStreamUtils.createNonTrustingXStream(new PureJavaReflectionProvider(), new DomDriver("UTF-8", new XmlFriendlyNameCoder("_-", "_"))
, CustomElementIgnore::new);
xstream.addPermission(new WildcardTypePermission(new String[]{"org.kie.server.api.**"}));
String[] voidDeny = {"void.class", "Void.class"};
xstream.denyTypes(voidDeny);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Set;

import com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.UnknownFieldException;
import org.assertj.core.api.Assertions;
import org.drools.compiler.kie.builder.impl.InternalKieModule;
import org.drools.compiler.kie.builder.impl.MemoryKieModule;
Expand All @@ -55,10 +57,12 @@
import org.kie.server.api.marshalling.objects.AnotherMessage;
import org.kie.server.api.marshalling.objects.DateObject;
import org.kie.server.api.marshalling.objects.Message;
import org.kie.server.api.marshalling.xstream.XStreamMarshaller;
import org.kie.server.api.model.KieContainerResourceFilter;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

Expand Down Expand Up @@ -249,4 +253,30 @@ public void testUnmarshallDateObject() {
assertEquals(LocalTime.of(10, 10, 10), dateObject.getLocalTime());
assertEquals(OffsetDateTime.of(LocalDateTime.of(2017, 1, 1, 10, 10, 10), ZoneOffset.ofHours(1)), dateObject.getOffsetDateTime());
}

@Test
public void testUnmarshallDateObjectWithExtraField() {
String expectedString = "<date-object>\n" +
" <localDate>2017-01-01</localDate>\n" +
" <localDateTime>2017-01-01T10:10:10</localDateTime>\n" +
" <localTime>10:10:10</localTime>\n" +
" <offsetDateTime>2017-01-01T10:10:10+01:00</offsetDateTime>\n" +
" <unknownField>jojojojo</unknownField>\n" +
"</date-object>";
Set<Class<?>> extraClasses = new HashSet<>();
extraClasses.add(DateObject.class);
Marshaller marshaller = MarshallerFactory.getMarshaller(extraClasses, MarshallingFormat.XSTREAM, getClass()
.getClassLoader());

assertThrows(UnknownFieldException.class, () -> marshaller.unmarshall(expectedString, DateObject.class));
DateObject dateObject = marshaller.unmarshall(expectedString, DateObject.class, Collections.singletonMap(
XStreamMarshaller.XSTREAM_IGNORE_UNKNOWN, Boolean.TRUE));
assertNotNull(dateObject);
assertEquals(LocalDate.of(2017, 1, 1), dateObject.getLocalDate());
assertEquals(LocalDateTime.of(2017, 1, 1, 10, 10, 10), dateObject.getLocalDateTime());
assertEquals(LocalTime.of(10, 10, 10), dateObject.getLocalTime());
assertEquals(OffsetDateTime.of(LocalDateTime.of(2017, 1, 1, 10, 10, 10), ZoneOffset.ofHours(1)), dateObject
.getOffsetDateTime());
assertThrows(UnknownFieldException.class, () -> marshaller.unmarshall(expectedString, DateObject.class));
elguardian marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ public <T> T unmarshal(String containerId, String data, String marshallingFormat
throw new IllegalArgumentException("No marshaller found for format " + format);
}

Object instance = marshaller.unmarshall(data, unmarshalType);
Object instance = marshaller.unmarshall(data, unmarshalType, MarshallingFormat.buildParameters(
marshallingFormat));

if (instance instanceof Wrapped) {
return (T) ((Wrapped) instance).unwrap();
Expand All @@ -126,7 +127,8 @@ public <T> T unmarshal(String data, String marshallingFormat, Class<T> unmarshal
serverMarshallers.put(format, marshaller);
}

Object instance = marshaller.unmarshall(data, unmarshalType);
Object instance = marshaller.unmarshall(data, unmarshalType, MarshallingFormat.buildParameters(
marshallingFormat));

if (instance instanceof Wrapped) {
return (T) ((Wrapped) instance).unwrap();
Expand Down