001: package org.kohsuke.rngom.parse.compact;
002:
003: import java.io.IOException;
004: import java.io.InputStream;
005: import java.io.InputStreamReader;
006: import java.io.PushbackInputStream;
007: import java.io.Reader;
008: import java.net.URL;
009:
010: import org.kohsuke.rngom.ast.builder.BuildException;
011: import org.kohsuke.rngom.ast.builder.IncludedGrammar;
012: import org.kohsuke.rngom.ast.builder.SchemaBuilder;
013: import org.kohsuke.rngom.ast.builder.Scope;
014: import org.kohsuke.rngom.ast.om.ParsedPattern;
015: import org.kohsuke.rngom.parse.IllegalSchemaException;
016: import org.kohsuke.rngom.parse.Parseable;
017: import org.kohsuke.rngom.xml.util.EncodingMap;
018: import org.xml.sax.ErrorHandler;
019: import org.xml.sax.InputSource;
020:
021: /**
022: * RELAX NG schema in the compact syntax.
023: */
024: public class CompactParseable implements Parseable {
025: private final InputSource in;
026: private final ErrorHandler eh;
027:
028: public CompactParseable(InputSource in, ErrorHandler eh) {
029: this .in = in;
030: this .eh = eh;
031: }
032:
033: public ParsedPattern parse(SchemaBuilder sb) throws BuildException,
034: IllegalSchemaException {
035: ParsedPattern p = new CompactSyntax(this , makeReader(in), in
036: .getSystemId(), sb, eh, "").parse(null);
037: return sb.expandPattern(p);
038: }
039:
040: public ParsedPattern parseInclude(String uri, SchemaBuilder sb,
041: IncludedGrammar g, String inheritedNs)
042: throws BuildException, IllegalSchemaException {
043: InputSource tem = new InputSource(uri);
044: tem.setEncoding(in.getEncoding());
045: return new CompactSyntax(this , makeReader(tem), uri, sb, eh,
046: inheritedNs).parseInclude(g);
047: }
048:
049: public ParsedPattern parseExternal(String uri, SchemaBuilder sb,
050: Scope scope, String inheritedNs) throws BuildException,
051: IllegalSchemaException {
052: InputSource tem = new InputSource(uri);
053: tem.setEncoding(in.getEncoding());
054: return new CompactSyntax(this , makeReader(tem), uri, sb, eh,
055: inheritedNs).parse(scope);
056: }
057:
058: private static final String UTF8 = EncodingMap.getJavaName("UTF-8");
059: private static final String UTF16 = EncodingMap
060: .getJavaName("UTF-16");
061:
062: private static Reader makeReader(InputSource is)
063: throws BuildException {
064: try {
065: Reader r = is.getCharacterStream();
066: if (r == null) {
067: InputStream in = is.getByteStream();
068: if (in == null) {
069: String systemId = is.getSystemId();
070: in = new URL(systemId).openStream();
071: }
072: String encoding = is.getEncoding();
073: if (encoding == null) {
074: PushbackInputStream pb = new PushbackInputStream(
075: in, 2);
076: encoding = detectEncoding(pb);
077: in = pb;
078: }
079: r = new InputStreamReader(in, encoding);
080: }
081: return r;
082: } catch (IOException e) {
083: throw new BuildException(e);
084: }
085: }
086:
087: static private String detectEncoding(PushbackInputStream in)
088: throws IOException {
089: String encoding = UTF8;
090: int b1 = in.read();
091: if (b1 != -1) {
092: int b2 = in.read();
093: if (b2 != -1) {
094: in.unread(b2);
095: if ((b1 == 0xFF && b2 == 0xFE)
096: || (b1 == 0xFE && b2 == 0xFF))
097: encoding = UTF16;
098: }
099: in.unread(b1);
100: }
101: return encoding;
102: }
103: }
|