23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
25 |
26 package com.sun.tools.internal.xjc; |
26 package com.sun.tools.internal.xjc; |
27 |
27 |
28 import java.net.URL; |
28 import java.io.IOException; |
29 |
29 import java.io.InputStream; |
|
30 import java.io.Reader; |
|
31 import java.util.ArrayList; |
|
32 import java.util.Collections; |
|
33 import java.util.List; |
|
34 |
|
35 import javax.xml.transform.stream.StreamSource; |
30 import javax.xml.validation.Schema; |
36 import javax.xml.validation.Schema; |
31 import javax.xml.validation.SchemaFactory; |
37 import javax.xml.validation.SchemaFactory; |
32 import javax.xml.validation.ValidatorHandler; |
38 import javax.xml.validation.ValidatorHandler; |
33 |
39 |
34 import com.sun.xml.internal.bind.v2.util.XmlFactory; |
40 import com.sun.xml.internal.bind.v2.util.XmlFactory; |
35 import javax.xml.XMLConstants; |
41 import javax.xml.XMLConstants; |
|
42 |
|
43 import org.w3c.dom.ls.LSInput; |
|
44 import org.w3c.dom.ls.LSResourceResolver; |
36 import org.xml.sax.SAXException; |
45 import org.xml.sax.SAXException; |
37 |
46 |
38 import static com.sun.xml.internal.bind.v2.util.XmlFactory.allowExternalAccess; |
47 import static com.sun.xml.internal.bind.v2.util.XmlFactory.allowExternalAccess; |
39 |
48 |
40 /** |
49 /** |
45 * |
54 * |
46 * @author Kohsuke Kawaguchi |
55 * @author Kohsuke Kawaguchi |
47 */ |
56 */ |
48 public final class SchemaCache { |
57 public final class SchemaCache { |
49 |
58 |
|
59 private final boolean createResolver; |
|
60 private final String resourceName; |
|
61 private final Class<?> clazz; |
|
62 |
50 private Schema schema; |
63 private Schema schema; |
51 |
64 |
52 private final URL source; |
65 public SchemaCache(String resourceName, Class<?> classToResolveResources) { |
53 |
66 this(resourceName, classToResolveResources, false); |
54 public SchemaCache(URL source) { |
67 } |
55 this.source = source; |
68 |
|
69 public SchemaCache(String resourceName, Class<?> classToResolveResources, boolean createResolver) { |
|
70 this.resourceName = resourceName; |
|
71 this.createResolver = createResolver; |
|
72 this.clazz = classToResolveResources; |
56 } |
73 } |
57 |
74 |
58 public ValidatorHandler newValidator() { |
75 public ValidatorHandler newValidator() { |
59 synchronized(this) { |
76 if (schema==null) { |
60 if(schema==null) { |
77 synchronized (this) { |
61 try { |
78 if (schema == null) { |
62 // do not disable secure processing - these are well-known schemas |
79 |
63 SchemaFactory sf = XmlFactory.createSchemaFactory(XMLConstants.W3C_XML_SCHEMA_NS_URI, false); |
80 ResourceResolver resourceResolver = null; |
64 schema = allowExternalAccess(sf, "file", false).newSchema(source); |
81 try (InputStream is = clazz.getResourceAsStream(resourceName)) { |
65 } catch (SAXException e) { |
82 |
66 // we make sure that the schema is correct before we ship. |
83 StreamSource source = new StreamSource(is); |
67 throw new AssertionError(e); |
84 source.setSystemId(resourceName); |
|
85 // do not disable secure processing - these are well-known schemas |
|
86 |
|
87 SchemaFactory sf = XmlFactory.createSchemaFactory(XMLConstants.W3C_XML_SCHEMA_NS_URI, false); |
|
88 SchemaFactory schemaFactory = allowExternalAccess(sf, "file", false); |
|
89 |
|
90 if (createResolver) { |
|
91 resourceResolver = new ResourceResolver(clazz); |
|
92 schemaFactory.setResourceResolver(resourceResolver); |
|
93 } |
|
94 schema = schemaFactory.newSchema(source); |
|
95 |
|
96 } catch (IOException | SAXException e) { |
|
97 throw new InternalError(e); |
|
98 } finally { |
|
99 if (resourceResolver != null) resourceResolver.closeStreams(); |
|
100 } |
68 } |
101 } |
69 } |
102 } |
70 } |
103 } |
71 |
104 return schema.newValidatorHandler(); |
72 ValidatorHandler handler = schema.newValidatorHandler(); |
105 } |
73 return handler; |
106 |
|
107 class ResourceResolver implements LSResourceResolver { |
|
108 |
|
109 private List<InputStream> streamsToClose = Collections.synchronizedList(new ArrayList<InputStream>()); |
|
110 private Class<?> clazz; |
|
111 |
|
112 ResourceResolver(Class<?> clazz) { |
|
113 this.clazz = clazz; |
|
114 } |
|
115 |
|
116 @Override |
|
117 public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) { |
|
118 // XSOM passes the namespace URI to the publicID parameter. |
|
119 // we do the same here . |
|
120 InputStream is = clazz.getResourceAsStream(systemId); |
|
121 streamsToClose.add(is); |
|
122 return new Input(is, publicId, systemId); |
|
123 } |
|
124 |
|
125 void closeStreams() { |
|
126 for (InputStream is : streamsToClose) { |
|
127 if (is != null) { |
|
128 try { |
|
129 is.close(); |
|
130 } catch (IOException e) { |
|
131 // nothing to do ... |
|
132 } |
|
133 } |
|
134 } |
|
135 } |
74 } |
136 } |
75 |
137 |
76 } |
138 } |
|
139 |
|
140 class Input implements LSInput { |
|
141 |
|
142 private InputStream is; |
|
143 private String publicId; |
|
144 private String systemId; |
|
145 |
|
146 public Input(InputStream is, String publicId, String systemId) { |
|
147 this.is = is; |
|
148 this.publicId = publicId; |
|
149 this.systemId = systemId; |
|
150 } |
|
151 |
|
152 @Override |
|
153 public Reader getCharacterStream() { |
|
154 return null; |
|
155 } |
|
156 |
|
157 @Override |
|
158 public void setCharacterStream(Reader characterStream) { |
|
159 } |
|
160 |
|
161 @Override |
|
162 public InputStream getByteStream() { |
|
163 return is; |
|
164 } |
|
165 |
|
166 @Override |
|
167 public void setByteStream(InputStream byteStream) { |
|
168 } |
|
169 |
|
170 @Override |
|
171 public String getStringData() { |
|
172 return null; |
|
173 } |
|
174 |
|
175 @Override |
|
176 public void setStringData(String stringData) { |
|
177 } |
|
178 |
|
179 @Override |
|
180 public String getSystemId() { |
|
181 return systemId; |
|
182 } |
|
183 |
|
184 @Override |
|
185 public void setSystemId(String systemId) { |
|
186 } |
|
187 |
|
188 @Override |
|
189 public String getPublicId() { |
|
190 return publicId; |
|
191 } |
|
192 |
|
193 @Override |
|
194 public void setPublicId(String publicId) { |
|
195 } |
|
196 |
|
197 @Override |
|
198 public String getBaseURI() { |
|
199 return null; |
|
200 } |
|
201 |
|
202 @Override |
|
203 public void setBaseURI(String baseURI) { |
|
204 } |
|
205 |
|
206 @Override |
|
207 public String getEncoding() { |
|
208 return null; |
|
209 } |
|
210 |
|
211 @Override |
|
212 public void setEncoding(String encoding) { |
|
213 } |
|
214 |
|
215 @Override |
|
216 public boolean getCertifiedText() { |
|
217 return false; |
|
218 } |
|
219 |
|
220 @Override |
|
221 public void setCertifiedText(boolean certifiedText) { |
|
222 } |
|
223 } |
|
224 |
|
225 |