1 /*
   2  * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 
   5 /*
   6  * Copyright 2005 The Apache Software Foundation.
   7  *
   8  * Licensed under the Apache License, Version 2.0 (the "License");
   9  * you may not use this file except in compliance with the License.
  10  * You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 
  21 package com.sun.xml.internal.stream;
  22 
  23 import java.io.InputStream;
  24 import java.io.Reader;
  25 import java.io.IOException;
  26 
  27 import com.sun.xml.internal.stream.util.BufferAllocator;
  28 import com.sun.xml.internal.stream.util.ThreadLocalBufferAllocator;
  29 import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
  30 
  31 /**
  32  * Entity information.
  33  *
  34  * @author
  35  */
  36 public abstract class Entity {
  37 
  38     //
  39     // Data
  40     //
  41 
  42     //xxx why dont we declare the type of entities, like assign integer for external/ internal etc..
  43 
  44     /** Entity name. */
  45     public String name;
  46 
  47     // whether this entity's declaration was found in the internal
  48     // or external subset
  49     public boolean inExternalSubset;
  50 
  51     //
  52     // Constructors
  53     //
  54 
  55     /** Default constructor. */
  56     public Entity() {
  57         clear();
  58     } // <init>()
  59 
  60     /** Constructs an entity. */
  61     public Entity(String name, boolean inExternalSubset) {
  62         this.name = name;
  63         this.inExternalSubset = inExternalSubset;
  64     } // <init>(String)
  65 
  66     //
  67     // Public methods
  68     //
  69 
  70     /** Returns true if this entity was declared in the external subset. */
  71     public boolean isEntityDeclInExternalSubset() {
  72         return inExternalSubset;
  73     }
  74 
  75     /** Returns true if this is an external entity. */
  76     public abstract boolean isExternal();
  77 
  78     /** Returns true if this is an unparsed entity. */
  79     public abstract boolean isUnparsed();
  80 
  81     /** Clears the entity. */
  82     public void clear() {
  83         name = null;
  84         inExternalSubset = false;
  85     } // clear()
  86 
  87     /** Sets the values of the entity. */
  88     public void setValues(Entity entity) {
  89         name = entity.name;
  90         inExternalSubset = entity.inExternalSubset;
  91     } // setValues(Entity)
  92 
  93 
  94     /**
  95      * Internal entity.
  96      *
  97      * @author nb131165
  98      */
  99     public static class InternalEntity
 100             extends Entity {
 101 
 102         //
 103         // Data
 104         //
 105 
 106         /** Text value of entity. */
 107         public String text;
 108 
 109         //
 110         // Constructors
 111         //
 112 
 113         /** Default constructor. */
 114         public InternalEntity() {
 115             clear();
 116         } // <init>()
 117 
 118         /** Constructs an internal entity. */
 119         public InternalEntity(String name, String text, boolean inExternalSubset) {
 120             super(name,inExternalSubset);
 121             this.text = text;
 122         } // <init>(String,String)
 123 
 124         //
 125         // Entity methods
 126         //
 127 
 128         /** Returns true if this is an external entity. */
 129         public final boolean isExternal() {
 130             return false;
 131         } // isExternal():boolean
 132 
 133         /** Returns true if this is an unparsed entity. */
 134         public final boolean isUnparsed() {
 135             return false;
 136         } // isUnparsed():boolean
 137 
 138         /** Clears the entity. */
 139         public void clear() {
 140             super.clear();
 141             text = null;
 142         } // clear()
 143 
 144         /** Sets the values of the entity. */
 145         public void setValues(Entity entity) {
 146             super.setValues(entity);
 147             text = null;
 148         } // setValues(Entity)
 149 
 150         /** Sets the values of the entity. */
 151         public void setValues(InternalEntity entity) {
 152             super.setValues(entity);
 153             text = entity.text;
 154         } // setValues(InternalEntity)
 155 
 156     } // class InternalEntity
 157 
 158     /**
 159      * External entity.
 160      *
 161      * @author nb131165
 162      */
 163     public  static class ExternalEntity
 164             extends Entity {
 165 
 166         //
 167         // Data
 168         //
 169 
 170         /** container for all relevant entity location information. */
 171         public XMLResourceIdentifier entityLocation;
 172 
 173         /** Notation name for unparsed entity. */
 174         public String notation;
 175 
 176         //
 177         // Constructors
 178         //
 179 
 180         /** Default constructor. */
 181         public ExternalEntity() {
 182             clear();
 183         } // <init>()
 184 
 185         /** Constructs an internal entity. */
 186         public ExternalEntity(String name, XMLResourceIdentifier entityLocation,
 187                 String notation, boolean inExternalSubset) {
 188             super(name,inExternalSubset);
 189             this.entityLocation = entityLocation;
 190             this.notation = notation;
 191         } // <init>(String,XMLResourceIdentifier, String)
 192 
 193         //
 194         // Entity methods
 195         //
 196 
 197         /** Returns true if this is an external entity. */
 198         public final boolean isExternal() {
 199             return true;
 200         } // isExternal():boolean
 201 
 202         /** Returns true if this is an unparsed entity. */
 203         public final boolean isUnparsed() {
 204             return notation != null;
 205         } // isUnparsed():boolean
 206 
 207         /** Clears the entity. */
 208         public void clear() {
 209             super.clear();
 210             entityLocation = null;
 211             notation = null;
 212         } // clear()
 213 
 214         /** Sets the values of the entity. */
 215         public void setValues(Entity entity) {
 216             super.setValues(entity);
 217             entityLocation = null;
 218             notation = null;
 219         } // setValues(Entity)
 220 
 221         /** Sets the values of the entity. */
 222         public void setValues(ExternalEntity entity) {
 223             super.setValues(entity);
 224             entityLocation = entity.entityLocation;
 225             notation = entity.notation;
 226         } // setValues(ExternalEntity)
 227 
 228     } // class ExternalEntity
 229 
 230     /**
 231      * Entity state.
 232      *
 233      * @author nb131165
 234      */
 235     public static class ScannedEntity
 236             extends Entity {
 237 
 238 
 239         /** Default buffer size (4096). */
 240         public static final int DEFAULT_BUFFER_SIZE = 8192;
 241         //4096;
 242 
 243         /**
 244          * Buffer size. We get this value from a property. The default size
 245          * is used if the input buffer size property is not specified.
 246          * REVISIT: do we need a property for internal entity buffer size?
 247          */
 248         public int fBufferSize = DEFAULT_BUFFER_SIZE;
 249 
 250         /** Default buffer size before we've finished with the XMLDecl:  */
 251         public static final int DEFAULT_XMLDECL_BUFFER_SIZE = 28;
 252 
 253         /** Default internal entity buffer size (1024). */
 254         public static final int DEFAULT_INTERNAL_BUFFER_SIZE = 1024;
 255 
 256         //
 257         // Data
 258         //
 259 
 260         // i/o
 261 
 262         /** XXX let these field remain public right now, though we have defined methods for them.
 263          * Input stream. */
 264         public InputStream stream;
 265 
 266         /** XXX let these field remain public right now, though we have defined methods for them.
 267          * Reader. */
 268         public Reader reader;
 269 
 270         // locator information
 271 
 272         /** entity location information */
 273         public XMLResourceIdentifier entityLocation;
 274 
 275         // encoding
 276 
 277         /** Auto-detected encoding. */
 278         public String encoding;
 279 
 280         // status
 281 
 282         /** True if in a literal.  */
 283         public boolean literal;
 284 
 285         // whether this is an external or internal scanned entity
 286         public boolean isExternal;
 287 
 288         //each 'external' parsed entity may have xml/text declaration containing version information
 289         public String  version ;
 290 
 291         // buffer
 292 
 293         /** Character buffer. */
 294         public char[] ch = null;
 295 
 296         /** Position in character buffer at any point of time. */
 297         public int position;
 298 
 299         /** Count of characters present in buffer. */
 300         public int count;
 301 
 302         /** Line number. */
 303         public int lineNumber = 1;
 304 
 305         /** Column number. */
 306         public int columnNumber = 1;
 307 
 308         /** Encoding has been set externally for eg: using DOMInput*/
 309         boolean declaredEncoding = false;
 310 
 311         // status
 312 
 313         /**
 314          * Encoding has been set externally, for example
 315          * using a SAX InputSource or a DOM LSInput.
 316          */
 317         boolean externallySpecifiedEncoding = false;
 318 
 319         /** XML version. **/
 320         public String xmlVersion = "1.0";
 321 
 322         /** This variable is used to calculate the current position in the XML stream.
 323          * Note that fCurrentEntity.position maintains the position relative to
 324          * the buffer.
 325          *  At any point of time absolute position in the XML stream can be calculated
 326          *  as fTotalCountTillLastLoad + fCurrentEntity.position
 327          */
 328         public int fTotalCountTillLastLoad ;
 329 
 330         /** This variable stores the number of characters read during the load()
 331          * operation. It is used to calculate fTotalCountTillLastLoad
 332          */
 333         public  int fLastCount ;
 334 
 335         /** Base character offset for computing absolute character offset. */
 336         public int baseCharOffset;
 337 
 338         /** Start position in character buffer. */
 339         public int startPosition;
 340 
 341         // to allow the reader/inputStream to behave efficiently:
 342         public boolean mayReadChunks;
 343 
 344         // to know that prolog is read
 345         public boolean xmlDeclChunkRead = false;
 346 
 347         /** returns the name of the current encoding
 348          *  @return current encoding name
 349          */
 350         public String getEncodingName(){
 351             return encoding ;
 352         }
 353 
 354         /**each 'external' parsed entity may have xml/text declaration containing version information
 355          * @return String version of the enity, for an internal entity version would be null
 356          */
 357         public String getEntityVersion(){
 358             return version ;
 359         }
 360 
 361         /** each 'external' parsed entity may have xml/text declaration containing version information
 362          * @param String version of the external parsed entity
 363          */
 364         public void setEntityVersion(String version){
 365             this.version = version ;
 366         }
 367 
 368         /**  Returns the java.io.Reader associated with this entity.Readers are used
 369          * to read from the file. Readers wrap any particular  InputStream that was
 370          * used to open the entity.
 371          * @return java.io.Reader Reader associated with this entity
 372          */
 373         public Reader getEntityReader(){
 374             return reader;
 375         }
 376 
 377 
 378         /** if entity was opened using the stream, return the associated inputstream
 379          * with this entity
 380          *@return java.io.InputStream InputStream associated with this entity
 381          */
 382         public InputStream getEntityInputStream(){
 383             return stream;
 384         }
 385 
 386         //
 387         // Constructors
 388         //
 389 
 390         /** Constructs a scanned entity. */
 391         public ScannedEntity(String name,
 392                 XMLResourceIdentifier entityLocation,
 393                 InputStream stream, Reader reader,
 394                 String encoding, boolean literal, boolean mayReadChunks, boolean isExternal) {
 395             this.name = name ;
 396             this.entityLocation = entityLocation;
 397             this.stream = stream;
 398             this.reader = reader;
 399             this.encoding = encoding;
 400             this.literal = literal;
 401             this.mayReadChunks = mayReadChunks;
 402             this.isExternal = isExternal;
 403             final int size = isExternal ? fBufferSize : DEFAULT_INTERNAL_BUFFER_SIZE;
 404             BufferAllocator ba = ThreadLocalBufferAllocator.getBufferAllocator();
 405             ch = ba.getCharBuffer(size);
 406             if (ch == null) {
 407                 this.ch = new char[size];
 408             }
 409         } // <init>(StringXMLResourceIdentifier,InputStream,Reader,String,boolean, boolean)
 410 
 411         /**
 412          * Release any resources associated with this entity.
 413          */
 414         public void close() throws IOException {
 415             BufferAllocator ba = ThreadLocalBufferAllocator.getBufferAllocator();
 416             ba.returnCharBuffer(ch);
 417             ch = null;
 418             reader.close();
 419         }
 420 
 421         //
 422         // Entity methods
 423         //
 424 
 425         /** Returns whether the encoding of this entity was externally specified. **/
 426         public boolean isEncodingExternallySpecified() {
 427             return externallySpecifiedEncoding;
 428         }
 429 
 430         /** Sets whether the encoding of this entity was externally specified. **/
 431         public void setEncodingExternallySpecified(boolean value) {
 432             externallySpecifiedEncoding = value;
 433         }
 434 
 435         public boolean isDeclaredEncoding() {
 436             return declaredEncoding;
 437         }
 438 
 439         public void setDeclaredEncoding(boolean value) {
 440             declaredEncoding = value;
 441         }
 442 
 443         /** Returns true if this is an external entity. */
 444         public final boolean isExternal() {
 445             return isExternal;
 446         } // isExternal():boolean
 447 
 448         /** Returns true if this is an unparsed entity. */
 449         public final boolean isUnparsed() {
 450             return false;
 451         } // isUnparsed():boolean
 452 
 453         //
 454         // Object methods
 455         //
 456 
 457         /** Returns a string representation of this object. */
 458         public String toString() {
 459 
 460             StringBuffer str = new StringBuffer();
 461             str.append("name=\""+name+'"');
 462             str.append(",ch="+ new String(ch));
 463             str.append(",position="+position);
 464             str.append(",count="+count);
 465             return str.toString();
 466 
 467         } // toString():String
 468 
 469     } // class ScannedEntity
 470 
 471 } // class Entity