001 /*
002 * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025 package java.beans;
026
027 import com.sun.beans.ObjectHandler;
028
029 import java.io.InputStream;
030 import java.io.IOException;
031
032 import java.lang.ref.Reference;
033 import java.lang.ref.WeakReference;
034
035 import org.xml.sax.SAXException;
036
037 import javax.xml.parsers.SAXParserFactory;
038 import javax.xml.parsers.ParserConfigurationException;
039 import javax.xml.parsers.SAXParser;
040
041 /**
042 * The <code>XMLDecoder</code> class is used to read XML documents
043 * created using the <code>XMLEncoder</code> and is used just like
044 * the <code>ObjectInputStream</code>. For example, one can use
045 * the following fragment to read the first object defined
046 * in an XML document written by the <code>XMLEncoder</code>
047 * class:
048 * <pre>
049 * XMLDecoder d = new XMLDecoder(
050 * new BufferedInputStream(
051 * new FileInputStream("Test.xml")));
052 * Object result = d.readObject();
053 * d.close();
054 * </pre>
055 *
056 *<p>
057 * For more information you might also want to check out
058 * <a
059 href="http://java.sun.com/products/jfc/tsc/articles/persistence3">Long Term Persistence of JavaBeans Components: XML Schema</a>,
060 * an article in <em>The Swing Connection.</em>
061 * @see XMLEncoder
062 * @see java.io.ObjectInputStream
063 *
064 * @since 1.4
065 *
066 * @version 1.38 05/05/07
067 * @author Philip Milne
068 */
069 public class XMLDecoder {
070 private InputStream in;
071 private Object owner;
072 private ExceptionListener exceptionListener;
073 private ObjectHandler handler;
074 private Reference clref;
075
076 /**
077 * Creates a new input stream for reading archives
078 * created by the <code>XMLEncoder</code> class.
079 *
080 * @param in The underlying stream.
081 *
082 * @see XMLEncoder#XMLEncoder(java.io.OutputStream)
083 */
084 public XMLDecoder(InputStream in) {
085 this (in, null);
086 }
087
088 /**
089 * Creates a new input stream for reading archives
090 * created by the <code>XMLEncoder</code> class.
091 *
092 * @param in The underlying stream.
093 * @param owner The owner of this stream.
094 *
095 */
096 public XMLDecoder(InputStream in, Object owner) {
097 this (in, owner, null);
098 }
099
100 /**
101 * Creates a new input stream for reading archives
102 * created by the <code>XMLEncoder</code> class.
103 *
104 * @param in the underlying stream.
105 * @param owner the owner of this stream.
106 * @param exceptionListener the exception handler for the stream;
107 * if <code>null</code> the default exception listener will be used.
108 */
109 public XMLDecoder(InputStream in, Object owner,
110 ExceptionListener exceptionListener) {
111 this (in, owner, exceptionListener, null);
112 }
113
114 /**
115 * Creates a new input stream for reading archives
116 * created by the <code>XMLEncoder</code> class.
117 *
118 * @param in the underlying stream. <code>null</code> may be passed without
119 * error, though the resulting XMLDecoder will be useless
120 * @param owner the owner of this stream. <code>null</code> is a legal
121 * value
122 * @param exceptionListener the exception handler for the stream, or
123 * <code>null</code> to use the default
124 * @param cl the class loader used for instantiating objects.
125 * <code>null</code> indicates that the default class loader should
126 * be used
127 * @since 1.5
128 */
129 public XMLDecoder(InputStream in, Object owner,
130 ExceptionListener exceptionListener, ClassLoader cl) {
131 this .in = in;
132 setOwner(owner);
133 setExceptionListener(exceptionListener);
134 setClassLoader(cl);
135 }
136
137 /**
138 * Set the class loader used to instantiate objects for this stream.
139 *
140 * @param cl a classloader to use; if null then the default class loader
141 * will be used
142 */
143 private void setClassLoader(ClassLoader cl) {
144 if (cl != null) {
145 this .clref = new WeakReference(cl);
146 }
147 }
148
149 /**
150 * Return the class loader used to instantiate objects. If the class loader
151 * has not been explicitly set then null is returned.
152 *
153 * @return the class loader used to instantiate objects
154 */
155 private ClassLoader getClassLoader() {
156 if (clref != null) {
157 return (ClassLoader) clref.get();
158 }
159 return null;
160 }
161
162 /**
163 * This method closes the input stream associated
164 * with this stream.
165 */
166 public void close() {
167 if (in != null) {
168 getHandler();
169 try {
170 in.close();
171 } catch (IOException e) {
172 getExceptionListener().exceptionThrown(e);
173 }
174 }
175 }
176
177 /**
178 * Sets the exception handler for this stream to <code>exceptionListener</code>.
179 * The exception handler is notified when this stream catches recoverable
180 * exceptions.
181 *
182 * @param exceptionListener The exception handler for this stream;
183 * if <code>null</code> the default exception listener will be used.
184 *
185 * @see #getExceptionListener
186 */
187 public void setExceptionListener(ExceptionListener exceptionListener) {
188 this .exceptionListener = exceptionListener;
189 }
190
191 /**
192 * Gets the exception handler for this stream.
193 *
194 * @return The exception handler for this stream.
195 * Will return the default exception listener if this has not explicitly been set.
196 *
197 * @see #setExceptionListener
198 */
199 public ExceptionListener getExceptionListener() {
200 return (exceptionListener != null) ? exceptionListener
201 : Statement.defaultExceptionListener;
202 }
203
204 /**
205 * Reads the next object from the underlying input stream.
206 *
207 * @return the next object read
208 *
209 * @throws ArrayIndexOutOfBoundsException if the stream contains no objects
210 * (or no more objects)
211 *
212 * @see XMLEncoder#writeObject
213 */
214 public Object readObject() {
215 if (in == null) {
216 return null;
217 }
218 return getHandler().dequeueResult();
219 }
220
221 /**
222 * Sets the owner of this decoder to <code>owner</code>.
223 *
224 * @param owner The owner of this decoder.
225 *
226 * @see #getOwner
227 */
228 public void setOwner(Object owner) {
229 this .owner = owner;
230 }
231
232 /**
233 * Gets the owner of this decoder.
234 *
235 * @return The owner of this decoder.
236 *
237 * @see #setOwner
238 */
239 public Object getOwner() {
240 return owner;
241 }
242
243 /**
244 * Returns the object handler for input stream.
245 * The object handler is created if necessary.
246 *
247 * @return the object handler
248 */
249 private ObjectHandler getHandler() {
250 if (handler == null) {
251 SAXParserFactory factory = SAXParserFactory.newInstance();
252 try {
253 SAXParser parser = factory.newSAXParser();
254 handler = new ObjectHandler(this , getClassLoader());
255 parser.parse(in, handler);
256 } catch (ParserConfigurationException e) {
257 getExceptionListener().exceptionThrown(e);
258 } catch (SAXException se) {
259 Exception e = se.getException();
260 if (e == null) {
261 e = se;
262 }
263 getExceptionListener().exceptionThrown(e);
264 } catch (IOException ioe) {
265 getExceptionListener().exceptionThrown(ioe);
266 }
267 }
268 return handler;
269 }
270 }
|