1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.opensaml.common.xml;
18
19 import java.lang.ref.SoftReference;
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.List;
23
24 import javax.xml.XMLConstants;
25 import javax.xml.transform.Source;
26 import javax.xml.transform.stream.StreamSource;
27 import javax.xml.validation.Schema;
28 import javax.xml.validation.SchemaFactory;
29
30 import org.opensaml.xml.parse.ClasspathResolver;
31 import org.opensaml.xml.parse.LoggingErrorHandler;
32 import org.slf4j.LoggerFactory;
33 import org.xml.sax.SAXException;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 public final class SAMLSchemaBuilder {
50
51
52 private static SoftReference<Schema> saml10Schema;
53
54
55 private static SoftReference<Schema> saml11Schema;
56
57
58 private static String[] baseXMLSchemas = { "/schema/xml.xsd", "/schema/XMLSchema.xsd",
59 "/schema/xmldsig-core-schema.xsd", "/schema/xenc-schema.xsd", };
60
61
62 private static String[] soapSchemas = { "/schema/soap-envelope.xsd", };
63
64
65 private static String[] saml10Schemas = { "/schema/cs-sstc-schema-assertion-01.xsd",
66 "/schema/cs-sstc-schema-protocol-01.xsd", };
67
68
69 private static String[] saml11Schemas = { "/schema/cs-sstc-schema-assertion-1.1.xsd",
70 "/schema/cs-sstc-schema-protocol-1.1.xsd", };
71
72
73 private static String[] saml20Schemas = {
74 "/schema/saml-schema-assertion-2.0.xsd",
75 "/schema/saml-schema-authn-context-2.0.xsd",
76 "/schema/saml-schema-authn-context-auth-telephony-2.0.xsd",
77 "/schema/saml-schema-authn-context-ip-2.0.xsd",
78 "/schema/saml-schema-authn-context-ippword-2.0.xsd",
79 "/schema/saml-schema-authn-context-kerberos-2.0.xsd",
80 "/schema/saml-schema-authn-context-mobileonefactor-reg-2.0.xsd",
81 "/schema/saml-schema-authn-context-mobileonefactor-unreg-2.0.xsd",
82 "/schema/saml-schema-authn-context-mobiletwofactor-reg-2.0.xsd",
83 "/schema/saml-schema-authn-context-mobiletwofactor-unreg-2.0.xsd",
84 "/schema/saml-schema-authn-context-nomad-telephony-2.0.xsd",
85 "/schema/saml-schema-authn-context-personal-telephony-2.0.xsd",
86 "/schema/saml-schema-authn-context-pgp-2.0.xsd",
87 "/schema/saml-schema-authn-context-ppt-2.0.xsd",
88 "/schema/saml-schema-authn-context-pword-2.0.xsd",
89 "/schema/saml-schema-authn-context-session-2.0.xsd",
90 "/schema/saml-schema-authn-context-smartcard-2.0.xsd",
91 "/schema/saml-schema-authn-context-smartcardpki-2.0.xsd",
92 "/schema/saml-schema-authn-context-softwarepki-2.0.xsd",
93 "/schema/saml-schema-authn-context-spki-2.0.xsd",
94 "/schema/saml-schema-authn-context-srp-2.0.xsd",
95 "/schema/saml-schema-authn-context-sslcert-2.0.xsd",
96 "/schema/saml-schema-authn-context-telephony-2.0.xsd",
97 "/schema/saml-schema-authn-context-timesync-2.0.xsd",
98 "/schema/saml-schema-authn-context-types-2.0.xsd",
99 "/schema/saml-schema-authn-context-x509-2.0.xsd",
100 "/schema/saml-schema-authn-context-xmldsig-2.0.xsd",
101 "/schema/saml-schema-dce-2.0.xsd",
102 "/schema/saml-schema-ecp-2.0.xsd",
103 "/schema/saml-schema-metadata-2.0.xsd",
104 "/schema/saml-schema-protocol-2.0.xsd",
105 "/schema/saml-schema-x500-2.0.xsd",
106 "/schema/saml-schema-xacml-2.0.xsd",
107 "/schema/sstc-saml-delegation.xsd",
108 "/schema/sstc-saml-idp-discovery.xsd",
109 "/schema/sstc-saml-metadata-ext-query.xsd",
110 "/schema/sstc-saml-protocol-ext-thirdparty.xsd",
111 "/schema/sstc-saml1x-metadata.xsd",
112 };
113
114
115 private static String[] baseExtSchemas = { "/schema/sstc-saml-protocol-ext-thirdparty.xsd",
116 "/schema/sstc-saml-metadata-ext-query.xsd", "/schema/sstc-saml1x-metadata.xsd", };
117
118
119 private static List<String> extensionSchema = new ArrayList<String>();
120
121
122 private SAMLSchemaBuilder() {
123
124 }
125
126
127
128
129
130
131
132
133 public static synchronized Schema getSAML10Schema() throws SAXException {
134 if (saml10Schema == null || saml10Schema.get() == null) {
135 saml10Schema = new SoftReference<Schema>(buildSchema(saml10Schemas));
136 }
137
138 return saml10Schema.get();
139 }
140
141
142
143
144
145
146
147
148 public static synchronized Schema getSAML11Schema() throws SAXException {
149 if (saml11Schema == null || saml11Schema.get() == null) {
150 saml11Schema = new SoftReference<Schema>(buildSchema(saml11Schemas));
151 }
152
153 return saml11Schema.get();
154 }
155
156
157
158
159
160
161 public static List<String> getExtensionSchema() {
162 return Collections.unmodifiableList(extensionSchema);
163 }
164
165
166
167
168
169
170 public static void addExtensionSchema(String schema) {
171 extensionSchema.add(schema);
172
173 saml10Schema = null;
174
175 saml11Schema = null;
176 }
177
178
179
180
181
182
183 public static void removeSchema(String schema) {
184 extensionSchema.remove(schema);
185
186 synchronized (saml10Schema) {
187 saml10Schema = null;
188 }
189
190 synchronized (saml11Schema) {
191 saml11Schema = null;
192 }
193 }
194
195
196
197
198
199
200
201
202
203
204 private static Schema buildSchema(String[] saml1Schema) throws SAXException {
205 Class<SAMLSchemaBuilder> clazz = SAMLSchemaBuilder.class;
206 List<Source> schemaSources = new ArrayList<Source>();
207
208 for (String source : baseXMLSchemas) {
209 schemaSources.add(new StreamSource(clazz.getResourceAsStream(source)));
210 }
211
212 for (String source : soapSchemas) {
213 schemaSources.add(new StreamSource(clazz.getResourceAsStream(source)));
214 }
215
216 for (String source : saml1Schema) {
217 schemaSources.add(new StreamSource(clazz.getResourceAsStream(source)));
218 }
219
220 for (String source : saml20Schemas) {
221 schemaSources.add(new StreamSource(clazz.getResourceAsStream(source)));
222 }
223
224 for (String source : baseExtSchemas) {
225 schemaSources.add(new StreamSource(clazz.getResourceAsStream(source)));
226 }
227
228 for (String source : extensionSchema) {
229 schemaSources.add(new StreamSource(clazz.getResourceAsStream(source)));
230 }
231
232 SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
233 schemaFactory.setResourceResolver(new ClasspathResolver());
234 schemaFactory.setErrorHandler(new LoggingErrorHandler(LoggerFactory.getLogger(clazz)));
235 return schemaFactory.newSchema(schemaSources.toArray(new StreamSource[0]));
236 }
237 }