Overview Package Class Use Source Tree Index Deprecated About
GNU Classpath (0.95)
Frames | No Frames

Source for java.beans.XMLDecoder

 1:  /* java.beans.XMLDecoder --
 2:  Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
 3: 
 4: This file is part of GNU Classpath.
 5: 
 6: GNU Classpath is free software; you can redistribute it and/or modify
 7: it under the terms of the GNU General Public License as published by
 8: the Free Software Foundation; either version 2, or (at your option)
 9: any later version.
 10: 
 11: GNU Classpath is distributed in the hope that it will be useful, but
 12: WITHOUT ANY WARRANTY; without even the implied warranty of
 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 14: General Public License for more details.
 15: 
 16: You should have received a copy of the GNU General Public License
 17: along with GNU Classpath; see the file COPYING. If not, write to the
 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 19: 02110-1301 USA.
 20: 
 21: Linking this library statically or dynamically with other modules is
 22: making a combined work based on this library. Thus, the terms and
 23: conditions of the GNU General Public License cover the whole
 24: combination.
 25: 
 26: As a special exception, the copyright holders of this library give you
 27: permission to link this library with independent modules to produce an
 28: executable, regardless of the license terms of these independent
 29: modules, and to copy and distribute the resulting executable under
 30: terms of your choice, provided that you also meet, for each linked
 31: independent module, the terms and conditions of the license of that
 32: module. An independent module is a module which is not derived from
 33: or based on this library. If you modify this library, you may extend
 34: this exception to your version of the library, but you are not
 35: obligated to do so. If you do not wish to do so, delete this
 36: exception statement from your version. */
 37: 
 38: 
 39:  package java.beans;
 40: 
 41:  import gnu.java.beans.DefaultExceptionListener;
 42:  import gnu.java.beans.decoder.PersistenceParser;
 43: 
 44:  import java.io.IOException;
 45:  import java.io.InputStream;
 46:  import java.util.Iterator;
 47:  import java.util.NoSuchElementException;
 48: 
 49:  /**
 50:  * The XMLDecoder reads XML data that is structured according to
 51:  * <a href="http://java.sun.com/products/jfc/tsc/articles/persistence3/javabeans.dtd">this</a> DTD
 52:  * and creates objects according to the content. Usually such data is generated using the
 53:  * {@link XMLEncoder} class.
 54:  * <p>
 55:  * An example XML document might look like this:
 56:  * <code>
 57:  * &lt;java&gt;
 58:  * &lt;string&gt;Hello World&lt;/string&gt;
 59:  * &lt;int&gt;200&lt;/int&gt;
 60:  * &lt;/java&gt;
 61:  * </code>
 62:  * <p>To read the <code>String</code> and the <code>Integer</code> instance the following can be used (assume
 63:  * the XML data can be obtained from the InputStream):</p>
 64:  * <code>
 65:  * XMLDecoder decoder = new XMLDecoder(inputStreamContainingXMLData);
 66:  * String message = (String) decoder.readObject();
 67:  * Integer number = (Integer) decoder.readObject();
 68:  * </code>
 69:  * <p>Besides this basic functionality the <code>XMLDecoder</code> has some more features that might come
 70:  * handy in certain situations:</p>
 71:  * <p>An owner object can be set using the <code>setOwner</code> method which can then be accessed when
 72:  * decoding. This feature is only useful if the XML data is aware of the owner object. Such data may
 73:  * look like this (assume that the owner object is a JFrame instance):</p>
 74:  * <code> 
 75:  * &lt;java&gt;
 76:  * &lt;void method="getOwner"&gt;
 77:  * &lt;void method="setVisible"&gt;
 78:  * &lt;boolean&gt;true&lt;boolean&gt;
 79:  * &lt;/void&gt;
 80:  * &lt;/void&gt;
 81:  * &lt;/java&gt;
 82:  * </code>
 83:  * This accesses the <code>JFrame</code> and makes it visible using the <code>setVisible</code> method.
 84:  * <p>Please note that changing the owner <b>after</b> the having read the first object has no effect,
 85:  * because all object have been decoded then.</p>
 86:  * <p>If the <code>XMLDecoder</code> is created with no {@link ExceptionListener} instance a default one
 87:  * is used that prints an error message to <code>System.err</code> whenever a recoverable exception
 88:  * is thrown. Recovarable exceptions occur when the XML data cannot be interpreted correctly (e.g
 89:  * unknown classes or methods, invocation on null, ...). In general be very careful when the
 90:  * <code>XMLDecoder</code> provoked such exceptions because the resulting object(s) may be in an
 91:  * undesirable state.</p>
 92:  * <p>Note that changing the ExceptionListener instance after <code>readObject</code> has been called
 93:  * once has no effect because the decoding is completed then.</p>
 94:  * <p>At last one can provide a specific <code>ClassLoader</code> which is then used when <code>Class</code>
 95:  * objects are accessed. See {@link java.lang.Class#forName(String, boolean, ClassLoader)} for details
 96:  * on this.</p>
 97:  * <p>Note: If the <code>InputStream</code> instance given to any of the constructors is <code>null</code>
 98:  * the resulting <code>XMLDecoder</code> will be silently (without any exception) useless. Each call
 99:  * to <code>readObject</code> will return <code>null</code> and never throws an
 100:  * <code>ArrayIndexOutOfBoundsException</code>.</p>
 101:  * 
 102:  * @author Robert Schuster
 103:  * @since 1.4
 104:  * @status updated to 1.5
 105:  */
 106:  public class XMLDecoder
 107: {
 108:  private Object owner;
 109: 
 110:  private ExceptionListener exceptionListener;
 111: 
 112:  private InputStream inputStream;
 113: 
 114:  private boolean isStreamClosed;
 115: 
 116:  private ClassLoader classLoader;
 117: 
 118:  private Iterator iterator;
 119: 
 120:  /** Creates a XMLDecoder instance that parses the XML data of the given input stream.
 121:  * Using this constructor no special ClassLoader, a default ExceptionListener
 122:  * and no owner object is used.
 123:  * 
 124:  * @param in InputStream to read XML data from.
 125:  */
 126:  public XMLDecoder(InputStream in)
 127:  {
 128:  this(in, null);
 129:  }
 130: 
 131:  /** Creates a XMLDecoder instance that parses the XML data of the given input stream.
 132:  * Using this constructor no special ClassLoader and a default ExceptionListener
 133:  * is used.
 134:  * 
 135:  * @param in InputStream to read XML data from.
 136:  * @param owner Owner object which can be accessed and modified while parsing.
 137:  */
 138:  public XMLDecoder(InputStream in, Object owner)
 139:  {
 140:  this(in, owner, null);
 141:  }
 142: 
 143:  /** Creates a XMLDecoder instance that parses the XML data of the given input stream.
 144:  * If the ExceptionListener argument is null a default implementation is used.
 145:  * 
 146:  * @param in InputStream to read XML data from.
 147:  * @param owner Owner object which can be accessed and modified while parsing.
 148:  * @param exceptionListener ExceptionListener instance to which exception notifications are send.
 149:  */
 150:  public XMLDecoder(
 151:  InputStream in,
 152:  Object owner,
 153:  ExceptionListener exceptionListener)
 154:  {
 155:  this(
 156:  in,
 157:  owner,
 158:  exceptionListener,
 159:  Thread.currentThread().getContextClassLoader());
 160:  }
 161: 
 162:  /** Creates a XMLDecoder instance that parses the XML data of the given input stream.
 163:  * If the ExceptionListener argument is null a default implementation is used.
 164:  * 
 165:  * @param in InputStream to read XML data from.
 166:  * @param owner Owner object which can be accessed and modified while parsing.
 167:  * @param exceptionListener ExceptionListener instance to which exception notifications are send.
 168:  * @param cl ClassLoader instance that is used for calls to <code>Class.forName(String, boolean, ClassLoader)</code>
 169:  * @since 1.5
 170:  */
 171:  public XMLDecoder(
 172:  InputStream in,
 173:  Object owner,
 174:  ExceptionListener listener,
 175:  ClassLoader cl)
 176:  {
 177:  // initially here was a check for the validity of the InputStream argument but some
 178:  // great engineers decided that this API should silently discard this and behave rather
 179:  // odd: readObject will always return null ...
 180:  inputStream = in;
 181: 
 182:  setExceptionListener(listener);
 183: 
 184:  // validity of this object is checked in Class.forName() and therefore may be null
 185:  classLoader = cl;
 186: 
 187:  this.owner = owner;
 188:  }
 189: 
 190:  /** Closes the stream associated with this decoder. This should be done after having read all 
 191:  * decoded objects.
 192:  * <p>See the description of the {@link #readObject()} for the effect caused by <code>close</code>.</p> 
 193:  */
 194:  public void close()
 195:  {
 196:  if (isStreamClosed)
 197:  {
 198:  return;
 199:  }
 200: 
 201:  try
 202:  {
 203:  inputStream.close();
 204:  isStreamClosed = true;
 205:  }
 206:  catch (IOException e)
 207:  {
 208:  // bad style forced by original API design ... 
 209:  }
 210:  }
 211: 
 212:  /** Returns the ExceptionListener instance associated with this decoder.
 213:  * <p>See the description of {@link XMLDecoder} class for more information on the ExceptionListener.</p>
 214:  * 
 215:  * @return Current ExceptionListener of the decoder.
 216:  */
 217:  public ExceptionListener getExceptionListener()
 218:  {
 219:  return exceptionListener;
 220:  }
 221: 
 222:  /** Returns the owner object of the decoder. This method is usually called
 223:  * from within the parsed XML data.
 224:  * <p>See the description of {@link XMLDecoder} class for more information on the owner object.</p>
 225:  * 
 226:  * @return The owner object of this decoder.
 227:  */
 228:  public Object getOwner()
 229:  {
 230:  return owner;
 231:  }
 232: 
 233:  /** Returns the next available decoded object.
 234:  * <p>Note that the actual decoding takes place when the method is called for the first time.</p>
 235:  * <p>If the <code>close</code> method was already called a <code>NoSuchElementException</code>
 236:  * is thrown.</p>
 237:  * <p>If the InputStream instance used in the constructors was <code>null</code> this method
 238:  * will always return <code>null</code> itself.</p>
 239:  * 
 240:  * @return The next object in a sequence decoded from XML data.
 241:  * @throws ArrayIndexOutOfBoundsException When no more objects are available.
 242:  */
 243:  public Object readObject() throws ArrayIndexOutOfBoundsException
 244:  {
 245:  // note: the RI does it this way ...
 246:  if(inputStream == null) {
 247:  return null;
 248:  }
 249:  
 250:  // note: the original API documentation says nothing on what to do
 251:  // when the stream was closed before readObject is called but it actually
 252:  // throws a NoSuchElementException - this behaviour is imitated here
 253:  if (isStreamClosed)
 254:  {
 255:  throw new NoSuchElementException("Cannot read any objects - XMLDecoder was already closed.");
 256:  }
 257: 
 258:  // creates the PersistenceParser (doing the parsing and decoding) and returns its
 259:  // Iterator on first invocation
 260:  if (iterator == null)
 261:  {
 262:  iterator =
 263:  new PersistenceParser(
 264:  inputStream,
 265:  exceptionListener,
 266:  classLoader,
 267:  this)
 268:  .iterator();
 269:  }
 270: 
 271:  // note: done according to the official documentation
 272:  if (!iterator.hasNext())
 273:  {
 274:  throw new ArrayIndexOutOfBoundsException("No more objects available from this XMLDecoder.");
 275:  }
 276: 
 277:  // returns just the next object if there was no problem
 278:  return iterator.next();
 279:  }
 280: 
 281:  /** Sets the ExceptionListener instance to which notifications of exceptions are send
 282:  * while parsing the XML data.
 283:  * <p>See the description of {@link XMLDecoder} class for more information on the ExceptionListener.</p>
 284:  *
 285:  * @param listener
 286:  */
 287:  public void setExceptionListener(ExceptionListener listener)
 288:  {
 289:  // uses a default implementation when null 
 290:  if (listener == null)
 291:  {
 292:  listener = DefaultExceptionListener.INSTANCE;
 293:  }
 294:  exceptionListener = listener;
 295:  }
 296: 
 297:  /** Sets the owner object which can be accessed from the parsed XML data.
 298:  * <p>See the description of {@link XMLDecoder} class for more information on the owner object.</p>
 299:  * 
 300:  * @param newOwner
 301:  */
 302:  public void setOwner(Object newOwner)
 303:  {
 304:  owner = newOwner;
 305:  }
 306: 
 307: }
Overview Package Class Use Source Tree Index Deprecated About
GNU Classpath (0.95)

AltStyle によって変換されたページ (->オリジナル) /