1/* 2 * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25/* 26 * Copyright (C) 2004-2011 27 * 28 * Permission is hereby granted, free of charge, to any person obtaining a copy 29 * of this software and associated documentation files (the "Software"), to deal 30 * in the Software without restriction, including without limitation the rights 31 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 32 * copies of the Software, and to permit persons to whom the Software is 33 * furnished to do so, subject to the following conditions: 34 * 35 * The above copyright notice and this permission notice shall be included in 36 * all copies or substantial portions of the Software. 37 * 38 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 39 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 40 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 41 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 42 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 43 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 44 * THE SOFTWARE. 45 */ 46package com.sun.xml.internal.rngom.parse.compact; 47 48import java.io.IOException; 49import java.io.InputStream; 50import java.io.InputStreamReader; 51import java.io.PushbackInputStream; 52import java.io.Reader; 53import java.net.URL; 54 55import com.sun.xml.internal.rngom.ast.builder.BuildException; 56import com.sun.xml.internal.rngom.ast.builder.IncludedGrammar; 57import com.sun.xml.internal.rngom.ast.builder.SchemaBuilder; 58import com.sun.xml.internal.rngom.ast.builder.Scope; 59import com.sun.xml.internal.rngom.ast.om.ParsedPattern; 60import com.sun.xml.internal.rngom.parse.IllegalSchemaException; 61import com.sun.xml.internal.rngom.parse.Parseable; 62import com.sun.xml.internal.rngom.xml.util.EncodingMap; 63import org.xml.sax.ErrorHandler; 64import org.xml.sax.InputSource; 65 66/** 67 * RELAX NG schema in the compact syntax. 68 */ 69public class CompactParseable implements Parseable { 70 private final InputSource in; 71 private final ErrorHandler eh; 72 73 public CompactParseable(InputSource in, ErrorHandler eh) { 74 this.in = in; 75 this.eh = eh; 76 } 77 78 public ParsedPattern parse(SchemaBuilder sb) throws BuildException, IllegalSchemaException { 79 ParsedPattern p = new CompactSyntax(this, makeReader(in), in.getSystemId(), sb, eh, "").parse(null); 80 return sb.expandPattern(p); 81 } 82 83 public ParsedPattern parseInclude(String uri, SchemaBuilder sb, IncludedGrammar g, String inheritedNs) 84 throws BuildException, IllegalSchemaException { 85 InputSource tem = new InputSource(uri); 86 tem.setEncoding(in.getEncoding()); 87 return new CompactSyntax(this, makeReader(tem), uri, sb, eh, inheritedNs).parseInclude(g); 88 } 89 90 public ParsedPattern parseExternal(String uri, SchemaBuilder sb, Scope scope, String inheritedNs) 91 throws BuildException, IllegalSchemaException { 92 InputSource tem = new InputSource(uri); 93 tem.setEncoding(in.getEncoding()); 94 return new CompactSyntax(this, makeReader(tem), uri, sb, eh, inheritedNs).parse(scope); 95 } 96 97 private static final String UTF8 = EncodingMap.getJavaName("UTF-8"); 98 private static final String UTF16 = EncodingMap.getJavaName("UTF-16"); 99 100 private static Reader makeReader(InputSource is) throws BuildException { 101 try { 102 Reader r = is.getCharacterStream(); 103 if (r == null) { 104 InputStream in = is.getByteStream(); 105 if (in == null) { 106 String systemId = is.getSystemId(); 107 in = new URL(systemId).openStream(); 108 } 109 String encoding = is.getEncoding(); 110 if (encoding == null) { 111 PushbackInputStream pb = new PushbackInputStream(in, 2); 112 encoding = detectEncoding(pb); 113 in = pb; 114 } 115 r = new InputStreamReader(in, encoding); 116 } 117 return r; 118 } 119 catch (IOException e) { 120 throw new BuildException(e); 121 } 122 } 123 124 static private String detectEncoding(PushbackInputStream in) throws IOException { 125 String encoding = UTF8; 126 int b1 = in.read(); 127 if (b1 != -1) { 128 int b2 = in.read(); 129 if (b2 != -1) { 130 in.unread(b2); 131 if ((b1 == 0xFF && b2 == 0xFE) || (b1 == 0xFE && b2 == 0xFF)) 132 encoding = UTF16; 133 } 134 in.unread(b1); 135 } 136 return encoding; 137 } 138} 139