Import GNU Classpath (20121202).
[official-gcc.git] / libjava / classpath / java / beans / XMLEncoder.java
blob894e4b873c4e019c64d1f373e8b3810c20836f7d
1 /* XMLEncoder.java
2 Copyright (C) 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package java.beans;
41 import gnu.java.beans.encoder.ScanEngine;
43 import java.io.OutputStream;
45 /**
46 * This class uses the {@link PersistenceDelegate} and {@link Encoder}
47 * infrastructure to generate an XML representation of the objects it
48 * serializes.
50 * @author Robert Schuster (robertschuster@fsfe.org)
51 * @since 1.4
53 public class XMLEncoder
54 extends Encoder
55 implements AutoCloseable
57 Object owner;
59 Exception exception;
61 ScanEngine scanEngine;
63 private int accessCounter = 0;
65 public XMLEncoder(OutputStream os)
67 scanEngine = new ScanEngine(os);
70 public void close()
72 if (scanEngine != null)
74 scanEngine.close();
75 scanEngine = null;
79 public void flush()
81 scanEngine.flush();
84 public void writeExpression(Expression expr)
86 // Implementation note: Why is this method overwritten and nearly exactly
87 // reimplemented as in Encoder?
88 // The Encoder class can (and should be) subclassed by users outside of the
89 // java.beans package. While I have doubts that this is possible from an
90 // API design point of view I tried to replicate the Encoder's behavior
91 // in the JDK as exactly as possible. This strictness however made it
92 // extremely complicated to implement the XMLEncoder's backend. Therefore
93 // I decided to copy the Encoder's implementation and make all changes
94 // I needed for a succesfull operation of XMLEncoder.
96 // The same is true for the writeStatement method.
98 // Silently ignore out of bounds calls.
99 if (accessCounter <= 0)
100 return;
102 scanEngine.writeExpression(expr);
105 Object target = expr.getTarget();
106 Object value = null;
107 Object newValue = null;
111 value = expr.getValue();
113 catch (Exception e)
115 getExceptionListener().exceptionThrown(e);
116 return;
120 newValue = get(value);
122 if (newValue == null)
124 Object newTarget = get(target);
125 if (newTarget == null)
127 writeObject(target);
128 newTarget = get(target);
130 // May happen if exception was thrown.
131 if (newTarget == null)
133 return;
137 Object[] args = expr.getArguments();
138 Object[] newArgs = new Object[args.length];
140 for (int i = 0; i < args.length; i++)
142 newArgs[i] = get(args[i]);
143 if (newArgs[i] == null || isImmutableType(args[i].getClass()))
145 writeObject(args[i]);
146 newArgs[i] = get(args[i]);
150 Expression newExpr = new Expression(newTarget, expr.getMethodName(),
151 newArgs);
153 // Fakes the result of Class.forName(<primitiveType>) to make it possible
154 // to hand such a type to the encoding process.
155 if (value instanceof Class && ((Class) value).isPrimitive())
156 newExpr.setValue(value);
158 // Instantiates the new object.
161 newValue = newExpr.getValue();
163 putCandidate(value, newValue);
165 catch (Exception e)
167 getExceptionListener().exceptionThrown(e);
169 // In Statement.writeExpression we had no possibility to flags
170 // an erroneous state to the ScanEngine without behaving different
171 // to the JDK.
172 scanEngine.revoke();
174 return;
177 writeObject(value);
180 else if(value.getClass() == String.class || value.getClass() == Class.class)
182 writeObject(value);
185 scanEngine.end();
188 public void writeStatement(Statement stmt)
190 // In case of questions have a at the implementation note in
191 // writeExpression.
193 scanEngine.writeStatement(stmt);
195 // Silently ignore out of bounds calls.
196 if (accessCounter <= 0)
197 return;
199 Object target = stmt.getTarget();
201 Object newTarget = get(target);
202 if (newTarget == null)
204 writeObject(target);
205 newTarget = get(target);
208 Object[] args = stmt.getArguments();
209 Object[] newArgs = new Object[args.length];
211 for (int i = 0; i < args.length; i++)
213 // Here is the difference to the original writeStatement
214 // method in Encoder. In case that the object is known or
215 // not an immutable we put it directly into the ScanEngine
216 // which will then generate an object reference for it.
217 newArgs[i] = get(args[i]);
218 if (newArgs[i] == null || isImmutableType(args[i].getClass()))
220 writeObject(args[i]);
221 newArgs[i] = get(args[i]);
223 else
224 scanEngine.writeObject(args[i]);
227 Statement newStmt = new Statement(newTarget, stmt.getMethodName(), newArgs);
231 newStmt.execute();
233 catch (Exception e)
235 getExceptionListener().exceptionThrown(e);
237 // In Statement.writeStatement we had no possibility to flags
238 // an erroneous state to the ScanEngine without behaving different
239 // to the JDK.
240 scanEngine.revoke();
241 return;
244 scanEngine.end();
247 public void writeObject(Object o)
249 accessCounter++;
251 scanEngine.writeObject(o);
253 if (get(o) == null)
254 super.writeObject(o);
256 accessCounter--;
259 public void setOwner(Object o)
261 owner = o;
264 public Object getOwner()
266 return owner;