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;
12 import java.io.Reader;
14 import java.net.URISyntaxException;
16 import java.util.Collections;
17 import java.util.HashMap;
19 import org.w3c.dom.ls.LSInput;
20 import org.w3c.dom.ls.LSResourceResolver;
23 * URL変換マップに従い、XML文書からの外部参照をリダイレクトする。
24 * 相対URIはこのクラスをベースに解決される。
25 * 主な用途は外部スキーマのリソース化など。
27 public class XmlResourceResolver
28 implements LSResourceResolver{
30 private static final URI EMPTY_URI = URI.create("");
33 private final Map<URI, URI> uriMap;
39 public XmlResourceResolver(){
43 map = new HashMap<>();
44 map = Collections.synchronizedMap(map);
52 * 絶対URIと相対URIを合成したURIを返す。
55 * @param base 絶対URIでなければならない。nullでもよい。
56 * @param relative 絶対URIでもよいがその場合baseは無視される。null可。
57 * @return 合成結果のURLオブジェクト。必ず絶対URIになる。
58 * @throws java.net.URISyntaxException URIとして変。
59 * @throws java.lang.IllegalArgumentException 絶対URIが生成できない。
61 protected static URI buildBaseRelativeURI(String base, String relative)
62 throws URISyntaxException,
63 IllegalArgumentException {
66 baseURI = new URI(base);
67 if( ! baseURI.isAbsolute() ){
68 throw new IllegalArgumentException();
76 relativeURI = new URI(relative);
78 relativeURI = EMPTY_URI;
81 URI result = buildBaseRelativeURI(baseURI, relativeURI);
86 * 絶対URIと相対URIを合成したURIを返す。
89 * @param baseURI 絶対URIでなければならない。nullでもよい。
90 * @param relativeURI 絶対URIでもよいがその場合baseは無視される。
91 * @return 合成結果のURLオブジェクト。必ず絶対URIになる。
92 * @throws java.lang.IllegalArgumentException 絶対URIが生成できない。
94 private static URI buildBaseRelativeURI(URI baseURI, URI relativeURI)
95 throws IllegalArgumentException {
98 if(baseURI == null || relativeURI.isAbsolute()){
99 resultURI = relativeURI;
101 resultURI = baseURI.resolve(relativeURI);
104 if( ! resultURI.isAbsolute() ){
105 throw new IllegalArgumentException();
108 resultURI = resultURI.normalize();
117 public static LSInput createLSInput(){
118 LSInput input = new LSInputImpl();
124 * オリジナルURIとリダイレクト先のURIを登録する。
125 * オリジナルURIへのアクセスはリダイレクトされる。
126 * @param original オリジナルURI
127 * @param redirect リダイレクトURI
129 private void putRedirectedImpl(URI original, URI redirect){
130 URI oridinalNorm = original.normalize();
131 URI redirectNorm = redirect.normalize();
133 this.uriMap.put(oridinalNorm, redirectNorm);
139 * オリジナルURIとリダイレクト先のURIを登録する。
140 * オリジナルURIへのアクセスはリダイレクトされる。
141 * @param original オリジナルURI
142 * @param redirect リダイレクトURI
144 public void putRedirected(URI original, URI redirect){
145 putRedirectedImpl(original, redirect);
150 * ローカル版リソース参照解決を登録する。
151 * @param lsc ローカル版リソース参照解決
153 public void putRedirected(LocalXmlResource lsc){
154 URI original = lsc.getOriginalResource();
155 if(original == null) return;
157 URI local = lsc.getLocalResource();
159 putRedirected(original, local);
168 public void putRedirected(XmlResourceResolver other){
169 this.uriMap.putAll(other.uriMap);
175 * @param original オリジナルURI
176 * @return リダイレクト先URI。未登録の場合はnull
178 public URI getRedirected(URI original){
179 URI keyURI = original.normalize();
180 URI resourceURI = this.uriMap.get(keyURI);
186 * @param original オリジナルURI
187 * @return リダイレクト先URI。未登録の場合はオリジナルを返す
189 public URI resolveRedirected(URI original){
190 URI result = getRedirected(original);
191 if(result == null) result = original;
196 * 登録済みリダイレクト先リソースの入力ストリームを得る。
197 * @param originalURI オリジナルURI
198 * @return 入力ストリーム。リダイレクト先が未登録の場合はnull
199 * @throws java.io.IOException 入出力エラー。
202 private InputStream getXMLResourceAsStream(URI originalURI)
204 URI resourceURI = getRedirected(originalURI);
205 if(resourceURI == null) return null;
207 URL resourceURL = resourceURI.toURL();
208 InputStream is = resourceURL.openStream();
215 * URL変換したあとの入力ソースを返す。
216 * @param type {@inheritDoc}
217 * @param namespaceURI {@inheritDoc}
218 * @param publicId {@inheritDoc}
219 * @param systemId {@inheritDoc}
220 * @param baseURI {@inheritDoc}
221 * @return {@inheritDoc}
224 public LSInput resolveResource(String type,
229 if(systemId == null) return null;
233 originalURI = buildBaseRelativeURI(baseURI, systemId);
234 }catch(URISyntaxException e){
240 is = getXMLResourceAsStream(originalURI);
241 }catch(IOException e){
244 if(is == null) return null;
246 LSInput input = createLSInput();
247 input.setBaseURI(baseURI);
248 input.setPublicId(publicId);
249 input.setSystemId(systemId);
250 input.setByteStream(is);
259 * org.w3c.dom.ls.DOMImplementationLS#createLSInput()
262 private static final class LSInputImpl implements LSInput {
264 private String baseURI = null;
265 private InputStream byteStream = null;
266 private boolean certifiedText = false;
267 private Reader characterStream = null;
268 private String encoding = null;
269 private String publicId = null;
270 private String stringData = null;
271 private String systemId = null;
283 * @return {@inheritDoc}
286 public String getBaseURI(){
292 * @param baseURI {@inheritDoc}
295 public void setBaseURI(String baseURI){
296 this.baseURI = baseURI;
302 * @return {@inheritDoc}
305 public InputStream getByteStream(){
306 return this.byteStream;
311 * @param byteStream {@inheritDoc}
314 public void setByteStream(InputStream byteStream){
315 this.byteStream = byteStream;
320 * @return {@inheritDoc}
323 public boolean getCertifiedText(){
324 return this.certifiedText;
329 * @param certifiedText {@inheritDoc}
332 public void setCertifiedText(boolean certifiedText){
333 this.certifiedText = certifiedText;
339 * @return {@inheritDoc}
342 public Reader getCharacterStream(){
343 return this.characterStream;
348 * @param characterStream {@inheritDoc}
351 public void setCharacterStream(Reader characterStream){
352 this.characterStream = characterStream;
357 * @return {@inheritDoc}
360 public String getEncoding(){
361 return this.encoding;
366 * @param encoding {@inheritDoc}
369 public void setEncoding(String encoding){
370 this.encoding = encoding;
376 * @return {@inheritDoc}
379 public String getPublicId(){
380 return this.publicId;
385 * @param publicId {@inheritDoc}
388 public void setPublicId(String publicId){
389 this.publicId = publicId;
395 * @return {@inheritDoc}
398 public String getStringData(){
399 return this.stringData;
404 * @param stringData {@inheritDoc}
407 public void setStringData(String stringData){
408 this.stringData = stringData;
414 * @return {@inheritDoc}
417 public String getSystemId(){
418 return this.systemId;
423 * @param systemId {@inheritDoc}
426 public void setSystemId(String systemId){
427 this.systemId = systemId;