文章

Restlet 2.1.4中 匪夷所思的ObjectRepresentation的构造函数

OneCoder使用Restlet最新版2.1.4开发样例,却一直抛出异常:

Exception in thread “main” java.lang.IllegalArgumentException : The serialized representation must have this media type: application/x-java-serialized-object or this one: application/x-java-serialized-object+xml
          at org.restlet.representation.ObjectRepresentation.(ObjectRepresentation.java:203)
     at org.restlet.representation.Objec tRepresentation.(ObjectRepresentation.java:114)

无论怎么设置MediaType都无效,无奈只能查看次构造函数的源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
public ObjectRepresentation(Representation serializedRepresentation,
            final ClassLoader classLoader) throws IOException,
            ClassNotFoundException, IllegalArgumentException {
        super(MediaType.APPLICATION_JAVA_OBJECT);


        if (serializedRepresentation.getMediaType().equals(
                MediaType. APPLICATION_JAVA_OBJECT)) {
            if (!VARIANT_OBJECT_BINARY_SUPPORTED ) {
                throw new IllegalArgumentException(
                        "SECURITY WARNING: The usage of ObjectInputStream when "
                                + "deserializing binary presentations from unstrusted "
                                + "sources can lead to malicious attacks. As pointed "
                                + "here (https://github.com/restlet/restlet-framework-java/issues/778), "
                                + "the ObjectInputStream class is able to force the JVM to execute unwanted "
                                + "Java code. Thus, the support of such format has been disactivated "
                                + "by default. You can activate this support by turning on the following system property: "
                                + "org.restlet.representation.ObjectRepresentation.VARIANT_OBJECT_BINARY_SUPPORTED." );
            }
            setMediaType(MediaType.APPLICATION_JAVA_OBJECT );
            InputStream is = serializedRepresentation.getStream();
            ObjectInputStream ois = null;
            if (classLoader != null) {
                ois = new ObjectInputStream(is) {
                    @Override
                    protected Class<?> resolveClass(
                            java.io.ObjectStreamClass desc)
                            throws java.io.IOException,
                            java.lang.ClassNotFoundException {
                        return Class
                                . forName(desc.getName(), false, classLoader);
                    }
                };
            } else {
                ois = new ObjectInputStream(is);
            }


            this.object = (T) ois.readObject();


            if (is.read() != -1) {
                throw new IOException(
                        "The input stream has not been fully read.");
            }


            ois.close();
        } else if (VARIANT_OBJECT_XML_SUPPORTED
                && serializedRepresentation.getMediaType().equals(
                        MediaType.APPLICATION_JAVA_OBJECT_XML )) {
            if (!VARIANT_OBJECT_XML_SUPPORTED ) {
                throw new IllegalArgumentException(
                        "SECURITY WARNING: The usage of XMLDecoder when "
                                + "deserializing XML presentations from unstrusted "
                                + "sources can lead to malicious attacks. As pointed "
                                + "here (http://blog.diniscruz.com/2013/08/using-xmldecoder-to-execute-server-side.html), "
                                + "the XMLDecoder class is able to force the JVM to "
                                + "execute unwanted Java code described inside the XML "
                                + "file. Thus, the support of such format has been "
                                + "disactivated by default. You can activate this "
                                + "support by turning on the following system property: "
                                + "org.restlet.representation.ObjectRepresentation.VARIANT_OBJECT_XML_SUPPORTED." );
            }
            setMediaType(MediaType.APPLICATION_JAVA_OBJECT_XML );
            InputStream is = serializedRepresentation.getStream();
            java.beans.XMLDecoder decoder = new java.beans.XMLDecoder(is);
            this.object = (T) decoder.readObject();


            if (is.read() != -1) {
                throw new IOException(
                        "The input stream has not been fully read.");
            }


            decoder.close();
        }
        throw new IllegalArgumentException(
                "The serialized representation must have this media type: "
                        + MediaType.APPLICATION_JAVA_OBJECT .toString()
                        + " or this one: "
                        + MediaType.APPLICATION_JAVA_OBJECT_XML .toString());
    }

惊呆的发现,最后的throw new IllegalArgumentException 逻辑被赤裸裸的暴露在外面,也就是不论上面走的是if还是else,最终都会走到这里抛出异常结束。这不免让我一头雾水,回头查看2.1.2版本的源码,发现抛出异常的代码是写在最后的else块里的,这可就大不相同了。

我只能以我目前粗浅的了解,怀疑这是restlet的一个粗心的bug,我已经给restlet发了邮件咨询了该问题,等待回复中。目前,我也只能降到2.1.2版本的restlet进行开发,在2.1.2版上无此问题。

注:已确认是bug。

本文由作者按照 CC BY 4.0 进行授权