1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.struts2.jasper.compiler;
18
19 import org.apache.struts2.jasper.JspCompilationContext;
20
21 import java.net.MalformedURLException;
22 import java.net.URL;
23 import java.util.Stack;
24
25 /***
26 * Mark represents a point in the JSP input.
27 *
28 * @author Anil K. Vijendran
29 */
30 final class Mark {
31
32
33 int cursor, line, col;
34
35
36 String baseDir;
37
38
39 char[] stream = null;
40
41
42 private int fileId;
43
44
45 private String fileName;
46
47
48
49
50
51 private Stack includeStack = null;
52
53
54 private String encoding = null;
55
56
57 private JspReader reader;
58
59 private JspCompilationContext ctxt;
60
61 /***
62 * Constructor
63 *
64 * @param reader JspReader this mark belongs to
65 * @param inStream current stream for this mark
66 * @param fileId id of requested jsp file
67 * @param name JSP file name
68 * @param inBaseDir base directory of requested jsp file
69 * @param inEncoding encoding of current file
70 */
71 Mark(JspReader reader, char[] inStream, int fileId, String name,
72 String inBaseDir, String inEncoding) {
73
74 this.reader = reader;
75 this.ctxt = reader.getJspCompilationContext();
76 this.stream = inStream;
77 this.cursor = 0;
78 this.line = 1;
79 this.col = 1;
80 this.fileId = fileId;
81 this.fileName = name;
82 this.baseDir = inBaseDir;
83 this.encoding = inEncoding;
84 this.includeStack = new Stack();
85 }
86
87
88 /***
89 * Constructor
90 */
91 Mark(Mark other) {
92
93 this.reader = other.reader;
94 this.ctxt = other.reader.getJspCompilationContext();
95 this.stream = other.stream;
96 this.fileId = other.fileId;
97 this.fileName = other.fileName;
98 this.cursor = other.cursor;
99 this.line = other.line;
100 this.col = other.col;
101 this.baseDir = other.baseDir;
102 this.encoding = other.encoding;
103
104
105 includeStack = new Stack();
106 for (int i = 0; i < other.includeStack.size(); i++) {
107 includeStack.addElement(other.includeStack.elementAt(i));
108 }
109 }
110
111
112 /***
113 * Constructor
114 */
115 Mark(JspCompilationContext ctxt, String filename, int line, int col) {
116
117 this.reader = null;
118 this.ctxt = ctxt;
119 this.stream = null;
120 this.cursor = 0;
121 this.line = line;
122 this.col = col;
123 this.fileId = -1;
124 this.fileName = filename;
125 this.baseDir = "le-basedir";
126 this.encoding = "le-endocing";
127 this.includeStack = null;
128 }
129
130
131 /***
132 * Sets this mark's state to a new stream.
133 * It will store the current stream in it's includeStack.
134 *
135 * @param inStream new stream for mark
136 * @param inFileId id of new file from which stream comes from
137 * @param inBaseDir directory of file
138 * @param inEncoding encoding of new file
139 */
140 public void pushStream(char[] inStream, int inFileId, String name,
141 String inBaseDir, String inEncoding) {
142
143 includeStack.push(new IncludeState(cursor, line, col, fileId,
144 fileName, baseDir,
145 encoding, stream));
146
147
148 cursor = 0;
149 line = 1;
150 col = 1;
151 fileId = inFileId;
152 fileName = name;
153 baseDir = inBaseDir;
154 encoding = inEncoding;
155 stream = inStream;
156 }
157
158
159 /***
160 * Restores this mark's state to a previously stored stream.
161 *
162 * @return The previous Mark instance when the stream was pushed, or null
163 * if there is no previous stream
164 */
165 public Mark popStream() {
166
167 if (includeStack.size() <= 0) {
168 return null;
169 }
170
171
172 IncludeState state = (IncludeState) includeStack.pop();
173
174
175 cursor = state.cursor;
176 line = state.line;
177 col = state.col;
178 fileId = state.fileId;
179 fileName = state.fileName;
180 baseDir = state.baseDir;
181 stream = state.stream;
182 return this;
183 }
184
185
186
187
188 public int getLineNumber() {
189 return line;
190 }
191
192 public int getColumnNumber() {
193 return col;
194 }
195
196 public String getSystemId() {
197 return getFile();
198 }
199
200 public String getPublicId() {
201 return null;
202 }
203
204 public String toString() {
205 return getFile() + "(" + line + "," + col + ")";
206 }
207
208 public String getFile() {
209 return this.fileName;
210 }
211
212 /***
213 * Gets the URL of the resource with which this Mark is associated
214 *
215 * @return URL of the resource with which this Mark is associated
216 * @throws MalformedURLException if the resource pathname is incorrect
217 */
218 public URL getURL() throws MalformedURLException {
219 return ctxt.getResource(getFile());
220 }
221
222 public String toShortString() {
223 return "(" + line + "," + col + ")";
224 }
225
226 public boolean equals(Object other) {
227 if (other instanceof Mark) {
228 Mark m = (Mark) other;
229 return this.reader == m.reader && this.fileId == m.fileId
230 && this.cursor == m.cursor && this.line == m.line
231 && this.col == m.col;
232 }
233 return false;
234 }
235
236 /***
237 * @return true if this Mark is greather than the <code>other</code>
238 * Mark, false otherwise.
239 */
240 public boolean isGreater(Mark other) {
241
242 boolean greater = false;
243
244 if (this.line > other.line) {
245 greater = true;
246 } else if (this.line == other.line && this.col > other.col) {
247 greater = true;
248 }
249
250 return greater;
251 }
252
253 /***
254 * Keep track of parser before parsing an included file.
255 * This class keeps track of the parser before we switch to parsing an
256 * included file. In other words, it's the parser's continuation to be
257 * reinstalled after the included file parsing is done.
258 */
259 class IncludeState {
260 int cursor, line, col;
261 int fileId;
262 String fileName;
263 String baseDir;
264 String encoding;
265 char[] stream = null;
266
267 IncludeState(int inCursor, int inLine, int inCol, int inFileId,
268 String name, String inBaseDir, String inEncoding,
269 char[] inStream) {
270 cursor = inCursor;
271 line = inLine;
272 col = inCol;
273 fileId = inFileId;
274 fileName = name;
275 baseDir = inBaseDir;
276 encoding = inEncoding;
277 stream = inStream;
278 }
279 }
280
281 }
282