2 * xml resource resolver
4 * License : The MIT License
5 * Copyright(c) 2009 olyutorskii
8 package jp.sfjp.mikutoga.xml;
10 import java.io.IOException;
11 import java.io.InputStream;
13 import java.net.URISyntaxException;
15 import java.util.Collections;
16 import java.util.HashMap;
18 import org.w3c.dom.DOMImplementation;
19 import org.w3c.dom.bootstrap.DOMImplementationRegistry;
20 import org.w3c.dom.ls.DOMImplementationLS;
21 import org.w3c.dom.ls.LSInput;
22 import org.w3c.dom.ls.LSResourceResolver;
25 * URL変換マップに従い、XML文書からの外部参照をリダイレクトする。
26 * 相対URIはこのクラスをベースに解決される。
27 * 主な用途は外部スキーマのリソース化など。
29 public class XmlResourceResolver
30 implements LSResourceResolver{
32 private static final URI EMPTY_URI = URI.create("");
34 private static final DOMImplementationLS DOM_LS;
37 private final Map<URI, URI> uriMap;
42 DOM_LS = buildDomImplLS();
43 }catch( ClassNotFoundException
44 | IllegalAccessException
45 | InstantiationException e){
46 throw new ExceptionInInitializerError(e);
54 public XmlResourceResolver(){
58 map = new HashMap<>();
59 map = Collections.synchronizedMap(map);
67 * return DOMImplementationLS implement.
69 * @return DOMImplementationLS implement
70 * @throws ClassNotFoundException no class
71 * @throws InstantiationException no object
72 * @throws IllegalAccessException no grant
74 private static DOMImplementationLS buildDomImplLS() throws
75 ClassNotFoundException,
76 InstantiationException,
77 IllegalAccessException {
78 DOMImplementationRegistry domReg;
79 DOMImplementation domImp;
80 DOMImplementationLS domImpLs;
82 domReg = DOMImplementationRegistry.newInstance();
83 domImp = domReg.getDOMImplementation("LS 3.0");
85 Object feature = domImp.getFeature("LS", "3.0");
86 assert feature instanceof DOMImplementationLS;
87 domImpLs = (DOMImplementationLS) feature;
93 * return LSInput implement.
95 * @return LSInput implement
97 public static LSInput createLSInput(){
98 LSInput input = DOM_LS.createLSInput();
103 * 絶対URIと相対URIを合成したURIを返す。
106 * @param base 絶対URIでなければならない。nullでもよい。
107 * @param relative 絶対URIでもよいがその場合baseは無視される。null可。
108 * @return 合成結果のURLオブジェクト。必ず絶対URIになる。
109 * @throws java.net.URISyntaxException URIとして変。
110 * @throws java.lang.IllegalArgumentException 絶対URIが生成できない。
112 protected static URI buildBaseRelativeURI(String base, String relative)
113 throws URISyntaxException,
114 IllegalArgumentException {
117 baseURI = new URI(base);
118 if( ! baseURI.isAbsolute() ){
119 throw new IllegalArgumentException();
126 if(relative != null){
127 relativeURI = new URI(relative);
129 relativeURI = EMPTY_URI;
132 URI result = buildBaseRelativeURI(baseURI, relativeURI);
137 * 絶対URIと相対URIを合成したURIを返す。
140 * @param baseURI 絶対URIでなければならない。nullでもよい。
141 * @param relativeURI 絶対URIでもよいがその場合baseは無視される。
142 * @return 合成結果のURLオブジェクト。必ず絶対URIになる。
143 * @throws java.lang.IllegalArgumentException 絶対URIが生成できない。
145 private static URI buildBaseRelativeURI(URI baseURI, URI relativeURI)
146 throws IllegalArgumentException {
149 if(baseURI == null || relativeURI.isAbsolute()){
150 resultURI = relativeURI;
152 resultURI = baseURI.resolve(relativeURI);
155 if( ! resultURI.isAbsolute() ){
156 throw new IllegalArgumentException();
159 resultURI = resultURI.normalize();
166 * オリジナルURIとリダイレクト先のURIを登録する。
167 * オリジナルURIへのアクセスはリダイレクトされる。
169 * @param original オリジナルURI
170 * @param redirect リダイレクトURI
172 private void putRedirectedImpl(URI original, URI redirect){
173 URI oridinalNorm = original.normalize();
174 URI redirectNorm = redirect.normalize();
176 this.uriMap.put(oridinalNorm, redirectNorm);
182 * オリジナルURIとリダイレクト先のURIを登録する。
183 * オリジナルURIへのアクセスはリダイレクトされる。
185 * @param original オリジナルURI
186 * @param redirect リダイレクトURI
188 public void putRedirected(URI original, URI redirect){
189 putRedirectedImpl(original, redirect);
194 * ローカル版リソース参照解決を登録する。
196 * @param lsc ローカル版リソース参照解決
198 public void putRedirected(LocalXmlResource lsc){
199 URI original = lsc.getOriginalResource();
200 if(original == null) return;
202 URI local = lsc.getLocalResource();
204 putRedirected(original, local);
214 public void putRedirected(XmlResourceResolver other){
215 this.uriMap.putAll(other.uriMap);
222 * @param original オリジナルURI
223 * @return リダイレクト先URI。未登録の場合はnull
225 public URI getRedirected(URI original){
226 URI keyURI = original.normalize();
227 URI resourceURI = this.uriMap.get(keyURI);
234 * @param original オリジナルURI
235 * @return リダイレクト先URI。未登録の場合はオリジナルを返す
237 public URI resolveRedirected(URI original){
238 URI result = getRedirected(original);
239 if(result == null) result = original;
244 * 登録済みリダイレクト先リソースの入力ストリームを得る。
246 * @param originalURI オリジナルURI
247 * @return 入力ストリーム。リダイレクト先が未登録の場合はnull
248 * @throws java.io.IOException 入出力エラー。
251 private InputStream getXMLResourceAsStream(URI originalURI)
253 URI resourceURI = getRedirected(originalURI);
254 if(resourceURI == null) return null;
256 URL resourceURL = resourceURI.toURL();
257 InputStream is = resourceURL.openStream();
265 * <p>URL変換したあとの入力ソースを返す。
267 * @param type {@inheritDoc}
268 * @param namespaceURI {@inheritDoc}
269 * @param publicId {@inheritDoc}
270 * @param systemId {@inheritDoc}
271 * @param baseURI {@inheritDoc}
272 * @return {@inheritDoc}
275 public LSInput resolveResource(String type,
280 if(systemId == null) return null;
284 originalURI = buildBaseRelativeURI(baseURI, systemId);
285 }catch(URISyntaxException e){
291 is = getXMLResourceAsStream(originalURI);
292 }catch(IOException e){
295 if(is == null) return null;
297 LSInput input = createLSInput();
298 input.setBaseURI(baseURI);
299 input.setPublicId(publicId);
300 input.setSystemId(systemId);
301 input.setByteStream(is);