EMMA Coverage Report (generated Sun Jan 17 14:36:44 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)63%  (543/859)62%  (118.2/191)

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

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