blob: 1dfc45ff22900ef0c5da996ea5e027b48996ce17 [file] [log] [blame]
/* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.xmlbeans.impl.schema;
import org.apache.xmlbeans.*;
import org.apache.xmlbeans.impl.common.QNameHelper;
import org.apache.xmlbeans.impl.store.Locale;
import org.apache.xmlbeans.impl.validator.ValidatingXMLInputStream;
import org.apache.xmlbeans.impl.xpath.XPathFactory;
import org.apache.xmlbeans.xml.stream.XMLInputStream;
import org.apache.xmlbeans.xml.stream.XMLStreamException;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Node;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamReader;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
public abstract class SchemaTypeLoaderBase implements SchemaTypeLoader {
private static final String USER_AGENT = "XMLBeans/" + XmlBeans.getVersion() + " (" + XmlBeans.getTitle() + ")";
private static String doCompilePath(String pathExpr, XmlOptions options) {
return XPathFactory.compilePath(pathExpr, options);
}
private static String doCompileQuery(String queryExpr, XmlOptions options) {
return XPathFactory.compileQuery(queryExpr, options);
}
public SchemaType findType(QName name) {
SchemaType.Ref ref = findTypeRef(name);
if (ref == null) {
return null;
}
SchemaType result = ref.get();
assert (result != null);
return result;
}
public SchemaType findDocumentType(QName name) {
SchemaType.Ref ref = findDocumentTypeRef(name);
if (ref == null) {
return null;
}
SchemaType result = ref.get();
assert (result != null);
return result;
}
public SchemaType findAttributeType(QName name) {
SchemaType.Ref ref = findAttributeTypeRef(name);
if (ref == null) {
return null;
}
SchemaType result = ref.get();
assert (result != null);
return result;
}
public SchemaModelGroup findModelGroup(QName name) {
SchemaModelGroup.Ref ref = findModelGroupRef(name);
if (ref == null) {
return null;
}
SchemaModelGroup result = ref.get();
assert (result != null);
return result;
}
public SchemaAttributeGroup findAttributeGroup(QName name) {
SchemaAttributeGroup.Ref ref = findAttributeGroupRef(name);
if (ref == null) {
return null;
}
SchemaAttributeGroup result = ref.get();
assert (result != null);
return result;
}
public SchemaGlobalElement findElement(QName name) {
SchemaGlobalElement.Ref ref = findElementRef(name);
if (ref == null) {
return null;
}
SchemaGlobalElement result = ref.get();
assert (result != null);
return result;
}
public SchemaGlobalAttribute findAttribute(QName name) {
SchemaGlobalAttribute.Ref ref = findAttributeRef(name);
if (ref == null) {
return null;
}
SchemaGlobalAttribute result = ref.get();
assert (result != null);
return result;
}
//
//
//
public XmlObject newInstance(SchemaType type, XmlOptions options) {
XmlFactoryHook hook = XmlFactoryHook.ThreadContext.getHook();
if (hook != null) {
return hook.newInstance(this, type, options);
}
return Locale.newInstance(this, type, options);
}
public XmlObject parse(String xmlText, SchemaType type, XmlOptions options) throws XmlException {
XmlFactoryHook hook = XmlFactoryHook.ThreadContext.getHook();
if (hook != null) {
return hook.parse(this, xmlText, type, options);
}
return Locale.parseToXmlObject(this, xmlText, type, options);
}
/**
* @deprecated XMLInputStream was deprecated by XMLStreamReader from STaX - jsr173 API.
*/
public XmlObject parse(XMLInputStream xis, SchemaType type, XmlOptions options) throws XmlException, XMLStreamException {
XmlFactoryHook hook = XmlFactoryHook.ThreadContext.getHook();
if (hook != null) {
return hook.parse(this, xis, type, options);
}
return Locale.parseToXmlObject(this, xis, type, options);
}
public XmlObject parse(XMLStreamReader xsr, SchemaType type, XmlOptions options) throws XmlException {
XmlFactoryHook hook = XmlFactoryHook.ThreadContext.getHook();
if (hook != null) {
return hook.parse(this, xsr, type, options);
}
return Locale.parseToXmlObject(this, xsr, type, options);
}
public XmlObject parse(File file, SchemaType type, XmlOptions options) throws XmlException, IOException {
String fileName = file.toURI().normalize().toString();
if (options == null) {
options = new XmlOptions();
options.setDocumentSourceName(fileName);
} else if (options.getDocumentSourceName() == null) {
options = new XmlOptions(options);
options.setDocumentSourceName(fileName);
}
try (InputStream fis = new FileInputStream(file)) {
return parse(fis, type, options);
}
}
public XmlObject parse(URL url, SchemaType type, XmlOptions options) throws XmlException, IOException {
if (options == null) {
options = new XmlOptions();
options.setDocumentSourceName(url.toString());
} else if (options.getDocumentSourceName() == null) {
options = new XmlOptions(options);
options.setDocumentSourceName(url.toString());
}
boolean redirected = false;
int count = 0;
URLConnection conn;
do {
conn = url.openConnection();
conn.addRequestProperty("User-Agent", USER_AGENT);
conn.addRequestProperty("Accept", "application/xml, text/xml, */*");
if (conn instanceof HttpURLConnection) {
HttpURLConnection httpcon = (HttpURLConnection) conn;
int code = httpcon.getResponseCode();
redirected = (code == HttpURLConnection.HTTP_MOVED_PERM || code == HttpURLConnection.HTTP_MOVED_TEMP);
if (redirected && count > 5) {
redirected = false;
}
if (redirected) {
String newLocation = httpcon.getHeaderField("Location");
if (newLocation == null) {
redirected = false;
} else {
url = new URL(newLocation);
count++;
}
}
}
} while (redirected);
try (InputStream stream = conn.getInputStream()) {
return parse(stream, type, options);
}
}
public XmlObject parse(InputStream jiois, SchemaType type, XmlOptions options) throws XmlException, IOException {
XmlFactoryHook hook = XmlFactoryHook.ThreadContext.getHook();
DigestInputStream digestStream = null;
setupDigest:
if (options != null && options.isLoadMessageDigest()) {
MessageDigest sha;
try {
sha = MessageDigest.getInstance("SHA");
} catch (NoSuchAlgorithmException e) {
break setupDigest;
}
digestStream = new DigestInputStream(jiois, sha);
jiois = digestStream;
}
if (hook != null) {
return hook.parse(this, jiois, type, options);
}
XmlObject result = Locale.parseToXmlObject(this, jiois, type, options);
if (digestStream != null) {
result.documentProperties().setMessageDigest(digestStream.getMessageDigest().digest());
}
return result;
}
public XmlObject parse(Reader jior, SchemaType type, XmlOptions options) throws XmlException, IOException {
XmlFactoryHook hook = XmlFactoryHook.ThreadContext.getHook();
if (hook != null) {
return hook.parse(this, jior, type, options);
}
return Locale.parseToXmlObject(this, jior, type, options);
}
public XmlObject parse(Node node, SchemaType type, XmlOptions options) throws XmlException {
XmlFactoryHook hook = XmlFactoryHook.ThreadContext.getHook();
if (hook != null) {
return hook.parse(this, node, type, options);
}
return Locale.parseToXmlObject(this, node, type, options);
}
public XmlSaxHandler newXmlSaxHandler(SchemaType type, XmlOptions options) {
XmlFactoryHook hook = XmlFactoryHook.ThreadContext.getHook();
if (hook != null) {
return hook.newXmlSaxHandler(this, type, options);
}
return Locale.newSaxHandler(this, type, options);
}
public DOMImplementation newDomImplementation(XmlOptions options) {
return Locale.newDomImplementation(this, options);
}
/**
* @deprecated XMLInputStream was deprecated by XMLStreamReader from STaX - jsr173 API.
*/
public XMLInputStream newValidatingXMLInputStream(XMLInputStream xis, SchemaType type, XmlOptions options) throws XmlException, XMLStreamException {
return new ValidatingXMLInputStream(xis, this, type, options);
}
//
//
//
public String compilePath(String pathExpr) {
return compilePath(pathExpr, null);
}
public String compilePath(String pathExpr, XmlOptions options) {
return doCompilePath(pathExpr, options);
}
public String compileQuery(String queryExpr) {
return compileQuery(queryExpr, null);
}
public String compileQuery(String queryExpr, XmlOptions options) {
return doCompileQuery(queryExpr, options);
}
/**
* Utility function to load a type from a signature.
* <p>
* A signature is the string you get from type.toString().
*/
public SchemaType typeForSignature(String signature) {
int end = signature.indexOf('@');
String uri;
if (end < 0) {
uri = "";
end = signature.length();
} else {
uri = signature.substring(end + 1);
}
List<String> parts = new ArrayList<>();
for (int index = 0; index < end; ) {
int nextc = signature.indexOf(':', index);
int nextd = signature.indexOf('|', index);
int next = (nextc < 0 ? nextd : nextd < 0 ? nextc : Math.min(nextc, nextd));
if (next < 0 || next > end) {
next = end;
}
String part = signature.substring(index, next);
parts.add(part);
index = next + 1;
}
SchemaType curType = null;
for (int i = parts.size() - 1; i >= 0; i -= 1) {
String part = parts.get(i);
if (part.length() < 1) {
throw new IllegalArgumentException();
}
int offset = (part.length() >= 2 && part.charAt(1) == '=') ? 2 : 1;
cases:
switch (part.charAt(0)) {
case 'T':
if (curType != null) {
throw new IllegalArgumentException();
}
curType = findType(QNameHelper.forLNS(part.substring(offset), uri));
if (curType == null) {
return null;
}
break;
case 'D':
if (curType != null) {
throw new IllegalArgumentException();
}
curType = findDocumentType(QNameHelper.forLNS(part.substring(offset), uri));
if (curType == null) {
return null;
}
break;
case 'C': // deprecated
case 'R': // current
if (curType != null) {
throw new IllegalArgumentException();
}
curType = findAttributeType(QNameHelper.forLNS(part.substring(offset), uri));
if (curType == null) {
return null;
}
break;
case 'E':
case 'U': // distinguish qualified/unqualified TBD
if (curType != null) {
if (curType.getContentType() < SchemaType.ELEMENT_CONTENT) {
return null;
}
SchemaType[] subTypes = curType.getAnonymousTypes();
String localName = part.substring(offset);
for (SchemaType subType : subTypes) {
SchemaField field = subType.getContainerField();
if (field != null && !field.isAttribute() && field.getName().getLocalPart().equals(localName)) {
curType = subType;
break cases;
}
}
return null;
} else {
SchemaGlobalElement elt = findElement(QNameHelper.forLNS(part.substring(offset), uri));
if (elt == null) {
return null;
}
curType = elt.getType();
}
break;
case 'A':
case 'Q': // distinguish qualified/unqualified TBD
if (curType != null) {
if (curType.isSimpleType()) {
return null;
}
SchemaType[] subTypes = curType.getAnonymousTypes();
String localName = part.substring(offset);
for (SchemaType subType : subTypes) {
SchemaField field = subType.getContainerField();
if (field != null && field.isAttribute() && field.getName().getLocalPart().equals(localName)) {
curType = subType;
break cases;
}
}
return null;
} else {
SchemaGlobalAttribute attr = findAttribute(QNameHelper.forLNS(part.substring(offset), uri));
if (attr == null) {
return null;
}
curType = attr.getType();
}
break;
case 'B':
if (curType == null) {
throw new IllegalArgumentException();
} else {
if (curType.getSimpleVariety() != SchemaType.ATOMIC) {
return null;
}
SchemaType[] subTypes = curType.getAnonymousTypes();
if (subTypes.length != 1) {
return null;
}
curType = subTypes[0];
}
break;
case 'I':
if (curType == null) {
throw new IllegalArgumentException();
} else {
if (curType.getSimpleVariety() != SchemaType.LIST) {
return null;
}
SchemaType[] subTypes = curType.getAnonymousTypes();
if (subTypes.length != 1) {
return null;
}
curType = subTypes[0];
}
break;
case 'M':
if (curType == null) {
throw new IllegalArgumentException();
} else {
int index;
try {
index = Integer.parseInt(part.substring(offset));
} catch (Exception e) {
throw new IllegalArgumentException();
}
if (curType.getSimpleVariety() != SchemaType.UNION) {
return null;
}
SchemaType[] subTypes = curType.getAnonymousTypes();
if (subTypes.length <= index) {
return null;
}
curType = subTypes[index];
}
break;
default:
throw new IllegalArgumentException();
}
}
return curType;
}
}