OSDN Git Service

strictry inhibit unknown mapping.
[mikutoga/TogaGem.git] / src / main / java / jp / sfjp / mikutoga / xml / XmlResourceResolver.java
1 /*
2  * xml resource resolver
3  *
4  * License : The MIT License
5  * Copyright(c) 2009 olyutorskii
6  */
7
8 package jp.sfjp.mikutoga.xml;
9
10 import java.io.BufferedInputStream;
11 import java.io.ByteArrayInputStream;
12 import java.io.IOException;
13 import java.io.InputStream;
14 import java.net.URI;
15 import java.net.URISyntaxException;
16 import java.net.URL;
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.Map;
20 import org.w3c.dom.DOMImplementation;
21 import org.w3c.dom.bootstrap.DOMImplementationRegistry;
22 import org.w3c.dom.ls.DOMImplementationLS;
23 import org.w3c.dom.ls.LSInput;
24 import org.w3c.dom.ls.LSResourceResolver;
25
26 /**
27  * register & redirect original URI to local resource contents.
28  */
29 public class XmlResourceResolver
30         implements LSResourceResolver{
31
32     private static final URI EMPTY_URI = URI.create("");
33
34     private static final DOMImplementationLS DOM_LS;
35
36
37     private final Map<URI, URI> uriMap;
38
39
40     static{
41         try{
42             DOM_LS = buildDomImplLS();
43         }catch(   ClassNotFoundException
44                 | IllegalAccessException
45                 | InstantiationException e){
46             throw new ExceptionInInitializerError(e);
47         }
48     }
49
50
51     /**
52      * Constructor.
53      */
54     public XmlResourceResolver(){
55         super();
56
57         Map<URI, URI> map;
58         map = new HashMap<>();
59         map = Collections.synchronizedMap(map);
60         this.uriMap = map;
61
62         return;
63     }
64
65
66     /**
67      * return DOMImplementationLS implement.
68      *
69      * @return DOMImplementationLS implement
70      * @throws ClassNotFoundException no class
71      * @throws InstantiationException no object
72      * @throws IllegalAccessException no grant
73      */
74     private static DOMImplementationLS buildDomImplLS() throws
75             ClassNotFoundException,
76             InstantiationException,
77             IllegalAccessException {
78         DOMImplementationRegistry domReg;
79         DOMImplementation         domImp;
80         DOMImplementationLS       domImpLs;
81
82         domReg = DOMImplementationRegistry.newInstance();
83         domImp = domReg.getDOMImplementation("LS 3.0");
84
85         Object feature = domImp.getFeature("LS", "3.0");
86         assert feature instanceof DOMImplementationLS;
87         domImpLs = (DOMImplementationLS) feature;
88
89         return domImpLs;
90     }
91
92     /**
93      * return LSInput implement.
94      *
95      * @return LSInput implement
96      */
97     public static LSInput createLSInput(){
98         LSInput input = DOM_LS.createLSInput();
99         return input;
100     }
101
102     /**
103      * merge base-uri text &amp; relative URI text.
104      *
105      * @param base base URI text must be absolute or null.
106      * @param relative relative URI text.
107      *     If absolute, base is ignored.
108      *     Ignored if null.
109      * @return merged absolute URI.
110      * @throws java.net.URISyntaxException illegal URI
111      * @throws java.lang.IllegalArgumentException result is not Absolute.
112      */
113     protected static URI buildBaseRelativeURI(String base, String relative)
114             throws URISyntaxException,
115                    IllegalArgumentException {
116         URI baseURI;
117         if(base != null){
118             baseURI = new URI(base);
119             if( ! baseURI.isAbsolute() ){
120                 throw new IllegalArgumentException();
121             }
122         }else{
123             baseURI = null;
124         }
125
126         URI relativeURI;
127         if(relative != null){
128             relativeURI = new URI(relative);
129         }else{
130             relativeURI = EMPTY_URI;
131         }
132
133         URI result = buildBaseRelativeURI(baseURI, relativeURI);
134         return result;
135     }
136
137     /**
138      * merge base-uri &amp; relative URI.
139      *
140      * @param baseURI base URI must be absolute or null.
141      * @param relativeURI relative URI. If absolute, baseURI is ignored.
142      * @return merged absolute URI.
143      * @throws java.lang.IllegalArgumentException result is not Absolute.
144      */
145     private static URI buildBaseRelativeURI(URI baseURI, URI relativeURI)
146             throws IllegalArgumentException {
147         URI resultURI;
148
149         if(baseURI == null || relativeURI.isAbsolute()){
150             resultURI = relativeURI;
151         }else{
152             resultURI = baseURI.resolve(relativeURI);
153         }
154
155         if( ! resultURI.isAbsolute() ){
156             throw new IllegalArgumentException();
157         }
158
159         resultURI = resultURI.normalize();
160
161         return resultURI;
162     }
163
164
165     /**
166      * map original URI &amp; local resource URI.
167      *
168      * @param original original URI
169      * @param redirect local resource URI
170      */
171     public void putRedirected(URI original, URI redirect){
172         URI oridinalNorm = original.normalize();
173         URI redirectNorm = redirect.normalize();
174
175         this.uriMap.put(oridinalNorm, redirectNorm);
176
177         return;
178     }
179
180     /**
181      * add other resolver mapping.
182      *
183      * @param other resolver
184      */
185     public void putRedirected(XmlResourceResolver other){
186         this.uriMap.putAll(other.uriMap);
187         return;
188     }
189
190     /**
191      * get redirected local resource URI.
192      *
193      * @param original original URI
194      * @return mapped local resource URI. null if unmapped.
195      */
196     public URI getRedirected(URI original){
197         URI keyURI = original.normalize();
198         URI resourceURI = this.uriMap.get(keyURI);
199         return resourceURI;
200     }
201
202     /**
203      * get redirected local input stream.
204      *
205      * @param originalURI original URI
206      * @return mapped local resource input stream.
207      *     If no mapping, return zero-length data stream.
208      * @throws java.io.IOException local resource i/o error
209      */
210     private InputStream getXMLResourceAsStream(URI originalURI)
211             throws IOException{
212         InputStream result;
213
214         URI resourceURI = getRedirected(originalURI);
215         if(resourceURI == null){
216             result = new ByteArrayInputStream(new byte[0]);
217         }else{
218             URL resourceURL = resourceURI.toURL();
219             result = resourceURL.openStream();
220         }
221
222         result = new BufferedInputStream(result);
223
224         return result;
225     }
226
227     /**
228      * {@inheritDoc}
229      *
230      * <p>Return redirected local resource data.
231      *
232      * @param type {@inheritDoc}
233      * @param namespaceURI {@inheritDoc}
234      * @param publicId {@inheritDoc}
235      * @param systemId {@inheritDoc}
236      * @param baseURI {@inheritDoc}
237      * @return {@inheritDoc} LSInput of local resource.
238      *     If no mapping, return zero-length data.
239      */
240     @Override
241     public LSInput resolveResource(
242             String type,
243             String namespaceURI,
244             String publicId,
245             String systemId,
246             String baseURI ){
247         if(systemId == null) return null;
248
249         URI originalURI;
250         try{
251             originalURI = buildBaseRelativeURI(baseURI, systemId);
252         }catch(URISyntaxException e){
253             assert false;
254             throw new AssertionError(e);
255         }
256
257         InputStream is;
258         try{
259             is = getXMLResourceAsStream(originalURI);
260         }catch(IOException e){
261             assert false;
262             throw new AssertionError(e);
263         }
264
265         LSInput input = createLSInput();
266         input.setBaseURI(baseURI);
267         input.setPublicId(publicId);
268         input.setSystemId(systemId);
269         input.setByteStream(is);
270
271         return input;
272     }
273
274 }