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 {
32 public static final String SCHEMA_XML =
33 "http://www.w3.org/2001/xml.xsd";
34 public static final String NS_XSD =
35 "http://www.w3.org/2001/XMLSchema-instance";
37 private static final String LOCAL_SCHEMA_XML =
38 "resources/xml-2009-01.xsd";
39 private static final URI EMPTY_URI = URI.create("");
40 private static final Class THISCLASS = XmlResourceResolver.class;
42 private final Map<URI, URI> uriMap = new HashMap<URI, URI>();
47 public XmlResourceResolver(){
50 assert this.getClass().equals(THISCLASS);
52 URI originalURI = URI.create(SCHEMA_XML);
53 URL redirectURL = THISCLASS.getResource(LOCAL_SCHEMA_XML);
56 redirectURI = redirectURL.toURI();
57 }catch(URISyntaxException e){
59 throw new AssertionError(e);
62 this.uriMap.put(originalURI, redirectURI);
68 * 絶対URIと相対URIを合成したURIを返す。
70 * @param base 絶対URIでなければならない。nullでもよい。
71 * @param relative 絶対URIでもよいがその場合baseは無視される。null可。
72 * @return 合成結果のURLオブジェクト。必ず絶対URIになる。
73 * @throws java.net.URISyntaxException URIとして変。
74 * @throws java.lang.IllegalArgumentException 絶対URIが生成できない。
76 protected static URI buildBaseRelativeURI(String base, String relative)
77 throws URISyntaxException,
78 IllegalArgumentException {
81 baseURI = new URI(base);
82 if( ! baseURI.isAbsolute() ) throw new IllegalArgumentException();
85 URI relativeURI = EMPTY_URI;
87 relativeURI = new URI(relative);
91 if(baseURI == null || relativeURI.isAbsolute()){
92 resultURI = relativeURI;
94 resultURI = baseURI.resolve(relativeURI);
97 if( ! resultURI.isAbsolute() ) throw new IllegalArgumentException();
99 resultURI = resultURI.normalize();
108 public static LSInput createLSInput(){
109 LSInput input = new LSInputImpl();
114 * オリジナルURIとリダイレクト先のURIを登録する。
115 * オリジナルURIへのアクセスはリダイレクトされる。
116 * @param original オリジナルURI
117 * @param redirect リダイレクトURI
119 public void putURIMap(URI original, URI redirect){
120 this.uriMap.put(original.normalize(), redirect.normalize());
125 * 変換後のリソースの入力ストリームを得る。
126 * @param originalURI オリジナルURI
128 * @throws java.io.IOException 入出力エラー
130 public InputStream getXMLResourceAsStream(URI originalURI)
132 URI resourceURI = this.uriMap.get(originalURI.normalize());
133 URL resourceURL = resourceURI.toURL();
134 InputStream is = resourceURL.openStream();
141 * URL変換したあとの入力ソースを返す。
142 * @param type {@inheritDoc}
143 * @param namespaceURI {@inheritDoc}
144 * @param publicId {@inheritDoc}
145 * @param systemId {@inheritDoc}
146 * @param baseURI {@inheritDoc}
147 * @return {@inheritDoc}
150 public LSInput resolveResource(String type,
155 if(systemId == null) return null;
159 originalURI = buildBaseRelativeURI(baseURI, systemId);
160 }catch(URISyntaxException e){
166 is = getXMLResourceAsStream(originalURI);
167 }catch(IOException e){
171 LSInput input = createLSInput();
172 input.setBaseURI(baseURI);
173 input.setPublicId(publicId);
174 input.setSystemId(systemId);
175 input.setByteStream(is);
182 * URL変換したあとの入力ソースを返す。
183 * @param publicId {@inheritDoc}
184 * @param systemId {@inheritDoc}
185 * @return {@inheritDoc}
186 * @throws org.xml.sax.SAXException {@inheritDoc}
187 * @throws java.io.IOException {@inheritDoc}
190 public InputSource resolveEntity(String publicId, String systemId)
191 throws SAXException, IOException{
192 if(systemId == null) return null;
196 originalUri = new URI(systemId);
197 }catch(URISyntaxException e){
201 InputStream is = getXMLResourceAsStream(originalUri);
203 InputSource source = new InputSource(is);
204 source.setPublicId(publicId);
205 source.setSystemId(systemId);
213 * org.w3c.dom.ls.DOMImplementationLS#createLSInput()
216 private static final class LSInputImpl implements LSInput {
218 private String baseURI = null;
219 private InputStream byteStream = null;
220 private boolean certifiedText = false;
221 private Reader characterStream = null;
222 private String encoding = null;
223 private String publicId = null;
224 private String stringData = null;
225 private String systemId = null;
230 private LSInputImpl(){
237 * @return {@inheritDoc}
240 public String getBaseURI(){
246 * @param baseURI {@inheritDoc}
249 public void setBaseURI(String baseURI){
250 this.baseURI = baseURI;
256 * @return {@inheritDoc}
259 public InputStream getByteStream(){
260 return this.byteStream;
265 * @param byteStream {@inheritDoc}
268 public void setByteStream(InputStream byteStream){
269 this.byteStream = byteStream;
274 * @return {@inheritDoc}
277 public boolean getCertifiedText(){
278 return this.certifiedText;
283 * @param certifiedText {@inheritDoc}
286 public void setCertifiedText(boolean certifiedText){
287 this.certifiedText = certifiedText;
293 * @return {@inheritDoc}
296 public Reader getCharacterStream(){
297 return this.characterStream;
302 * @param characterStream {@inheritDoc}
305 public void setCharacterStream(Reader characterStream){
306 this.characterStream = characterStream;
311 * @return {@inheritDoc}
314 public String getEncoding(){
315 return this.encoding;
320 * @param encoding {@inheritDoc}
323 public void setEncoding(String encoding){
324 this.encoding = encoding;
330 * @return {@inheritDoc}
333 public String getPublicId(){
334 return this.publicId;
339 * @param publicId {@inheritDoc}
342 public void setPublicId(String publicId){
343 this.publicId = publicId;
349 * @return {@inheritDoc}
352 public String getStringData(){
353 return this.stringData;
358 * @param stringData {@inheritDoc}
361 public void setStringData(String stringData){
362 this.stringData = stringData;
368 * @return {@inheritDoc}
371 public String getSystemId(){
372 return this.systemId;
377 * @param systemId {@inheritDoc}
380 public void setSystemId(String systemId){
381 this.systemId = systemId;
387 // TODO OASIS XML Catalog などと調和したい。