1 package com.ctc.wstx.io;
2
3 import java.io.IOException;
4 import java.net.URL;
5
6 import javax.xml.stream.XMLStreamException;
7
8 /**
9 * Abstract base class that implements shared functionality that all current
10 * {@link WstxInputSource} implementations Woodstox includes need.
11 */
12 public abstract class BaseInputSource
13 extends WstxInputSource
14 {
15 final String mPublicId;
16
17 /**
18 * URL for/from systemId points to original source of input, if known; null if not
19 * known (source constructed with just a stream or reader). Used for
20 * resolving references from the input that's read from this source.
21 * Can be overridden by reader; done if P_BASE_URL is changed on
22 * stream reader for which this input source is the currently
23 * active input source.
24 */
25 SystemId mSystemId;
26
27 /**
28 * Input buffer this input source uses, if any.
29 */
30 protected char[] mBuffer;
31
32 /**
33 * Length of the buffer, if buffer used
34 */
35 protected int mInputLast;
36
37 /*
38 ////////////////////////////////////////////////////////////////
39 // Saved location information; active information is directly
40 // handled by Reader, and then saved to input source when switching
41 // to a nested input source.
42 ////////////////////////////////////////////////////////////////
43 */
44
45 /**
46 * Number of characters read from the current input source prior to
47 * the current buffer
48 */
49 long mSavedInputProcessed = 0;
50
51 int mSavedInputRow = 1;
52 int mSavedInputRowStart = 0;
53
54 int mSavedInputPtr = 0;
55
56 /*
57 ////////////////////////////////////////////////////////////////
58 // Some simple lazy-loading/reusing support...
59 ////////////////////////////////////////////////////////////////
60 */
61
62 transient WstxInputLocation mParentLocation = null;
63
64 /*
65 ////////////////////////////////////////////////////////////////
66 // Life-cycle
67 ////////////////////////////////////////////////////////////////
68 */
69 protected BaseInputSource(WstxInputSource parent, String fromEntity,
70 String publicId, SystemId systemId)
71 {
72 super(parent, fromEntity);
73 mSystemId = systemId;
74 mPublicId = publicId;
75 }
76
77 @Override
78 public void overrideSource(URL src)
79 {
80 //19-May-2014, tatu: I assume this should also override observed systemId...
81 mSystemId = SystemId.construct(src);
82 }
83
84 @Override
85 public abstract boolean fromInternalEntity();
86
87 @Override
88 public URL getSource() throws IOException {
89 return (mSystemId == null) ? null : mSystemId.asURL();
90 }
91
92 @Override
93 public String getPublicId() {
94 return mPublicId;
95 }
96
97 @Override
98 public String getSystemId() {
99 return (mSystemId == null) ? null : mSystemId.toString();
100 }
101
102 @Override
103 protected abstract void doInitInputLocation(WstxInputData reader);
104
105 @Override
106 public abstract int readInto(WstxInputData reader)
107 throws IOException, XMLStreamException;
108
109 @Override
110 public abstract boolean readMore(WstxInputData reader, int minAmount)
111 throws IOException, XMLStreamException;
112
113 @Override
114 public void saveContext(WstxInputData reader)
115 {
116 // First actual input data
117 mSavedInputPtr = reader.mInputPtr;
118
119 // then location
120 mSavedInputProcessed = reader.mCurrInputProcessed;
121 mSavedInputRow = reader.mCurrInputRow;
122 mSavedInputRowStart = reader.mCurrInputRowStart;
123 }
124
125 @Override
126 public void restoreContext(WstxInputData reader)
127 {
128 reader.mInputBuffer = mBuffer;
129 reader.mInputEnd = mInputLast;
130 reader.mInputPtr = mSavedInputPtr;
131
132 // then location
133 reader.mCurrInputProcessed = mSavedInputProcessed;
134 reader.mCurrInputRow = mSavedInputRow;
135 reader.mCurrInputRowStart = mSavedInputRowStart;
136 }
137
138 @Override
139 public abstract void close() throws IOException;
140
141 /*
142 //////////////////////////////////////////////////////////
143 // Methods for accessing location information
144 //////////////////////////////////////////////////////////
145 */
146
147 /**
148 * This method only gets called by the 'child' input source (for example,
149 * contents of an expanded entity), to get the enclosing context location.
150 */
151 @Override
152 protected final WstxInputLocation getLocation()
153 {
154 // Note: columns are 1-based, need to add 1.
155 return getLocation(mSavedInputProcessed + mSavedInputPtr - 1L,
156 mSavedInputRow,
157 mSavedInputPtr - mSavedInputRowStart + 1);
158 }
159
160 @Override
161 public final WstxInputLocation getLocation(long total, int row, int col)
162 {
163 WstxInputLocation pl;
164
165 if (mParent == null) {
166 pl = null;
167 } else {
168 /* 13-Apr-2005, TSa: We can actually reuse parent location, since
169 * it can not change during lifetime of this child context...
170 */
171 pl = mParentLocation;
172 if (pl == null) {
173 mParentLocation = pl = mParent.getLocation();
174 }
175 pl = mParent.getLocation();
176 }
177 /* !!! 15-Apr-2005, TSa: This will cause overflow for total count,
178 * but since StAX 1.0 API doesn't have any way to deal with that,
179 * let's just let that be...
180 */
181 return new WstxInputLocation(pl, getPublicId(), getSystemId(),
182 total, row, col);
183 }
184 }
185