OSDN Git Service

close schema files explicitly.
authorOlyutorskii <olyutorskii@users.osdn.me>
Tue, 25 Jun 2019 06:28:14 +0000 (15:28 +0900)
committerOlyutorskii <olyutorskii@users.osdn.me>
Tue, 25 Jun 2019 06:28:14 +0000 (15:28 +0900)
src/main/java/jp/sfjp/mikutoga/xml/SchemaUtil.java

index 9e2ae10..c0f9eb2 100644 (file)
@@ -10,11 +10,9 @@ package jp.sfjp.mikutoga.xml;
 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;
@@ -27,6 +25,8 @@ import org.xml.sax.SAXNotSupportedException;
 
 /**
  * XML schema (XSD) utilities.
+ *
+ * <p>RELAX NG is not supported.
  */
 public final class SchemaUtil {
 
@@ -51,11 +51,16 @@ 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());
     }
@@ -104,23 +109,23 @@ public final class SchemaUtil {
                 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 &amp; 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;
         }
 
@@ -133,79 +138,48 @@ public final class SchemaUtil {
     }
 
     /**
-     * ローカルリソースを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 &amp; 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;
     }