Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/classes/java/beans/PersistenceDelegate.java
41152 views
1
/*
2
* Copyright (c) 2000, 2020, 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. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
package java.beans;
26
27
/**
28
* The PersistenceDelegate class takes the responsibility
29
* for expressing the state of an instance of a given class
30
* in terms of the methods in the class's public API. Instead
31
* of associating the responsibility of persistence with
32
* the class itself as is done, for example, by the
33
* {@code readObject} and {@code writeObject}
34
* methods used by the {@code ObjectOutputStream}, streams like
35
* the {@code XMLEncoder} which
36
* use this delegation model can have their behavior controlled
37
* independently of the classes themselves. Normally, the class
38
* is the best place to put such information and conventions
39
* can easily be expressed in this delegation scheme to do just that.
40
* Sometimes however, it is the case that a minor problem
41
* in a single class prevents an entire object graph from
42
* being written and this can leave the application
43
* developer with no recourse but to attempt to shadow
44
* the problematic classes locally or use alternative
45
* persistence techniques. In situations like these, the
46
* delegation model gives a relatively clean mechanism for
47
* the application developer to intervene in all parts of the
48
* serialization process without requiring that modifications
49
* be made to the implementation of classes which are not part
50
* of the application itself.
51
* <p>
52
* In addition to using a delegation model, this persistence
53
* scheme differs from traditional serialization schemes
54
* in requiring an analog of the {@code writeObject}
55
* method without a corresponding {@code readObject}
56
* method. The {@code writeObject} analog encodes each
57
* instance in terms of its public API and there is no need to
58
* define a {@code readObject} analog
59
* since the procedure for reading the serialized form
60
* is defined by the semantics of method invocation as laid
61
* out in the Java Language Specification.
62
* Breaking the dependency between {@code writeObject}
63
* and {@code readObject} implementations, which may
64
* change from version to version, is the key factor
65
* in making the archives produced by this technique immune
66
* to changes in the private implementations of the classes
67
* to which they refer.
68
* <p>
69
* A persistence delegate, may take control of all
70
* aspects of the persistence of an object including:
71
* <ul>
72
* <li>
73
* Deciding whether or not an instance can be mutated
74
* into another instance of the same class.
75
* <li>
76
* Instantiating the object, either by calling a
77
* public constructor or a public factory method.
78
* <li>
79
* Performing the initialization of the object.
80
* </ul>
81
* @see XMLEncoder
82
*
83
* @since 1.4
84
*
85
* @author Philip Milne
86
*/
87
88
public abstract class PersistenceDelegate {
89
90
/**
91
* Constructs a {@code PersistenceDelegate}.
92
*/
93
protected PersistenceDelegate() {}
94
95
/**
96
* The {@code writeObject} is a single entry point to the persistence
97
* and is used by an {@code Encoder} in the traditional
98
* mode of delegation. Although this method is not final,
99
* it should not need to be subclassed under normal circumstances.
100
* <p>
101
* This implementation first checks to see if the stream
102
* has already encountered this object. Next the
103
* {@code mutatesTo} method is called to see if
104
* that candidate returned from the stream can
105
* be mutated into an accurate copy of {@code oldInstance}.
106
* If it can, the {@code initialize} method is called to
107
* perform the initialization. If not, the candidate is removed
108
* from the stream, and the {@code instantiate} method
109
* is called to create a new candidate for this object.
110
*
111
* @param oldInstance The instance that will be created by this expression.
112
* @param out The stream to which this expression will be written.
113
*
114
* @throws NullPointerException if {@code out} is {@code null}
115
*/
116
public void writeObject(Object oldInstance, Encoder out) {
117
Object newInstance = out.get(oldInstance);
118
if (!mutatesTo(oldInstance, newInstance)) {
119
out.remove(oldInstance);
120
out.writeExpression(instantiate(oldInstance, out));
121
}
122
else {
123
initialize(oldInstance.getClass(), oldInstance, newInstance, out);
124
}
125
}
126
127
/**
128
* Returns true if an <em>equivalent</em> copy of {@code oldInstance} may be
129
* created by applying a series of statements to {@code newInstance}.
130
* In the specification of this method, we mean by equivalent that the modified instance
131
* is indistinguishable from {@code oldInstance} in the behavior
132
* of the relevant methods in its public API. [Note: we use the
133
* phrase <em>relevant</em> methods rather than <em>all</em> methods
134
* here only because, to be strictly correct, methods like {@code hashCode}
135
* and {@code toString} prevent most classes from producing truly
136
* indistinguishable copies of their instances].
137
* <p>
138
* The default behavior returns {@code true}
139
* if the classes of the two instances are the same.
140
*
141
* @param oldInstance The instance to be copied.
142
* @param newInstance The instance that is to be modified.
143
* @return True if an equivalent copy of {@code newInstance} may be
144
* created by applying a series of mutations to {@code oldInstance}.
145
*/
146
protected boolean mutatesTo(Object oldInstance, Object newInstance) {
147
return (newInstance != null && oldInstance != null &&
148
oldInstance.getClass() == newInstance.getClass());
149
}
150
151
/**
152
* Returns an expression whose value is {@code oldInstance}.
153
* This method is used to characterize the constructor
154
* or factory method that should be used to create the given object.
155
* For example, the {@code instantiate} method of the persistence
156
* delegate for the {@code Field} class could be defined as follows:
157
* <pre>
158
* Field f = (Field)oldInstance;
159
* return new Expression(f, f.getDeclaringClass(), "getField", new Object[]{f.getName()});
160
* </pre>
161
* Note that we declare the value of the returned expression so that
162
* the value of the expression (as returned by {@code getValue})
163
* will be identical to {@code oldInstance}.
164
*
165
* @param oldInstance The instance that will be created by this expression.
166
* @param out The stream to which this expression will be written.
167
* @return An expression whose value is {@code oldInstance}.
168
*
169
* @throws NullPointerException if {@code out} is {@code null}
170
* and this value is used in the method
171
*/
172
protected abstract Expression instantiate(Object oldInstance, Encoder out);
173
174
/**
175
* Produce a series of statements with side effects on {@code newInstance}
176
* so that the new instance becomes <em>equivalent</em> to {@code oldInstance}.
177
* In the specification of this method, we mean by equivalent that, after the method
178
* returns, the modified instance is indistinguishable from
179
* {@code newInstance} in the behavior of all methods in its
180
* public API.
181
* <p>
182
* The implementation typically achieves this goal by producing a series of
183
* "what happened" statements involving the {@code oldInstance}
184
* and its publicly available state. These statements are sent
185
* to the output stream using its {@code writeExpression}
186
* method which returns an expression involving elements in
187
* a cloned environment simulating the state of an input stream during
188
* reading. Each statement returned will have had all instances
189
* the old environment replaced with objects which exist in the new
190
* one. In particular, references to the target of these statements,
191
* which start out as references to {@code oldInstance} are returned
192
* as references to the {@code newInstance} instead.
193
* Executing these statements effects an incremental
194
* alignment of the state of the two objects as a series of
195
* modifications to the objects in the new environment.
196
* By the time the initialize method returns it should be impossible
197
* to tell the two instances apart by using their public APIs.
198
* Most importantly, the sequence of steps that were used to make
199
* these objects appear equivalent will have been recorded
200
* by the output stream and will form the actual output when
201
* the stream is flushed.
202
* <p>
203
* The default implementation, calls the {@code initialize}
204
* method of the type's superclass.
205
*
206
* @param type the type of the instances
207
* @param oldInstance The instance to be copied.
208
* @param newInstance The instance that is to be modified.
209
* @param out The stream to which any initialization statements should be written.
210
*
211
* @throws NullPointerException if {@code out} is {@code null}
212
*/
213
protected void initialize(Class<?> type,
214
Object oldInstance, Object newInstance,
215
Encoder out)
216
{
217
Class<?> superType = type.getSuperclass();
218
PersistenceDelegate info = out.getPersistenceDelegate(superType);
219
info.initialize(superType, oldInstance, newInstance, out);
220
}
221
}
222
223