2 * xml resource resolver
4 * License : The MIT License
5 * Copyright(c) 2009 olyutorskii
8 package jp.sourceforge.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;
21 import org.xml.sax.EntityResolver;
22 import org.xml.sax.InputSource;
23 import org.xml.sax.SAXException;
26 * URL変換マップに従い、XML文書からの外部参照をリダイレクトする。
27 * 相対URIはこのクラスをベースに解決される。
28 * 主な用途は外部スキーマのリソース化など。
30 public class XmlResourceResolver
31 implements LSResourceResolver, EntityResolver {
34 public static final String SCHEMA_XML =
35 "http://www.w3.org/2001/xml.xsd";
38 public static final String NS_XSD =
39 "http://www.w3.org/2001/XMLSchema-instance";
41 private static final String LOCAL_SCHEMA_XML =
42 "resources/xmlspace.xsd";
44 private static final URI EMPTY_URI = URI.create("");
46 private static final Class<?> THISCLASS = XmlResourceResolver.class;
49 private final Map<URI, URI> uriMap;
55 public XmlResourceResolver(){
58 assert this.getClass().equals(THISCLASS);
61 map = new HashMap<URI, URI>();
62 map = Collections.synchronizedMap(map);
65 URL redirectRes = THISCLASS.getResource(LOCAL_SCHEMA_XML);
66 String redirectResName = redirectRes.toString();
68 URI originalURI = URI.create(SCHEMA_XML);
69 URI redirectURI = URI.create(redirectResName);
71 putRedirectedImpl(originalURI, redirectURI);
78 * 絶対URIと相対URIを合成したURIを返す。
80 * @param base 絶対URIでなければならない。nullでもよい。
81 * @param relative 絶対URIでもよいがその場合baseは無視される。null可。
82 * @return 合成結果のURLオブジェクト。必ず絶対URIになる。
83 * @throws java.net.URISyntaxException URIとして変。
84 * @throws java.lang.IllegalArgumentException 絶対URIが生成できない。
86 protected static URI buildBaseRelativeURI(String base, String relative)
87 throws URISyntaxException,
88 IllegalArgumentException {
91 baseURI = new URI(base);
92 if( ! baseURI.isAbsolute() ){
93 throw new IllegalArgumentException();
100 if(relative != null){
101 relativeURI = new URI(relative);
103 relativeURI = EMPTY_URI;
107 if(baseURI == null || relativeURI.isAbsolute()){
108 resultURI = relativeURI;
110 resultURI = baseURI.resolve(relativeURI);
113 if( ! resultURI.isAbsolute() ){
114 throw new IllegalArgumentException();
117 resultURI = resultURI.normalize();
126 public static LSInput createLSInput(){
127 LSInput input = new LSInputImpl();
133 * オリジナルURIとリダイレクト先のURIを登録する。
134 * オリジナルURIへのアクセスはリダイレクトされる。
135 * @param original オリジナルURI
136 * @param redirect リダイレクトURI
138 private void putRedirectedImpl(URI original, URI redirect){
139 URI oridinalNorm = original.normalize();
140 URI redirectNorm = redirect.normalize();
142 this.uriMap.put(oridinalNorm, redirectNorm);
148 * オリジナルURIとリダイレクト先のURIを登録する。
149 * オリジナルURIへのアクセスはリダイレクトされる。
150 * @param original オリジナルURI
151 * @param redirect リダイレクトURI
153 public void putRedirected(URI original, URI redirect){
154 putRedirectedImpl(original, redirect);
162 public void putRedirected(XmlResourceResolver other){
163 this.uriMap.putAll(other.uriMap);
169 * @param original オリジナルURI
170 * @return リダイレクト先URI。未登録の場合はnull
172 public URI getRedirected(URI original){
173 URI keyURI = original.normalize();
174 URI resourceURI = this.uriMap.get(keyURI);
180 * @param original オリジナルURI
181 * @return リダイレクト先URI。未登録の場合はオリジナルを返す
183 public URI resolveRedirected(URI original){
184 URI result = getRedirected(original);
185 if(result == null) result = original;
190 * 登録済みリダイレクト先リソースの入力ストリームを得る。
191 * @param originalURI オリジナルURI
192 * @return 入力ストリーム。リダイレクト先が未登録の場合はnull
193 * @throws java.io.IOException 入出力エラー。
196 private InputStream getXMLResourceAsStream(URI originalURI)
198 URI resourceURI = getRedirected(originalURI);
199 if(resourceURI == null) return null;
201 URL resourceURL = resourceURI.toURL();
202 InputStream is = resourceURL.openStream();
209 * URL変換したあとの入力ソースを返す。
210 * @param type {@inheritDoc}
211 * @param namespaceURI {@inheritDoc}
212 * @param publicId {@inheritDoc}
213 * @param systemId {@inheritDoc}
214 * @param baseURI {@inheritDoc}
215 * @return {@inheritDoc}
218 public LSInput resolveResource(String type,
223 if(systemId == null) return null;
227 originalURI = buildBaseRelativeURI(baseURI, systemId);
228 }catch(URISyntaxException e){
234 is = getXMLResourceAsStream(originalURI);
235 }catch(IOException e){
238 if(is == null) return null;
240 LSInput input = createLSInput();
241 input.setBaseURI(baseURI);
242 input.setPublicId(publicId);
243 input.setSystemId(systemId);
244 input.setByteStream(is);
251 * URL変換したあとの入力ソースを返す。
252 * @param publicId {@inheritDoc}
253 * @param systemId {@inheritDoc}
254 * @return {@inheritDoc}
255 * @throws org.xml.sax.SAXException {@inheritDoc}
256 * @throws java.io.IOException {@inheritDoc}
259 public InputSource resolveEntity(String publicId, String systemId)
260 throws SAXException, IOException{
261 if(systemId == null) return null;
265 originalUri = new URI(systemId);
266 }catch(URISyntaxException e){
270 InputStream is = getXMLResourceAsStream(originalUri);
271 if(is == null) return null;
273 InputSource source = new InputSource(is);
274 source.setPublicId(publicId);
275 source.setSystemId(systemId);
283 * org.w3c.dom.ls.DOMImplementationLS#createLSInput()
286 private static final class LSInputImpl implements LSInput {
288 private String baseURI = null;
289 private InputStream byteStream = null;
290 private boolean certifiedText = false;
291 private Reader characterStream = null;
292 private String encoding = null;
293 private String publicId = null;
294 private String stringData = null;
295 private String systemId = null;
307 * @return {@inheritDoc}
310 public String getBaseURI(){
316 * @param baseURI {@inheritDoc}
319 public void setBaseURI(String baseURI){
320 this.baseURI = baseURI;
326 * @return {@inheritDoc}
329 public InputStream getByteStream(){
330 return this.byteStream;
335 * @param byteStream {@inheritDoc}
338 public void setByteStream(InputStream byteStream){
339 this.byteStream = byteStream;
344 * @return {@inheritDoc}
347 public boolean getCertifiedText(){
348 return this.certifiedText;
353 * @param certifiedText {@inheritDoc}
356 public void setCertifiedText(boolean certifiedText){
357 this.certifiedText = certifiedText;
363 * @return {@inheritDoc}
366 public Reader getCharacterStream(){
367 return this.characterStream;
372 * @param characterStream {@inheritDoc}
375 public void setCharacterStream(Reader characterStream){
376 this.characterStream = characterStream;
381 * @return {@inheritDoc}
384 public String getEncoding(){
385 return this.encoding;
390 * @param encoding {@inheritDoc}
393 public void setEncoding(String encoding){
394 this.encoding = encoding;
400 * @return {@inheritDoc}
403 public String getPublicId(){
404 return this.publicId;
409 * @param publicId {@inheritDoc}
412 public void setPublicId(String publicId){
413 this.publicId = publicId;
419 * @return {@inheritDoc}
422 public String getStringData(){
423 return this.stringData;
428 * @param stringData {@inheritDoc}
431 public void setStringData(String stringData){
432 this.stringData = stringData;
438 * @return {@inheritDoc}
441 public String getSystemId(){
442 return this.systemId;
447 * @param systemId {@inheritDoc}
450 public void setSystemId(String systemId){
451 this.systemId = systemId;