1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 package org.jomc.modlet;
32
33 import java.io.IOException;
34 import java.text.MessageFormat;
35 import java.util.HashMap;
36 import java.util.Map;
37 import java.util.ResourceBundle;
38 import java.util.logging.Level;
39 import javax.xml.bind.JAXBException;
40 import javax.xml.bind.util.JAXBSource;
41 import javax.xml.validation.Validator;
42 import org.xml.sax.SAXException;
43
44
45
46
47
48
49
50
51
52 public class DefaultModletValidator implements ModletValidator
53 {
54
55
56
57
58
59
60
61 public static final String ENABLED_ATTRIBUTE_NAME = "org.jomc.modlet.DefaultModletValidator.enabledAttribute";
62
63
64
65
66
67
68 private static final String DEFAULT_ENABLED_PROPERTY_NAME =
69 "org.jomc.modlet.DefaultModletValidator.defaultEnabled";
70
71
72
73
74
75
76 private static final Boolean DEFAULT_ENABLED = Boolean.TRUE;
77
78
79
80
81 private static volatile Boolean defaultEnabled;
82
83
84
85
86 private volatile Boolean enabled;
87
88
89
90
91
92
93 private static final String DEFAULT_ORDINAL_PROPERTY_NAME =
94 "org.jomc.modlet.DefaultModletValidator.defaultOrdinal";
95
96
97
98
99
100
101 private static final Integer DEFAULT_ORDINAL = 0;
102
103
104
105
106 private static volatile Integer defaultOrdinal;
107
108
109
110
111 private volatile Integer ordinal;
112
113
114
115
116 public DefaultModletValidator()
117 {
118 super();
119 }
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135 public static boolean isDefaultEnabled()
136 {
137 if ( defaultEnabled == null )
138 {
139 defaultEnabled = Boolean.valueOf( System.getProperty(
140 DEFAULT_ENABLED_PROPERTY_NAME, Boolean.toString( DEFAULT_ENABLED ) ) );
141
142 }
143
144 return defaultEnabled;
145 }
146
147
148
149
150
151
152
153
154 public static void setDefaultEnabled( final Boolean value )
155 {
156 defaultEnabled = value;
157 }
158
159
160
161
162
163
164
165
166
167 public final boolean isEnabled()
168 {
169 if ( this.enabled == null )
170 {
171 this.enabled = isDefaultEnabled();
172 }
173
174 return this.enabled;
175 }
176
177
178
179
180
181
182
183
184 public final void setEnabled( final Boolean value )
185 {
186 this.enabled = value;
187 }
188
189
190
191
192
193
194
195
196
197
198
199
200
201 public static int getDefaultOrdinal()
202 {
203 if ( defaultOrdinal == null )
204 {
205 defaultOrdinal = Integer.getInteger( DEFAULT_ORDINAL_PROPERTY_NAME, DEFAULT_ORDINAL );
206 }
207
208 return defaultOrdinal;
209 }
210
211
212
213
214
215
216
217
218 public static void setDefaultOrdinal( final Integer value )
219 {
220 defaultOrdinal = value;
221 }
222
223
224
225
226
227
228
229
230
231 public final int getOrdinal()
232 {
233 if ( this.ordinal == null )
234 {
235 this.ordinal = getDefaultOrdinal();
236 }
237
238 return this.ordinal;
239 }
240
241
242
243
244
245
246
247
248 public final void setOrdinal( final Integer value )
249 {
250 this.ordinal = value;
251 }
252
253 @Override
254 public ModelValidationReport validateModlets( final ModelContext context, final Modlets modlets )
255 throws NullPointerException, ModelException
256 {
257 if ( context == null )
258 {
259 throw new NullPointerException( "context" );
260 }
261 if ( modlets == null )
262 {
263 throw new NullPointerException( "modlets" );
264 }
265
266 try
267 {
268 boolean contextEnabled = this.isEnabled();
269 if ( DEFAULT_ENABLED == contextEnabled
270 && context.getAttribute( ENABLED_ATTRIBUTE_NAME ) instanceof Boolean )
271 {
272 contextEnabled = (Boolean) context.getAttribute( ENABLED_ATTRIBUTE_NAME );
273 }
274
275 final ModelValidationReport report = new ModelValidationReport();
276
277 if ( contextEnabled )
278 {
279 final javax.xml.validation.Schema modletSchema = context.createSchema( ModletObject.MODEL_PUBLIC_ID );
280 final Validator validator = modletSchema.newValidator();
281 validator.setErrorHandler( new ModelErrorHandler( context, report ) );
282 validator.validate( new JAXBSource( context.createContext( ModletObject.MODEL_PUBLIC_ID ),
283 new ObjectFactory().createModlets( modlets ) ) );
284
285 final Map<String, Schemas> schemasByModel = new HashMap<String, Schemas>( 128 );
286 final Map<Schema, Modlet> modletBySchema = new HashMap<Schema, Modlet>( 128 );
287
288 for ( final Modlet modlet : modlets.getModlet() )
289 {
290 if ( modlet.getSchemas() != null )
291 {
292 Schemas modelSchemas = schemasByModel.get( modlet.getModel() );
293
294 if ( modelSchemas == null )
295 {
296 modelSchemas = new Schemas();
297 schemasByModel.put( modlet.getModel(), modelSchemas );
298 }
299
300 for ( int i = 0, s0 = modlet.getSchemas().getSchema().size(); i < s0; i++ )
301 {
302 final Schema schema = modlet.getSchemas().getSchema().get( i );
303 modletBySchema.put( schema, modlet );
304
305 final Schema existingPublicIdSchema =
306 modelSchemas.getSchemaByPublicId( schema.getPublicId() );
307
308 final Schema existingSystemIdSchema =
309 modelSchemas.getSchemaBySystemId( schema.getSystemId() );
310
311 if ( existingPublicIdSchema != null )
312 {
313 final Modlet modletOfSchema = modletBySchema.get( existingPublicIdSchema );
314 final ModelValidationReport.Detail detail =
315 new ModelValidationReport.Detail(
316 "MODEL_SCHEMA_PUBLIC_ID_CONSTRAINT",
317 Level.SEVERE,
318 getMessage( "modelSchemaPublicIdConstraint", modlet.getModel(),
319 modlet.getName(), modletOfSchema.getName(),
320 schema.getPublicId() ),
321 new ObjectFactory().createModlet( modlet ) );
322
323 report.getDetails().add( detail );
324 }
325
326 if ( existingSystemIdSchema != null )
327 {
328 final Modlet modletOfSchema = modletBySchema.get( existingSystemIdSchema );
329 final ModelValidationReport.Detail detail =
330 new ModelValidationReport.Detail(
331 "MODEL_SCHEMA_SYSTEM_ID_CONSTRAINT",
332 Level.SEVERE,
333 getMessage( "modelSchemaSystemIdConstraint", modlet.getModel(),
334 modlet.getName(), modletOfSchema.getName(),
335 schema.getSystemId() ),
336 new ObjectFactory().createModlet( modlet ) );
337
338 report.getDetails().add( detail );
339 }
340
341 modelSchemas.getSchema().add( schema );
342 }
343 }
344 }
345 }
346 else if ( context.isLoggable( Level.FINER ) )
347 {
348 context.log( Level.FINER, getMessage( "disabled", this.getClass().getSimpleName() ), null );
349 }
350
351 return report;
352 }
353 catch ( final IOException e )
354 {
355 throw new ModelException( getMessage( e ), e );
356 }
357 catch ( final JAXBException e )
358 {
359 String message = getMessage( e );
360
361 if ( message == null && e.getLinkedException() != null )
362 {
363 message = getMessage( e.getLinkedException() );
364 }
365
366 throw new ModelException( message, e );
367 }
368 catch ( final SAXException e )
369 {
370 String message = getMessage( e );
371
372 if ( message == null && e.getException() != null )
373 {
374 message = getMessage( e.getException() );
375 }
376
377 throw new ModelException( message, e );
378 }
379 }
380
381 private static String getMessage( final String key, final Object... arguments )
382 {
383 return MessageFormat.format( ResourceBundle.getBundle(
384 DefaultModletValidator.class.getName().replace( '.', '/' ) ).getString( key ), arguments );
385
386 }
387
388 private static String getMessage( final Throwable t )
389 {
390 return t != null
391 ? t.getMessage() != null && t.getMessage().trim().length() > 0
392 ? t.getMessage()
393 : getMessage( t.getCause() )
394 : null;
395
396 }
397
398 }