import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.net.MalformedURLException;
import java.net.URI;
+import java.net.URISyntaxException;
import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
import javax.xml.XMLConstants;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
/**
* XML schema (XSD) utilities.
+ *
+ * <p>RELAX NG is not supported.
*/
public final class SchemaUtil {
static{
- URL redirectRes = THISCLASS.getResource(LOCAL_SCHEMA_XML);
- String redirectResName = redirectRes.toString();
+ URL localXsdUrl = THISCLASS.getResource(LOCAL_SCHEMA_XML);
+ URI localXsdUri;
+ try{
+ localXsdUri = localXsdUrl.toURI();
+ }catch(URISyntaxException e){
+ throw new ExceptionInInitializerError(e);
+ }
URI_XSD_ORIG = URI.create(SCHEMA_XML);
- URI_XSD_LOCAL = URI.create(redirectResName);
+ URI_XSD_LOCAL = localXsdUri;
assert ALLOWED_USCHEMA.equalsIgnoreCase(URI_XSD_ORIG.getScheme());
}
XMLConstants.W3C_XML_SCHEMA_NS_URI);
try{
- // Prevent denial of service attack.
+ // Prevent denial-of-service attack.
schemaFactory.setFeature(
XMLConstants.FEATURE_SECURE_PROCESSING, true);
}catch(SAXNotRecognizedException | SAXNotSupportedException e){
- // FEATURE MUST BE SUPPORTED
+ // THIS FEATURE MUST BE SUPPORTED
assert false;
}
try{
- // Disallow external entity reference & external DTD access.
+ // Disallow external entity reference & external DTD access.
schemaFactory.setProperty(
XMLConstants.ACCESS_EXTERNAL_DTD, "");
// Allow only HTTP external schema file.
schemaFactory.setProperty(
XMLConstants.ACCESS_EXTERNAL_SCHEMA, ALLOWED_USCHEMA);
}catch(SAXNotRecognizedException | SAXNotSupportedException e){
- // PROPERTY MUST BE SUPPORTED JAXP1.5 or later
+ // THIS PROPERTY MUST BE SUPPORTED JAXP1.5 or later
assert false;
}
}
/**
- * ローカルリソースをSourceに変換する。
- * @param resource ローカルリソース
- * @return XML Source
- * @throws MalformedURLException 不正なURI
- * @throws IOException オープンエラー
- */
- private static Source toLocalSource(LocalXmlResource resource)
- throws MalformedURLException, IOException{
- URI localUri = resource.getLocalResource();
- URL localUrl = localUri.toURL();
-
- InputStream is = localUrl.openStream();
- is = new BufferedInputStream(is);
-
- Source result = new StreamSource(is);
- return result;
- }
-
- /**
- * ローカルリソース群をSource群に変換する。
- * @param resArray ローカルリソースURI並び
- * @return XML Source並び
- * @throws MalformedURLException 不正なURI
- * @throws IOException オープンエラー
+ * pre-load & pre-compile local schema files.
+ *
+ * @param localSchemaUris local schema resources.
+ * @return schema
+ * @throws SAXException invalid schema definition
+ * @throws IOException local resource i/o error
*/
- private static Source[] toLocalSourceArray(LocalXmlResource... resArray)
- throws MalformedURLException, IOException{
- List<Source> sourceList = new ArrayList<>(resArray.length);
+ public static Schema newSchema(URI... localSchemaUris)
+ throws SAXException, IOException{
+ SchemaFactory schemaFactory = newSchemaFactory();
- for(LocalXmlResource resource : resArray){
- Source localSource = toLocalSource(resource);
- sourceList.add(localSource);
+ int uris = localSchemaUris.length;
+ if(uris <= 0){
+ // on-demand xml-schema with schemaLocation attribute.
+ return schemaFactory.newSchema();
}
- Source[] result = new Source[sourceList.size()];
- result = sourceList.toArray(result);
- return result;
- }
-
- /**
- * ローカルスキーマをロードする。
- *
- * <p>任意のリゾルバを指定可能
- *
- * @param resArray ローカルスキーマ情報並び
- * @return スキーマ
- */
- public static Schema newSchema(LocalXmlResource... resArray){
- Source[] sources;
- try{
- sources = toLocalSourceArray(resArray);
- }catch(IOException e){ // ビルド障害
- assert false;
- throw new AssertionError(e);
+ InputStream[] iss = new InputStream[uris];
+ for(int idx = 0; idx < uris; idx++){
+ URI localUri = localSchemaUris[idx];
+ URL localUrl = localUri.toURL();
+ InputStream is;
+ is = localUrl.openStream();
+ is = new BufferedInputStream(is);
+ iss[idx] = is;
}
- SchemaFactory schemaFactory = newSchemaFactory();
+ Source[] sources = new Source[uris];
+ for(int idx = 0; idx < uris; idx++){
+ InputStream is = iss[idx];
+ sources[idx] = new StreamSource(is);
+ }
Schema result;
try{
- if(sources.length <= 0){
- // ドキュメント埋め込みスキーマURLにリゾルバ経由でアクセス
- result = schemaFactory.newSchema();
- }else{
- result = schemaFactory.newSchema(sources);
+ result = schemaFactory.newSchema(sources);
+ }finally{
+ for(InputStream is : iss){
+ is.close();
}
- }catch(SAXException e){ // Build error
- assert false;
- throw new AssertionError(e);
}
- // TODO: Sourceを閉めるのは誰の責務?
-
return result;
}