mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			270 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			270 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* XMLEncoder.java
 | |
|  Copyright (C) 2004, 2005 Free Software Foundation, Inc.
 | |
| 
 | |
|  This file is part of GNU Classpath.
 | |
| 
 | |
|  GNU Classpath is free software; you can redistribute it and/or modify
 | |
|  it under the terms of the GNU General Public License as published by
 | |
|  the Free Software Foundation; either version 2, or (at your option)
 | |
|  any later version.
 | |
| 
 | |
|  GNU Classpath is distributed in the hope that it will be useful, but
 | |
|  WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
|  General Public License for more details.
 | |
| 
 | |
|  You should have received a copy of the GNU General Public License
 | |
|  along with GNU Classpath; see the file COPYING.  If not, write to the
 | |
|  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | |
|  02110-1301 USA.
 | |
| 
 | |
|  Linking this library statically or dynamically with other modules is
 | |
|  making a combined work based on this library.  Thus, the terms and
 | |
|  conditions of the GNU General Public License cover the whole
 | |
|  combination.
 | |
| 
 | |
|  As a special exception, the copyright holders of this library give you
 | |
|  permission to link this library with independent modules to produce an
 | |
|  executable, regardless of the license terms of these independent
 | |
|  modules, and to copy and distribute the resulting executable under
 | |
|  terms of your choice, provided that you also meet, for each linked
 | |
|  independent module, the terms and conditions of the license of that
 | |
|  module.  An independent module is a module which is not derived from
 | |
|  or based on this library.  If you modify this library, you may extend
 | |
|  this exception to your version of the library, but you are not
 | |
|  obligated to do so.  If you do not wish to do so, delete this
 | |
|  exception statement from your version. */
 | |
| 
 | |
| 
 | |
| package java.beans;
 | |
| 
 | |
| import gnu.java.beans.encoder.ScanEngine;
 | |
| 
 | |
| import java.io.OutputStream;
 | |
| 
 | |
| /**
 | |
|  * This class uses the {@link PersistenceDelegate} and {@link Encoder}
 | |
|  * infrastructure to generate an XML representation of the objects it
 | |
|  * serializes.
 | |
|  *
 | |
|  * @author Robert Schuster (robertschuster@fsfe.org)
 | |
|  * @since 1.4
 | |
|  */
 | |
| public class XMLEncoder
 | |
|   extends Encoder
 | |
|   implements AutoCloseable
 | |
| {
 | |
|   Object owner;
 | |
| 
 | |
|   Exception exception;
 | |
| 
 | |
|   ScanEngine scanEngine;
 | |
| 
 | |
|   private int accessCounter = 0;
 | |
| 
 | |
|   public XMLEncoder(OutputStream os)
 | |
|   {
 | |
|     scanEngine = new ScanEngine(os);
 | |
|   }
 | |
| 
 | |
|   public void close()
 | |
|   {
 | |
|     if (scanEngine != null)
 | |
|       {
 | |
|         scanEngine.close();
 | |
|         scanEngine = null;
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   public void flush()
 | |
|   {
 | |
|     scanEngine.flush();
 | |
|   }
 | |
| 
 | |
|   public void writeExpression(Expression expr)
 | |
|   {
 | |
|     // Implementation note: Why is this method overwritten and nearly exactly
 | |
|     // reimplemented as in Encoder?
 | |
|     // The Encoder class can (and should be) subclassed by users outside of the
 | |
|     // java.beans package. While I have doubts that this is possible from an
 | |
|     // API design point of view I tried to replicate the Encoder's behavior
 | |
|     // in the JDK as exactly as possible. This strictness however made it
 | |
|     // extremely complicated to implement the XMLEncoder's backend. Therefore
 | |
|     // I decided to copy the Encoder's implementation and make all changes
 | |
|     // I needed for a succesfull operation of XMLEncoder.
 | |
|     //
 | |
|     // The same is true for the writeStatement method.
 | |
| 
 | |
|     //  Silently ignore out of bounds calls.
 | |
|     if (accessCounter <= 0)
 | |
|       return;
 | |
| 
 | |
|     scanEngine.writeExpression(expr);
 | |
| 
 | |
| 
 | |
|     Object target = expr.getTarget();
 | |
|     Object value = null;
 | |
|     Object newValue = null;
 | |
| 
 | |
|     try
 | |
|       {
 | |
|         value = expr.getValue();
 | |
|       }
 | |
|     catch (Exception e)
 | |
|       {
 | |
|         getExceptionListener().exceptionThrown(e);
 | |
|         return;
 | |
|       }
 | |
| 
 | |
| 
 | |
|     newValue = get(value);
 | |
| 
 | |
|     if (newValue == null)
 | |
|       {
 | |
|         Object newTarget = get(target);
 | |
|         if (newTarget == null)
 | |
|           {
 | |
|             writeObject(target);
 | |
|             newTarget = get(target);
 | |
| 
 | |
|             // May happen if exception was thrown.
 | |
|             if (newTarget == null)
 | |
|               {
 | |
|                 return;
 | |
|               }
 | |
|           }
 | |
| 
 | |
|         Object[] args = expr.getArguments();
 | |
|         Object[] newArgs = new Object[args.length];
 | |
| 
 | |
|         for (int i = 0; i < args.length; i++)
 | |
|           {
 | |
|             newArgs[i] = get(args[i]);
 | |
|             if (newArgs[i] == null || isImmutableType(args[i].getClass()))
 | |
|               {
 | |
|                 writeObject(args[i]);
 | |
|                 newArgs[i] = get(args[i]);
 | |
|               }
 | |
|           }
 | |
| 
 | |
|         Expression newExpr = new Expression(newTarget, expr.getMethodName(),
 | |
|                                             newArgs);
 | |
| 
 | |
|         // Fakes the result of Class.forName(<primitiveType>) to make it possible
 | |
|         // to hand such a type to the encoding process.
 | |
|         if (value instanceof Class && ((Class) value).isPrimitive())
 | |
|           newExpr.setValue(value);
 | |
| 
 | |
|         // Instantiates the new object.
 | |
|         try
 | |
|           {
 | |
|             newValue = newExpr.getValue();
 | |
| 
 | |
|             putCandidate(value, newValue);
 | |
|           }
 | |
|         catch (Exception e)
 | |
|           {
 | |
|             getExceptionListener().exceptionThrown(e);
 | |
| 
 | |
|             // In Statement.writeExpression we had no possibility to flags
 | |
|             // an erroneous state to the ScanEngine without behaving different
 | |
|             // to the JDK.
 | |
|             scanEngine.revoke();
 | |
| 
 | |
|             return;
 | |
|           }
 | |
| 
 | |
|         writeObject(value);
 | |
| 
 | |
|       }
 | |
|     else if(value.getClass() == String.class || value.getClass() == Class.class)
 | |
|       {
 | |
|         writeObject(value);
 | |
|       }
 | |
| 
 | |
|     scanEngine.end();
 | |
|   }
 | |
| 
 | |
|   public void writeStatement(Statement stmt)
 | |
|   {
 | |
|     // In case of questions have a at the implementation note in
 | |
|     // writeExpression.
 | |
| 
 | |
|     scanEngine.writeStatement(stmt);
 | |
| 
 | |
|     //  Silently ignore out of bounds calls.
 | |
|     if (accessCounter <= 0)
 | |
|       return;
 | |
| 
 | |
|     Object target = stmt.getTarget();
 | |
| 
 | |
|     Object newTarget = get(target);
 | |
|     if (newTarget == null)
 | |
|       {
 | |
|         writeObject(target);
 | |
|         newTarget = get(target);
 | |
|       }
 | |
| 
 | |
|     Object[] args = stmt.getArguments();
 | |
|     Object[] newArgs = new Object[args.length];
 | |
| 
 | |
|     for (int i = 0; i < args.length; i++)
 | |
|       {
 | |
|         // Here is the difference to the original writeStatement
 | |
|         // method in Encoder. In case that the object is known or
 | |
|         // not an immutable we put it directly into the ScanEngine
 | |
|         // which will then generate an object reference for it.
 | |
|         newArgs[i] = get(args[i]);
 | |
|         if (newArgs[i] == null || isImmutableType(args[i].getClass()))
 | |
|           {
 | |
|             writeObject(args[i]);
 | |
|             newArgs[i] = get(args[i]);
 | |
|           }
 | |
|         else
 | |
|           scanEngine.writeObject(args[i]);
 | |
|       }
 | |
| 
 | |
|     Statement newStmt = new Statement(newTarget, stmt.getMethodName(), newArgs);
 | |
| 
 | |
|     try
 | |
|       {
 | |
|         newStmt.execute();
 | |
|       }
 | |
|     catch (Exception e)
 | |
|       {
 | |
|         getExceptionListener().exceptionThrown(e);
 | |
| 
 | |
|         // In Statement.writeStatement we had no possibility to flags
 | |
|         // an erroneous state to the ScanEngine without behaving different
 | |
|         // to the JDK.
 | |
|         scanEngine.revoke();
 | |
|         return;
 | |
|       }
 | |
| 
 | |
|     scanEngine.end();
 | |
|   }
 | |
| 
 | |
|   public void writeObject(Object o)
 | |
|   {
 | |
|     accessCounter++;
 | |
| 
 | |
|     scanEngine.writeObject(o);
 | |
| 
 | |
|     if (get(o) == null)
 | |
|       super.writeObject(o);
 | |
| 
 | |
|     accessCounter--;
 | |
|   }
 | |
| 
 | |
|   public void setOwner(Object o)
 | |
|   {
 | |
|     owner = o;
 | |
|   }
 | |
| 
 | |
|   public Object getOwner()
 | |
|   {
 | |
|     return owner;
 | |
|   }
 | |
| 
 | |
| }
 |