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/xml-2009-01.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 putURIMapImpl(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 putURIMapImpl(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 putURIMap(URI original, URI redirect){
154 putURIMapImpl(original, redirect);
159 * 登録済みリダイレクト先リソースの入力ストリームを得る。
160 * @param originalURI オリジナルURI
161 * @return 入力ストリーム。リダイレクト先が未登録の場合はnull
162 * @throws java.io.IOException 入出力エラー。
165 private InputStream getXMLResourceAsStream(URI originalURI)
167 URI keyURI = originalURI.normalize();
168 URI resourceURI = this.uriMap.get(keyURI);
169 if(resourceURI == null){
173 URL resourceURL = resourceURI.toURL();
174 InputStream is = resourceURL.openStream();
181 * URL変換したあとの入力ソースを返す。
182 * @param type {@inheritDoc}
183 * @param namespaceURI {@inheritDoc}
184 * @param publicId {@inheritDoc}
185 * @param systemId {@inheritDoc}
186 * @param baseURI {@inheritDoc}
187 * @return {@inheritDoc}
190 public LSInput resolveResource(String type,
195 if(systemId == null) return null;
199 originalURI = buildBaseRelativeURI(baseURI, systemId);
200 }catch(URISyntaxException e){
206 is = getXMLResourceAsStream(originalURI);
207 }catch(IOException e){
210 if(is == null) return null;
212 LSInput input = createLSInput();
213 input.setBaseURI(baseURI);
214 input.setPublicId(publicId);
215 input.setSystemId(systemId);
216 input.setByteStream(is);
223 * URL変換したあとの入力ソースを返す。
224 * @param publicId {@inheritDoc}
225 * @param systemId {@inheritDoc}
226 * @return {@inheritDoc}
227 * @throws org.xml.sax.SAXException {@inheritDoc}
228 * @throws java.io.IOException {@inheritDoc}
231 public InputSource resolveEntity(String publicId, String systemId)
232 throws SAXException, IOException{
233 if(systemId == null) return null;
237 originalUri = new URI(systemId);
238 }catch(URISyntaxException e){
242 InputStream is = getXMLResourceAsStream(originalUri);
243 if(is == null) return null;
245 InputSource source = new InputSource(is);
246 source.setPublicId(publicId);
247 source.setSystemId(systemId);
255 * org.w3c.dom.ls.DOMImplementationLS#createLSInput()
258 private static final class LSInputImpl implements LSInput {
260 private String baseURI = null;
261 private InputStream byteStream = null;
262 private boolean certifiedText = false;
263 private Reader characterStream = null;
264 private String encoding = null;
265 private String publicId = null;
266 private String stringData = null;
267 private String systemId = null;
279 * @return {@inheritDoc}
282 public String getBaseURI(){
288 * @param baseURI {@inheritDoc}
291 public void setBaseURI(String baseURI){
292 this.baseURI = baseURI;
298 * @return {@inheritDoc}
301 public InputStream getByteStream(){
302 return this.byteStream;
307 * @param byteStream {@inheritDoc}
310 public void setByteStream(InputStream byteStream){
311 this.byteStream = byteStream;
316 * @return {@inheritDoc}
319 public boolean getCertifiedText(){
320 return this.certifiedText;
325 * @param certifiedText {@inheritDoc}
328 public void setCertifiedText(boolean certifiedText){
329 this.certifiedText = certifiedText;
335 * @return {@inheritDoc}
338 public Reader getCharacterStream(){
339 return this.characterStream;
344 * @param characterStream {@inheritDoc}
347 public void setCharacterStream(Reader characterStream){
348 this.characterStream = characterStream;
353 * @return {@inheritDoc}
356 public String getEncoding(){
357 return this.encoding;
362 * @param encoding {@inheritDoc}
365 public void setEncoding(String encoding){
366 this.encoding = encoding;
372 * @return {@inheritDoc}
375 public String getPublicId(){
376 return this.publicId;
381 * @param publicId {@inheritDoc}
384 public void setPublicId(String publicId){
385 this.publicId = publicId;
391 * @return {@inheritDoc}
394 public String getStringData(){
395 return this.stringData;
400 * @param stringData {@inheritDoc}
403 public void setStringData(String stringData){
404 this.stringData = stringData;
410 * @return {@inheritDoc}
413 public String getSystemId(){
414 return this.systemId;
419 * @param systemId {@inheritDoc}
422 public void setSystemId(String systemId){
423 this.systemId = systemId;