X-Git-Url: http://git.osdn.net/view?p=mikutoga%2FTogaGem.git;a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fjp%2Fsfjp%2Fmikutoga%2Fxml%2FXmlResourceResolver.java;h=bf5ba8e753ce5dfebf3595d3a300c2561f522599;hp=0d1c8defdc5fcbb8242dbf558c9db97ac66881b4;hb=a05e9ba0600cb2cc705ad41e91255dd2b4ddac35;hpb=3fd0f125fb25fb0955bf2d7f7a557f488b4fd98a diff --git a/src/main/java/jp/sfjp/mikutoga/xml/XmlResourceResolver.java b/src/main/java/jp/sfjp/mikutoga/xml/XmlResourceResolver.java index 0d1c8de..bf5ba8e 100644 --- a/src/main/java/jp/sfjp/mikutoga/xml/XmlResourceResolver.java +++ b/src/main/java/jp/sfjp/mikutoga/xml/XmlResourceResolver.java @@ -7,81 +7,108 @@ package jp.sfjp.mikutoga.xml; +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; 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.DOMImplementation; +import org.w3c.dom.bootstrap.DOMImplementationRegistry; +import org.w3c.dom.ls.DOMImplementationLS; 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はこのクラスをベースに解決される。 - * 主な用途は外部スキーマのリソース化など。 + * register & redirect original URI to local resource contents. */ 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"; + implements LSResourceResolver{ private static final URI EMPTY_URI = URI.create(""); - private static final Class THISCLASS = XmlResourceResolver.class; + private static final DOMImplementationLS DOM_LS; private final Map uriMap; + static{ + try{ + DOM_LS = buildDomImplLS(); + }catch( ClassNotFoundException + | IllegalAccessException + | InstantiationException e){ + throw new ExceptionInInitializerError(e); + } + } + + /** - * コンストラクタ。 + * Constructor. */ public XmlResourceResolver(){ super(); - assert this.getClass().equals(THISCLASS); - Map map; - map = new HashMap(); + map = new HashMap<>(); 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); + return; + } - putRedirectedImpl(originalURI, redirectURI); - return; + /** + * return DOMImplementationLS implement. + * + * @return DOMImplementationLS implement + * @throws ClassNotFoundException no class + * @throws InstantiationException no object + * @throws IllegalAccessException no grant + */ + private static DOMImplementationLS buildDomImplLS() throws + ClassNotFoundException, + InstantiationException, + IllegalAccessException { + DOMImplementationRegistry domReg; + DOMImplementation domImp; + DOMImplementationLS domImpLs; + + domReg = DOMImplementationRegistry.newInstance(); + domImp = domReg.getDOMImplementation("LS 3.0"); + + Object feature = domImp.getFeature("LS", "3.0"); + assert feature instanceof DOMImplementationLS; + domImpLs = (DOMImplementationLS) feature; + + return domImpLs; } + /** + * return LSInput implement. + * + * @return LSInput implement + */ + public static LSInput createLSInput(){ + LSInput input = DOM_LS.createLSInput(); + return input; + } /** - * 絶対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が生成できない。 + * merge base-uri text & relative URI text. + * + * @param base base URI text must be absolute or null. + * @param relative relative URI text. + * If absolute, base is ignored. + * Ignored if null. + * @return merged absolute URI. + * @throws java.net.URISyntaxException illegal URI + * @throws java.lang.IllegalArgumentException result is not Absolute. */ protected static URI buildBaseRelativeURI(String base, String relative) throws URISyntaxException, @@ -103,7 +130,22 @@ public class XmlResourceResolver relativeURI = EMPTY_URI; } + URI result = buildBaseRelativeURI(baseURI, relativeURI); + return result; + } + + /** + * merge base-uri & relative URI. + * + * @param baseURI base URI must be absolute or null. + * @param relativeURI relative URI. If absolute, baseURI is ignored. + * @return merged absolute URI. + * @throws java.lang.IllegalArgumentException result is not Absolute. + */ + private static URI buildBaseRelativeURI(URI baseURI, URI relativeURI) + throws IllegalArgumentException { URI resultURI; + if(baseURI == null || relativeURI.isAbsolute()){ resultURI = relativeURI; }else{ @@ -119,23 +161,14 @@ public class XmlResourceResolver return resultURI; } - /** - * LSInput実装を生成する。 - * @return LSInput実装 - */ - public static LSInput createLSInput(){ - LSInput input = new LSInputImpl(); - return input; - } - /** - * オリジナルURIとリダイレクト先のURIを登録する。 - * オリジナルURIへのアクセスはリダイレクトされる。 - * @param original オリジナルURI - * @param redirect リダイレクトURI + * map original URI & local resource URI. + * + * @param original original URI + * @param redirect local resource URI */ - private void putRedirectedImpl(URI original, URI redirect){ + public void putRedirected(URI original, URI redirect){ URI oridinalNorm = original.normalize(); URI redirectNorm = redirect.normalize(); @@ -145,34 +178,9 @@ public class XmlResourceResolver } /** - * オリジナルURIとリダイレクト先のURIを登録する。 - * オリジナルURIへのアクセスはリダイレクトされる。 - * @param original オリジナルURI - * @param redirect リダイレクトURI - */ - public void putRedirected(URI original, URI redirect){ - putRedirectedImpl(original, redirect); - return; - } - - /** - * ローカル版リソース参照解決を登録する。 - * @param lsc ローカル版リソース参照解決 - */ - public void putRedirected(LocalXmlResource lsc){ - URI original = lsc.getOriginalResource(); - if(original == null) return; - - URI local = lsc.getLocalResource(); - - putRedirected(original, local); - - return; - } - - /** - * 別リゾルバの登録内容を追加登録する。 - * @param other 別リゾルバ + * add other resolver mapping. + * + * @param other resolver */ public void putRedirected(XmlResourceResolver other){ this.uriMap.putAll(other.uriMap); @@ -180,9 +188,10 @@ public class XmlResourceResolver } /** - * 登録済みリダイレクト先URIを返す。 - * @param original オリジナルURI - * @return リダイレクト先URI。未登録の場合はnull + * get redirected local resource URI. + * + * @param original original URI + * @return mapped local resource URI. null if unmapped. */ public URI getRedirected(URI original){ URI keyURI = original.normalize(); @@ -191,66 +200,67 @@ public class XmlResourceResolver } /** - * 登録済みリダイレクト先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 入出力エラー。 - * もしくはリソースが見つからない。 + * get redirected local input stream. + * + * @param originalURI original URI + * @return mapped local resource input stream. + * If no mapping, return zero-length data stream. + * @throws java.io.IOException local resource i/o error */ private InputStream getXMLResourceAsStream(URI originalURI) throws IOException{ + InputStream result; + URI resourceURI = getRedirected(originalURI); - if(resourceURI == null) return null; + if(resourceURI == null){ + result = new ByteArrayInputStream(new byte[0]); + }else{ + URL resourceURL = resourceURI.toURL(); + result = resourceURL.openStream(); + } - URL resourceURL = resourceURI.toURL(); - InputStream is = resourceURL.openStream(); + result = new BufferedInputStream(result); - return is; + return result; } /** * {@inheritDoc} - * URL変換したあとの入力ソースを返す。 + * + *

Return redirected local resource data. + * * @param type {@inheritDoc} * @param namespaceURI {@inheritDoc} * @param publicId {@inheritDoc} * @param systemId {@inheritDoc} * @param baseURI {@inheritDoc} - * @return {@inheritDoc} + * @return {@inheritDoc} LSInput of local resource. + * If no mapping, return zero-length data. */ @Override - public LSInput resolveResource(String type, - String namespaceURI, - String publicId, - String systemId, - String baseURI ){ + 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; + assert false; + throw new AssertionError(e); } InputStream is; try{ is = getXMLResourceAsStream(originalURI); }catch(IOException e){ - return null; + assert false; + throw new AssertionError(e); } - if(is == null) return null; LSInput input = createLSInput(); input.setBaseURI(baseURI); @@ -261,212 +271,4 @@ public class XmlResourceResolver 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; - } - - } - }