KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > xml > xmlc > misc > SSIReader


1 /*
2  * Enhydra Java Application Server Project
3  *
4  * The contents of this file are subject to the Enhydra Public License
5  * Version 1.1 (the "License"); you may not use this file except in
6  * compliance with the License. You may obtain a copy of the License on
7  * the Enhydra web site ( http://www.enhydra.org/ ).
8  *
9  * Software distributed under the License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
11  * the License for the specific terms governing rights and limitations
12  * under the License.
13  *
14  * The Initial Developer of the Enhydra Application Server is Lutris
15  * Technologies, Inc. The Enhydra Application Server and portions created
16  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
17  * All Rights Reserved.
18  *
19  * Contributor(s):
20  *
21  * $Id: SSIReader.java,v 1.4 2005/01/26 08:29:24 jkjome Exp $
22  */

23
24 package org.enhydra.xml.xmlc.misc;
25
26 import java.io.File JavaDoc;
27 import java.io.IOException JavaDoc;
28 import java.io.Reader JavaDoc;
29
30 import org.xml.sax.InputSource JavaDoc;
31
32 //FIXME: Keeping the LineNumberMap maybe inefficient. We might want to
33
//drop this in favor of just tracking the current line number (and maybe
34
//one back. Need to see how the parser behaves. Plus, with this class
35
//reading everything into memory, we could just lines when actually
36
//needed. Also, all of the line number map stuff isn't abstracted.
37

38 /**
39  * A reader that implements Server-Side Includes (SSI). This used the syntax
40  * defined by Apache mod_include, however it only implements the `include'
41  * directive.
42  * <p>
43  * This input stream automatically closes on reaching EOF.
44  */

45 public final class SSIReader extends Reader JavaDoc {
46     /**
47      * Listener for SSI open/close events.
48      */

49     public class Listener {
50         /** Classed when a new include file is opened. */
51
52     }
53
54     /**
55      * Include command and arguments.
56      */

57     private static final String JavaDoc INCLUDE = "include";
58     private static final String JavaDoc INCLUDE_FILE = "file";
59     private static final String JavaDoc INCLUDE_VIRTUAL = "virtual";
60     private static final String JavaDoc[] INCLUDE_VALID_ARGS = {
61         INCLUDE_FILE,
62         INCLUDE_VIRTUAL
63     };
64
65     // dbr_20020128.3_start
66
/**
67      * The ssi-base set
68      */

69     private String JavaDoc ssiBase = null;
70     // dbr_20020128.3_end
71

72     /**
73      * Input stream we are reading from. Also the top of the stack,
74      * if others have been included.
75      */

76     private SSIParsedStream fIn;
77
78     /**
79      * Map of stream position to source file and line number.
80      */

81     private LineNumberRecorder fLineNumbers;
82
83     /**
84      * Construct a new reader for the specified file.
85      */

86     //public SSIReader(InputSource source) throws IOException {
87
public SSIReader(InputSource JavaDoc source, String JavaDoc ssiBase) throws IOException JavaDoc {
88         fLineNumbers = new LineNumberRecorder();
89         fIn = new SSIParsedStream(source, fLineNumbers);
90         // dbr_20020128.2_start
91
this.ssiBase = ssiBase;
92         // dbr_20020128.2_end
93
}
94
95     /**
96      * Get the system id of the currently opened file.
97      */

98     public String JavaDoc getSystemId() {
99         if (fIn != null) {
100             return fIn.getSystemId();
101         } else {
102             return null;
103         }
104     }
105
106     /**
107      * Open a SSI include file, pushing on the stack.
108      */

109     private void openSSIInclude(String JavaDoc includingFileName,
110                                 String JavaDoc fileName) throws IOException JavaDoc {
111         // Get path to file, relative to source directory
112
// dbr_20020129.1_start
113
if (ssiBase != null) {
114             // The following maybe written better, but I think SSI-syntax needs the leading slash,
115
// so it should work.
116
if (fileName.startsWith("/")) {
117                 fileName = ssiBase + File.separator + fileName;
118             }
119         }
120         // dbr_20020129.1_end
121
File JavaDoc includingFile = new File JavaDoc(includingFileName);
122         File JavaDoc inclFile = new File JavaDoc(fileName);
123         File JavaDoc baseDir = null;
124         if (!inclFile.isAbsolute()) {
125             baseDir = includingFile.getParentFile();
126         }
127         File JavaDoc inclPath = new File JavaDoc(baseDir, fileName);
128         
129         // Open new reader, push current one
130
fIn = new SSIParsedStream(new InputSource JavaDoc(inclPath.getPath()),
131                                   fLineNumbers, fIn);
132     }
133
134     /**
135      * Process a SSI include directive.
136      */

137     private void processSSIInclude(SSIDirective directive) throws IOException JavaDoc {
138         // Validate
139
directive.validateArgumentNames(INCLUDE_VALID_ARGS);
140         if (directive.getNumArgs() < 1) {
141             throw new IOException JavaDoc("SSI include must have at least one argument");
142         }
143         
144         // Open includes. Done in reverse, as they are pushed on a stack
145
for (int idx = directive.getNumArgs()-1; idx >= 0; idx--) {
146             openSSIInclude(directive.getSystemId(), directive.getArgValue(idx));
147         }
148     }
149
150     /**
151      * Process the SSI directive that is next in the stream.
152      */

153     private void processSSIDirective() throws IOException JavaDoc {
154         SSIDirective directive = fIn.parseSSIDirective();
155         if (directive.getCmd().equals(INCLUDE)) {
156             processSSIInclude(directive);
157         } else {
158             throw new IOException JavaDoc("Invalid or unsupport SSI command \""
159                                   + directive.getCmd() + "\": "
160                                   + fIn.getSystemId());
161         }
162     }
163
164     /**
165      * Read a character.
166      * @return The character, -1 if no more characters are available.
167      */

168     public int read() throws IOException JavaDoc {
169         int ch;
170         do {
171             ch = fIn.read();
172             if (ch == SSIParsedStream.AT_EOF) {
173                 fIn = fIn.pop();
174                 if (fIn == null) {
175                     return -1; // EOF
176
}
177             } else if (ch == SSIParsedStream.AT_SSI) {
178                 processSSIDirective();
179             }
180         } while (ch < 0);
181         return ch;
182     }
183
184     /**
185      * Read characters into a portion of an array. To simplify the
186      * handling of an SSI directive, a directive is only processed if
187      * it's at the start of the buffer. SSIs in the middle of the
188      * read result in a partial read.
189      *
190      * @see java.io.FilterReader#read
191      * @exception IOException If an I/O error occurs
192      */

193     public int read(char cbuf[], int off, int len) throws IOException JavaDoc {
194         int readLen;
195         do {
196             readLen = fIn.read(cbuf, off, len);
197             if (readLen == SSIParsedStream.AT_EOF) {
198                 fIn = fIn.pop();
199                 if (fIn == null) {
200                     return -1; // EOF
201
}
202             } else if (readLen == SSIParsedStream.AT_SSI) {
203                 // Directive might change fIn to a new file.
204
processSSIDirective();
205             }
206         } while (readLen < 0);
207         return readLen;
208     }
209
210     /**
211      * Close the stream.
212      *
213      * @exception IOException If an I/O error occurs
214      */

215     public void close() throws IOException JavaDoc {
216         fIn = null;
217     }
218
219     /**
220      * Get the line number map.
221      */

222     public final LineNumberMap getLineNumberMap() {
223         return fLineNumbers;
224     }
225
226     /**
227      * Construct an InputSource containing an SSI reader.
228      */

229     // dbr_20020128.4_start
230
//public static InputSource create(InputSource inputSource) throws IOException {
231
public static InputSource JavaDoc create(InputSource JavaDoc inputSource, String JavaDoc ssiBase) throws IOException JavaDoc {
232         InputSource JavaDoc ssiSource
233             //= new InputSource(new SSIReader(inputSource));
234
= new InputSource JavaDoc(new SSIReader(inputSource, ssiBase));
235     // dbr_20020128.4_end
236
ssiSource.setPublicId(inputSource.getPublicId());
237         ssiSource.setSystemId(inputSource.getSystemId());
238         ssiSource.setEncoding(inputSource.getEncoding());
239         return ssiSource;
240     }
241 }
242
Popular Tags