EMMA Coverage Report (generated Tue Jan 19 17:53:40 UTC 2010)
[all classes][org.jomc.model]

COVERAGE SUMMARY FOR SOURCE FILE [ModelContext.java]

nameclass, %method, %block, %line, %
ModelContext.java60%  (3/5)76%  (25/33)66%  (667/1007)63%  (140.2/221)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ModelContext$10%   (0/1)0%   (0/2)0%   (0/20)0%   (0/2)
ModelContext$1 (ModelContext, ClassLoader): void 0%   (0/1)0%   (0/7)0%   (0/1)
toString (): String 0%   (0/1)0%   (0/13)0%   (0/1)
     
class ModelContext$Listener0%   (0/1)0%   (0/1)0%   (0/3)0%   (0/1)
ModelContext$Listener (): void 0%   (0/1)0%   (0/3)0%   (0/1)
     
class ModelErrorHandler100% (1/1)67%  (4/6)56%  (35/63)71%  (10/14)
fatalError (SAXParseException): void 0%   (0/1)0%   (0/14)0%   (0/2)
warning (SAXParseException): void 0%   (0/1)0%   (0/14)0%   (0/2)
ModelErrorHandler (): void 100% (1/1)100% (4/4)100% (2/2)
ModelErrorHandler (ModelValidationReport): void 100% (1/1)100% (6/6)100% (3/3)
error (SAXParseException): void 100% (1/1)100% (14/14)100% (2/2)
getReport (): ModelValidationReport 100% (1/1)100% (11/11)100% (3/3)
     
class ModelContext100% (1/1)86%  (19/22)68%  (622/911)63%  (128.2/202)
setDefaultLogLevel (Level): void 0%   (0/1)0%   (0/3)0%   (0/2)
setLogLevel (Level): void 0%   (0/1)0%   (0/4)0%   (0/2)
setModelContextClassName (String): void 0%   (0/1)0%   (0/3)0%   (0/2)
createModelContext (ClassLoader): ModelContext 100% (1/1)14%  (10/70)12%  (2/17)
findClass (String): Class 100% (1/1)39%  (13/33)43%  (3/7)
getClassLoader (): ClassLoader 100% (1/1)46%  (6/13)67%  (2/3)
log (Level, String, Throwable): void 100% (1/1)48%  (14/29)57%  (3.4/6)
loadProviders (Class): Collection 100% (1/1)57%  (111/194)54%  (19/35)
validateModel (Source): ModelValidationReport 100% (1/1)61%  (27/44)64%  (8.9/14)
isLoggable (Level): boolean 100% (1/1)65%  (11/17)63%  (1.9/3)
findResources (String): Enumeration 100% (1/1)67%  (12/18)60%  (3/5)
processModules (Modules): Modules 100% (1/1)80%  (114/143)72%  (23/32)
validateModel (Modules): ModelValidationReport 100% (1/1)84%  (63/75)76%  (13/17)
findModules (): Modules 100% (1/1)86%  (145/169)78%  (28/36)
<static initializer> 100% (1/1)100% (3/3)100% (1/1)
ModelContext (ClassLoader): void 100% (1/1)100% (6/6)100% (3/3)
findResource (String): URL 100% (1/1)100% (12/12)100% (3/3)
getDefaultLogLevel (): Level 100% (1/1)100% (10/10)100% (3/3)
getListeners (): List 100% (1/1)100% (11/11)100% (3/3)
getLogLevel (): Level 100% (1/1)100% (30/30)100% (4/4)
getMessage (String, Object): String 100% (1/1)100% (15/15)100% (1/1)
getModelContextClassName (): String 100% (1/1)100% (9/9)100% (3/3)
     
class ModelContext$2100% (1/1)100% (2/2)100% (10/10)100% (2/2)
ModelContext$2 (ModelContext): void 100% (1/1)100% (6/6)100% (1/1)
compare (String, String): int 100% (1/1)100% (4/4)100% (1/1)

1/*
2 *   Copyright (c) 2009 The JOMC Project
3 *   Copyright (c) 2005 Christian Schulte <cs@jomc.org>
4 *   All rights reserved.
5 *
6 *   Redistribution and use in source and binary forms, with or without
7 *   modification, are permitted provided that the following conditions
8 *   are met:
9 *
10 *     o Redistributions of source code must retain the above copyright
11 *       notice, this list of conditions and the following disclaimer.
12 *
13 *     o Redistributions in binary form must reproduce the above copyright
14 *       notice, this list of conditions and the following disclaimer in
15 *       the documentation and/or other materials provided with the
16 *       distribution.
17 *
18 *   THIS SOFTWARE IS PROVIDED BY THE JOMC PROJECT AND CONTRIBUTORS "AS IS"
19 *   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 *   THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 *   PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE JOMC PROJECT OR
22 *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 *   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 *   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 *   OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 *   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 *   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 *   $Id: ModelContext.java 1336 2010-01-19 04:00:00Z schulte2005 $
31 *
32 */
33package org.jomc.model;
34 
35import java.io.BufferedReader;
36import java.io.File;
37import java.io.FileInputStream;
38import java.io.IOException;
39import java.io.InputStream;
40import java.io.InputStreamReader;
41import java.io.StringReader;
42import java.io.StringWriter;
43import java.lang.reflect.Constructor;
44import java.lang.reflect.InvocationTargetException;
45import java.net.URL;
46import java.text.MessageFormat;
47import java.util.Collection;
48import java.util.Comparator;
49import java.util.Enumeration;
50import java.util.LinkedList;
51import java.util.List;
52import java.util.Locale;
53import java.util.Map;
54import java.util.ResourceBundle;
55import java.util.TreeMap;
56import java.util.logging.Level;
57import javax.xml.bind.JAXBContext;
58import javax.xml.bind.JAXBException;
59import javax.xml.bind.Marshaller;
60import javax.xml.bind.Unmarshaller;
61import javax.xml.transform.Source;
62import javax.xml.validation.Schema;
63import javax.xml.validation.Validator;
64import org.w3c.dom.ls.LSResourceResolver;
65import org.xml.sax.EntityResolver;
66import org.xml.sax.SAXException;
67import org.xml.sax.SAXParseException;
68import org.xml.sax.helpers.DefaultHandler;
69 
70/**
71 * Object management and configuration model context interface.
72 *
73 * @author <a href="mailto:cs@jomc.org">Christian Schulte</a>
74 * @version $Id: ModelContext.java 1336 2010-01-19 04:00:00Z schulte2005 $
75 * @see #createModelContext(java.lang.ClassLoader)
76 */
77public abstract class ModelContext
78{
79 
80    /** Listener interface. */
81    public abstract static class Listener
82    {
83 
84        /**
85         * Get called on logging.
86         *
87         * @param level The level of the event.
88         * @param message The message of the event or {@code null}.
89         * @param t The throwable of the event or {@code null}.
90         *
91         * @throws NullPointerException if {@code level} is {@code null}.
92         */
93        public abstract void onLog( Level level, String message, Throwable t );
94 
95    }
96 
97    /**
98     * Log level events are logged at by default.
99     * @see #getDefaultLogLevel()
100     */
101    private static final Level DEFAULT_LOG_LEVEL = Level.WARNING;
102 
103    /** Default log level. */
104    private static volatile Level defaultLogLevel;
105 
106    /** Class name of the {@code ModelContext} implementation. */
107    private static volatile String modelContextClassName;
108 
109    /** The listeners of the instance. */
110    private List<Listener> listeners;
111 
112    /** Log level of the instance. */
113    private Level logLevel;
114 
115    /** The class loader of the context. */
116    private ClassLoader classLoader;
117 
118    /**
119     * Creates a new {@code ModelContext} instance taking a class loader.
120     *
121     * @param classLoader The class loader of the context.
122     */
123    protected ModelContext( final ClassLoader classLoader )
124    {
125        super();
126        this.classLoader = classLoader;
127    }
128 
129    /**
130     * Gets the class loader of the context.
131     *
132     * @return The class loader of the context.
133     */
134    public ClassLoader getClassLoader()
135    {
136        if ( this.classLoader == null )
137        {
138            this.classLoader = new ClassLoader( null )
139            {
140 
141                @Override
142                public String toString()
143                {
144                    return ModelContext.class.getName() + ".BootstrapClassLoader@" + System.identityHashCode( this );
145                }
146 
147            };
148 
149        }
150 
151        return this.classLoader;
152    }
153 
154    /**
155     * Gets the list of registered listeners.
156     * <p>This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you make
157     * to the returned list will be present inside the object. This is why there is no {@code set} method for the
158     * listeners property.</p>
159     *
160     * @return The list of registered listeners.
161     *
162     * @see #log(java.util.logging.Level, java.lang.String, java.lang.Throwable)
163     */
164    public List<Listener> getListeners()
165    {
166        if ( this.listeners == null )
167        {
168            this.listeners = new LinkedList<Listener>();
169        }
170 
171        return this.listeners;
172    }
173 
174    /**
175     * Gets the default log level events are logged at.
176     * <p>The default log level is controlled by system property
177     * {@code org.jomc.model.ModelContext.defaultLogLevel} holding the log level to log events at by default.
178     * If that property is not set, the {@code WARNING} default is returned.</p>
179     *
180     * @return The log level events are logged at by default.
181     *
182     * @see #getLogLevel()
183     * @see Level#parse(java.lang.String)
184     */
185    public static Level getDefaultLogLevel()
186    {
187        if ( defaultLogLevel == null )
188        {
189            defaultLogLevel = Level.parse( System.getProperty(
190                "org.jomc.model.ModelContext.defaultLogLevel", DEFAULT_LOG_LEVEL.getName() ) );
191 
192        }
193 
194        return defaultLogLevel;
195    }
196 
197    /**
198     * Sets the default log level events are logged at.
199     *
200     * @param value The new default level events are logged at or {@code null}.
201     *
202     * @see #getDefaultLogLevel()
203     */
204    public static void setDefaultLogLevel( final Level value )
205    {
206        defaultLogLevel = value;
207    }
208 
209    /**
210     * Gets the log level of the instance.
211     *
212     * @return The log level of the instance.
213     *
214     * @see #getDefaultLogLevel()
215     * @see #setLogLevel(java.util.logging.Level)
216     * @see #isLoggable(java.util.logging.Level)
217     */
218    public Level getLogLevel()
219    {
220        if ( this.logLevel == null )
221        {
222            this.logLevel = getDefaultLogLevel();
223            this.log( Level.CONFIG, this.getMessage( "defaultLogLevelInfo", new Object[]
224                {
225                    this.getClass().getCanonicalName(), this.logLevel.getLocalizedName()
226                } ), null );
227 
228        }
229 
230        return this.logLevel;
231    }
232 
233    /**
234     * Sets the log level of the instance.
235     *
236     * @param value The new log level of the instance or {@code null}.
237     *
238     * @see #getLogLevel()
239     * @see #isLoggable(java.util.logging.Level)
240     */
241    public void setLogLevel( final Level value )
242    {
243        this.logLevel = value;
244    }
245 
246    /**
247     * Checks if a message at a given level is provided to the listeners of the instance.
248     *
249     * @param level The level to test.
250     *
251     * @return {@code true} if messages at {@code level} are provided to the listeners of the instance;
252     * {@code false} if messages at {@code level} are not provided to the listeners of the instance.
253     *
254     * @throws NullPointerException if {@code level} is {@code null}.
255     *
256     * @see #getLogLevel()
257     * @see #setLogLevel(java.util.logging.Level)
258     */
259    public boolean isLoggable( final Level level )
260    {
261        if ( level == null )
262        {
263            throw new NullPointerException( "level" );
264        }
265 
266        return level.intValue() >= this.getLogLevel().intValue();
267    }
268 
269    /**
270     * Notifies registered listeners.
271     *
272     * @param level The level of the event.
273     * @param message The message of the event or {@code null}.
274     * @param throwable The throwable of the event {@code null}.
275     *
276     * @throws NullPointerException if {@code level} is {@code null}.
277     *
278     * @see #getListeners()
279     * @see #isLoggable(java.util.logging.Level)
280     */
281    public void log( final Level level, final String message, final Throwable throwable )
282    {
283        if ( level == null )
284        {
285            throw new NullPointerException( "level" );
286        }
287 
288        if ( this.isLoggable( level ) )
289        {
290            for ( Listener l : this.getListeners() )
291            {
292                l.onLog( level, message, throwable );
293            }
294        }
295    }
296 
297    /**
298     * Gets the name of the class providing the {@code ModelContext} implementation.
299     * <p>The name of the class providing the {@code ModelContext} implementation returned by method
300     * {@link #createModelContext(java.lang.ClassLoader)} is controlled by system property
301     * {@code org.jomc.model.ModelContext.className}. If that property is not set, the name of the
302     * {@link DefaultModelContext} class is returned.</p>
303     *
304     * @return The name of the class providing the {@code ModelContext} implementation.
305     *
306     * @see #setModelContextClassName(java.lang.String)
307     */
308    public static String getModelContextClassName()
309    {
310        if ( modelContextClassName == null )
311        {
312            modelContextClassName = System.getProperty( "org.jomc.model.ModelContext.className",
313                                                        DefaultModelContext.class.getName() );
314 
315        }
316 
317        return modelContextClassName;
318    }
319 
320    /**
321     * Sets the name of the class providing the ModelContext implementation.
322     *
323     * @param value The new name of the class providing the ModelContext implementation or {@code null}.
324     *
325     * @see #getModelContextClassName()
326     */
327    public static void setModelContextClassName( final String value )
328    {
329        modelContextClassName = value;
330    }
331 
332    /**
333     * Searches the context for a class with a given name.
334     *
335     * @param name The name of the class to return.
336     *
337     * @return A Class object of the class with name {@code name} or {@code null} if no such class is found.
338     *
339     * @throws NullPointerException if {@code name} is {@code null}.
340     * @throws ModelException if searching fails.
341     */
342    public Class findClass( final String name ) throws ModelException
343    {
344        if ( name == null )
345        {
346            throw new NullPointerException( "name" );
347        }
348 
349        try
350        {
351            return Class.forName( name, true, this.getClassLoader() );
352        }
353        catch ( final ClassNotFoundException e )
354        {
355            if ( this.isLoggable( Level.FINE ) )
356            {
357                this.log( Level.FINE, this.getMessage( "classNotFound", new Object[]
358                    {
359                        name
360                    } ), e );
361 
362            }
363 
364            return null;
365        }
366    }
367 
368    /**
369     * Searches the context for a resource with a given name.
370     *
371     * @param name The name of the resource to return.
372     *
373     * @return An URL object for reading the resource or {@code null} if no such resource is found.
374     *
375     * @throws NullPointerException if {@code name} is {@code null}.
376     * @throws ModelException if searching fails.
377     */
378    public URL findResource( final String name ) throws ModelException
379    {
380        if ( name == null )
381        {
382            throw new NullPointerException( "name" );
383        }
384 
385        return this.getClassLoader().getResource( name );
386    }
387 
388    /**
389     * Searches the context for resources with a given name.
390     *
391     * @param name The name of the resources to return.
392     *
393     * @return An enumeration of URL objects for reading the resources. If no resources are found, the enumeration will
394     * be empty.
395     *
396     * @throws NullPointerException if {@code name} is {@code null}.
397     * @throws ModelException if searching fails.
398     */
399    public Enumeration<URL> findResources( final String name ) throws ModelException
400    {
401        if ( name == null )
402        {
403            throw new NullPointerException( "name" );
404        }
405 
406        try
407        {
408            return this.getClassLoader().getResources( name );
409        }
410        catch ( final IOException e )
411        {
412            throw new ModelException( e );
413        }
414    }
415 
416    /**
417     * Searches the context for modules.
418     * <p>This method loads {@code ModelProvider} classes setup via
419     * {@code META-INF/services/org.jomc.model.ModelProvider} resources and returns a list of provided modules.</p>
420     *
421     * @return The modules found in the context.
422     *
423     * @throws ModelException if searching modules fails.
424     *
425     * @see ModelProvider#findModules(org.jomc.model.ModelContext)
426     */
427    public Modules findModules() throws ModelException
428    {
429        try
430        {
431            final Text text = new Text();
432            text.setLanguage( "en" );
433            text.setValue( this.getMessage( "contextModulesInfo", null ) );
434 
435            final Modules modules = new Modules();
436            modules.setDocumentation( new Texts() );
437            modules.getDocumentation().setDefaultLanguage( "en" );
438            modules.getDocumentation().getText().add( text );
439 
440            final Collection<Class<ModelProvider>> providers = this.loadProviders( ModelProvider.class );
441            for ( Class<ModelProvider> provider : providers )
442            {
443                if ( this.isLoggable( Level.CONFIG ) )
444                {
445                    this.log( Level.CONFIG, this.getMessage( "modelProviderInfo", new Object[]
446                        {
447                            provider.getName()
448                        } ), null );
449 
450                }
451 
452                final ModelProvider modelProvider = provider.newInstance();
453                final Modules provided = modelProvider.findModules( this );
454                if ( provided != null )
455                {
456                    modules.getModule().addAll( provided.getModule() );
457                }
458            }
459 
460            if ( this.isLoggable( Level.FINEST ) )
461            {
462                final StringWriter stringWriter = new StringWriter();
463                final Marshaller m = this.createMarshaller();
464                m.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
465                m.marshal( new ObjectFactory().createModules( modules ), stringWriter );
466                stringWriter.close();
467 
468                this.log( Level.FINEST, this.getMessage( "foundModules", null ), null );
469 
470                final BufferedReader reader = new BufferedReader( new StringReader( stringWriter.toString() ) );
471                String line;
472 
473                while ( ( line = reader.readLine() ) != null )
474                {
475                    this.log( Level.FINEST, "\t" + line, null );
476                }
477 
478                reader.close();
479            }
480 
481            return modules;
482        }
483        catch ( final InstantiationException e )
484        {
485            throw new ModelException( e );
486        }
487        catch ( final IllegalAccessException e )
488        {
489            throw new ModelException( e );
490        }
491        catch ( final IOException e )
492        {
493            throw new ModelException( e );
494        }
495        catch ( final JAXBException e )
496        {
497            throw new ModelException( e );
498        }
499    }
500 
501    /**
502     * Processes modules.
503     * <p>This method loads {@code ModelProcessor} classes setup via
504     * {@code META-INF/services/org.jomc.model.ModelProcessor} resources and returns a list of processed modules.</p>
505     *
506     * @param modules The modules to process.
507     *
508     * @return The processed modules.
509     *
510     * @throws NullPointerException if {@code modules} is {@code null}.
511     * @throws ModelException if processing modules fails.
512     *
513     * @see ModelProcessor#processModules(org.jomc.model.ModelContext, org.jomc.model.Modules)
514     */
515    public Modules processModules( final Modules modules ) throws ModelException
516    {
517        if ( modules == null )
518        {
519            throw new NullPointerException( "modules" );
520        }
521 
522        try
523        {
524            Modules processed = modules;
525            final Collection<Class<ModelProcessor>> processors = this.loadProviders( ModelProcessor.class );
526 
527            for ( Class<ModelProcessor> processor : processors )
528            {
529                if ( this.isLoggable( Level.CONFIG ) )
530                {
531                    this.log( Level.CONFIG, this.getMessage( "modelProcessorInfo", new Object[]
532                        {
533                            processor.getName()
534                        } ), null );
535 
536                }
537 
538                final ModelProcessor modelProcessor = processor.newInstance();
539                final Modules current = modelProcessor.processModules( this, processed );
540                if ( current != null )
541                {
542                    processed = current;
543                }
544            }
545 
546            if ( this.isLoggable( Level.FINEST ) )
547            {
548                final StringWriter stringWriter = new StringWriter();
549                final Marshaller m = this.createMarshaller();
550                m.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
551                m.marshal( new ObjectFactory().createModules( processed ), stringWriter );
552                stringWriter.close();
553 
554                this.log( Level.FINEST, this.getMessage( "processedModules", null ), null );
555 
556                final BufferedReader reader = new BufferedReader( new StringReader( stringWriter.toString() ) );
557                String line;
558 
559                while ( ( line = reader.readLine() ) != null )
560                {
561                    this.log( Level.FINEST, "\t" + line, null );
562                }
563 
564                reader.close();
565            }
566 
567            return processed;
568        }
569        catch ( final InstantiationException e )
570        {
571            throw new ModelException( e );
572        }
573        catch ( final IllegalAccessException e )
574        {
575            throw new ModelException( e );
576        }
577        catch ( final IOException e )
578        {
579            throw new ModelException( e );
580        }
581        catch ( final JAXBException e )
582        {
583            throw new ModelException( e );
584        }
585    }
586 
587    /**
588     * Validates a given model.
589     *
590     * @param model A source providing the model to validate.
591     *
592     * @return Validation report.
593     *
594     * @throws NullPointerException if {@code model} is {@code null}.
595     * @throws ModelException if validating the model fails.
596     */
597    public ModelValidationReport validateModel( final Source model ) throws ModelException
598    {
599        if ( model == null )
600        {
601            throw new NullPointerException( "model" );
602        }
603 
604        final Schema schema = this.createSchema();
605        final Validator validator = schema.newValidator();
606        final ModelErrorHandler modelErrorHandler = new ModelErrorHandler();
607        validator.setErrorHandler( modelErrorHandler );
608 
609        try
610        {
611            validator.validate( model );
612        }
613        catch ( final SAXException e )
614        {
615            if ( modelErrorHandler.getReport().isModelValid() )
616            {
617                throw new ModelException( e );
618            }
619        }
620        catch ( final IOException e )
621        {
622            throw new ModelException( e );
623        }
624 
625        return modelErrorHandler.getReport();
626    }
627 
628    /**
629     * Validates a given list of modules.
630     * <p>This method loads {@code ModelValidator} classes setup via
631     * {@code META-INF/services/org.jomc.model.ModelValidator} resources and returns an aggregated validation report.</p>
632     *
633     * @param modules The list of modules to validate.
634     *
635     * @return Validation report.
636     *
637     * @throws NullPointerException if {@code modules} is {@code null}.
638     * @throws ModelException if validating the modules fails.
639     *
640     * @see ModelValidator#validateModel(org.jomc.model.ModelContext, org.jomc.model.Modules)
641     */
642    public ModelValidationReport validateModel( final Modules modules ) throws ModelException
643    {
644        if ( modules == null )
645        {
646            throw new NullPointerException( "modules" );
647        }
648 
649        try
650        {
651            final Collection<Class<ModelValidator>> validators = this.loadProviders( ModelValidator.class );
652            final ModelValidationReport report = new ModelValidationReport();
653 
654            for ( Class<ModelValidator> validator : validators )
655            {
656                if ( this.isLoggable( Level.CONFIG ) )
657                {
658                    this.log( Level.CONFIG, this.getMessage( "modelValidatorInfo", new Object[]
659                        {
660                            validator.getName()
661                        } ), null );
662 
663                }
664 
665                final ModelValidator modelValidator = validator.newInstance();
666                final ModelValidationReport current = modelValidator.validateModel( this, modules );
667                if ( current != null )
668                {
669                    report.getDetails().addAll( current.getDetails() );
670                }
671            }
672 
673            return report;
674        }
675        catch ( final InstantiationException e )
676        {
677            throw new ModelException( e );
678        }
679        catch ( final IllegalAccessException e )
680        {
681            throw new ModelException( e );
682        }
683    }
684 
685    /**
686     * Creates a new object management and configuration model {@code ModelContext} instance.
687     *
688     * @param classLoader The class loader to create a new object management and configuration model context instance
689     * with or {@code null} to create a new context using the platform's bootstrap class loader.
690     *
691     * @return A new {@code ModelContext} instance.
692     *
693     * @throws ModelException if creating a new object management and configuration model context instance fails.
694     *
695     * @see #getModelContextClassName()
696     */
697    public static ModelContext createModelContext( final ClassLoader classLoader ) throws ModelException
698    {
699        if ( DefaultModelContext.class.getName().equals( getModelContextClassName() ) )
700        {
701            return new DefaultModelContext( classLoader );
702        }
703 
704        try
705        {
706            final Class clazz = Class.forName( getModelContextClassName(), true, classLoader );
707            final Constructor ctor = clazz.getConstructor( ClassLoader.class );
708            return (ModelContext) ctor.newInstance( classLoader );
709        }
710        catch ( final ClassNotFoundException e )
711        {
712            throw new ModelException( e );
713        }
714        catch ( final NoSuchMethodException e )
715        {
716            throw new ModelException( e );
717        }
718        catch ( final InstantiationException e )
719        {
720            throw new ModelException( e );
721        }
722        catch ( final IllegalAccessException e )
723        {
724            throw new ModelException( e );
725        }
726        catch ( final InvocationTargetException e )
727        {
728            throw new ModelException( e );
729        }
730        catch ( final ClassCastException e )
731        {
732            throw new ModelException( e );
733        }
734    }
735 
736    /**
737     * Creates a new object management and configuration model SAX entity resolver instance.
738     *
739     * @return A new object management and configuration model SAX entity resolver instance.
740     *
741     * @throws ModelException if creating a new object management and configuration model SAX entity resolver instance
742     * fails.
743     */
744    public abstract EntityResolver createEntityResolver() throws ModelException;
745 
746    /**
747     * Creates a new object management and configuration model L/S resource resolver instance.
748     *
749     * @return A new object management and configuration model L/S resource resolver instance.
750     *
751     * @throws ModelException if creating a new object management and configuration model L/S resource resolver instance
752     * fails.
753     */
754    public abstract LSResourceResolver createResourceResolver() throws ModelException;
755 
756    /**
757     * Creates a new object management and configuration model JAXP schema instance.
758     *
759     * @return A new object management and configuration model JAXP schema instance.
760     *
761     * @throws ModelException if creating a new object management and configuration model JAXP schema instance fails.
762     */
763    public abstract Schema createSchema() throws ModelException;
764 
765    /**
766     * Creates a new object management and configuration model JAXB context instance.
767     *
768     * @return A new object management and configuration model JAXB context instance.
769     *
770     * @throws ModelException if creating a new object management and configuration model JAXB context instance fails.
771     */
772    public abstract JAXBContext createContext() throws ModelException;
773 
774    /**
775     * Creates a new object management and configuration model JAXB marshaller instance.
776     *
777     * @return A new object management and configuration model JAXB marshaller instance.
778     *
779     * @throws ModelException if creating a new object management and configuration model JAXB marshaller instance
780     * fails.
781     */
782    public abstract Marshaller createMarshaller() throws ModelException;
783 
784    /**
785     * Creates a new object management and configuration model JAXB unmarshaller instance.
786     *
787     * @return A new object management and configuration model JAXB unmarshaller instance.
788     *
789     * @throws ModelException if creating a new object management and configuration model JAXB unmarshaller instance
790     * fails.
791     */
792    public abstract Unmarshaller createUnmarshaller() throws ModelException;
793 
794    private <T> Collection<Class<T>> loadProviders( final Class<T> providerClass ) throws ModelException
795    {
796        try
797        {
798            final String providerNamePrefix = providerClass.getName() + ".";
799            final Map<String, Class<T>> providers = new TreeMap<String, Class<T>>( new Comparator<String>()
800            {
801 
802                public int compare( final String key1, final String key2 )
803                {
804                    return key1.compareTo( key2 );
805                }
806 
807            } );
808 
809            final File platformProviders = new File( new StringBuilder().append( System.getProperty( "java.home" ) ).
810                append( File.separator ).append( "jre" ).append( File.separator ).append( "lib" ).
811                append( File.separator ).append( "jomc.properties" ).toString() );
812 
813            if ( platformProviders.exists() )
814            {
815                if ( this.isLoggable( Level.CONFIG ) )
816                {
817                    this.log( Level.CONFIG, this.getMessage( "processing", new Object[]
818                        {
819                            platformProviders.getAbsolutePath()
820                        } ), null );
821 
822                }
823 
824                InputStream in = null;
825                final java.util.Properties p = new java.util.Properties();
826 
827                try
828                {
829                    in = new FileInputStream( platformProviders );
830                    p.load( in );
831                }
832                finally
833                {
834                    if ( in != null )
835                    {
836                        in.close();
837                    }
838                }
839 
840                for ( Map.Entry e : p.entrySet() )
841                {
842                    if ( e.getKey().toString().startsWith( providerNamePrefix ) )
843                    {
844                        final Class<T> provider = this.findClass( e.getValue().toString() );
845                        if ( provider != null )
846                        {
847                            providers.put( e.getKey().toString(), provider );
848                        }
849                    }
850                }
851            }
852 
853            final Enumeration<URL> serviceProviders =
854                this.findResources( "META-INF/services/" + providerClass.getName() );
855 
856            while ( serviceProviders.hasMoreElements() )
857            {
858                final URL url = serviceProviders.nextElement();
859                final BufferedReader reader = new BufferedReader( new InputStreamReader( url.openStream(), "UTF-8" ) );
860 
861                String line = null;
862                while ( ( line = reader.readLine() ) != null )
863                {
864                    if ( line.contains( "#" ) )
865                    {
866                        continue;
867                    }
868 
869                    final Class<T> provider = this.findClass( line );
870                    if ( provider != null )
871                    {
872                        providers.put( providerNamePrefix + providers.size(), provider );
873                    }
874                }
875 
876                reader.close();
877            }
878 
879            return providers.values();
880        }
881        catch ( final IOException e )
882        {
883            throw new ModelException( e );
884        }
885    }
886 
887    private String getMessage( final String key, final Object args )
888    {
889        return new MessageFormat( ResourceBundle.getBundle( ModelContext.class.getName().replace( '.', '/' ),
890                                                            Locale.getDefault() ).getString( key ) ).format( args );
891 
892    }
893 
894}
895 
896/**
897 * {@code ErrorHandler} collecting {@code ModelValidationReport} details.
898 *
899 * @author <a href="mailto:cs@jomc.org">Christian Schulte</a>
900 * @version $Id: ModelContext.java 1336 2010-01-19 04:00:00Z schulte2005 $
901 */
902class ModelErrorHandler extends DefaultHandler
903{
904 
905    /** The report of the instance. */
906    private ModelValidationReport report;
907 
908    /** Creates a new {@code ModelErrorHandler} instance. */
909    public ModelErrorHandler()
910    {
911        this( null );
912    }
913 
914    /**
915     * Creates a new {@code ModelErrorHandler} instance taking a report to use for collecting validation events.
916     *
917     * @param report A report to use for collecting validation events.
918     */
919    public ModelErrorHandler( final ModelValidationReport report )
920    {
921        super();
922        this.report = report;
923    }
924 
925    /**
926     * Gets the report of the instance.
927     *
928     * @return The report of the instance.
929     */
930    public ModelValidationReport getReport()
931    {
932        if ( this.report == null )
933        {
934            this.report = new ModelValidationReport();
935        }
936 
937        return this.report;
938    }
939 
940    @Override
941    public void warning( final SAXParseException exception ) throws SAXException
942    {
943        this.getReport().getDetails().add( new ModelValidationReport.Detail(
944            "W3C XML 1.0 Recommendation - Warning condition", Level.WARNING, exception.getMessage(), null ) );
945 
946    }
947 
948    @Override
949    public void error( final SAXParseException exception ) throws SAXException
950    {
951        this.getReport().getDetails().add( new ModelValidationReport.Detail(
952            "W3C XML 1.0 Recommendation - Section 1.2 - Error", Level.SEVERE, exception.getMessage(), null ) );
953 
954    }
955 
956    @Override
957    public void fatalError( final SAXParseException exception ) throws SAXException
958    {
959        this.getReport().getDetails().add( new ModelValidationReport.Detail(
960            "W3C XML 1.0 Recommendation - Section 1.2 - Fatal Error", Level.SEVERE, exception.getMessage(), null ) );
961 
962    }
963 
964}

[all classes][org.jomc.model]
EMMA 2.0.5312 (C) Vladimir Roubtsov