OSDN Git Service

PMD出力機能及びXML入出力機能のソースをマージ
[mikutoga/TogaGem.git] / src / main / java / jp / sourceforge / mikutoga / xml / XmlResourceResolver.java
1 /*\r
2  * xml resource resolver\r
3  *\r
4  * License : The MIT License\r
5  * Copyright(c) 2009 olyutorskii\r
6  */\r
7 \r
8 package jp.sourceforge.mikutoga.xml;\r
9 \r
10 import java.io.IOException;\r
11 import java.io.InputStream;\r
12 import java.io.Reader;\r
13 import java.net.URI;\r
14 import java.net.URISyntaxException;\r
15 import java.net.URL;\r
16 import java.util.HashMap;\r
17 import java.util.Map;\r
18 import org.w3c.dom.ls.LSInput;\r
19 import org.w3c.dom.ls.LSResourceResolver;\r
20 import org.xml.sax.EntityResolver;\r
21 import org.xml.sax.InputSource;\r
22 import org.xml.sax.SAXException;\r
23 \r
24 /**\r
25  * URL変換マップに従い、XML文書からの外部参照をリダイレクトする。\r
26  * 相対URIはこのクラスをベースに解決される。\r
27  * 主な用途は外部スキーマのリソース化など。\r
28  */\r
29 public class XmlResourceResolver\r
30         implements LSResourceResolver, EntityResolver {\r
31 \r
32     public static final String SCHEMA_XML =\r
33             "http://www.w3.org/2001/xml.xsd";\r
34     public static final String NS_XSD =\r
35             "http://www.w3.org/2001/XMLSchema-instance";\r
36 \r
37     private static final String LOCAL_SCHEMA_XML =\r
38             "./resources/xml-2009-01.xsd";\r
39     private static final URI EMPTY_URI = URI.create("");\r
40     private static final Class THISCLASS = XmlResourceResolver.class;\r
41 \r
42 \r
43     /**\r
44      * 絶対URIと相対URIを合成したURIを返す。\r
45      * 正規化も行われる。\r
46      * @param base 絶対URIでなければならない。nullでもよい。\r
47      * @param relative 絶対URIでもよいがその場合baseは無視される。null可。\r
48      * @return 合成結果のURLオブジェクト。必ず絶対URIになる。\r
49      * @throws java.net.URISyntaxException URIとして変。\r
50      * @throws java.lang.IllegalArgumentException 絶対URIが生成できない。\r
51      */\r
52     protected static URI buildBaseRelativeURI(String base, String relative)\r
53             throws URISyntaxException,\r
54                    IllegalArgumentException {\r
55         URI baseURI = null;\r
56         if(base != null){\r
57             baseURI = new URI(base);\r
58             if( ! baseURI.isAbsolute() ) throw new IllegalArgumentException();\r
59         }\r
60 \r
61         URI relativeURI = EMPTY_URI;\r
62         if(relative != null){\r
63             relativeURI = new URI(relative);\r
64         }\r
65 \r
66         URI resultURI;\r
67         if(baseURI == null || relativeURI.isAbsolute()){\r
68             resultURI = relativeURI;\r
69         }else{\r
70             resultURI = baseURI.resolve(relativeURI);\r
71         }\r
72 \r
73         if( ! resultURI.isAbsolute() ) throw new IllegalArgumentException();\r
74 \r
75         resultURI = resultURI.normalize();\r
76 \r
77         return resultURI;\r
78     }\r
79 \r
80     /**\r
81      * LSInput実装を生成する。\r
82      * @return LSInput実装\r
83      */\r
84     public static LSInput createLSInput(){\r
85         LSInput input = new LSInputImpl();\r
86         return input;\r
87     }\r
88 \r
89     private final Map<URI, URI> uriMap = new HashMap<URI, URI>();\r
90 \r
91     /**\r
92      * コンストラクタ。\r
93      */\r
94     public XmlResourceResolver(){\r
95         super();\r
96 \r
97         assert this.getClass().equals(THISCLASS);\r
98 \r
99         URI originalURI = URI.create(SCHEMA_XML);\r
100         URL redirectURL = THISCLASS.getResource(LOCAL_SCHEMA_XML);\r
101         URI redirectURI;\r
102         try{\r
103             redirectURI = redirectURL.toURI();\r
104         }catch(URISyntaxException e){\r
105             assert false;\r
106             throw new AssertionError(e);\r
107         }\r
108 \r
109         this.uriMap.put(originalURI, redirectURI);\r
110 \r
111         return;\r
112     }\r
113 \r
114     /**\r
115      * オリジナルURIとリダイレクト先のURIを登録する。\r
116      * オリジナルURIへのアクセスはリダイレクトされる。\r
117      * @param original オリジナルURI\r
118      * @param redirect リダイレクトURI\r
119      */\r
120     public void putURIMap(URI original, URI redirect){\r
121         this.uriMap.put(original.normalize(), redirect.normalize());\r
122         return;\r
123     }\r
124 \r
125     /**\r
126      * 変換後のリソースの入力ストリームを得る。\r
127      * @param originalURI オリジナルURI\r
128      * @return 入力ストリーム\r
129      * @throws java.io.IOException 入出力エラー\r
130      */\r
131     public InputStream getXMLResourceAsStream(URI originalURI)\r
132             throws IOException{\r
133         URI resourceURI = this.uriMap.get(originalURI.normalize());\r
134         URL resourceURL = resourceURI.toURL();\r
135         InputStream is = resourceURL.openStream();\r
136 \r
137         return is;\r
138     }\r
139 \r
140     /**\r
141      * {@inheritDoc}\r
142      * URL変換したあとの入力ソースを返す。\r
143      * @param type {@inheritDoc}\r
144      * @param namespaceURI {@inheritDoc}\r
145      * @param publicId {@inheritDoc}\r
146      * @param systemId {@inheritDoc}\r
147      * @param baseURI {@inheritDoc}\r
148      * @return {@inheritDoc}\r
149      */\r
150     public LSInput resolveResource(String type,\r
151                                      String namespaceURI,\r
152                                      String publicId,\r
153                                      String systemId,\r
154                                      String baseURI ){\r
155         if(systemId == null) return null;\r
156 \r
157         URI originalURI;\r
158         try{\r
159             originalURI = buildBaseRelativeURI(baseURI, systemId);\r
160         }catch(URISyntaxException e){\r
161             return null;\r
162         }\r
163 \r
164         InputStream is;\r
165         try{\r
166             is = getXMLResourceAsStream(originalURI);\r
167         }catch(IOException e){\r
168             return null;\r
169         }\r
170 \r
171         LSInput input = createLSInput();\r
172         input.setBaseURI(baseURI);\r
173         input.setPublicId(publicId);\r
174         input.setSystemId(systemId);\r
175         input.setByteStream(is);\r
176 \r
177         return input;\r
178     }\r
179 \r
180     /**\r
181      * {@inheritDoc}\r
182      * URL変換したあとの入力ソースを返す。\r
183      * @param publicId {@inheritDoc}\r
184      * @param systemId {@inheritDoc}\r
185      * @return {@inheritDoc}\r
186      * @throws org.xml.sax.SAXException {@inheritDoc}\r
187      * @throws java.io.IOException {@inheritDoc}\r
188      */\r
189     public InputSource resolveEntity(String publicId, String systemId)\r
190             throws SAXException, IOException{\r
191         if(systemId == null) return null;\r
192 \r
193         URI originalUri;\r
194         try{\r
195             originalUri = new URI(systemId);\r
196         }catch(URISyntaxException e){\r
197             return null;\r
198         }\r
199 \r
200         InputStream is = getXMLResourceAsStream(originalUri);\r
201 \r
202         InputSource source = new InputSource(is);\r
203         source.setPublicId(publicId);\r
204         source.setSystemId(systemId);\r
205 \r
206         return source;\r
207     }\r
208 \r
209     /**\r
210      * JRE1.5用LSInput実装。\r
211      * JRE1.6なら\r
212      * org.w3c.dom.ls.DOMImplementationLS#createLSInput()\r
213      * で生成可能かも。\r
214      */\r
215     private static class LSInputImpl implements LSInput {\r
216 \r
217         private String baseURI = null;\r
218         private InputStream byteStream = null;\r
219         private boolean certifiedText = false;\r
220         private Reader characterStream = null;\r
221         private String encoding = null;\r
222         private String publicId = null;\r
223         private String stringData = null;\r
224         private String systemId = null;\r
225 \r
226         /**\r
227          * コンストラクタ。\r
228          */\r
229         private LSInputImpl(){\r
230             super();\r
231             return;\r
232         }\r
233 \r
234         /**\r
235          * {@inheritDoc}\r
236          * @return {@inheritDoc}\r
237          */\r
238         public String getBaseURI(){\r
239             return this.baseURI;\r
240         }\r
241 \r
242         /**\r
243          * {@inheritDoc}\r
244          * @param baseURI {@inheritDoc}\r
245          */\r
246         public void setBaseURI(String baseURI){\r
247             this.baseURI = baseURI;\r
248             return;\r
249         }\r
250 \r
251         /**\r
252          * {@inheritDoc}\r
253          * @return {@inheritDoc}\r
254          */\r
255         public InputStream getByteStream(){\r
256             return this.byteStream;\r
257         }\r
258 \r
259         /**\r
260          * {@inheritDoc}\r
261          * @param byteStream {@inheritDoc}\r
262          */\r
263         public void setByteStream(InputStream byteStream){\r
264             this.byteStream = byteStream;\r
265         }\r
266 \r
267         /**\r
268          * {@inheritDoc}\r
269          * @return {@inheritDoc}\r
270          */\r
271         public boolean getCertifiedText(){\r
272             return this.certifiedText;\r
273         }\r
274 \r
275         /**\r
276          * {@inheritDoc}\r
277          * @param certifiedText {@inheritDoc}\r
278          */\r
279         public void setCertifiedText(boolean certifiedText){\r
280             this.certifiedText = certifiedText;\r
281             return;\r
282         }\r
283 \r
284         /**\r
285          * {@inheritDoc}\r
286          * @return {@inheritDoc}\r
287          */\r
288         public Reader getCharacterStream(){\r
289             return this.characterStream;\r
290         }\r
291 \r
292         /**\r
293          * {@inheritDoc}\r
294          * @param characterStream {@inheritDoc}\r
295          */\r
296         public void setCharacterStream(Reader characterStream){\r
297             this.characterStream = characterStream;\r
298         }\r
299 \r
300         /**\r
301          * {@inheritDoc}\r
302          * @return {@inheritDoc}\r
303          */\r
304         public String getEncoding(){\r
305             return this.encoding;\r
306         }\r
307 \r
308         /**\r
309          * {@inheritDoc}\r
310          * @param encoding {@inheritDoc}\r
311          */\r
312         public void setEncoding(String encoding){\r
313             this.encoding = encoding;\r
314             return;\r
315         }\r
316 \r
317         /**\r
318          * {@inheritDoc}\r
319          * @return {@inheritDoc}\r
320          */\r
321         public String getPublicId(){\r
322             return this.publicId;\r
323         }\r
324 \r
325         /**\r
326          * {@inheritDoc}\r
327          * @param publicId {@inheritDoc}\r
328          */\r
329         public void setPublicId(String publicId){\r
330             this.publicId = publicId;\r
331             return;\r
332         }\r
333 \r
334         /**\r
335          * {@inheritDoc}\r
336          * @return {@inheritDoc}\r
337          */\r
338         public String getStringData(){\r
339             return this.stringData;\r
340         }\r
341 \r
342         /**\r
343          * {@inheritDoc}\r
344          * @param stringData {@inheritDoc}\r
345          */\r
346         public void setStringData(String stringData){\r
347             this.stringData = stringData;\r
348             return;\r
349         }\r
350 \r
351         /**\r
352          * {@inheritDoc}\r
353          * @return {@inheritDoc}\r
354          */\r
355         public String getSystemId(){\r
356             return this.systemId;\r
357         }\r
358 \r
359         /**\r
360          * {@inheritDoc}\r
361          * @param systemId {@inheritDoc}\r
362          */\r
363         public void setSystemId(String systemId){\r
364             this.systemId = systemId;\r
365             return;\r
366         }\r
367 \r
368     }\r
369 \r
370     // TODO OASIS XML Catalog などと調和したい。\r
371 }\r