OSDN Git Service

2.102.2版リリース準備
[mikutoga/TogaGem.git] / src / main / java / jp / sourceforge / mikutoga / xml / XmlResourceResolver.java
index 779edec..4ea9167 100644 (file)
-/*\r
- * xml resource resolver\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2009 olyutorskii\r
- */\r
-\r
-package jp.sourceforge.mikutoga.xml;\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.HashMap;\r
-import java.util.Map;\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, EntityResolver {\r
-\r
-    public static final String SCHEMA_XML =\r
-            "http://www.w3.org/2001/xml.xsd";\r
-    public static final String NS_XSD =\r
-            "http://www.w3.org/2001/XMLSchema-instance";\r
-\r
-    private static final String LOCAL_SCHEMA_XML =\r
-            "./resources/xml-2009-01.xsd";\r
-    private static final URI EMPTY_URI = URI.create("");\r
-    private static final Class THISCLASS = XmlResourceResolver.class;\r
-\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 = new HashMap<URI, URI>();\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     */\r
-    public XmlResourceResolver(){\r
-        super();\r
-\r
-        assert this.getClass().equals(THISCLASS);\r
-\r
-        URI originalURI = URI.create(SCHEMA_XML);\r
-        URL redirectURL = THISCLASS.getResource(LOCAL_SCHEMA_XML);\r
-        URI redirectURI;\r
-        try{\r
-            redirectURI = redirectURL.toURI();\r
-        }catch(URISyntaxException e){\r
-            assert false;\r
-            throw new AssertionError(e);\r
-        }\r
-\r
-        this.uriMap.put(originalURI, redirectURI);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * オリジナルURIとリダイレクト先のURIを登録する。\r
-     * オリジナルURIへのアクセスはリダイレクトされる。\r
-     * @param original オリジナルURI\r
-     * @param redirect リダイレクトURI\r
-     */\r
-    public void putURIMap(URI original, URI redirect){\r
-        this.uriMap.put(original.normalize(), redirect.normalize());\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
-    private 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
-        private 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
+/*
+ * xml resource resolver
+ *
+ * License : The MIT License
+ * Copyright(c) 2009 olyutorskii
+ */
+
+package jp.sourceforge.mikutoga.xml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import org.w3c.dom.ls.LSInput;
+import org.w3c.dom.ls.LSResourceResolver;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * URL変換マップに従い、XML文書からの外部参照をリダイレクトする。
+ * 相対URIはこのクラスをベースに解決される。
+ * 主な用途は外部スキーマのリソース化など。
+ */
+public class XmlResourceResolver
+        implements LSResourceResolver, EntityResolver {
+
+    /** XML Schema. */
+    public static final String SCHEMA_XML =
+            "http://www.w3.org/2001/xml.xsd";
+
+    /** XSD名前空間。 */
+    public static final String NS_XSD =
+            "http://www.w3.org/2001/XMLSchema-instance";
+
+    private static final String LOCAL_SCHEMA_XML =
+            "resources/xmlspace.xsd";
+
+    private static final URI EMPTY_URI = URI.create("");
+
+    private static final Class<?> THISCLASS = XmlResourceResolver.class;
+
+
+    private final Map<URI, URI> uriMap;
+
+
+    /**
+     * コンストラクタ。
+     */
+    public XmlResourceResolver(){
+        super();
+
+        assert this.getClass().equals(THISCLASS);
+
+        Map<URI, URI> map;
+        map = new HashMap<URI, URI>();
+        map = Collections.synchronizedMap(map);
+        this.uriMap = map;
+
+        URL redirectRes = THISCLASS.getResource(LOCAL_SCHEMA_XML);
+        String redirectResName = redirectRes.toString();
+
+        URI originalURI = URI.create(SCHEMA_XML);
+        URI redirectURI = URI.create(redirectResName);
+
+        putRedirectedImpl(originalURI, redirectURI);
+
+        return;
+    }
+
+
+    /**
+     * 絶対URIと相対URIを合成したURIを返す。
+     * 正規化も行われる。
+     * @param base 絶対URIでなければならない。nullでもよい。
+     * @param relative 絶対URIでもよいがその場合baseは無視される。null可。
+     * @return 合成結果のURLオブジェクト。必ず絶対URIになる。
+     * @throws java.net.URISyntaxException URIとして変。
+     * @throws java.lang.IllegalArgumentException 絶対URIが生成できない。
+     */
+    protected static URI buildBaseRelativeURI(String base, String relative)
+            throws URISyntaxException,
+                   IllegalArgumentException {
+        URI baseURI;
+        if(base != null){
+            baseURI = new URI(base);
+            if( ! baseURI.isAbsolute() ){
+                throw new IllegalArgumentException();
+            }
+        }else{
+            baseURI = null;
+        }
+
+        URI relativeURI;
+        if(relative != null){
+            relativeURI = new URI(relative);
+        }else{
+            relativeURI = EMPTY_URI;
+        }
+
+        URI resultURI;
+        if(baseURI == null || relativeURI.isAbsolute()){
+            resultURI = relativeURI;
+        }else{
+            resultURI = baseURI.resolve(relativeURI);
+        }
+
+        if( ! resultURI.isAbsolute() ){
+            throw new IllegalArgumentException();
+        }
+
+        resultURI = resultURI.normalize();
+
+        return resultURI;
+    }
+
+    /**
+     * LSInput実装を生成する。
+     * @return LSInput実装
+     */
+    public static LSInput createLSInput(){
+        LSInput input = new LSInputImpl();
+        return input;
+    }
+
+
+    /**
+     * オリジナルURIとリダイレクト先のURIを登録する。
+     * オリジナルURIへのアクセスはリダイレクトされる。
+     * @param original オリジナルURI
+     * @param redirect リダイレクトURI
+     */
+    private void putRedirectedImpl(URI original, URI redirect){
+        URI oridinalNorm = original.normalize();
+        URI redirectNorm = redirect.normalize();
+
+        this.uriMap.put(oridinalNorm, redirectNorm);
+
+        return;
+    }
+
+    /**
+     * オリジナルURIとリダイレクト先のURIを登録する。
+     * オリジナルURIへのアクセスはリダイレクトされる。
+     * @param original オリジナルURI
+     * @param redirect リダイレクトURI
+     */
+    public void putRedirected(URI original, URI redirect){
+        putRedirectedImpl(original, redirect);
+        return;
+    }
+
+    /**
+     * 別リゾルバの登録内容を追加登録する。
+     * @param other 別リゾルバ
+     */
+    public void putRedirected(XmlResourceResolver other){
+        this.uriMap.putAll(other.uriMap);
+        return;
+    }
+
+    /**
+     * 登録済みリダイレクト先URIを返す。
+     * @param original オリジナルURI
+     * @return リダイレクト先URI。未登録の場合はnull
+     */
+    public URI getRedirected(URI original){
+        URI keyURI = original.normalize();
+        URI resourceURI = this.uriMap.get(keyURI);
+        return resourceURI;
+    }
+
+    /**
+     * 登録済みリダイレクト先URIを返す。
+     * @param original オリジナルURI
+     * @return リダイレクト先URI。未登録の場合はオリジナルを返す
+     */
+    public URI resolveRedirected(URI original){
+        URI result = getRedirected(original);
+        if(result == null) result = original;
+        return result;
+    }
+
+    /**
+     * 登録済みリダイレクト先リソースの入力ストリームを得る。
+     * @param originalURI オリジナルURI
+     * @return 入力ストリーム。リダイレクト先が未登録の場合はnull
+     * @throws java.io.IOException 入出力エラー。
+     * もしくはリソースが見つからない。
+     */
+    private InputStream getXMLResourceAsStream(URI originalURI)
+            throws IOException{
+        URI resourceURI = getRedirected(originalURI);
+        if(resourceURI == null) return null;
+
+        URL resourceURL = resourceURI.toURL();
+        InputStream is = resourceURL.openStream();
+
+        return is;
+    }
+
+    /**
+     * {@inheritDoc}
+     * URL変換したあとの入力ソースを返す。
+     * @param type {@inheritDoc}
+     * @param namespaceURI {@inheritDoc}
+     * @param publicId {@inheritDoc}
+     * @param systemId {@inheritDoc}
+     * @param baseURI {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public LSInput resolveResource(String type,
+                                     String namespaceURI,
+                                     String publicId,
+                                     String systemId,
+                                     String baseURI ){
+        if(systemId == null) return null;
+
+        URI originalURI;
+        try{
+            originalURI = buildBaseRelativeURI(baseURI, systemId);
+        }catch(URISyntaxException e){
+            return null;
+        }
+
+        InputStream is;
+        try{
+            is = getXMLResourceAsStream(originalURI);
+        }catch(IOException e){
+            return null;
+        }
+        if(is == null) return null;
+
+        LSInput input = createLSInput();
+        input.setBaseURI(baseURI);
+        input.setPublicId(publicId);
+        input.setSystemId(systemId);
+        input.setByteStream(is);
+
+        return input;
+    }
+
+    /**
+     * {@inheritDoc}
+     * URL変換したあとの入力ソースを返す。
+     * @param publicId {@inheritDoc}
+     * @param systemId {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws org.xml.sax.SAXException {@inheritDoc}
+     * @throws java.io.IOException {@inheritDoc}
+     */
+    @Override
+    public InputSource resolveEntity(String publicId, String systemId)
+            throws SAXException, IOException{
+        if(systemId == null) return null;
+
+        URI originalUri;
+        try{
+            originalUri = new URI(systemId);
+        }catch(URISyntaxException e){
+            return null;
+        }
+
+        InputStream is = getXMLResourceAsStream(originalUri);
+        if(is == null) return null;
+
+        InputSource source = new InputSource(is);
+        source.setPublicId(publicId);
+        source.setSystemId(systemId);
+
+        return source;
+    }
+
+    /**
+     * JRE1.5用LSInput実装。
+     * JRE1.6なら
+     * org.w3c.dom.ls.DOMImplementationLS#createLSInput()
+     * で生成可能かも。
+     */
+    private static final class LSInputImpl implements LSInput {
+
+        private String baseURI = null;
+        private InputStream byteStream = null;
+        private boolean certifiedText = false;
+        private Reader characterStream = null;
+        private String encoding = null;
+        private String publicId = null;
+        private String stringData = null;
+        private String systemId = null;
+
+        /**
+         * コンストラクタ。
+         */
+        LSInputImpl(){
+            super();
+            return;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return {@inheritDoc}
+         */
+        @Override
+        public String getBaseURI(){
+            return this.baseURI;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param baseURI {@inheritDoc}
+         */
+        @Override
+        public void setBaseURI(String baseURI){
+            this.baseURI = baseURI;
+            return;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return {@inheritDoc}
+         */
+        @Override
+        public InputStream getByteStream(){
+            return this.byteStream;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param byteStream {@inheritDoc}
+         */
+        @Override
+        public void setByteStream(InputStream byteStream){
+            this.byteStream = byteStream;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return {@inheritDoc}
+         */
+        @Override
+        public boolean getCertifiedText(){
+            return this.certifiedText;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param certifiedText {@inheritDoc}
+         */
+        @Override
+        public void setCertifiedText(boolean certifiedText){
+            this.certifiedText = certifiedText;
+            return;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return {@inheritDoc}
+         */
+        @Override
+        public Reader getCharacterStream(){
+            return this.characterStream;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param characterStream {@inheritDoc}
+         */
+        @Override
+        public void setCharacterStream(Reader characterStream){
+            this.characterStream = characterStream;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return {@inheritDoc}
+         */
+        @Override
+        public String getEncoding(){
+            return this.encoding;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param encoding {@inheritDoc}
+         */
+        @Override
+        public void setEncoding(String encoding){
+            this.encoding = encoding;
+            return;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return {@inheritDoc}
+         */
+        @Override
+        public String getPublicId(){
+            return this.publicId;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param publicId {@inheritDoc}
+         */
+        @Override
+        public void setPublicId(String publicId){
+            this.publicId = publicId;
+            return;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return {@inheritDoc}
+         */
+        @Override
+        public String getStringData(){
+            return this.stringData;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param stringData {@inheritDoc}
+         */
+        @Override
+        public void setStringData(String stringData){
+            this.stringData = stringData;
+            return;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @return {@inheritDoc}
+         */
+        @Override
+        public String getSystemId(){
+            return this.systemId;
+        }
+
+        /**
+         * {@inheritDoc}
+         * @param systemId {@inheritDoc}
+         */
+        @Override
+        public void setSystemId(String systemId){
+            this.systemId = systemId;
+            return;
+        }
+
+    }
+
+}