Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/beans/XMLDecoder.java
38829 views
/*1* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package java.beans;2526import com.sun.beans.decoder.DocumentHandler;2728import java.io.Closeable;29import java.io.InputStream;30import java.io.IOException;31import java.security.AccessControlContext;32import java.security.AccessController;33import java.security.PrivilegedAction;3435import org.xml.sax.InputSource;36import org.xml.sax.helpers.DefaultHandler;3738/**39* The <code>XMLDecoder</code> class is used to read XML documents40* created using the <code>XMLEncoder</code> and is used just like41* the <code>ObjectInputStream</code>. For example, one can use42* the following fragment to read the first object defined43* in an XML document written by the <code>XMLEncoder</code>44* class:45* <pre>46* XMLDecoder d = new XMLDecoder(47* new BufferedInputStream(48* new FileInputStream("Test.xml")));49* Object result = d.readObject();50* d.close();51* </pre>52*53*<p>54* For more information you might also want to check out55* <a56href="http://java.sun.com/products/jfc/tsc/articles/persistence3">Long Term Persistence of JavaBeans Components: XML Schema</a>,57* an article in <em>The Swing Connection.</em>58* @see XMLEncoder59* @see java.io.ObjectInputStream60*61* @since 1.462*63* @author Philip Milne64*/65public class XMLDecoder implements AutoCloseable {66private final AccessControlContext acc = AccessController.getContext();67private final DocumentHandler handler = new DocumentHandler();68private final InputSource input;69private Object owner;70private Object[] array;71private int index;7273/**74* Creates a new input stream for reading archives75* created by the <code>XMLEncoder</code> class.76*77* @param in The underlying stream.78*79* @see XMLEncoder#XMLEncoder(java.io.OutputStream)80*/81public XMLDecoder(InputStream in) {82this(in, null);83}8485/**86* Creates a new input stream for reading archives87* created by the <code>XMLEncoder</code> class.88*89* @param in The underlying stream.90* @param owner The owner of this stream.91*92*/93public XMLDecoder(InputStream in, Object owner) {94this(in, owner, null);95}9697/**98* Creates a new input stream for reading archives99* created by the <code>XMLEncoder</code> class.100*101* @param in the underlying stream.102* @param owner the owner of this stream.103* @param exceptionListener the exception handler for the stream;104* if <code>null</code> the default exception listener will be used.105*/106public XMLDecoder(InputStream in, Object owner, ExceptionListener exceptionListener) {107this(in, owner, exceptionListener, null);108}109110/**111* Creates a new input stream for reading archives112* created by the <code>XMLEncoder</code> class.113*114* @param in the underlying stream. <code>null</code> may be passed without115* error, though the resulting XMLDecoder will be useless116* @param owner the owner of this stream. <code>null</code> is a legal117* value118* @param exceptionListener the exception handler for the stream, or119* <code>null</code> to use the default120* @param cl the class loader used for instantiating objects.121* <code>null</code> indicates that the default class loader should122* be used123* @since 1.5124*/125public XMLDecoder(InputStream in, Object owner,126ExceptionListener exceptionListener, ClassLoader cl) {127this(new InputSource(in), owner, exceptionListener, cl);128}129130131/**132* Creates a new decoder to parse XML archives133* created by the {@code XMLEncoder} class.134* If the input source {@code is} is {@code null},135* no exception is thrown and no parsing is performed.136* This behavior is similar to behavior of other constructors137* that use {@code InputStream} as a parameter.138*139* @param is the input source to parse140*141* @since 1.7142*/143public XMLDecoder(InputSource is) {144this(is, null, null, null);145}146147/**148* Creates a new decoder to parse XML archives149* created by the {@code XMLEncoder} class.150*151* @param is the input source to parse152* @param owner the owner of this decoder153* @param el the exception handler for the parser,154* or {@code null} to use the default exception handler155* @param cl the class loader used for instantiating objects,156* or {@code null} to use the default class loader157*158* @since 1.7159*/160private XMLDecoder(InputSource is, Object owner, ExceptionListener el, ClassLoader cl) {161this.input = is;162this.owner = owner;163setExceptionListener(el);164this.handler.setClassLoader(cl);165this.handler.setOwner(this);166}167168/**169* This method closes the input stream associated170* with this stream.171*/172public void close() {173if (parsingComplete()) {174close(this.input.getCharacterStream());175close(this.input.getByteStream());176}177}178179private void close(Closeable in) {180if (in != null) {181try {182in.close();183}184catch (IOException e) {185getExceptionListener().exceptionThrown(e);186}187}188}189190private boolean parsingComplete() {191if (this.input == null) {192return false;193}194if (this.array == null) {195if ((this.acc == null) && (null != System.getSecurityManager())) {196throw new SecurityException("AccessControlContext is not set");197}198AccessController.doPrivileged(new PrivilegedAction<Void>() {199public Void run() {200XMLDecoder.this.handler.parse(XMLDecoder.this.input);201return null;202}203}, this.acc);204this.array = this.handler.getObjects();205}206return true;207}208209/**210* Sets the exception handler for this stream to <code>exceptionListener</code>.211* The exception handler is notified when this stream catches recoverable212* exceptions.213*214* @param exceptionListener The exception handler for this stream;215* if <code>null</code> the default exception listener will be used.216*217* @see #getExceptionListener218*/219public void setExceptionListener(ExceptionListener exceptionListener) {220if (exceptionListener == null) {221exceptionListener = Statement.defaultExceptionListener;222}223this.handler.setExceptionListener(exceptionListener);224}225226/**227* Gets the exception handler for this stream.228*229* @return The exception handler for this stream.230* Will return the default exception listener if this has not explicitly been set.231*232* @see #setExceptionListener233*/234public ExceptionListener getExceptionListener() {235return this.handler.getExceptionListener();236}237238/**239* Reads the next object from the underlying input stream.240*241* @return the next object read242*243* @throws ArrayIndexOutOfBoundsException if the stream contains no objects244* (or no more objects)245*246* @see XMLEncoder#writeObject247*/248public Object readObject() {249return (parsingComplete())250? this.array[this.index++]251: null;252}253254/**255* Sets the owner of this decoder to <code>owner</code>.256*257* @param owner The owner of this decoder.258*259* @see #getOwner260*/261public void setOwner(Object owner) {262this.owner = owner;263}264265/**266* Gets the owner of this decoder.267*268* @return The owner of this decoder.269*270* @see #setOwner271*/272public Object getOwner() {273return owner;274}275276/**277* Creates a new handler for SAX parser278* that can be used to parse embedded XML archives279* created by the {@code XMLEncoder} class.280*281* The {@code owner} should be used if parsed XML document contains282* the method call within context of the <java> element.283* The {@code null} value may cause illegal parsing in such case.284* The same problem may occur, if the {@code owner} class285* does not contain expected method to call. See details <a286* href="http://java.sun.com/products/jfc/tsc/articles/persistence3/">here</a>.287*288* @param owner the owner of the default handler289* that can be used as a value of <java> element290* @param el the exception handler for the parser,291* or {@code null} to use the default exception handler292* @param cl the class loader used for instantiating objects,293* or {@code null} to use the default class loader294* @return an instance of {@code DefaultHandler} for SAX parser295*296* @since 1.7297*/298public static DefaultHandler createHandler(Object owner, ExceptionListener el, ClassLoader cl) {299DocumentHandler handler = new DocumentHandler();300handler.setOwner(owner);301handler.setExceptionListener(el);302handler.setClassLoader(cl);303return handler;304}305}306307308