001    /*
002      Copyright (C) 2001-2002 Renaud Pawlak, Lionel Seinturier.
003    
004      This program is free software; you can redistribute it and/or modify
005      it under the terms of the GNU Lesser General Public License as
006      published by the Free Software Foundation; either version 2 of the
007      License, or (at your option) any later version.
008    
009      This program is distributed in the hope that it will be useful, but
010      WITHOUT ANY WARRANTY; without even the implied warranty of
011      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
012      Lesser General Public License for more details.
013    
014      You should have received a copy of the GNU Lesser General Public
015      License along with this program; if not, write to the Free Software
016      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
017      USA */
018    
019    package org.objectweb.jac.core;
020    
021    import java.io.IOException;
022    import java.io.ObjectOutputStream;
023    import java.io.OutputStream;
024    import org.apache.log4j.Logger;
025    import org.objectweb.jac.core.rtti.MethodItem;
026    
027    /**
028     * <code>JacObjectOutputStream</code> is used to write JAC objects
029     * into an output stream during a serialization process.
030     *
031     * <p>This stream is used when serializing a JAC object into an array
032     * of bytes when calling <code>JacObject.serialize()</code>. All the
033     * objects that are not JAC objects are serialized with the default
034     * procedure. When a JAC object is encountered, a
035     * <code>whenSerialized</code> event is thrown on the current AC
036     * manager so that the aspect components can parametrize the
037     * serialization process.
038     *
039     * <p>A symetric process for deserialization is implemented by
040     * <code>JacObjectInputStream</code>.
041     *
042     * @see ACManager#whenSerialized(Wrappee,SerializedJacObject)
043     * @see JacObjectInputStream
044     *
045     * @author Renaud Pawlak
046     * @author Lionel Seinturier
047     */
048     
049    public class JacObjectOutputStream extends ObjectOutputStream {
050        static Logger logger = Logger.getLogger("serialization");
051    
052        /**
053        * Creates a JacObjectInputStream. 
054        *
055        * @param os the output stream where the bytes are written. 
056        */
057        public JacObjectOutputStream(OutputStream os) throws IOException {   
058            super(os);
059            enableReplaceObject(true);
060        }
061    
062        /**
063        * This method is upcalled by the Java serialization process each
064        * time a new object to serialize is encountered.
065        *
066        * <p>If a JAC object is encountered (instance of
067        * <code>Wrappee</code>), the aspect component manager is upcalled
068        * to parametrize the serialization.
069        *
070        * @param obj the encountered JAC object 
071        * @return the final serialized JAC object
072        *
073        * @see SerializedJacObject
074        * @see ACManager#whenSerialized(Wrappee,SerializedJacObject) */
075       
076        protected Object replaceObject(Object obj) throws IOException {
077            if (obj instanceof Wrappee) {
078                SerializedJacObject sjo = 
079                    new SerializedJacObject(obj.getClass().getName());
080                if (obj.getClass().getName().startsWith("org.objectweb.jac.lib.java.util")) {
081                    sjo.disableForwarding();
082                }
083                ((ACManager)ACManager.get()).whenSerialized((Wrappee)obj,sjo);
084                return sjo;
085            } else if (obj instanceof AspectComponent) {
086                SerializedJacObject sjo = 
087                    new SerializedJacObject(obj.getClass().getName());
088                return sjo;
089            } else if (obj instanceof MethodItem) {
090                return new SerializedMethodItem((MethodItem)obj);
091            } else if (obj.getClass().getName().equals("org.objectweb.jac.aspects.gui.DisplayContext")) {
092                // <HACK reason="Don't crash when trying to serialize displayContext">
093                logger.debug("replaceObject "+obj+" -> null");
094                return null;
095                // </HACK>
096            }
097            return obj;
098        }
099    
100    }