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.HashMap;
18 import org.w3c.dom.ls.LSInput;
19 import org.w3c.dom.ls.LSResourceResolver;
20 import org.xml.sax.EntityResolver;
21 import org.xml.sax.InputSource;
22 import org.xml.sax.SAXException;
25 * URL変換マップに従い、XML文書からの外部参照をリダイレクトする。
26 * 相対URIはこのクラスをベースに解決される。
27 * 主な用途は外部スキーマのリソース化など。
29 public class XmlResourceResolver
30 implements LSResourceResolver, EntityResolver {
33 public static final String SCHEMA_XML =
34 "http://www.w3.org/2001/xml.xsd";
37 public static final String NS_XSD =
38 "http://www.w3.org/2001/XMLSchema-instance";
40 private static final String LOCAL_SCHEMA_XML =
41 "resources/xml-2009-01.xsd";
42 private static final URI EMPTY_URI = URI.create("");
43 private static final Class<?> THISCLASS = XmlResourceResolver.class;
45 private final Map<URI, URI> uriMap = new HashMap<URI, URI>();
50 public XmlResourceResolver(){
53 assert this.getClass().equals(THISCLASS);
55 URI originalURI = URI.create(SCHEMA_XML);
56 URL redirectURL = THISCLASS.getResource(LOCAL_SCHEMA_XML);
59 redirectURI = redirectURL.toURI();
60 }catch(URISyntaxException e){
62 throw new AssertionError(e);
65 this.uriMap.put(originalURI, redirectURI);
71 * 絶対URIと相対URIを合成したURIを返す。
73 * @param base 絶対URIでなければならない。nullでもよい。
74 * @param relative 絶対URIでもよいがその場合baseは無視される。null可。
75 * @return 合成結果のURLオブジェクト。必ず絶対URIになる。
76 * @throws java.net.URISyntaxException URIとして変。
77 * @throws java.lang.IllegalArgumentException 絶対URIが生成できない。
79 protected static URI buildBaseRelativeURI(String base, String relative)
80 throws URISyntaxException,
81 IllegalArgumentException {
84 baseURI = new URI(base);
85 if( ! baseURI.isAbsolute() ) throw new IllegalArgumentException();
88 URI relativeURI = EMPTY_URI;
90 relativeURI = new URI(relative);
94 if(baseURI == null || relativeURI.isAbsolute()){
95 resultURI = relativeURI;
97 resultURI = baseURI.resolve(relativeURI);
100 if( ! resultURI.isAbsolute() ) throw new IllegalArgumentException();
102 resultURI = resultURI.normalize();
111 public static LSInput createLSInput(){
112 LSInput input = new LSInputImpl();
117 * オリジナルURIとリダイレクト先のURIを登録する。
118 * オリジナルURIへのアクセスはリダイレクトされる。
119 * @param original オリジナルURI
120 * @param redirect リダイレクトURI
122 public void putURIMap(URI original, URI redirect){
123 this.uriMap.put(original.normalize(), redirect.normalize());
128 * 変換後のリソースの入力ストリームを得る。
129 * @param originalURI オリジナルURI
131 * @throws java.io.IOException 入出力エラー
133 public InputStream getXMLResourceAsStream(URI originalURI)
135 URI resourceURI = this.uriMap.get(originalURI.normalize());
136 URL resourceURL = resourceURI.toURL();
137 InputStream is = resourceURL.openStream();
144 * URL変換したあとの入力ソースを返す。
145 * @param type {@inheritDoc}
146 * @param namespaceURI {@inheritDoc}
147 * @param publicId {@inheritDoc}
148 * @param systemId {@inheritDoc}
149 * @param baseURI {@inheritDoc}
150 * @return {@inheritDoc}
153 public LSInput resolveResource(String type,
158 if(systemId == null) return null;
162 originalURI = buildBaseRelativeURI(baseURI, systemId);
163 }catch(URISyntaxException e){
169 is = getXMLResourceAsStream(originalURI);
170 }catch(IOException e){
174 LSInput input = createLSInput();
175 input.setBaseURI(baseURI);
176 input.setPublicId(publicId);
177 input.setSystemId(systemId);
178 input.setByteStream(is);
185 * URL変換したあとの入力ソースを返す。
186 * @param publicId {@inheritDoc}
187 * @param systemId {@inheritDoc}
188 * @return {@inheritDoc}
189 * @throws org.xml.sax.SAXException {@inheritDoc}
190 * @throws java.io.IOException {@inheritDoc}
193 public InputSource resolveEntity(String publicId, String systemId)
194 throws SAXException, IOException{
195 if(systemId == null) return null;
199 originalUri = new URI(systemId);
200 }catch(URISyntaxException e){
204 InputStream is = getXMLResourceAsStream(originalUri);
206 InputSource source = new InputSource(is);
207 source.setPublicId(publicId);
208 source.setSystemId(systemId);
216 * org.w3c.dom.ls.DOMImplementationLS#createLSInput()
219 private static final class LSInputImpl implements LSInput {
221 private String baseURI = null;
222 private InputStream byteStream = null;
223 private boolean certifiedText = false;
224 private Reader characterStream = null;
225 private String encoding = null;
226 private String publicId = null;
227 private String stringData = null;
228 private String systemId = null;
240 * @return {@inheritDoc}
243 public String getBaseURI(){
249 * @param baseURI {@inheritDoc}
252 public void setBaseURI(String baseURI){
253 this.baseURI = baseURI;
259 * @return {@inheritDoc}
262 public InputStream getByteStream(){
263 return this.byteStream;
268 * @param byteStream {@inheritDoc}
271 public void setByteStream(InputStream byteStream){
272 this.byteStream = byteStream;
277 * @return {@inheritDoc}
280 public boolean getCertifiedText(){
281 return this.certifiedText;
286 * @param certifiedText {@inheritDoc}
289 public void setCertifiedText(boolean certifiedText){
290 this.certifiedText = certifiedText;
296 * @return {@inheritDoc}
299 public Reader getCharacterStream(){
300 return this.characterStream;
305 * @param characterStream {@inheritDoc}
308 public void setCharacterStream(Reader characterStream){
309 this.characterStream = characterStream;
314 * @return {@inheritDoc}
317 public String getEncoding(){
318 return this.encoding;
323 * @param encoding {@inheritDoc}
326 public void setEncoding(String encoding){
327 this.encoding = encoding;
333 * @return {@inheritDoc}
336 public String getPublicId(){
337 return this.publicId;
342 * @param publicId {@inheritDoc}
345 public void setPublicId(String publicId){
346 this.publicId = publicId;
352 * @return {@inheritDoc}
355 public String getStringData(){
356 return this.stringData;
361 * @param stringData {@inheritDoc}
364 public void setStringData(String stringData){
365 this.stringData = stringData;
371 * @return {@inheritDoc}
374 public String getSystemId(){
375 return this.systemId;
380 * @param systemId {@inheritDoc}
383 public void setSystemId(String systemId){
384 this.systemId = systemId;
390 // TODO OASIS XML Catalog などと調和したい。