OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [java/] [beans/] [Encoder.java] - Blame information for rev 771

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 771 jeremybenn
/* Encoder.java
2
 Copyright (C) 2005, 2006 Free Software Foundation, Inc.
3
 
4
 This file is part of GNU Classpath.
5
 
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.
10
 
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.
15
 
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.
20
 
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.
25
 
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. */
37
 
38
 
39
package java.beans;
40
 
41
import gnu.java.beans.DefaultExceptionListener;
42
import gnu.java.beans.encoder.ArrayPersistenceDelegate;
43
import gnu.java.beans.encoder.ClassPersistenceDelegate;
44
import gnu.java.beans.encoder.CollectionPersistenceDelegate;
45
import gnu.java.beans.encoder.MapPersistenceDelegate;
46
import gnu.java.beans.encoder.PrimitivePersistenceDelegate;
47
 
48
import java.util.AbstractCollection;
49
import java.util.HashMap;
50
import java.util.IdentityHashMap;
51
 
52
/**
53
 * @author Robert Schuster (robertschuster@fsfe.org)
54
 * @since 1.4
55
 */
56
public class Encoder
57
{
58
 
59
  /**
60
   * An internal DefaultPersistenceDelegate instance that is used for every
61
   * class that does not a have a special special PersistenceDelegate.
62
   */
63
  private static PersistenceDelegate defaultPersistenceDelegate;
64
 
65
  private static PersistenceDelegate fakePersistenceDelegate;
66
 
67
  /**
68
   * Stores the relation Class->PersistenceDelegate.
69
   */
70
  private static HashMap delegates = new HashMap();
71
 
72
  /**
73
   * Stores the relation oldInstance->newInstance
74
   */
75
  private IdentityHashMap candidates = new IdentityHashMap();
76
 
77
  private ExceptionListener exceptionListener;
78
 
79
  /**
80
   * A simple number that is used to restrict the access to writeExpression and
81
   * writeStatement. The rule is that both methods should only be used when an
82
   * object is written to the stream (= writeObject). Therefore accessCounter is
83
   * incremented just before the call to writeObject and decremented afterwards.
84
   * Then writeStatement and writeExpression allow execution only if
85
   * accessCounter is bigger than zero.
86
   */
87
  private int accessCounter = 0;
88
 
89
  public Encoder()
90
  {
91
    setupDefaultPersistenceDelegates();
92
 
93
    setExceptionListener(null);
94
  }
95
 
96
  /**
97
   * Sets up a bunch of {@link PersistenceDelegate} instances which are needed
98
   * for the basic working of a {@link Encoder}s.
99
   */
100
  private static void setupDefaultPersistenceDelegates()
101
  {
102
    synchronized (delegates)
103
      {
104
        if (defaultPersistenceDelegate != null)
105
          return;
106
 
107
        delegates.put(Class.class, new ClassPersistenceDelegate());
108
 
109
        PersistenceDelegate pd = new PrimitivePersistenceDelegate();
110
        delegates.put(Boolean.class, pd);
111
        delegates.put(Byte.class, pd);
112
        delegates.put(Short.class, pd);
113
        delegates.put(Integer.class, pd);
114
        delegates.put(Long.class, pd);
115
        delegates.put(Float.class, pd);
116
        delegates.put(Double.class, pd);
117
 
118
        delegates.put(Object[].class, new ArrayPersistenceDelegate());
119
 
120
        pd = new CollectionPersistenceDelegate();
121
        delegates.put(AbstractCollection.class, pd);
122
 
123
        pd = new MapPersistenceDelegate();
124
        delegates.put(java.util.AbstractMap.class, pd);
125
        delegates.put(java.util.Hashtable.class, pd);
126
 
127
        defaultPersistenceDelegate = new DefaultPersistenceDelegate();
128
        delegates.put(Object.class, defaultPersistenceDelegate);
129
 
130
        // Creates a PersistenceDelegate implementation which is
131
        // returned for 'null'. In practice this instance is
132
        // not used in any way and is just here to be compatible
133
        // with the reference implementation which returns a
134
        // similar instance when calling getPersistenceDelegate(null) .
135
        fakePersistenceDelegate = new PersistenceDelegate()
136
        {
137
          protected Expression instantiate(Object o, Encoder e)
138
          {
139
            return null;
140
          }
141
        };
142
 
143
      }
144
  }
145
 
146
  protected void writeObject(Object o)
147
  {
148
    // 'null' has no PersistenceDelegate and will not
149
    // create an Expression which has to be cloned.
150
    // However subclasses should be aware that writeObject
151
    // may be called with a 'null' argument and should
152
    // write the proper representation of it.
153
    if (o == null)
154
      return;
155
 
156
    PersistenceDelegate pd = getPersistenceDelegate(o.getClass());
157
 
158
    accessCounter++;
159
    pd.writeObject(o, this);
160
    accessCounter--;
161
 
162
  }
163
 
164
  /**
165
   * Sets the {@link ExceptionListener} instance to be used for reporting
166
   * recorable exceptions in the instantiation and initialization sequence. If
167
   * the argument is <code>null</code> a default instance will be used that
168
   * prints the thrown exception to <code>System.err</code>.
169
   */
170
  public void setExceptionListener(ExceptionListener listener)
171
  {
172
    exceptionListener = (listener != null)
173
        ? listener : DefaultExceptionListener.INSTANCE;
174
  }
175
 
176
  /**
177
   * Returns the currently active {@link ExceptionListener} instance.
178
   */
179
  public ExceptionListener getExceptionListener()
180
  {
181
    return exceptionListener;
182
  }
183
 
184
  public PersistenceDelegate getPersistenceDelegate(Class<?> type)
185
  {
186
    // This is not specified but the JDK behaves like this.
187
    if (type == null)
188
      return fakePersistenceDelegate;
189
 
190
    // Treats all array classes in the same way and assigns
191
    // them a shared PersistenceDelegate implementation tailored
192
    // for array instantation and initialization.
193
    if (type.isArray())
194
      return (PersistenceDelegate) delegates.get(Object[].class);
195
 
196
    PersistenceDelegate pd = (PersistenceDelegate) delegates.get(type);
197
 
198
    return (pd != null) ? pd : defaultPersistenceDelegate;
199
  }
200
 
201
  /**
202
   * Sets the {@link PersistenceDelegate} instance for the given class.
203
   * <p>
204
   * Note: Throws a <code>NullPointerException</code> if the argument is
205
   * <code>null</code>.
206
   * </p>
207
   * <p>
208
   * Note: Silently ignores PersistenceDelegates for Array types and primitive
209
   * wrapper classes.
210
   * </p>
211
   * <p>
212
   * Note: Although this method is not declared <code>static</code> changes to
213
   * the {@link PersistenceDelegate}s affect <strong>all</strong>
214
   * {@link Encoder} instances. <strong>In this implementation</strong> the
215
   * access is thread safe.
216
   * </p>
217
   */
218
  public void setPersistenceDelegate(Class<?> type,
219
                                     PersistenceDelegate delegate)
220
  {
221
    // If the argument is null this will cause a NullPointerException
222
    // which is expected behavior.
223
 
224
    // This makes custom PDs for array, primitive types and their wrappers
225
    // impossible but this is how the JDK behaves.
226
    if (type.isArray() || type.isPrimitive() || type == Boolean.class
227
        || type == Byte.class || type == Short.class || type == Integer.class
228
        || type == Long.class || type == Float.class || type == Double.class)
229
      return;
230
 
231
    synchronized (delegates)
232
      {
233
        delegates.put(type, delegate);
234
      }
235
 
236
  }
237
 
238
  public Object remove(Object oldInstance)
239
  {
240
    return candidates.remove(oldInstance);
241
  }
242
 
243
  /**
244
   * Returns the replacement object which has been created by the encoder during
245
   * the instantiation sequence or <code>null</code> if the object has not
246
   * been processed yet.
247
   * <p>
248
   * Note: The <code>String</code> class acts as an endpoint for the
249
   * inherently recursive algorithm of the {@link Encoder}. Therefore instances
250
   * of <code>String</code> will always be returned by this method. In other
251
   * words the assertion: <code>
252
   * assert (anyEncoder.get(anyString) == anyString)
253
   * </code<
254
   * will always hold.</p>
255
   *
256
   * <p>Note: If <code>null</code> is requested, the result will
257
   * always be <code>null</code>.</p>
258
   */
259
  public Object get(Object oldInstance)
260
  {
261
    // String instances are handled in a special way.
262
    // No one knows why this is not officially specified
263
    // because this is a rather important design decision.
264
    return (oldInstance == null) ? null :
265
             (oldInstance.getClass() == String.class) ?
266
               oldInstance : candidates.get(oldInstance);
267
  }
268
 
269
  /**
270
   * <p>
271
   * Note: If you call this method not from within an object instantiation and
272
   * initialization sequence it will be silently ignored.
273
   * </p>
274
   */
275
  public void writeStatement(Statement stmt)
276
  {
277
    // Silently ignore out of bounds calls.
278
    if (accessCounter <= 0)
279
      return;
280
 
281
    Object target = stmt.getTarget();
282
 
283
    Object newTarget = get(target);
284
    if (newTarget == null)
285
      {
286
        writeObject(target);
287
        newTarget = get(target);
288
      }
289
 
290
    Object[] args = stmt.getArguments();
291
    Object[] newArgs = new Object[args.length];
292
 
293
    for (int i = 0; i < args.length; i++)
294
      {
295
        newArgs[i] = get(args[i]);
296
        if (newArgs[i] == null || isImmutableType(args[i].getClass()))
297
          {
298
            writeObject(args[i]);
299
            newArgs[i] = get(args[i]);
300
          }
301
      }
302
 
303
    Statement newStmt = new Statement(newTarget, stmt.getMethodName(), newArgs);
304
 
305
    try
306
      {
307
        newStmt.execute();
308
      }
309
    catch (Exception e)
310
      {
311
        exceptionListener.exceptionThrown(e);
312
      }
313
 
314
  }
315
 
316
  /**
317
   * <p>
318
   * Note: If you call this method not from within an object instantiation and
319
   * initialization sequence it will be silently ignored.
320
   * </p>
321
   */
322
  public void writeExpression(Expression expr)
323
  {
324
    // Silently ignore out of bounds calls.
325
    if (accessCounter <= 0)
326
      return;
327
 
328
    Object target = expr.getTarget();
329
    Object value = null;
330
    Object newValue = null;
331
 
332
    try
333
      {
334
        value = expr.getValue();
335
      }
336
    catch (Exception e)
337
      {
338
        exceptionListener.exceptionThrown(e);
339
        return;
340
      }
341
 
342
 
343
    newValue = get(value);
344
 
345
    if (newValue == null)
346
      {
347
        Object newTarget = get(target);
348
        if (newTarget == null)
349
          {
350
            writeObject(target);
351
            newTarget = get(target);
352
 
353
            // May happen if exception was thrown.
354
            if (newTarget == null)
355
              {
356
                return;
357
              }
358
          }
359
 
360
        Object[] args = expr.getArguments();
361
        Object[] newArgs = new Object[args.length];
362
 
363
        for (int i = 0; i < args.length; i++)
364
          {
365
            newArgs[i] = get(args[i]);
366
            if (newArgs[i] == null || isImmutableType(args[i].getClass()))
367
              {
368
                writeObject(args[i]);
369
                newArgs[i] = get(args[i]);
370
              }
371
          }
372
 
373
        Expression newExpr = new Expression(newTarget, expr.getMethodName(),
374
                                            newArgs);
375
 
376
        // Fakes the result of Class.forName(<primitiveType>) to make it possible
377
        // to hand such a type to the encoding process.
378
        if (value instanceof Class && ((Class) value).isPrimitive())
379
          newExpr.setValue(value);
380
 
381
        // Instantiates the new object.
382
        try
383
          {
384
            newValue = newExpr.getValue();
385
 
386
            candidates.put(value, newValue);
387
          }
388
        catch (Exception e)
389
          {
390
            exceptionListener.exceptionThrown(e);
391
 
392
            return;
393
          }
394
 
395
        writeObject(value);
396
 
397
      }
398
    else if(value.getClass() == String.class || value.getClass() == Class.class)
399
      {
400
        writeObject(value);
401
      }
402
 
403
  }
404
 
405
  /** Returns whether the given class is an immutable
406
   * type which has to be handled differently when serializing it.
407
   *
408
   * <p>Immutable objects always have to be instantiated instead of
409
   * modifying an existing instance.</p>
410
   *
411
   * @param type The class to test.
412
   * @return Whether the first argument is an immutable type.
413
   */
414
  boolean isImmutableType(Class type)
415
  {
416
    return type == String.class || type == Class.class
417
      || type == Integer.class || type == Boolean.class
418
      || type == Byte.class || type == Short.class
419
      || type == Long.class || type == Float.class
420
      || type == Double.class;
421
  }
422
 
423
  /** Sets the stream candidate for a given object.
424
   *
425
   * @param oldObject The object given to the encoder.
426
   * @param newObject The object the encoder generated.
427
   */
428
  void putCandidate(Object oldObject, Object newObject)
429
  {
430
    candidates.put(oldObject, newObject);
431
  }
432
 
433
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.