Merge from mainline
[official-gcc.git] / libjava / classpath / java / beans / XMLEncoder.java
blobf9cbe63963d4d4944261f402f5da1726692e054a
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 extends Encoder
55 Object owner;
57 Exception exception;
59 ScanEngine scanEngine;
61 private int accessCounter = 0;
63 public XMLEncoder(OutputStream os)
65 scanEngine = new ScanEngine(os);
68 public void close()
70 if (scanEngine != null)
72 scanEngine.close();
73 scanEngine = null;
77 public void flush()
79 scanEngine.flush();
82 public void writeExpression(Expression expr)
84 // Implementation note: Why is this method overwritten and nearly exactly
85 // reimplemented as in Encoder?
86 // The Encoder class can (and should be) subclassed by users outside of the
87 // java.beans package. While I have doubts that this is possible from an
88 // API design point of view I tried to replicate the Encoder's behavior
89 // in the JDK as exactly as possible. This strictness however made it
90 // extremely complicated to implement the XMLEncoder's backend. Therefore
91 // I decided to copy the Encoder's implementation and make all changes
92 // I needed for a succesfull operation of XMLEncoder.
94 // The same is true for the writeStatement method.
96 // Silently ignore out of bounds calls.
97 if (accessCounter <= 0)
98 return;
100 scanEngine.writeExpression(expr);
103 Object target = expr.getTarget();
104 Object value = null;
105 Object newValue = null;
109 value = expr.getValue();
111 catch (Exception e)
113 getExceptionListener().exceptionThrown(e);
114 return;
118 newValue = get(value);
120 if (newValue == null)
122 Object newTarget = get(target);
123 if (newTarget == null)
125 writeObject(target);
126 newTarget = get(target);
128 // May happen if exception was thrown.
129 if (newTarget == null)
131 return;
135 Object[] args = expr.getArguments();
136 Object[] newArgs = new Object[args.length];
138 for (int i = 0; i < args.length; i++)
140 newArgs[i] = get(args[i]);
141 if (newArgs[i] == null || isImmutableType(args[i].getClass()))
143 writeObject(args[i]);
144 newArgs[i] = get(args[i]);
148 Expression newExpr = new Expression(newTarget, expr.getMethodName(),
149 newArgs);
151 // Fakes the result of Class.forName(<primitiveType>) to make it possible
152 // to hand such a type to the encoding process.
153 if (value instanceof Class && ((Class) value).isPrimitive())
154 newExpr.setValue(value);
156 // Instantiates the new object.
159 newValue = newExpr.getValue();
161 putCandidate(value, newValue);
163 catch (Exception e)
165 getExceptionListener().exceptionThrown(e);
167 // In Statement.writeExpression we had no possibility to flags
168 // an erroneous state to the ScanEngine without behaving different
169 // to the JDK.
170 scanEngine.revoke();
173 writeObject(value);
176 else if(value.getClass() == String.class || value.getClass() == Class.class)
178 writeObject(value);
181 scanEngine.end();
184 public void writeStatement(Statement stmt)
186 // In case of questions have a at the implementation note in
187 // writeExpression.
189 scanEngine.writeStatement(stmt);
191 // Silently ignore out of bounds calls.
192 if (accessCounter <= 0)
193 return;
195 Object target = stmt.getTarget();
197 Object newTarget = get(target);
198 if (newTarget == null)
200 writeObject(target);
201 newTarget = get(target);
204 Object[] args = stmt.getArguments();
205 Object[] newArgs = new Object[args.length];
207 for (int i = 0; i < args.length; i++)
209 // Here is the difference to the original writeStatement
210 // method in Encoder. In case that the object is known or
211 // not an immutable we put it directly into the ScanEngine
212 // which will then generate an object reference for it.
213 newArgs[i] = get(args[i]);
214 if (newArgs[i] == null || isImmutableType(args[i].getClass()))
216 writeObject(args[i]);
217 newArgs[i] = get(args[i]);
219 else
220 scanEngine.writeObject(args[i]);
223 Statement newStmt = new Statement(newTarget, stmt.getMethodName(), newArgs);
227 newStmt.execute();
229 catch (Exception e)
231 getExceptionListener().exceptionThrown(e);
233 // In Statement.writeStatement we had no possibility to flags
234 // an erroneous state to the ScanEngine without behaving different
235 // to the JDK.
236 scanEngine.revoke();
237 return;
240 scanEngine.end();
243 public void writeObject(Object o)
245 accessCounter++;
247 scanEngine.writeObject(o);
249 if (get(o) == null);
250 super.writeObject(o);
252 accessCounter--;
255 public void setOwner(Object o)
257 owner = o;
260 public Object getOwner()
262 return owner;