/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: EObjectOutputStream.java * Written by: Dmitry Nadezhin, Sun Microsystems. * * Copyright (c) 2003 Sun Microsystems and Static Free Software * * Electric(tm) 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 3 of the License, or * (at your option) any later version. * * Electric(tm) 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 Electric(tm); see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, Mass 02111-1307, USA. */ package com.sun.electric.database; import com.sun.electric.database.hierarchy.Cell; import com.sun.electric.database.hierarchy.EDatabase; import com.sun.electric.database.hierarchy.Nodable; import com.sun.electric.database.hierarchy.View; import com.sun.electric.database.id.IdManager; import com.sun.electric.database.network.Netlist; import com.sun.electric.database.network.Network; import com.sun.electric.database.topology.NodeInst; import com.sun.electric.database.variable.ElectricObject; import com.sun.electric.database.variable.MutableTextDescriptor; import com.sun.electric.database.variable.TextDescriptor; import com.sun.electric.database.variable.Variable; import com.sun.electric.tool.Tool; import java.awt.Component; import java.io.IOException; import java.io.InvalidObjectException; import java.io.NotSerializableException; import java.io.ObjectOutputStream; import java.io.ObjectStreamException; import java.io.OutputStream; import java.io.Serializable; import java.util.Iterator; /** * ObjectOutputStream which repalaces Electric objects by serializable key objects. * On reading key objects are resolved to Electric objects again. */ public class EObjectOutputStream extends ObjectOutputStream { private final EDatabase database; public EObjectOutputStream(OutputStream out, EDatabase database) throws IOException { super(out); enableReplaceObject(true); this.database = database; } public EDatabase getDatabase() { return database; } public IdManager getIdManager() { return database.getIdManager(); } /** * This method will allow trusted subclasses of ObjectOutputStream to * substitute one object for another during serialization. Replacing * objects is disabled until enableReplaceObject is called. The * enableReplaceObject method checks that the stream requesting to do * replacement can be trusted. The first occurrence of each object written * into the serialization stream is passed to replaceObject. Subsequent * references to the object are replaced by the object returned by the * original call to replaceObject. To ensure that the private state of * objects is not unintentionally exposed, only trusted streams may use * replaceObject. * * <p>The ObjectOutputStream.writeObject method takes a parameter of type * Object (as opposed to type Serializable) to allow for cases where * non-serializable objects are replaced by serializable ones. * * <p>When a subclass is replacing objects it must insure that either a * complementary substitution must be made during deserialization or that * the substituted object is compatible with every field where the * reference will be stored. Objects whose type is not a subclass of the * type of the field or array element abort the serialization by raising an * exception and the object is not be stored. * * <p>This method is called only once when each object is first * encountered. All subsequent references to the object will be redirected * to the new object. This method should return the object to be * substituted or the original object. * * <p>Null can be returned as the object to be substituted, but may cause * NullReferenceException in classes that contain references to the * original object since they may be expecting an object instead of * null. * * @param obj the object to be replaced * @return the alternate object that replaced the specified one * @throws IOException Any exception thrown by the underlying * OutputStream. */ protected Object replaceObject(Object obj) throws IOException { if (obj instanceof ElectricObject && ((ElectricObject) obj).getDatabase() != database) { throw new NotSerializableException("other database"); } if (obj instanceof View) { return new EView((View) obj); } if (obj instanceof Tool) { return new ETool((Tool) obj); } if (obj instanceof Variable.Key) { return new EVariableKey((Variable.Key) obj); } if (obj instanceof TextDescriptor) { return new ETextDescriptor((TextDescriptor) obj); } if (obj instanceof Network) { return new ENetwork((Network) obj, database); } if (obj instanceof Nodable && !(obj instanceof NodeInst)) { return new ENodable((Nodable) obj, database); } if (obj instanceof Component) { throw new Error("Found AWT class " + obj.getClass() + " in serialized object"); } return obj; } private static class EView implements Serializable { String abbreviation; private EView(View view) { abbreviation = view.getAbbreviation(); } private Object readResolve() throws ObjectStreamException { View view = View.findView(abbreviation); if (view == null) { throw new InvalidObjectException("View"); } return view; } } private static class ETool implements Serializable { String toolName; private ETool(Tool tool) { toolName = tool.getName(); } private Object readResolve() throws ObjectStreamException { Tool tool = Tool.findTool(toolName); if (tool == null) { throw new InvalidObjectException("Tool"); } return tool; } } private static class EVariableKey implements Serializable { String varName; private EVariableKey(Variable.Key varKey) { varName = varKey.toString(); } private Object readResolve() throws ObjectStreamException { return Variable.newKey(varName); } } private static class ETextDescriptor implements Serializable { /** the text descriptor is displayable */ private boolean display; /** the bits of the text descriptor */ private long bits; /** the color of the text descriptor */ private int colorIndex; /** the name of font of text descriptor */ private String fontName; private ETextDescriptor(TextDescriptor td) { display = td.isDisplay(); bits = td.lowLevelGet(); colorIndex = td.getColorIndex(); int face = td.getFace(); if (face != 0) { fontName = TextDescriptor.ActiveFont.findActiveFont(face).toString(); } } private Object readResolve() throws ObjectStreamException { MutableTextDescriptor mtd = new MutableTextDescriptor(bits, colorIndex, display); int face = 0; if (fontName != null) { face = TextDescriptor.ActiveFont.findActiveFont(fontName).getIndex(); } mtd.setFace(face); TextDescriptor td = TextDescriptor.newTextDescriptor(mtd); if (td == null) { throw new InvalidObjectException("TextDescriptor"); } return td; } } private static class ENetwork implements Serializable { Cell cell; int netIndex; Netlist.ShortResistors shortResistors; private ENetwork(Network net, EDatabase database) throws NotSerializableException { cell = net.getParent(); if (cell.getDatabase() != database || !cell.isLinked()) { throw new NotSerializableException(cell + " not linked"); } netIndex = net.getNetIndex(); shortResistors = net.getNetlist().getShortResistors(); if (cell.getNetlist(shortResistors).getNetwork(netIndex) != net) { throw new NotSerializableException(net + " not linked"); } } private Object readResolve() throws ObjectStreamException { Netlist netlist = cell.getNetlist(shortResistors); Network net = netlist.getNetwork(netIndex); // It is necessary to check that it is the same Netlist if (net == null) { throw new InvalidObjectException("Network"); } return net; } } private static class ENodable implements Serializable { Cell cell; String nodableName; private ENodable(Nodable no, EDatabase database) throws NotSerializableException { cell = no.getParent(); if (cell.getDatabase() != database || !cell.isLinked()) { throw new NotSerializableException(cell + " not linked"); } nodableName = no.getName(); } private Object readResolve() throws ObjectStreamException { Netlist netlist = cell.getNetlist(); Nodable nodable = null; for (Iterator<Nodable> it = netlist.getNodables(); it.hasNext();) { Nodable no = it.next(); if (no.getName().equals(nodableName)) { nodable = no; break; } } if (nodable == null) { throw new InvalidObjectException("Nodable"); } return nodable; } } }