Test4679556.java revision 9330:8b1f1c2a400f
1/*
2 * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/*
25 * @test
26 * @bug 4679556
27 * @summary Tests for duplication of some kind instances
28 * @author Sergey Malenkov, Mark Davidson, Philip Milne
29 */
30
31import java.beans.DefaultPersistenceDelegate;
32import java.beans.Encoder;
33import java.beans.Expression;
34import java.beans.XMLEncoder;
35
36/**
37 * Demonstrates the archiver bug, where the XMLEncoder duplicates
38 * the instance of class A because it is required as the target of
39 * a factory method (to produce an instance of class C).
40 * See the output in the file Test.xml for the results and note
41 * the (invalid) forward reference to the instance of class C.
42 *
43 * TO FIX
44 *
45 * Move the first line of the XMLEncoder::mark(Statement method)
46 * to the end of the method.
47 * I.e. replace the mark() method in XMLEncoder with this:
48 * <pre>private void mark(Statement stm) {
49 *     Object[] args = stm.getArguments();
50 *     for (int i = 0; i < args.length; i++) {
51 *         Object arg = args[i];
52 *         mark(arg, true);
53 *     }
54 *     mark(stm.getTarget(), false);
55 * }</pre>
56 *
57 * VALID ARCHIVE (WITH FIX):
58 * <pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
59 * &lt;java version="1.4.0" class="java.beans.XMLDecoder"&gt;
60 *  &lt;object class="TestDuplicates$A"&gt;
61 *   &lt;void id="TestDuplicates$C0" method="createC"/&gt;
62 *   &lt;void property="x"&gt;
63 *    &lt;void property="x"&gt;
64 *     &lt;object idref="TestDuplicates$C0"/&gt;
65 *    &lt;/void&gt;
66 *   &lt;/void&gt;
67 *  &lt;/object&gt;
68 * &lt;/java&gt;</pre>
69 *
70 * INVALID ARCHIVE (WITHOUT FIX):
71 *  &lt;object class="TestDuplicates$A"&gt;
72 *   &lt;void property="x"&gt;
73 *    &lt;void property="x"&gt;
74 *     &lt;void class="TestDuplicates$A"&gt;
75 *      &lt;void property="x"&gt;
76 *       &lt;void property="x"&gt;
77 *        &lt;object idref="TestDuplicates$C0"/&gt;
78 *       &lt;/void&gt;
79 *      &lt;/void&gt;
80 *      &lt;void id="TestDuplicates$C0" method="createC"/&gt;
81 *     &lt;/void&gt;
82 *     &lt;object idref="TestDuplicates$C0"/&gt;
83 *    &lt;/void&gt;
84 *   &lt;/void&gt;
85 *   &lt;void id="TestDuplicates$C0" method="createC"/&gt;
86 *  &lt;/object&gt;
87 * &lt;/java&gt;</pre>
88 */
89public class Test4679556 extends AbstractTest {
90    public static void main(String[] args) {
91        new Test4679556().test(true);
92    }
93
94    protected Object getObject() {
95        A a = new A();
96        B b = (B) a.getX();
97        b.setX(a.createC());
98        return a;
99    }
100
101    protected Object getAnotherObject() {
102        return new A();
103    }
104
105    protected void initialize(XMLEncoder encoder) {
106        encoder.setPersistenceDelegate(C.class, new DefaultPersistenceDelegate() {
107            protected Expression instantiate(Object oldInstance, Encoder out) {
108                C c = (C) oldInstance;
109                return new Expression(c, c.getX(), "createC", new Object[] {});
110            }
111        });
112    }
113
114    public static class Base {
115        private Object x;
116
117        public Object getX() {
118            return this.x;
119        }
120
121        public void setX(Object x) {
122            this.x = x;
123        }
124    }
125
126    public static class A extends Base {
127        public A() {
128            setX(new B());
129        }
130
131        public C createC() {
132            return new C(this);
133        }
134    }
135
136    public static class B extends Base {
137    }
138
139    public static class C extends Base {
140        private C(Object x) {
141            setX(x);
142        }
143    }
144}
145