OSDN Git Service

Merge commit '2458eff3aea04f67893bc824b5cf896fbb767332'
[jindolf/Jindolf.git] / src / main / java / jp / sourceforge / jindolf / XmlResourceResolver.java
diff --git a/src/main/java/jp/sourceforge/jindolf/XmlResourceResolver.java b/src/main/java/jp/sourceforge/jindolf/XmlResourceResolver.java
new file mode 100644 (file)
index 0000000..39f3b32
--- /dev/null
@@ -0,0 +1,337 @@
+/*\r
+ * xml resource resolver\r
+ *\r
+ * Copyright(c) 2009 olyutorskii\r
+ * $Id: XmlResourceResolver.java 888 2009-11-04 06:23:35Z olyutorskii $\r
+ */\r
+\r
+package jp.sourceforge.jindolf;\r
+\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.Reader;\r
+import java.net.URI;\r
+import java.net.URISyntaxException;\r
+import java.net.URL;\r
+import java.util.Map;\r
+import jp.sourceforge.jindolf.corelib.XmlResource;\r
+import org.w3c.dom.ls.LSInput;\r
+import org.w3c.dom.ls.LSResourceResolver;\r
+import org.xml.sax.EntityResolver;\r
+import org.xml.sax.InputSource;\r
+import org.xml.sax.SAXException;\r
+\r
+/**\r
+ * URL変換マップに従い、XML文書からの外部参照をリダイレクトする。\r
+ * 相対URIはこのクラスをベースに解決される。\r
+ * 主な用途は外部スキーマのリソース化など。\r
+ */\r
+public class XmlResourceResolver\r
+        implements LSResourceResolver,\r
+                   EntityResolver{\r
+\r
+    private static final URI EMPTY_URI = URI.create("");\r
+\r
+    /**\r
+     * 絶対URIと相対URIを合成したURIを返す。\r
+     * 正規化も行われる。\r
+     * @param base 絶対URIでなければならない。nullでもよい。\r
+     * @param relative 絶対URIでもよいがその場合baseは無視される。null可。\r
+     * @return 合成結果のURLオブジェクト。必ず絶対URIになる。\r
+     * @throws java.net.URISyntaxException URIとして変。\r
+     * @throws java.lang.IllegalArgumentException 絶対URIが生成できない。\r
+     */\r
+    protected static URI buildBaseRelativeURI(String base, String relative)\r
+            throws URISyntaxException,\r
+                   IllegalArgumentException {\r
+        URI baseURI = null;\r
+        if(base != null){\r
+            baseURI = new URI(base);\r
+            if( ! baseURI.isAbsolute() ) throw new IllegalArgumentException();\r
+        }\r
+\r
+        URI relativeURI = EMPTY_URI;\r
+        if(relative != null){\r
+            relativeURI = new URI(relative);\r
+        }\r
+\r
+        URI resultURI;\r
+        if(baseURI == null || relativeURI.isAbsolute()){\r
+            resultURI = relativeURI;\r
+        }else{\r
+            resultURI = baseURI.resolve(relativeURI);\r
+        }\r
+\r
+        if( ! resultURI.isAbsolute() ) throw new IllegalArgumentException();\r
+\r
+        resultURI = resultURI.normalize();\r
+\r
+        return resultURI;\r
+    }\r
+\r
+    /**\r
+     * LSInput実装を生成する。\r
+     * @return LSInput実装\r
+     */\r
+    public static LSInput createLSInput(){\r
+        LSInput input = new LSInputImpl();\r
+        return input;\r
+    }\r
+\r
+    private final Map<URI, URI> uriMap = XmlResource.RESOLVE_MAP;\r
+\r
+    /**\r
+     * コンストラクタ。\r
+     */\r
+    public XmlResourceResolver(){\r
+        super();\r
+        return;\r
+    }\r
+\r
+    /**\r
+     * 変換後のリソースの入力ストリームを得る。\r
+     * @param originalURI オリジナルURI\r
+     * @return 入力ストリーム\r
+     * @throws java.io.IOException 入出力エラー\r
+     */\r
+    public InputStream getXMLResourceAsStream(URI originalURI)\r
+            throws IOException{\r
+        URI resourceURI = this.uriMap.get(originalURI.normalize());\r
+        URL resourceURL = resourceURI.toURL();\r
+        InputStream is = resourceURL.openStream();\r
+\r
+        return is;\r
+    }\r
+\r
+    /**\r
+     * {@inheritDoc}\r
+     * URL変換したあとの入力ソースを返す。\r
+     * @param type {@inheritDoc}\r
+     * @param namespaceURI {@inheritDoc}\r
+     * @param publicId {@inheritDoc}\r
+     * @param systemId {@inheritDoc}\r
+     * @param baseURI {@inheritDoc}\r
+     * @return {@inheritDoc}\r
+     */\r
+    public LSInput resolveResource(String type,\r
+                                     String namespaceURI,\r
+                                     String publicId,\r
+                                     String systemId,\r
+                                     String baseURI ){\r
+        if(systemId == null) return null;\r
+\r
+        URI originalURI;\r
+        try{\r
+            originalURI = buildBaseRelativeURI(baseURI, systemId);\r
+        }catch(URISyntaxException e){\r
+            return null;\r
+        }\r
+\r
+        InputStream is;\r
+        try{\r
+            is = getXMLResourceAsStream(originalURI);\r
+        }catch(IOException e){\r
+            return null;\r
+        }\r
+\r
+        LSInput input = createLSInput();\r
+        input.setBaseURI(baseURI);\r
+        input.setPublicId(publicId);\r
+        input.setSystemId(systemId);\r
+        input.setByteStream(is);\r
+\r
+        return input;\r
+    }\r
+\r
+    /**\r
+     * {@inheritDoc}\r
+     * URL変換したあとの入力ソースを返す。\r
+     * @param publicId {@inheritDoc}\r
+     * @param systemId {@inheritDoc}\r
+     * @return {@inheritDoc}\r
+     * @throws org.xml.sax.SAXException {@inheritDoc}\r
+     * @throws java.io.IOException {@inheritDoc}\r
+     */\r
+    public InputSource resolveEntity(String publicId, String systemId)\r
+            throws SAXException, IOException{\r
+        if(systemId == null) return null;\r
+\r
+        URI originalUri;\r
+        try{\r
+            originalUri = new URI(systemId);\r
+        }catch(URISyntaxException e){\r
+            return null;\r
+        }\r
+\r
+        InputStream is = getXMLResourceAsStream(originalUri);\r
+\r
+        InputSource source = new InputSource(is);\r
+        source.setPublicId(publicId);\r
+        source.setSystemId(systemId);\r
+\r
+        return source;\r
+    }\r
+\r
+    /**\r
+     * JRE1.5用LSInput実装。\r
+     * JRE1.6なら\r
+     * org.w3c.dom.ls.DOMImplementationLS#createLSInput()\r
+     * で生成可能かも。\r
+     */\r
+    public static class LSInputImpl implements LSInput{\r
+\r
+        private String baseURI = null;\r
+        private InputStream byteStream = null;\r
+        private boolean certifiedText = false;\r
+        private Reader characterStream = null;\r
+        private String encoding = null;\r
+        private String publicId = null;\r
+        private String stringData = null;\r
+        private String systemId = null;\r
+\r
+        /**\r
+         * コンストラクタ。\r
+         */\r
+        public LSInputImpl(){\r
+            super();\r
+            return;\r
+        }\r
+\r
+        /**\r
+         * {@inheritDoc}\r
+         * @return {@inheritDoc}\r
+         */\r
+        public String getBaseURI(){\r
+            return this.baseURI;\r
+        }\r
+\r
+        /**\r
+         * {@inheritDoc}\r
+         * @param baseURI {@inheritDoc}\r
+         */\r
+        public void setBaseURI(String baseURI){\r
+            this.baseURI = baseURI;\r
+            return;\r
+        }\r
+\r
+        /**\r
+         * {@inheritDoc}\r
+         * @return {@inheritDoc}\r
+         */\r
+        public InputStream getByteStream(){\r
+            return this.byteStream;\r
+        }\r
+\r
+        /**\r
+         * {@inheritDoc}\r
+         * @param byteStream {@inheritDoc}\r
+         */\r
+        public void setByteStream(InputStream byteStream){\r
+            this.byteStream = byteStream;\r
+        }\r
+\r
+        /**\r
+         * {@inheritDoc}\r
+         * @return {@inheritDoc}\r
+         */\r
+        public boolean getCertifiedText(){\r
+            return this.certifiedText;\r
+        }\r
+\r
+        /**\r
+         * {@inheritDoc}\r
+         * @param certifiedText {@inheritDoc}\r
+         */\r
+        public void setCertifiedText(boolean certifiedText){\r
+            this.certifiedText = certifiedText;\r
+            return;\r
+        }\r
+\r
+        /**\r
+         * {@inheritDoc}\r
+         * @return {@inheritDoc}\r
+         */\r
+        public Reader getCharacterStream(){\r
+            return this.characterStream;\r
+        }\r
+\r
+        /**\r
+         * {@inheritDoc}\r
+         * @param characterStream {@inheritDoc}\r
+         */\r
+        public void setCharacterStream(Reader characterStream){\r
+            this.characterStream = characterStream;\r
+        }\r
+\r
+        /**\r
+         * {@inheritDoc}\r
+         * @return {@inheritDoc}\r
+         */\r
+        public String getEncoding(){\r
+            return this.encoding;\r
+        }\r
+\r
+        /**\r
+         * {@inheritDoc}\r
+         * @param encoding {@inheritDoc}\r
+         */\r
+        public void setEncoding(String encoding){\r
+            this.encoding = encoding;\r
+            return;\r
+        }\r
+\r
+        /**\r
+         * {@inheritDoc}\r
+         * @return {@inheritDoc}\r
+         */\r
+        public String getPublicId(){\r
+            return this.publicId;\r
+        }\r
+\r
+        /**\r
+         * {@inheritDoc}\r
+         * @param publicId {@inheritDoc}\r
+         */\r
+        public void setPublicId(String publicId){\r
+            this.publicId = publicId;\r
+            return;\r
+        }\r
+\r
+        /**\r
+         * {@inheritDoc}\r
+         * @return {@inheritDoc}\r
+         */\r
+        public String getStringData(){\r
+            return this.stringData;\r
+        }\r
+\r
+        /**\r
+         * {@inheritDoc}\r
+         * @param stringData {@inheritDoc}\r
+         */\r
+        public void setStringData(String stringData){\r
+            this.stringData = stringData;\r
+            return;\r
+        }\r
+\r
+        /**\r
+         * {@inheritDoc}\r
+         * @return {@inheritDoc}\r
+         */\r
+        public String getSystemId(){\r
+            return this.systemId;\r
+        }\r
+\r
+        /**\r
+         * {@inheritDoc}\r
+         * @param systemId {@inheritDoc}\r
+         */\r
+        public void setSystemId(String systemId){\r
+            this.systemId = systemId;\r
+            return;\r
+        }\r
+\r
+    }\r
+\r
+    // TODO OASIS XML Catalog などと調和したい。\r
+}\r