1 23 24 package org.enhydra.xml.xmlc.misc; 25 26 import java.io.File ; 27 import java.io.IOException ; 28 import java.io.Reader ; 29 30 import org.xml.sax.InputSource ; 31 32 38 45 public final class SSIReader extends Reader { 46 49 public class Listener { 50 51 52 } 53 54 57 private static final String INCLUDE = "include"; 58 private static final String INCLUDE_FILE = "file"; 59 private static final String INCLUDE_VIRTUAL = "virtual"; 60 private static final String [] INCLUDE_VALID_ARGS = { 61 INCLUDE_FILE, 62 INCLUDE_VIRTUAL 63 }; 64 65 69 private String ssiBase = null; 70 72 76 private SSIParsedStream fIn; 77 78 81 private LineNumberRecorder fLineNumbers; 82 83 86 public SSIReader(InputSource source, String ssiBase) throws IOException { 88 fLineNumbers = new LineNumberRecorder(); 89 fIn = new SSIParsedStream(source, fLineNumbers); 90 this.ssiBase = ssiBase; 92 } 94 95 98 public String getSystemId() { 99 if (fIn != null) { 100 return fIn.getSystemId(); 101 } else { 102 return null; 103 } 104 } 105 106 109 private void openSSIInclude(String includingFileName, 110 String fileName) throws IOException { 111 if (ssiBase != null) { 114 if (fileName.startsWith("/")) { 117 fileName = ssiBase + File.separator + fileName; 118 } 119 } 120 File includingFile = new File (includingFileName); 122 File inclFile = new File (fileName); 123 File baseDir = null; 124 if (!inclFile.isAbsolute()) { 125 baseDir = includingFile.getParentFile(); 126 } 127 File inclPath = new File (baseDir, fileName); 128 129 fIn = new SSIParsedStream(new InputSource (inclPath.getPath()), 131 fLineNumbers, fIn); 132 } 133 134 137 private void processSSIInclude(SSIDirective directive) throws IOException { 138 directive.validateArgumentNames(INCLUDE_VALID_ARGS); 140 if (directive.getNumArgs() < 1) { 141 throw new IOException ("SSI include must have at least one argument"); 142 } 143 144 for (int idx = directive.getNumArgs()-1; idx >= 0; idx--) { 146 openSSIInclude(directive.getSystemId(), directive.getArgValue(idx)); 147 } 148 } 149 150 153 private void processSSIDirective() throws IOException { 154 SSIDirective directive = fIn.parseSSIDirective(); 155 if (directive.getCmd().equals(INCLUDE)) { 156 processSSIInclude(directive); 157 } else { 158 throw new IOException ("Invalid or unsupport SSI command \"" 159 + directive.getCmd() + "\": " 160 + fIn.getSystemId()); 161 } 162 } 163 164 168 public int read() throws IOException { 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; } 177 } else if (ch == SSIParsedStream.AT_SSI) { 178 processSSIDirective(); 179 } 180 } while (ch < 0); 181 return ch; 182 } 183 184 193 public int read(char cbuf[], int off, int len) throws IOException { 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; } 202 } else if (readLen == SSIParsedStream.AT_SSI) { 203 processSSIDirective(); 205 } 206 } while (readLen < 0); 207 return readLen; 208 } 209 210 215 public void close() throws IOException { 216 fIn = null; 217 } 218 219 222 public final LineNumberMap getLineNumberMap() { 223 return fLineNumbers; 224 } 225 226 229 public static InputSource create(InputSource inputSource, String ssiBase) throws IOException { 232 InputSource ssiSource 233 = new InputSource (new SSIReader(inputSource, ssiBase)); 235 ssiSource.setPublicId(inputSource.getPublicId()); 237 ssiSource.setSystemId(inputSource.getSystemId()); 238 ssiSource.setEncoding(inputSource.getEncoding()); 239 return ssiSource; 240 } 241 } 242 | Popular Tags |