001 /*
002 * Copyright (c) 2009 The JOMC Project
003 * Copyright (c) 2005 Christian Schulte <cs@jomc.org>
004 * All rights reserved.
005 *
006 * Redistribution and use in source and binary forms, with or without
007 * modification, are permitted provided that the following conditions
008 * are met:
009 *
010 * o Redistributions of source code must retain the above copyright
011 * notice, this list of conditions and the following disclaimer.
012 *
013 * o Redistributions in binary form must reproduce the above copyright
014 * notice, this list of conditions and the following disclaimer in
015 * the documentation and/or other materials provided with the
016 * distribution.
017 *
018 * THIS SOFTWARE IS PROVIDED BY THE JOMC PROJECT AND CONTRIBUTORS "AS IS"
019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE JOMC PROJECT OR
022 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
027 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
028 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 *
030 * $Id: DefaultModelManager.java 738 2009-10-06 01:48:21Z schulte2005 $
031 *
032 */
033 package org.jomc.model;
034
035 import java.io.IOException;
036 import java.io.InputStream;
037 import java.io.Reader;
038 import java.io.StringReader;
039 import java.io.StringWriter;
040 import java.lang.reflect.Constructor;
041 import java.lang.reflect.InvocationTargetException;
042 import java.lang.reflect.Method;
043 import java.lang.reflect.Modifier;
044 import java.net.URI;
045 import java.net.URISyntaxException;
046 import java.net.URL;
047 import java.text.MessageFormat;
048 import java.util.ArrayList;
049 import java.util.Enumeration;
050 import java.util.HashMap;
051 import java.util.HashSet;
052 import java.util.Iterator;
053 import java.util.LinkedList;
054 import java.util.List;
055 import java.util.Locale;
056 import java.util.Map;
057 import java.util.ResourceBundle;
058 import java.util.Set;
059 import java.util.jar.Attributes;
060 import java.util.jar.Manifest;
061 import java.util.logging.Level;
062 import javax.xml.XMLConstants;
063 import javax.xml.bind.JAXBContext;
064 import javax.xml.bind.JAXBElement;
065 import javax.xml.bind.JAXBException;
066 import javax.xml.bind.Marshaller;
067 import javax.xml.bind.Unmarshaller;
068 import javax.xml.bind.util.JAXBResult;
069 import javax.xml.bind.util.JAXBSource;
070 import javax.xml.transform.ErrorListener;
071 import javax.xml.transform.Source;
072 import javax.xml.transform.Transformer;
073 import javax.xml.transform.TransformerConfigurationException;
074 import javax.xml.transform.TransformerException;
075 import javax.xml.transform.TransformerFactory;
076 import javax.xml.transform.URIResolver;
077 import javax.xml.transform.sax.SAXSource;
078 import javax.xml.transform.stream.StreamSource;
079 import javax.xml.validation.SchemaFactory;
080 import javax.xml.validation.Validator;
081 import org.jomc.model.bootstrap.BootstrapObject;
082 import org.jomc.model.bootstrap.Schema;
083 import org.jomc.model.bootstrap.Schemas;
084 import org.jomc.util.ParseException;
085 import org.jomc.util.TokenMgrError;
086 import org.jomc.util.VersionParser;
087 import org.jomc.util.WeakIdentityHashMap;
088 import org.w3c.dom.ls.LSInput;
089 import org.w3c.dom.ls.LSResourceResolver;
090 import org.xml.sax.EntityResolver;
091 import org.xml.sax.InputSource;
092 import org.xml.sax.SAXException;
093
094 /**
095 * Default {@code ModelManager} implementation.
096 *
097 * <p><b>Classpath support</b><ul>
098 * <li>{@link #getClassLoader() }</li>
099 * <li>{@link #setClassLoader(java.lang.ClassLoader) }</li>
100 * <li>{@link #getDefaultDocumentLocation() }</li>
101 * <li>{@link #getClasspathModule(org.jomc.model.Modules) }</li>
102 * <li>{@link #getClasspathModules(java.lang.String) }</li>
103 * <li>{@link #getDefaultStylesheetLocation() }</li>
104 * <li>{@link #getClasspathTransformers(java.lang.String) }</li>
105 * </ul></p>
106 *
107 * <p><b>Logging</b><ul>
108 * <li>{@link #getListeners() }</li>
109 * <li>{@link #log(java.util.logging.Level, java.lang.String, java.lang.Throwable) }</li>
110 * </ul></p>
111 *
112 * <p><b>Model bootstrapping</b><ul>
113 * <li>{@link #getBootstrapContext() }</li>
114 * <li>{@link #getBootstrapDocumentLocation() }</li>
115 * <li>{@link #getBootstrapMarshaller(boolean, boolean) }</li>
116 * <li>{@link #getBootstrapObjectFactory() }</li>
117 * <li>{@link #getBootstrapSchema() }</li>
118 * <li>{@link #getBootstrapUnmarshaller(boolean) }</li>
119 * <li>{@link #validateBootstrapObject(javax.xml.bind.JAXBElement) }</li>
120 * <li>{@link #transformBootstrapObject(javax.xml.bind.JAXBElement, javax.xml.transform.Transformer) }</li>
121 * </ul></p>
122 *
123 * @author <a href="mailto:cs@jomc.org">Christian Schulte</a>
124 * @version $Id: DefaultModelManager.java 738 2009-10-06 01:48:21Z schulte2005 $
125 */
126 public class DefaultModelManager implements ModelManager
127 {
128 // SECTION-START[ModelManager]
129
130 public ObjectFactory getObjectFactory()
131 {
132 if ( this.objectFactory == null )
133 {
134 this.objectFactory = new ObjectFactory();
135 }
136
137 return this.objectFactory;
138 }
139
140 public EntityResolver getEntityResolver()
141 {
142 if ( this.entityResolver == null )
143 {
144 this.entityResolver = new EntityResolver()
145 {
146
147 public InputSource resolveEntity( final String publicId, final String systemId )
148 throws SAXException, IOException
149 {
150 if ( systemId == null )
151 {
152 throw new NullPointerException( "systemId" );
153 }
154
155 InputSource schemaSource = null;
156
157 try
158 {
159 final Schema s = getSchemas().getSchema( publicId );
160 if ( s != null )
161 {
162 schemaSource = new InputSource();
163 schemaSource.setPublicId( publicId );
164
165 if ( s.getClasspathId() != null )
166 {
167 schemaSource.setSystemId( getClassLoader().getResource( s.getClasspathId() ).
168 toExternalForm() );
169
170 }
171 else
172 {
173 schemaSource.setSystemId( s.getSystemId() );
174 }
175 }
176
177 if ( schemaSource == null )
178 {
179 final URI systemUri = new URI( systemId );
180 String schemaName = systemUri.getPath();
181 if ( schemaName != null )
182 {
183 final int lastIndexOfSlash = schemaName.lastIndexOf( '/' );
184 if ( lastIndexOfSlash != -1 && lastIndexOfSlash < schemaName.length() )
185 {
186 schemaName = schemaName.substring( lastIndexOfSlash + 1 );
187 }
188
189 for ( URL url : getSchemaResources() )
190 {
191 if ( url.getPath().endsWith( schemaName ) )
192 {
193 schemaSource = new InputSource();
194 schemaSource.setPublicId( publicId );
195 schemaSource.setSystemId( url.toExternalForm() );
196
197 log( Level.FINE, getMessage( "resolvedSystemIdUri", new Object[]
198 {
199 systemUri.toASCIIString(),
200 schemaSource.getSystemId()
201 } ), null );
202
203 break;
204 }
205 }
206 }
207 else
208 {
209 log( Level.WARNING, getMessage( "unsupportedSystemIdUri", new Object[]
210 {
211 systemId, systemUri.toASCIIString()
212 } ), null );
213
214 schemaSource = null;
215 }
216 }
217 }
218 catch ( final URISyntaxException e )
219 {
220 log( Level.WARNING, getMessage( "unsupportedSystemIdUri", new Object[]
221 {
222 systemId, e.getMessage()
223 } ), null );
224
225 schemaSource = null;
226 }
227 catch ( final JAXBException e )
228 {
229 throw (IOException) new IOException( e.getMessage() ).initCause( e );
230 }
231
232 return schemaSource;
233 }
234
235 };
236 }
237
238 return this.entityResolver;
239 }
240
241 public LSResourceResolver getLSResourceResolver()
242 {
243 if ( this.resourceResolver == null )
244 {
245 this.resourceResolver = new LSResourceResolver()
246 {
247
248 public LSInput resolveResource( final String type, final String namespaceURI, final String publicId,
249 final String systemId, final String baseURI )
250 {
251 LSInput input = null;
252 try
253 {
254 final InputSource schemaSource = getEntityResolver().resolveEntity( publicId, systemId );
255
256 if ( schemaSource != null )
257 {
258 input = new LSInput()
259 {
260
261 public Reader getCharacterStream()
262 {
263 return schemaSource.getCharacterStream();
264 }
265
266 public void setCharacterStream( final Reader characterStream )
267 {
268 throw new UnsupportedOperationException();
269 }
270
271 public InputStream getByteStream()
272 {
273 return schemaSource.getByteStream();
274 }
275
276 public void setByteStream( final InputStream byteStream )
277 {
278 throw new UnsupportedOperationException();
279 }
280
281 public String getStringData()
282 {
283 return null;
284 }
285
286 public void setStringData( final String stringData )
287 {
288 throw new UnsupportedOperationException();
289 }
290
291 public String getSystemId()
292 {
293 return schemaSource.getSystemId();
294 }
295
296 public void setSystemId( final String systemId )
297 {
298 throw new UnsupportedOperationException();
299 }
300
301 public String getPublicId()
302 {
303 return schemaSource.getPublicId();
304 }
305
306 public void setPublicId( final String publicId )
307 {
308 throw new UnsupportedOperationException();
309 }
310
311 public String getBaseURI()
312 {
313 return null;
314 }
315
316 public void setBaseURI( final String baseURI )
317 {
318 throw new UnsupportedOperationException();
319 }
320
321 public String getEncoding()
322 {
323 return schemaSource.getEncoding();
324 }
325
326 public void setEncoding( final String encoding )
327 {
328 throw new UnsupportedOperationException();
329 }
330
331 public boolean getCertifiedText()
332 {
333 return false;
334 }
335
336 public void setCertifiedText( final boolean certifiedText )
337 {
338 throw new UnsupportedOperationException();
339 }
340
341 };
342 }
343
344 }
345 catch ( final SAXException e )
346 {
347 log( Level.WARNING, getMessage( "unsupportedSystemIdUri", new Object[]
348 {
349 systemId, e.getMessage()
350 } ), null );
351
352 input = null;
353 }
354 catch ( final IOException e )
355 {
356 log( Level.WARNING, getMessage( "unsupportedSystemIdUri", new Object[]
357 {
358 systemId, e.getMessage()
359 } ), null );
360
361 input = null;
362 }
363
364 return input;
365 }
366
367 };
368 }
369
370 return this.resourceResolver;
371 }
372
373 public javax.xml.validation.Schema getSchema() throws IOException, SAXException, JAXBException
374 {
375 if ( this.schema == null )
376 {
377 final SchemaFactory f = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI );
378 final List<Source> sources = new ArrayList<Source>( this.getSchemas().getSchema().size() );
379
380 for ( Schema s : this.getSchemas().getSchema() )
381 {
382 sources.add( new StreamSource( this.getClassLoader().getResourceAsStream( s.getClasspathId() ),
383 s.getSystemId() ) );
384
385 }
386
387 this.schema = f.newSchema( sources.toArray( new Source[ sources.size() ] ) );
388 }
389
390 return this.schema;
391 }
392
393 public JAXBContext getContext() throws IOException, SAXException, JAXBException
394 {
395 if ( this.context == null )
396 {
397 final StringBuilder pkgs = new StringBuilder();
398
399 for ( final Iterator<Schema> s = this.getSchemas().getSchema().iterator(); s.hasNext(); )
400 {
401 pkgs.append( s.next().getContextId() );
402 if ( s.hasNext() )
403 {
404 pkgs.append( ':' );
405 }
406 }
407
408 if ( pkgs.length() == 0 )
409 {
410 throw new IOException( this.getMessage( "missingSchemas", new Object[]
411 {
412 this.getBootstrapDocumentLocation()
413 } ) );
414
415 }
416
417 this.context = JAXBContext.newInstance( pkgs.toString(), this.getClassLoader() );
418 }
419
420 return this.context;
421 }
422
423 public Marshaller getMarshaller( final boolean validating, final boolean formattedOutput )
424 throws IOException, SAXException, JAXBException
425 {
426 final Marshaller m = this.getContext().createMarshaller();
427 final StringBuilder schemaLocation = new StringBuilder();
428
429 for ( final Iterator<Schema> it = this.getSchemas().getSchema().iterator(); it.hasNext(); )
430 {
431 final Schema s = it.next();
432 schemaLocation.append( s.getPublicId() ).append( ' ' ).append( s.getSystemId() );
433 if ( it.hasNext() )
434 {
435 schemaLocation.append( ' ' );
436 }
437 }
438
439 m.setProperty( Marshaller.JAXB_SCHEMA_LOCATION, schemaLocation.toString() );
440 m.setProperty( Marshaller.JAXB_ENCODING, "UTF-8" );
441 m.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.valueOf( formattedOutput ) );
442
443 if ( validating )
444 {
445 m.setSchema( this.getSchema() );
446 }
447
448 return m;
449 }
450
451 public Unmarshaller getUnmarshaller( final boolean validating ) throws IOException, SAXException, JAXBException
452 {
453 final Unmarshaller u = this.getContext().createUnmarshaller();
454
455 if ( validating )
456 {
457 u.setSchema( this.getSchema() );
458 }
459
460 return u;
461 }
462
463 public void validateModelObject( final JAXBElement<? extends ModelObject> modelObject )
464 throws ModelException, IOException, SAXException, JAXBException
465 {
466 if ( modelObject == null )
467 {
468 throw new NullPointerException( "modelObject" );
469 }
470
471 final StringWriter stringWriter = new StringWriter();
472 final Validator validator = this.getSchema().newValidator();
473 final ModelExceptionErrorHandler errorHandler = new ModelExceptionErrorHandler();
474 validator.setErrorHandler( errorHandler );
475 this.getMarshaller( false, false ).marshal( modelObject, stringWriter );
476
477 try
478 {
479 validator.validate( new StreamSource( new StringReader( stringWriter.toString() ) ) );
480 }
481 catch ( final SAXException e )
482 {
483 final ModelException modelException = new ModelException( this.getMessage( "validationFailed", null ), e );
484 modelException.getDetails().addAll( errorHandler.getDetails() );
485 throw modelException;
486 }
487 }
488
489 public void validateModules( final Modules modules )
490 throws ModelException, IOException, SAXException, JAXBException
491 {
492 if ( modules == null )
493 {
494 throw new NullPointerException( "modules" );
495 }
496
497 this.validateModelObject( this.getObjectFactory().createModules( modules ) );
498 final List<ModelException.Detail> details = new LinkedList<ModelException.Detail>();
499
500 try
501 {
502 for ( Module m : modules.getModule() )
503 {
504 if ( m.getSpecifications() != null )
505 {
506 for ( SpecificationReference r : m.getSpecifications().getReference() )
507 {
508 details.add( this.newModuleSpecificationReferenceDeclarationConstraintDetail(
509 this.getObjectFactory().createModule( m ), m, r ) );
510
511 }
512 }
513
514 if ( m.getImplementations() != null )
515 {
516 for ( ImplementationReference r : m.getImplementations().getReference() )
517 {
518 details.add( this.newModuleImplementationReferenceDeclarationConstraintDetail(
519 this.getObjectFactory().createImplementations( m.getImplementations() ), m, r ) );
520
521 }
522 }
523
524 if ( m.getMessages() != null )
525 {
526 for ( Message msg : m.getMessages().getMessage() )
527 {
528 if ( msg.isFinal() )
529 {
530 details.add( this.newFinalModuleMessageConstraintDetail(
531 this.getObjectFactory().createMessage( msg ), m, msg ) );
532
533 }
534 if ( msg.isOverride() )
535 {
536 details.add( this.newOverrideModuleMessageConstraintDetail(
537 this.getObjectFactory().createMessage( msg ), m, msg ) );
538
539 }
540 }
541 for ( MessageReference r : m.getMessages().getReference() )
542 {
543 details.add( this.newModuleMessageReferenceDeclarationConstraintDetail(
544 this.getObjectFactory().createMessages( m.getMessages() ), m, r ) );
545
546 }
547 }
548
549 if ( m.getProperties() != null )
550 {
551 for ( Property p : m.getProperties().getProperty() )
552 {
553 if ( p.isFinal() )
554 {
555 details.add( this.newFinalModulePropertyConstraintDetail(
556 this.getObjectFactory().createProperty( p ), m, p ) );
557
558 }
559 if ( p.isOverride() )
560 {
561 details.add( this.newOverrideModulePropertyConstraintDetail(
562 this.getObjectFactory().createProperty( p ), m, p ) );
563
564 }
565 }
566 for ( PropertyReference r : m.getProperties().getReference() )
567 {
568 details.add( this.newModulePropertyReferenceDeclarationConstraintDetail(
569 this.getObjectFactory().createProperties( m.getProperties() ), m, r ) );
570
571 }
572 }
573
574 if ( m.getImplementations() != null )
575 {
576 for ( Implementation i : m.getImplementations().getImplementation() )
577 {
578 this.assertImplementationMessagesUniqueness( i, details );
579 this.assertImplementationPropertiesUniqueness( i, details );
580
581 if ( i.getImplementations() != null )
582 {
583 for ( Implementation decl : i.getImplementations().getImplementation() )
584 {
585 details.add( this.newImplementationImplementationDeclarationConstraintDetail(
586 this.getObjectFactory().createImplementations( i.getImplementations() ), i, decl ) );
587
588 }
589 }
590
591 if ( i.getSpecifications() != null )
592 {
593 for ( Specification s : i.getSpecifications().getSpecification() )
594 {
595 details.add( this.newImplementationSpecificationDeclarationConstraintDetail(
596 this.getObjectFactory().createImplementation( i ), i, s ) );
597
598 }
599 }
600
601 if ( i.isAbstract() && i.getLocation() != null )
602 {
603 details.add( this.newAbstractLocationConstraintDetail(
604 this.getObjectFactory().createImplementation( i ), i, i.getLocation() ) );
605
606 }
607
608 final Implementation cycle = this.findInheritanceCycle( modules, i, i, new Implementations() );
609 if ( cycle != null )
610 {
611 details.add( this.newImplementationInheritanceCycleConstraintDetail(
612 this.getObjectFactory().createImplementation( i ), i, cycle ) );
613
614 }
615
616 final Specifications specs = modules.getSpecifications( i.getIdentifier() );
617 final Dependencies deps = modules.getDependencies( i.getIdentifier() );
618
619 if ( specs != null )
620 {
621 for ( SpecificationReference r : specs.getReference() )
622 {
623 final Specification s = specs.getSpecification( r.getIdentifier() );
624
625 if ( s != null && r.getVersion() != null )
626 {
627 if ( s.getVersion() == null )
628 {
629 details.add( this.newSpecificationVersioningConstraintDetail(
630 this.getObjectFactory().createSpecifications( specs ), i, s ) );
631
632 }
633 else if ( VersionParser.compare( r.getVersion(), s.getVersion() ) != 0 )
634 {
635 final Module moduleOfSpecification =
636 modules.getModuleOfSpecification( s.getIdentifier() );
637
638 details.add( this.newIncompatibleImplementationDetail(
639 this.getObjectFactory().createImplementation( i ),
640 i.getIdentifier(), m.getName(),
641 r.getIdentifier(), moduleOfSpecification == null
642 ? "<>" : moduleOfSpecification.getName(),
643 r.getVersion(), s.getVersion() ) );
644
645 }
646 }
647 }
648 }
649
650 if ( deps != null )
651 {
652 for ( Dependency d : deps.getDependency() )
653 {
654 final Specification s = modules.getSpecification( d.getIdentifier() );
655
656 if ( s != null )
657 {
658 if ( d.getVersion() != null )
659 {
660 if ( s.getVersion() == null )
661 {
662 details.add( this.newSpecificationVersioningConstraintDetail(
663 this.getObjectFactory().createDependency( d ), i, s ) );
664
665 }
666 else if ( VersionParser.compare( d.getVersion(), s.getVersion() ) > 0 )
667 {
668 final Module moduleOfSpecification =
669 modules.getModuleOfSpecification( s.getIdentifier() );
670
671 details.add( this.newIncompatibleDependencyDetail(
672 this.getObjectFactory().createDependency( d ),
673 i.getIdentifier(), m.getName(),
674 d.getIdentifier(), moduleOfSpecification == null
675 ? "<>" : moduleOfSpecification.getName(),
676 d.getVersion(), s.getVersion() ) );
677
678 }
679 }
680
681 if ( d.getProperties() != null )
682 {
683 for ( PropertyReference r : d.getProperties().getReference() )
684 {
685 details.add( this.newDependencyPropertyReferenceDeclarationConstraintDetail(
686 this.getObjectFactory().createDependency( d ), i, d, r ) );
687
688 }
689
690 if ( s.getScope() != null )
691 {
692 for ( Property p : d.getProperties().getProperty() )
693 {
694 details.add( this.newDependencyPropertiesOverrideConstraintDetail(
695 this.getObjectFactory().createDependency( d ), i, d, s, p ) );
696
697 }
698 }
699 }
700 }
701
702 final Implementations available = modules.getImplementations( d.getIdentifier() );
703
704 if ( !d.isOptional() )
705 {
706 boolean missing = false;
707
708 if ( available == null )
709 {
710 missing = true;
711 }
712 else if ( available.getImplementation().isEmpty() )
713 {
714 missing = true;
715 }
716 else if ( d.getImplementationName() != null &&
717 available.getImplementationByName( d.getImplementationName() ) == null )
718 {
719 missing = true;
720 }
721
722 if ( missing )
723 {
724 details.add( this.newMandatoryDependencyConstraintDetail(
725 this.getObjectFactory().createDependency( d ), i.getIdentifier(),
726 d.getName() ) );
727
728 }
729 }
730 }
731 }
732
733 if ( i.getImplementations() != null )
734 {
735 final Implementations finalSuperImplementations = new Implementations();
736 this.collectFinalSuperImplementations( modules, i, finalSuperImplementations,
737 new Implementations(), false );
738
739 for ( Implementation finalSuper : finalSuperImplementations.getImplementation() )
740 {
741 details.add( this.newImplementationInheritanceConstraintDetail(
742 this.getObjectFactory().createImplementation( i ), i, finalSuper ) );
743
744 }
745
746 for ( ImplementationReference r : i.getImplementations().getReference() )
747 {
748 final Implementation referenced = modules.getImplementation( r.getIdentifier() );
749 if ( referenced != null && r.getVersion() != null )
750 {
751 if ( referenced.getVersion() == null )
752 {
753 details.add( this.newImplementationVersioningConstraintDetail(
754 this.getObjectFactory().createImplementations( i.getImplementations() ),
755 i, referenced ) );
756
757 }
758 else if ( VersionParser.compare( r.getVersion(), referenced.getVersion() ) > 0 )
759 {
760 details.add( this.newImplementationInheritanceCompatibilityConstraintDetail(
761 this.getObjectFactory().createImplementation( i ), i, referenced,
762 r.getVersion() ) );
763
764 }
765 }
766 }
767 }
768
769 if ( i.getSpecifications() != null )
770 {
771 final Specifications superSpecifications = new Specifications();
772 modules.collectSpecifications( i, superSpecifications, new Implementations(), false );
773
774 for ( SpecificationReference r : i.getSpecifications().getReference() )
775 {
776 boolean override = false;
777
778 if ( i.getImplementations() != null )
779 {
780 final Implementations finalSuperSpecifications = new Implementations();
781 this.collectFinalSuperSpecifications( modules, i, r.getIdentifier(),
782 finalSuperSpecifications,
783 new Implementations(), false );
784
785 for ( Implementation finalSuper : finalSuperSpecifications.getImplementation() )
786 {
787 details.add( this.newSpecificationInheritanceConstraintDetail(
788 this.getObjectFactory().createImplementation( i ), i, r, finalSuper ) );
789
790 }
791
792 override = superSpecifications.getReference( r.getIdentifier() ) != null;
793 }
794
795 if ( r.isOverride() && !override )
796 {
797 details.add( this.newSpecificationOverrideConstraintDetail(
798 this.getObjectFactory().createSpecifications( i.getSpecifications() ), i, r ) );
799
800 }
801 if ( !r.isOverride() && override )
802 {
803 this.log( Level.WARNING, this.getMessage( "specificationOverrideWarning",
804 new Object[]
805 {
806 i.getIdentifier(), r.getIdentifier()
807 } ), null );
808
809 }
810 }
811 }
812
813 if ( i.getDependencies() != null )
814 {
815 final Dependencies superDependencies = new Dependencies();
816 modules.collectDependencies( i, superDependencies, new Implementations(), false );
817
818 for ( Dependency d : i.getDependencies().getDependency() )
819 {
820 boolean override = false;
821
822 if ( i.getImplementations() != null )
823 {
824 final Implementations finalSuperDependencies = new Implementations();
825 this.collectFinalSuperDependencies( modules, i, d.getName(), finalSuperDependencies,
826 new Implementations(), false );
827
828 for ( Implementation finalSuper : finalSuperDependencies.getImplementation() )
829 {
830 details.add( this.newDependencyInheritanceConstraintDetail(
831 this.getObjectFactory().createImplementation( i ), i, d, finalSuper ) );
832
833 }
834
835 override = superDependencies.getDependency( d.getName() ) != null;
836 }
837
838 if ( d.isOverride() && !override )
839 {
840 details.add( this.newDependencyOverrideConstraintDetail(
841 this.getObjectFactory().createDependency( d ), i, d ) );
842
843 }
844 if ( !d.isOverride() && override )
845 {
846 this.log( Level.WARNING, this.getMessage( "dependencyOverrideWarning", new Object[]
847 {
848 i.getIdentifier(), d.getName()
849 } ), null );
850
851 }
852 }
853 }
854
855 if ( i.getProperties() != null )
856 {
857 final Properties superProperties = new Properties();
858 modules.collectProperties( i, superProperties, new Implementations(), false );
859
860 for ( Property p : i.getProperties().getProperty() )
861 {
862 boolean override = false;
863
864 if ( i.getImplementations() != null )
865 {
866 final Implementations finalSuperProperties = new Implementations();
867 this.collectFinalSuperProperties( modules, i, p.getName(), finalSuperProperties,
868 new Implementations(), false );
869
870 for ( Implementation finalSuper : finalSuperProperties.getImplementation() )
871 {
872 details.add( this.newPropertyInheritanceConstraintDetail(
873 this.getObjectFactory().createImplementation( i ), i, p, finalSuper ) );
874
875 }
876
877 override = superProperties.getProperty( p.getName() ) != null;
878 }
879
880 if ( p.isOverride() && !override )
881 {
882 details.add( this.newPropertyOverrideConstraintDetail(
883 this.getObjectFactory().createProperty( p ), i, p ) );
884
885 }
886 if ( !p.isOverride() && override )
887 {
888 this.log( Level.WARNING, this.getMessage( "propertyOverrideWarning", new Object[]
889 {
890 i.getIdentifier(), p.getName()
891 } ), null );
892
893 }
894 }
895
896 for ( PropertyReference r : i.getProperties().getReference() )
897 {
898 boolean override = false;
899
900 if ( i.getImplementations() != null )
901 {
902 final Implementations finalSuperProperties = new Implementations();
903 this.collectFinalSuperProperties( modules, i, r.getName(), finalSuperProperties,
904 new Implementations(), false );
905
906 for ( Implementation finalSuper : finalSuperProperties.getImplementation() )
907 {
908 details.add( this.newPropertyInheritanceConstraintDetail(
909 this.getObjectFactory().createImplementation( i ), i, r, finalSuper ) );
910
911 }
912
913 override = superProperties.getProperty( r.getName() ) != null;
914 }
915
916 if ( r.isOverride() && !override )
917 {
918 details.add( this.newPropertyOverrideConstraintDetail(
919 this.getObjectFactory().createProperties( i.getProperties() ), i, r ) );
920
921 }
922 if ( !r.isOverride() && override )
923 {
924 this.log( Level.WARNING, this.getMessage( "propertyOverrideWarning", new Object[]
925 {
926 i.getIdentifier(), r.getName()
927 } ), null );
928
929 }
930 }
931 }
932
933 if ( i.getMessages() != null )
934 {
935 final Messages superMessages = new Messages();
936 modules.collectMessages( i, superMessages, new Implementations(), false );
937
938 for ( Message msg : i.getMessages().getMessage() )
939 {
940 boolean override = false;
941
942 if ( i.getImplementations() != null )
943 {
944 final Implementations finalSuperMessages = new Implementations();
945 this.collectFinalSuperMessages( modules, i, msg.getName(), finalSuperMessages,
946 new Implementations(), false );
947
948 for ( Implementation finalSuper : finalSuperMessages.getImplementation() )
949 {
950 details.add( this.newMessageInheritanceConstraintDetail(
951 this.getObjectFactory().createImplementation( i ), i, msg, finalSuper ) );
952
953 }
954
955 override = superMessages.getMessage( msg.getName() ) != null;
956 }
957
958 if ( msg.isOverride() && !override )
959 {
960 details.add( this.newMessageOverrideConstraintDetail(
961 this.getObjectFactory().createMessage( msg ), i, msg ) );
962
963 }
964 if ( !msg.isOverride() && override )
965 {
966 this.log( Level.WARNING, this.getMessage( "messageOverrideWarning", new Object[]
967 {
968 i.getIdentifier(), msg.getName()
969 } ), null );
970
971 }
972 }
973
974 for ( MessageReference r : i.getMessages().getReference() )
975 {
976 boolean override = false;
977
978 if ( i.getImplementations() != null )
979 {
980 final Implementations finalSuperMessages = new Implementations();
981 this.collectFinalSuperMessages( modules, i, r.getName(), finalSuperMessages,
982 new Implementations(), false );
983
984 for ( Implementation finalSuper : finalSuperMessages.getImplementation() )
985 {
986 details.add( this.newMessageInheritanceConstraintDetail(
987 this.getObjectFactory().createImplementation( i ), i, r, finalSuper ) );
988
989 }
990
991 override = superMessages.getMessage( r.getName() ) != null;
992 }
993
994 if ( r.isOverride() && !override )
995 {
996 details.add( this.newMessageOverrideConstraintDetail(
997 this.getObjectFactory().createMessages( i.getMessages() ), i, r ) );
998
999 }
1000 if ( !r.isOverride() && override )
1001 {
1002 this.log( Level.WARNING, this.getMessage( "messageOverrideWarning", new Object[]
1003 {
1004 i.getIdentifier(), r.getName()
1005 } ), null );
1006
1007 }
1008 }
1009 }
1010
1011 if ( i.getImplementations() != null )
1012 {
1013 final Map<String, List<SpecificationReference>> specMap =
1014 new HashMap<String, List<SpecificationReference>>();
1015
1016 final Map<String, List<Dependency>> dependencyMap =
1017 new HashMap<String, List<Dependency>>();
1018
1019 final Map<String, List<Message>> messageMap =
1020 new HashMap<String, List<Message>>();
1021
1022 final Map<String, List<Property>> propertyMap =
1023 new HashMap<String, List<Property>>();
1024
1025 for ( ImplementationReference r : i.getImplementations().getReference() )
1026 {
1027 final Specifications currentSpecs = new Specifications();
1028 final Dependencies currentDependencies = new Dependencies();
1029 final Properties currentProperties = new Properties();
1030 final Messages currentMessages = new Messages();
1031 final Implementation current = modules.getImplementation( r.getIdentifier() );
1032
1033 modules.collectSpecifications( current, currentSpecs, new Implementations(), true );
1034 modules.collectDependencies( current, currentDependencies, new Implementations(), true );
1035 modules.collectMessages( current, currentMessages, new Implementations(), true );
1036 modules.collectProperties( current, currentProperties, new Implementations(), true );
1037
1038 for ( SpecificationReference ref : currentSpecs.getReference() )
1039 {
1040 List<SpecificationReference> list = specMap.get( ref.getIdentifier() );
1041 if ( list == null )
1042 {
1043 list = new LinkedList<SpecificationReference>();
1044 specMap.put( ref.getIdentifier(), list );
1045 }
1046
1047 list.add( ref );
1048 }
1049
1050 for ( Dependency d : currentDependencies.getDependency() )
1051 {
1052 List<Dependency> list = dependencyMap.get( d.getName() );
1053 if ( list == null )
1054 {
1055 list = new LinkedList<Dependency>();
1056 dependencyMap.put( d.getName(), list );
1057 }
1058
1059 list.add( d );
1060 }
1061
1062 for ( Message msg : currentMessages.getMessage() )
1063 {
1064 List<Message> list = messageMap.get( msg.getName() );
1065 if ( list == null )
1066 {
1067 list = new LinkedList<Message>();
1068 messageMap.put( msg.getName(), list );
1069 }
1070
1071 list.add( msg );
1072 }
1073
1074 for ( Property p : currentProperties.getProperty() )
1075 {
1076 List<Property> list = propertyMap.get( p.getName() );
1077 if ( list == null )
1078 {
1079 list = new LinkedList<Property>();
1080 propertyMap.put( p.getName(), list );
1081 }
1082
1083 list.add( p );
1084 }
1085 }
1086
1087 for ( Map.Entry<String, List<SpecificationReference>> e : specMap.entrySet() )
1088 {
1089 if ( e.getValue().size() > 1 &&
1090 ( i.getSpecifications() == null ||
1091 i.getSpecifications().getReference( e.getKey() ) == null ) )
1092 {
1093 details.add(
1094 this.newSpecificationMultipleInheritanceContraintDetail(
1095 this.getObjectFactory().createImplementation( i ), i, e.getValue().get( 0 ) ) );
1096
1097 }
1098 }
1099
1100 for ( Map.Entry<String, List<Dependency>> e : dependencyMap.entrySet() )
1101 {
1102 if ( e.getValue().size() > 1 &&
1103 ( i.getDependencies() == null ||
1104 i.getDependencies().getDependency( e.getKey() ) == null ) )
1105 {
1106 details.add(
1107 this.newDependencyMultipleInheritanceContraintDetail(
1108 this.getObjectFactory().createImplementation( i ), i, e.getValue().get( 0 ) ) );
1109
1110 }
1111 }
1112
1113 for ( Map.Entry<String, List<Message>> e : messageMap.entrySet() )
1114 {
1115 if ( e.getValue().size() > 1 &&
1116 ( i.getMessages() == null ||
1117 ( i.getMessages().getMessage( e.getKey() ) == null &&
1118 i.getMessages().getReference( e.getKey() ) == null ) ) )
1119 {
1120 details.add(
1121 this.newMessageMultipleInheritanceContraintDetail(
1122 this.getObjectFactory().createImplementation( i ), i, e.getValue().get( 0 ) ) );
1123
1124 }
1125 }
1126
1127 for ( Map.Entry<String, List<Property>> e : propertyMap.entrySet() )
1128 {
1129 if ( e.getValue().size() > 1 &&
1130 ( i.getProperties() == null ||
1131 ( i.getProperties().getProperty( e.getKey() ) == null &&
1132 i.getProperties().getReference( e.getKey() ) == null ) ) )
1133 {
1134 details.add(
1135 this.newPropertyMultipleInheritanceContraintDetail(
1136 this.getObjectFactory().createImplementation( i ), i, e.getValue().get( 0 ) ) );
1137
1138 }
1139 }
1140 }
1141 }
1142 }
1143
1144 if ( m.getSpecifications() != null )
1145 {
1146 for ( Specification s : m.getSpecifications().getSpecification() )
1147 {
1148 if ( s.getProperties() != null )
1149 {
1150 for ( PropertyReference r : s.getProperties().getReference() )
1151 {
1152 details.add( this.newSpecificationPropertyReferenceDeclarationConstraintDetail(
1153 this.getObjectFactory().createSpecification( s ), s, r ) );
1154
1155 }
1156 }
1157
1158 final Implementations impls = modules.getImplementations( s.getIdentifier() );
1159
1160 if ( impls != null )
1161 {
1162 final Map<String, Implementations> map = new HashMap<String, Implementations>();
1163
1164 for ( Implementation i : impls.getImplementation() )
1165 {
1166 Implementations implementations = map.get( i.getName() );
1167 if ( implementations == null )
1168 {
1169 implementations = new Implementations();
1170 map.put( i.getName(), implementations );
1171 }
1172
1173 implementations.getImplementation().add( i );
1174 }
1175
1176 for ( Map.Entry<String, Implementations> e : map.entrySet() )
1177 {
1178 if ( e.getValue().getImplementation().size() > 1 )
1179 {
1180 for ( Implementation i : e.getValue().getImplementation() )
1181 {
1182 details.add( this.newImplementationNameConstraintDetail(
1183 this.getObjectFactory().createSpecification( s ), s, i ) );
1184
1185 }
1186 }
1187 }
1188
1189 if ( s.getMultiplicity() == Multiplicity.ONE && impls.getImplementation().size() > 1 )
1190 {
1191 for ( Implementation i : impls.getImplementation() )
1192 {
1193 details.add( this.newMultiplicityConstraintDetail(
1194 this.getObjectFactory().createImplementation( i ), s, i ) );
1195
1196 }
1197 }
1198 }
1199 }
1200 }
1201 }
1202
1203 if ( !details.isEmpty() )
1204 {
1205 final ModelException modelException = new ModelException( this.getMessage( "validationFailed", null ) );
1206 modelException.getDetails().addAll( details );
1207 throw modelException;
1208 }
1209 }
1210 catch ( final TokenMgrError e )
1211 {
1212 throw new ModelException( e.getMessage(), e );
1213 }
1214 catch ( final ParseException e )
1215 {
1216 throw new ModelException( e.getMessage(), e );
1217 }
1218 }
1219
1220 public <T extends ModelObject> T transformModelObject(
1221 final JAXBElement<T> modelObject, final Transformer transformer )
1222 throws IOException, SAXException, JAXBException, TransformerException
1223 {
1224 if ( modelObject == null )
1225 {
1226 throw new NullPointerException( "modelObject" );
1227 }
1228 if ( transformer == null )
1229 {
1230 throw new NullPointerException( "transformer" );
1231 }
1232
1233 final JAXBContext ctx = this.getContext();
1234 final JAXBSource source = new JAXBSource( ctx, modelObject );
1235 final JAXBResult result = new JAXBResult( ctx );
1236 transformer.transform( source, result );
1237 return ( (JAXBElement<T>) result.getResult() ).getValue();
1238 }
1239
1240 public Instance getInstance( final Modules modules, final Implementation implementation, final ClassLoader cl )
1241 {
1242 if ( modules == null )
1243 {
1244 throw new NullPointerException( "modules" );
1245 }
1246 if ( implementation == null )
1247 {
1248 throw new NullPointerException( "implementation" );
1249 }
1250 if ( cl == null )
1251 {
1252 throw new NullPointerException( "classLoader" );
1253 }
1254
1255 final Instance instance = new Instance();
1256 instance.setIdentifier( implementation.getIdentifier() );
1257 instance.setImplementationName( implementation.getName() );
1258 instance.setClazz( implementation.getClazz() );
1259 instance.setClassLoader( cl );
1260 instance.setStateless( implementation.isStateless() );
1261 instance.setDependencies( modules.getDependencies( implementation.getIdentifier() ) );
1262 instance.setProperties( modules.getProperties( implementation.getIdentifier() ) );
1263 instance.setMessages( modules.getMessages( implementation.getIdentifier() ) );
1264 instance.setSpecifications( modules.getSpecifications( implementation.getIdentifier() ) );
1265 return instance;
1266 }
1267
1268 public Instance getInstance( final Modules modules, final Implementation implementation,
1269 final Dependency dependency, final ClassLoader cl )
1270 {
1271 if ( modules == null )
1272 {
1273 throw new NullPointerException( "modules" );
1274 }
1275 if ( implementation == null )
1276 {
1277 throw new NullPointerException( "implementation" );
1278 }
1279 if ( dependency == null )
1280 {
1281 throw new NullPointerException( "dependency" );
1282 }
1283 if ( cl == null )
1284 {
1285 throw new NullPointerException( "cl" );
1286 }
1287
1288 final Instance instance = this.getInstance( modules, implementation, cl );
1289 final Specification dependencySpecification = modules.getSpecification( dependency.getIdentifier() );
1290
1291 if ( dependencySpecification != null && dependencySpecification.getScope() == null &&
1292 dependency.getProperties() != null && !dependency.getProperties().getProperty().isEmpty() )
1293 {
1294 final Properties properties = new Properties();
1295 properties.getProperty().addAll( dependency.getProperties().getProperty() );
1296
1297 if ( instance.getProperties() != null )
1298 {
1299 for ( Property p : instance.getProperties().getProperty() )
1300 {
1301 if ( properties.getProperty( p.getName() ) == null )
1302 {
1303 properties.getProperty().add( p );
1304 }
1305 }
1306 }
1307
1308 instance.setProperties( properties );
1309 }
1310
1311 return instance;
1312 }
1313
1314 public Instance getInstance( final Modules modules, final Object object )
1315 {
1316 if ( modules == null )
1317 {
1318 throw new NullPointerException( "modules" );
1319 }
1320 if ( object == null )
1321 {
1322 throw new NullPointerException( "object" );
1323 }
1324
1325 synchronized ( this.objects )
1326 {
1327 Instance instance = (Instance) this.objects.get( object );
1328
1329 if ( instance == null )
1330 {
1331 final Implementation i = this.getImplementation( modules, object );
1332
1333 if ( i != null )
1334 {
1335 ClassLoader cl = object.getClass().getClassLoader();
1336 if ( cl == null )
1337 {
1338 cl = ClassLoader.getSystemClassLoader();
1339 }
1340
1341 instance = this.getInstance( modules, i, cl );
1342 if ( instance != null )
1343 {
1344 this.objects.put( object, instance );
1345 }
1346 }
1347 }
1348
1349 return instance;
1350 }
1351 }
1352
1353 public Object getObject( final Modules modules, final Specification specification, final Instance instance )
1354 throws InstantiationException
1355 {
1356 if ( modules == null )
1357 {
1358 throw new NullPointerException( "modules" );
1359 }
1360 if ( specification == null )
1361 {
1362 throw new NullPointerException( "specification" );
1363 }
1364 if ( instance == null )
1365 {
1366 throw new NullPointerException( "instance" );
1367 }
1368
1369 Object object = null;
1370
1371 try
1372 {
1373 final Class specClass = Class.forName( specification.getClazz(), true, instance.getClassLoader() );
1374 final Class clazz = Class.forName( instance.getClazz(), true, instance.getClassLoader() );
1375
1376 if ( Modifier.isPublic( clazz.getModifiers() ) )
1377 {
1378 Constructor ctor = null;
1379
1380 try
1381 {
1382 ctor = clazz.getConstructor( NO_CLASSES );
1383 }
1384 catch ( final NoSuchMethodException e )
1385 {
1386 this.log( Level.FINE, this.getMessage( "noSuchMethod", new Object[]
1387 {
1388 e.getMessage()
1389 } ), null );
1390
1391 ctor = null;
1392 }
1393
1394 if ( ctor != null && specClass.isAssignableFrom( clazz ) )
1395 {
1396 synchronized ( this.objects )
1397 {
1398 object = clazz.newInstance();
1399 this.objects.put( object, instance );
1400 }
1401 }
1402 else
1403 {
1404 final StringBuilder methodNames = new StringBuilder().append( '[' );
1405 Method factoryMethod = null;
1406 String methodName = null;
1407
1408 char[] c = instance.getImplementationName().toCharArray();
1409 c[0] = Character.toUpperCase( c[0] );
1410 methodName = "get" + String.valueOf( c );
1411
1412 boolean javaIdentifier = Character.isJavaIdentifierStart( c[0] );
1413 if ( javaIdentifier )
1414 {
1415 for ( int idx = c.length - 1; idx > 0; idx-- )
1416 {
1417 if ( !Character.isJavaIdentifierPart( c[idx] ) )
1418 {
1419 javaIdentifier = false;
1420 break;
1421 }
1422 }
1423 }
1424
1425 if ( javaIdentifier )
1426 {
1427 methodNames.append( methodName );
1428 factoryMethod = this.getFactoryMethod( clazz, methodName );
1429 }
1430
1431 if ( factoryMethod == null )
1432 {
1433 methodName = specification.getIdentifier().substring(
1434 specification.getIdentifier().lastIndexOf( '.' ) + 1 );
1435
1436 c = methodName.toCharArray();
1437 c[0] = Character.toUpperCase( c[0] );
1438
1439 javaIdentifier = Character.isJavaIdentifierStart( c[0] );
1440 if ( javaIdentifier )
1441 {
1442 for ( int idx = c.length - 1; idx > 0; idx-- )
1443 {
1444 if ( !Character.isJavaIdentifierPart( c[idx] ) )
1445 {
1446 javaIdentifier = false;
1447 break;
1448 }
1449 }
1450 }
1451
1452 if ( javaIdentifier )
1453 {
1454 methodName = "get" + String.valueOf( c );
1455 methodNames.append( " " ).append( methodName );
1456 factoryMethod = this.getFactoryMethod( clazz, methodName );
1457 }
1458 }
1459
1460 if ( factoryMethod == null )
1461 {
1462 methodName = "getObject";
1463 methodNames.append( " " ).append( methodName );
1464 factoryMethod = this.getFactoryMethod( clazz, methodName );
1465 }
1466
1467 methodNames.append( ']' );
1468
1469 if ( factoryMethod == null )
1470 {
1471 throw new InstantiationException( this.getMessage( "missingFactoryMethod", new Object[]
1472 {
1473 clazz.getName(), instance.getIdentifier(), methodNames.toString()
1474 } ) );
1475
1476 }
1477
1478 if ( Modifier.isStatic( factoryMethod.getModifiers() ) )
1479 {
1480 object = factoryMethod.invoke( null, NO_OBJECTS );
1481 }
1482 else if ( ctor != null )
1483 {
1484 synchronized ( this.objects )
1485 {
1486 object = ctor.newInstance();
1487 this.objects.put( object, instance );
1488 object = factoryMethod.invoke( object, NO_OBJECTS );
1489 this.objects.put( object, instance );
1490 }
1491 }
1492 else
1493 {
1494 throw new InstantiationException( this.getMessage( "missingFactoryMethod", new Object[]
1495 {
1496 clazz.getName(), instance.getIdentifier(), methodNames.toString()
1497 } ) );
1498
1499 }
1500 }
1501 }
1502
1503 return object;
1504 }
1505 catch ( final InvocationTargetException e )
1506 {
1507 throw (InstantiationException) new InstantiationException().initCause(
1508 e.getTargetException() != null ? e.getTargetException() : e );
1509
1510 }
1511 catch ( final IllegalAccessException e )
1512 {
1513 throw (InstantiationException) new InstantiationException().initCause( e );
1514 }
1515 catch ( final ClassNotFoundException e )
1516 {
1517 throw (InstantiationException) new InstantiationException().initCause( e );
1518 }
1519 }
1520
1521 // SECTION-END
1522 // SECTION-START[DefaultModelManager]
1523 /** Listener interface. */
1524 public interface Listener
1525 {
1526
1527 /**
1528 * Get called on logging.
1529 *
1530 * @param level The level of the event.
1531 * @param message The message of the event or {@code null}.
1532 * @param t The throwable of the event or {@code null}.
1533 */
1534 void onLog( Level level, String message, Throwable t );
1535
1536 }
1537
1538 /**
1539 * Constant for the name of the classpath module.
1540 * @see #getClasspathModuleName()
1541 */
1542 private static final String DEFAULT_CLASSPATH_MODULE_NAME = "Java Classpath";
1543
1544 /**
1545 * Classpath location searched for documents by default.
1546 * @see #getDefaultDocumentLocation()
1547 */
1548 private static final String DEFAULT_DOCUMENT_LOCATION = "META-INF/jomc.xml";
1549
1550 /**
1551 * Classpath location searched for style sheets by default.
1552 * @see #getDefaultStylesheetLocation()
1553 */
1554 private static final String DEFAULT_STYLESHEET_LOCATION = "META-INF/jomc.xslt";
1555
1556 /** Classpath location of the bootstrap schema. */
1557 private static final String BOOTSTRAP_SCHEMA_LOCATION =
1558 Schemas.class.getPackage().getName().replace( '.', '/' ) + "/jomc-bootstrap-1.0.xsd";
1559
1560 /**
1561 * Classpath location searched for bootstrap documents by default.
1562 * @see #getBootstrapDocumentLocation()
1563 */
1564 private static final String DEFAULT_BOOTSTRAP_DOCUMENT_LOCATION = "META-INF/jomc-bootstrap.xml";
1565
1566 /** JAXB context of the bootstrap schema. */
1567 private static final String BOOTSTRAP_CONTEXT = Schemas.class.getPackage().getName();
1568
1569 /** Supported schema name extensions. */
1570 private static final String[] SCHEMA_EXTENSIONS = new String[]
1571 {
1572 "xsd"
1573 };
1574
1575 /** Empty {@code Class} array. */
1576 private static final Class[] NO_CLASSES =
1577 {
1578 };
1579
1580 /** Empty {@code Object} array. */
1581 private static final Object[] NO_OBJECTS =
1582 {
1583 };
1584
1585 /** Class loader of the instance. */
1586 private ClassLoader classLoader;
1587
1588 /** The entity resolver of the instance. */
1589 private EntityResolver entityResolver;
1590
1591 /** The L/S resolver of the instance. */
1592 private LSResourceResolver resourceResolver;
1593
1594 /** The context of the instance. */
1595 private JAXBContext context;
1596
1597 /** The schema of the instance. */
1598 private javax.xml.validation.Schema schema;
1599
1600 /** The bootstrap schema. */
1601 private javax.xml.validation.Schema bootstrapSchema;
1602
1603 /** URLs of all available classpath schema resources. */
1604 private Set<URL> schemaResources;
1605
1606 /** Schemas of the instance. */
1607 private Schemas schemas;
1608
1609 /** Object factory of the instance. */
1610 private ObjectFactory objectFactory;
1611
1612 /** Bootstrap object factory of the instance. */
1613 private org.jomc.model.bootstrap.ObjectFactory bootstrapObjectFactory;
1614
1615 /** The listeners of the instance. */
1616 private List<Listener> listeners;
1617
1618 /** Maps objects to {@code Instance}s. */
1619 private final Map objects = new WeakIdentityHashMap( 1024 );
1620
1621 /** Creates a new {@code DefaultModelManager} instance. */
1622 public DefaultModelManager()
1623 {
1624 super();
1625 }
1626
1627 /**
1628 * Gets the bootstrap object factory of the instance.
1629 *
1630 * @return The bootstrap object factory of the instance.
1631 */
1632 public org.jomc.model.bootstrap.ObjectFactory getBootstrapObjectFactory()
1633 {
1634 if ( this.bootstrapObjectFactory == null )
1635 {
1636 this.bootstrapObjectFactory = new org.jomc.model.bootstrap.ObjectFactory();
1637 }
1638
1639 return this.bootstrapObjectFactory;
1640 }
1641
1642 /**
1643 * Gets a new bootstrap context instance.
1644 *
1645 * @return A new bootstrap context instance.
1646 *
1647 * @throws JAXBException if creating a new bootstrap context instance fails.
1648 */
1649 public JAXBContext getBootstrapContext() throws JAXBException
1650 {
1651 return JAXBContext.newInstance( BOOTSTRAP_CONTEXT, this.getClassLoader() );
1652 }
1653
1654 /**
1655 * Gets a new bootstrap {@code Marshaller}.
1656 *
1657 * @param validating {@code true} for a marshaller with additional schema validation support enabled; {@code false}
1658 * for a marshaller without additional schema validation support enabled.
1659 * @param formattedOutput {@code true} for the marshaller to produce formatted output; {@code false} for the
1660 * marshaller to not apply any formatting when marshalling.
1661 *
1662 * @return A new bootstrap {@code Marshaller}.
1663 *
1664 * @throws IOException if reading schema resources fails.
1665 * @throws SAXException if parsing schema resources fails.
1666 * @throws JAXBException if unmarshalling schema resources fails.
1667 */
1668 public Marshaller getBootstrapMarshaller( final boolean validating, final boolean formattedOutput )
1669 throws IOException, SAXException, JAXBException
1670 {
1671 final Marshaller m = this.getBootstrapContext().createMarshaller();
1672 m.setProperty( Marshaller.JAXB_ENCODING, "UTF-8" );
1673 m.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.valueOf( formattedOutput ) );
1674
1675 if ( validating )
1676 {
1677 m.setSchema( this.getBootstrapSchema() );
1678 }
1679
1680 return m;
1681 }
1682
1683 /**
1684 * Gets a new bootstrap {@code Unmarshaller}.
1685 *
1686 * @param validating {@code true} for an unmarshaller with additional schema validation support enabled;
1687 * {@code false} for an unmarshaller without additional schema validation support enabled.
1688 *
1689 * @return A new bootstrap {@code Unmarshaller}.
1690 *
1691 * @throws IOException if reading schema resources fails.
1692 * @throws SAXException if parsing schema resources fails.
1693 * @throws JAXBException if unmarshalling schema resources fails.
1694 */
1695 public Unmarshaller getBootstrapUnmarshaller( final boolean validating )
1696 throws IOException, SAXException, JAXBException
1697 {
1698 final Unmarshaller u = this.getBootstrapContext().createUnmarshaller();
1699 if ( validating )
1700 {
1701 u.setSchema( this.getBootstrapSchema() );
1702 }
1703
1704 return u;
1705 }
1706
1707 /**
1708 * Gets the bootstrap schema.
1709 *
1710 * @return The bootstrap schema.
1711 *
1712 * @throws SAXException if parsing the bootstrap schema fails.
1713 */
1714 public javax.xml.validation.Schema getBootstrapSchema() throws SAXException
1715 {
1716 if ( this.bootstrapSchema == null )
1717 {
1718 final URL url = this.getClassLoader().getResource( BOOTSTRAP_SCHEMA_LOCATION );
1719 this.log( Level.FINE, this.getMessage( "processing", new Object[]
1720 {
1721 url.toExternalForm()
1722 } ), null );
1723
1724 this.bootstrapSchema = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI ).newSchema( url );
1725 }
1726
1727 return this.bootstrapSchema;
1728 }
1729
1730 /**
1731 * Validates a given bootstrap object.
1732 *
1733 * @param bootstrapObject The object to validate.
1734 *
1735 * @throws NullPointerException if {@code bootstrapObject} is {@code null}.
1736 * @throws ModelException if {@code bootstrapObject} is invalid.
1737 * @throws IOException if reading schema resources fails.
1738 * @throws SAXException if parsing schema resources fails.
1739 * @throws JAXBException if unmarshalling schema resources fails.
1740 */
1741 public void validateBootstrapObject( final JAXBElement<? extends BootstrapObject> bootstrapObject )
1742 throws ModelException, IOException, SAXException, JAXBException
1743 {
1744 if ( bootstrapObject == null )
1745 {
1746 throw new NullPointerException( "bootstrapObject" );
1747 }
1748
1749 final StringWriter stringWriter = new StringWriter();
1750 final Validator validator = this.getBootstrapSchema().newValidator();
1751 final ModelExceptionErrorHandler errorHandler = new ModelExceptionErrorHandler();
1752 validator.setErrorHandler( errorHandler );
1753 this.getBootstrapMarshaller( false, false ).marshal( bootstrapObject, stringWriter );
1754
1755 try
1756 {
1757 validator.validate( new StreamSource( new StringReader( stringWriter.toString() ) ) );
1758 }
1759 catch ( final SAXException e )
1760 {
1761 final ModelException modelException = new ModelException( this.getMessage( "validationFailed", null ), e );
1762 modelException.getDetails().addAll( errorHandler.getDetails() );
1763 throw modelException;
1764 }
1765 }
1766
1767 /**
1768 * Transforms a given {@code BootstrapObject} with a given {@code Transformer}.
1769 *
1770 * @param bootstrapObject The {@code BootstrapObject} to transform.
1771 * @param transformer The {@code Transformer} to transform {@code bootstrapObject} with.
1772 * @param <T> The type of {@code bootstrapObject}.
1773 *
1774 * @return {@code bootstrapObject} transformed with {@code transformer}.
1775 *
1776 * @throws NullPointerException if {@code bootstrapObject} or {@code transformer} is {@code null}.
1777 * @throws IOException if reading schema resources fails.
1778 * @throws SAXException if parsing schema resources fails.
1779 * @throws JAXBException if binding fails.
1780 * @throws TransformerException if the transformation fails.
1781 */
1782 public <T extends BootstrapObject> T transformBootstrapObject(
1783 final JAXBElement<T> bootstrapObject, final Transformer transformer )
1784 throws IOException, SAXException, JAXBException, TransformerException
1785 {
1786 if ( bootstrapObject == null )
1787 {
1788 throw new NullPointerException( "bootstrapObject" );
1789 }
1790 if ( transformer == null )
1791 {
1792 throw new NullPointerException( "transformer" );
1793 }
1794
1795 final JAXBContext ctx = this.getBootstrapContext();
1796 final JAXBSource source = new JAXBSource( ctx, bootstrapObject );
1797 final JAXBResult result = new JAXBResult( ctx );
1798 transformer.transform( source, result );
1799 return ( (JAXBElement<T>) result.getResult() ).getValue();
1800 }
1801
1802 /**
1803 * Sets the object factory of the instance.
1804 *
1805 * @param value The new object factory of the instance or {@code null}.
1806 *
1807 * @see #getObjectFactory()
1808 */
1809 public void setObjectFactory( final ObjectFactory value )
1810 {
1811 this.objectFactory = value;
1812 }
1813
1814 /**
1815 * Sets the entity resolver of the instance.
1816 *
1817 * @param value The new entity resolver of the instance or {@code null}.
1818 *
1819 * @see #getEntityResolver()
1820 */
1821 public void setEntityResolver( final EntityResolver value )
1822 {
1823 this.entityResolver = value;
1824 }
1825
1826 /**
1827 * Sets the L/S resolver of the instance.
1828 *
1829 * @param value The new L/S resolver of the instance or {@code null}.
1830 *
1831 * @see #getLSResourceResolver()
1832 */
1833 public void setLSResourceResolver( final LSResourceResolver value )
1834 {
1835 this.resourceResolver = value;
1836 }
1837
1838 /**
1839 * Sets the JAXB context of the instance.
1840 *
1841 * @param value The new JAXB context of the instance or {@code null}.
1842 *
1843 * @see #getContext()
1844 */
1845 public void setContext( final JAXBContext value )
1846 {
1847 this.context = value;
1848 }
1849
1850 /**
1851 * Sets the schema of the instance.
1852 *
1853 * @param value The new schema of the instance or {@code null}.
1854 *
1855 * @see #getSchema()
1856 */
1857 public void setSchema( final javax.xml.validation.Schema value )
1858 {
1859 this.schema = value;
1860 }
1861
1862 /**
1863 * Gets the list of registered listeners.
1864 *
1865 * @return The list of registered listeners.
1866 *
1867 * @see #log(java.util.logging.Level, java.lang.String, java.lang.Throwable)
1868 */
1869 public List<Listener> getListeners()
1870 {
1871 if ( this.listeners == null )
1872 {
1873 this.listeners = new LinkedList<Listener>();
1874 }
1875
1876 return this.listeners;
1877 }
1878
1879 /**
1880 * Gets the location to search for bootstrap documents.
1881 * <p>The bootstrap document location is controlled by system property
1882 * {@code org.jomc.model.DefaultModelManager.bootstrapDocumentLocation} holding the location to search at. If that
1883 * property is not set, the {@code META-INF/jomc-bootstrap.xml} default is returned.</p>
1884 *
1885 * @return The location to search for bootstrap documents.
1886 *
1887 * @see #getSchemas()
1888 */
1889 public String getBootstrapDocumentLocation()
1890 {
1891 return System.getProperty( "org.jomc.model.DefaultModelManager.bootstrapDocumentLocation",
1892 DEFAULT_BOOTSTRAP_DOCUMENT_LOCATION );
1893
1894 }
1895
1896 /**
1897 * Gets the schemas backing the instance.
1898 *
1899 * @return The schemas backing the instance.
1900 *
1901 * @throws IOException if reading schema resources fails.
1902 * @throws SAXException if parsing schema resources fails.
1903 * @throws JAXBException if unmarshalling schema resources fails.
1904 *
1905 * @see #getBootstrapDocumentLocation()
1906 */
1907 public Schemas getSchemas() throws IOException, JAXBException, SAXException
1908 {
1909 if ( this.schemas == null )
1910 {
1911 this.schemas = new Schemas();
1912
1913 final JAXBContext ctx = JAXBContext.newInstance( BOOTSTRAP_CONTEXT, this.getClassLoader() );
1914 final Unmarshaller u = ctx.createUnmarshaller();
1915 final String bootstrapLocation = this.getBootstrapDocumentLocation();
1916 this.log( Level.FINE, this.getMessage( "bootstrapLocation", new Object[]
1917 {
1918 bootstrapLocation
1919 } ), null );
1920
1921 final Enumeration<URL> e = this.getClassLoader().getResources( bootstrapLocation );
1922 u.setSchema( this.getBootstrapSchema() );
1923
1924 while ( e.hasMoreElements() )
1925 {
1926 final URL url = e.nextElement();
1927 this.log( Level.FINE, this.getMessage( "processing", new Object[]
1928 {
1929 url.toExternalForm()
1930 } ), null );
1931
1932 Object content = u.unmarshal( url );
1933 if ( content instanceof JAXBElement )
1934 {
1935 content = ( (JAXBElement) content ).getValue();
1936 }
1937
1938 if ( content instanceof Schema )
1939 {
1940 final Schema s = (Schema) content;
1941 this.log( Level.FINE, this.getMessage( "addingSchema", new Object[]
1942 {
1943 s.getPublicId(), s.getSystemId(), s.getContextId(), s.getClasspathId()
1944 } ), null );
1945
1946 this.schemas.getSchema().add( s );
1947 }
1948 else if ( content instanceof Schemas )
1949 {
1950 for ( Schema s : ( (Schemas) content ).getSchema() )
1951 {
1952 this.log( Level.FINE, this.getMessage( "addingSchema", new Object[]
1953 {
1954 s.getPublicId(), s.getSystemId(), s.getContextId(), s.getClasspathId()
1955 } ), null );
1956
1957 this.schemas.getSchema().add( s );
1958 }
1959 }
1960 }
1961 }
1962
1963 return this.schemas;
1964 }
1965
1966 /**
1967 * Gets the default location to search for documents.
1968 * <p>The default document location is controlled by system property
1969 * {@code org.jomc.model.DefaultModelManager.defaultDocumentLocation} holding the location to search at by default.
1970 * If that property is not set, the {@code META-INF/jomc.xml} default is returned.</p>
1971 *
1972 * @return The default location to search for documents.
1973 *
1974 * @see #getClasspathModules(java.lang.String)
1975 */
1976 public String getDefaultDocumentLocation()
1977 {
1978 return System.getProperty( "org.jomc.model.DefaultModelManager.defaultDocumentLocation",
1979 DEFAULT_DOCUMENT_LOCATION );
1980
1981 }
1982
1983 /**
1984 * Gets modules by searching the class loader of the instance for resources.
1985 * <p><b>Note:</b><br/>
1986 * This method does not validate the modules.</p>
1987 *
1988 * @param location The location to search at.
1989 *
1990 * @return All resources from the class loader of the instance matching {@code location}.
1991 *
1992 * @throws NullPointerException if {@code location} is {@code null}.
1993 * @throws IOException if reading resources fails.
1994 * @throws SAXException if parsing schema resources fails.
1995 * @throws JAXBException if unmarshalling schema resources fails.
1996 *
1997 * @see #getDefaultDocumentLocation()
1998 */
1999 public Modules getClasspathModules( final String location ) throws IOException, SAXException, JAXBException
2000 {
2001 if ( location == null )
2002 {
2003 throw new NullPointerException( "location" );
2004 }
2005
2006 this.log( Level.FINE, this.getMessage( "documentLocation", new Object[]
2007 {
2008 location
2009 } ), null );
2010
2011 final long t0 = System.currentTimeMillis();
2012 final Text text = new Text();
2013 text.setLanguage( "en" );
2014 text.setValue( this.getMessage( "classpathModulesInfo", new Object[]
2015 {
2016 location
2017 } ) );
2018
2019 final Modules mods = new Modules();
2020 mods.setDocumentation( new Texts() );
2021 mods.getDocumentation().setDefaultLanguage( "en" );
2022 mods.getDocumentation().getText().add( text );
2023
2024 final Unmarshaller u = this.getUnmarshaller( false );
2025 final Enumeration<URL> resources = this.getClassLoader().getResources( location );
2026
2027 Integer count = 0;
2028 while ( resources.hasMoreElements() )
2029 {
2030 count++;
2031 final URL url = resources.nextElement();
2032
2033 this.log( Level.FINE, this.getMessage( "processing", new Object[]
2034 {
2035 url.toExternalForm()
2036 } ), null );
2037
2038 Object content = u.unmarshal( url );
2039 if ( content instanceof JAXBElement )
2040 {
2041 content = ( (JAXBElement) content ).getValue();
2042 }
2043
2044 if ( content instanceof Module )
2045 {
2046 mods.getModule().add( (Module) content );
2047 }
2048 else
2049 {
2050 this.log( Level.WARNING, this.getMessage( "ignoringDocument", new Object[]
2051 {
2052 content == null ? "<>" : content.toString(), url.toExternalForm()
2053 } ), null );
2054
2055 }
2056 }
2057
2058 this.log( Level.FINE, this.getMessage( "classpathReport", new Object[]
2059 {
2060 count, Long.valueOf( System.currentTimeMillis() - t0 )
2061 } ), null );
2062
2063 return mods;
2064 }
2065
2066 /**
2067 * Gets the classpath module name.
2068 * <p>The classpath module name is controlled by system property
2069 * {@code org.jomc.model.DefaultModelManager.classpathModuleName} holding the classpath module name.
2070 * If that property is not set, the {@code Java Classpath} default is returned.</p>
2071 *
2072 * @return The name of the classpath module.
2073 *
2074 * @see #getClasspathModule(org.jomc.model.Modules)
2075 */
2076 public String getClasspathModuleName()
2077 {
2078 return System.getProperty( "org.jomc.model.DefaultModelManager.classpathModuleName",
2079 DEFAULT_CLASSPATH_MODULE_NAME );
2080
2081 }
2082
2083 /**
2084 * Gets a module holding model objects resolved by inspecting the class loader of the instance.
2085 * <p>This method searches the given modules for unresolved references and tries to resolve each unresolved
2086 * reference by inspecting the class loader of the instance.</p>
2087 *
2088 * @param modules The modules to resolve by inspecting the class loader of the instance.
2089 *
2090 * @return A module holding model objects resolved by inspecting the class loader of the instance or {@code null} if
2091 * nothing could be resolved.
2092 *
2093 * @see #getClasspathModuleName()
2094 */
2095 public Module getClasspathModule( final Modules modules )
2096 {
2097 final Module module = new Module();
2098 module.setVersion( System.getProperty( "java.specification.version" ) );
2099 module.setName( this.getClasspathModuleName() );
2100
2101 this.resolveClasspath( modules, module );
2102
2103 final boolean resolved = ( module.getSpecifications() != null &&
2104 !module.getSpecifications().getSpecification().isEmpty() ) ||
2105 ( module.getImplementations() != null &&
2106 !module.getImplementations().getImplementation().isEmpty() );
2107
2108 return resolved ? module : null;
2109 }
2110
2111 /**
2112 * Gets the default location to search for style sheets.
2113 * <p>The default style sheet location is controlled by system property
2114 * {@code org.jomc.model.DefaultModelManager.defaultStylesheetLocation} holding the location to search at by
2115 * default. If that property is not set, the {@code META-INF/jomc.xslt} default is returned.</p>
2116 *
2117 * @return The default location to search for style sheets.
2118 *
2119 * @see #getClasspathTransformers(java.lang.String)
2120 */
2121 public String getDefaultStylesheetLocation()
2122 {
2123 return System.getProperty( "org.jomc.model.DefaultModelManager.defaultStylesheetLocation",
2124 DEFAULT_STYLESHEET_LOCATION );
2125
2126 }
2127
2128 /**
2129 * Gets transformers by searching the class loader of the instance for resources.
2130 *
2131 * @param location The location to search at.
2132 *
2133 * @return All resources from the class loader of the instance matching {@code location}.
2134 *
2135 * @throws NullPointerException if {@code location} is {@code null}.
2136 * @throws IOException if reading resources fails.
2137 * @throws TransformerConfigurationException if getting the transformers fails.
2138 *
2139 * @see #getDefaultStylesheetLocation()
2140 */
2141 public List<Transformer> getClasspathTransformers( final String location )
2142 throws IOException, TransformerConfigurationException
2143 {
2144 if ( location == null )
2145 {
2146 throw new NullPointerException( "location" );
2147 }
2148
2149 this.log( Level.FINE, this.getMessage( "stylesheetLocation", new Object[]
2150 {
2151 location
2152 } ), null );
2153
2154 final long t0 = System.currentTimeMillis();
2155 final List<Transformer> transformers = new LinkedList<Transformer>();
2156 final TransformerFactory transformerFactory = TransformerFactory.newInstance();
2157 final Enumeration<URL> resources = this.getClassLoader().getResources( location );
2158 final ErrorListener errorListener = new ErrorListener()
2159 {
2160
2161 public void warning( final TransformerException exception ) throws TransformerException
2162 {
2163 log( Level.WARNING, exception.getMessage(), exception );
2164 }
2165
2166 public void error( final TransformerException exception ) throws TransformerException
2167 {
2168 log( Level.SEVERE, exception.getMessage(), exception );
2169 throw exception;
2170 }
2171
2172 public void fatalError( final TransformerException exception ) throws TransformerException
2173 {
2174 log( Level.SEVERE, exception.getMessage(), exception );
2175 throw exception;
2176 }
2177
2178 };
2179
2180 final URIResolver uriResolver = new URIResolver()
2181 {
2182
2183 public Source resolve( final String href, final String base ) throws TransformerException
2184 {
2185 try
2186 {
2187 Source source = null;
2188 final InputSource inputSource = getEntityResolver().resolveEntity( null, href );
2189
2190 if ( inputSource != null )
2191 {
2192 source = new SAXSource( inputSource );
2193 }
2194
2195 return source;
2196 }
2197 catch ( final SAXException e )
2198 {
2199 log( Level.SEVERE, e.getMessage(), e );
2200 throw new TransformerException( e );
2201 }
2202 catch ( final IOException e )
2203 {
2204 log( Level.SEVERE, e.getMessage(), e );
2205 throw new TransformerException( e );
2206 }
2207 }
2208
2209 };
2210
2211 transformerFactory.setErrorListener( errorListener );
2212 transformerFactory.setURIResolver( uriResolver );
2213
2214 Integer count = 0;
2215 while ( resources.hasMoreElements() )
2216 {
2217 count++;
2218 final URL url = resources.nextElement();
2219
2220 this.log( Level.FINE, this.getMessage( "processing", new Object[]
2221 {
2222 url.toExternalForm()
2223 } ), null );
2224
2225 final InputStream in = url.openStream();
2226 final Transformer transformer = transformerFactory.newTransformer( new StreamSource( in ) );
2227 in.close();
2228
2229 transformer.setErrorListener( errorListener );
2230 transformer.setURIResolver( uriResolver );
2231 transformers.add( transformer );
2232 }
2233
2234 this.log( Level.FINE, this.getMessage( "classpathReport", new Object[]
2235 {
2236 count, Long.valueOf( System.currentTimeMillis() - t0 )
2237 } ), null );
2238
2239 return transformers;
2240 }
2241
2242 /**
2243 * Gets the class loader of the instance.
2244 *
2245 * @return The class loader of the instance.
2246 *
2247 * @see #setClassLoader(java.lang.ClassLoader)
2248 */
2249 public ClassLoader getClassLoader()
2250 {
2251 if ( this.classLoader == null )
2252 {
2253 this.classLoader = this.getClass().getClassLoader();
2254 if ( this.classLoader == null )
2255 {
2256 this.classLoader = ClassLoader.getSystemClassLoader();
2257 }
2258
2259 }
2260
2261 return this.classLoader;
2262 }
2263
2264 /**
2265 * Sets the class loader of the instance.
2266 *
2267 * @param value The new class loader of the instance.
2268 *
2269 * @see #getClassLoader()
2270 */
2271 public void setClassLoader( final ClassLoader value )
2272 {
2273 this.classLoader = value;
2274 this.bootstrapSchema = null;
2275 this.schema = null;
2276 this.schemas = null;
2277 this.schemaResources = null;
2278 this.entityResolver = null;
2279 this.resourceResolver = null;
2280 this.context = null;
2281 }
2282
2283 /**
2284 * Notifies registered listeners.
2285 *
2286 * @param level The level of the event.
2287 * @param message The message of the event or {@code null}.
2288 * @param throwable The throwable of the event {@code null}.
2289 *
2290 * @see #getListeners()
2291 */
2292 protected void log( final Level level, final String message, final Throwable throwable )
2293 {
2294 for ( Listener l : this.getListeners() )
2295 {
2296 l.onLog( level, message, throwable );
2297 }
2298 }
2299
2300 /**
2301 * Resolves references by inspecting the class loader of the instance.
2302 *
2303 * @param modules The modules to resolve.
2304 * @param cpModule The module for resolved references.
2305 *
2306 * @throws NullPointerException if {@code cpModule} is {@code null}.
2307 */
2308 private void resolveClasspath( final Modules modules, final Module cpModule )
2309 {
2310 for ( Module m : modules.getModule() )
2311 {
2312 if ( m.getSpecifications() != null )
2313 {
2314 this.resolveClasspath( modules, m.getSpecifications(), cpModule );
2315 }
2316
2317 if ( m.getImplementations() != null )
2318 {
2319 this.resolveClasspath( modules, m.getImplementations(), cpModule );
2320 }
2321
2322 }
2323 }
2324
2325 private void resolveClasspath( final Modules modules, final SpecificationReference ref, final Module cpModule )
2326 {
2327 if ( modules.getSpecification( ref.getIdentifier() ) == null )
2328 {
2329 this.resolveClasspath( ref.getIdentifier(), cpModule );
2330 }
2331 }
2332
2333 private void resolveClasspath( final Modules modules, final Specifications references, final Module cpModule )
2334 {
2335 for ( SpecificationReference ref : references.getReference() )
2336 {
2337 this.resolveClasspath( modules, ref, cpModule );
2338 }
2339
2340 }
2341
2342 private void resolveClasspath( final Modules modules, final Implementations implementations, final Module cpModule )
2343 {
2344 for ( Implementation implementation : implementations.getImplementation() )
2345 {
2346 if ( implementation.getSpecifications() != null )
2347 {
2348 this.resolveClasspath( modules, implementation.getSpecifications(), cpModule );
2349 }
2350
2351 if ( implementation.getDependencies() != null )
2352 {
2353 this.resolveClasspath( modules, implementation.getDependencies(), cpModule );
2354 }
2355 }
2356 }
2357
2358 private void resolveClasspath( final Modules modules, final Dependencies dependencies, final Module cpModule )
2359 {
2360 for ( Dependency dependency : dependencies.getDependency() )
2361 {
2362 this.resolveClasspath( modules, dependency, cpModule );
2363 }
2364 }
2365
2366 private void resolveClasspath( final String identifier, final Module cpModule )
2367 {
2368 Specification specification =
2369 cpModule.getSpecifications() == null ? null
2370 : cpModule.getSpecifications().getSpecification( identifier );
2371
2372 if ( specification == null )
2373 {
2374 try
2375 {
2376 final Class classpathSpec = Class.forName( identifier, true, this.getClassLoader() );
2377 if ( Modifier.isPublic( classpathSpec.getModifiers() ) )
2378 {
2379 String vendor = null;
2380 String version = null;
2381
2382 if ( classpathSpec.getPackage() != null )
2383 {
2384 vendor = classpathSpec.getPackage().getSpecificationVendor();
2385 version = classpathSpec.getPackage().getSpecificationVersion();
2386 }
2387
2388 specification = new Specification();
2389 specification.setIdentifier( identifier );
2390 specification.setClazz( classpathSpec.getName() );
2391 specification.setMultiplicity( Multiplicity.MANY );
2392 specification.setVendor( vendor );
2393 specification.setVersion( version );
2394
2395 this.log( Level.FINE, this.getMessage( "classpathSpecification", new Object[]
2396 {
2397 specification.getIdentifier(),
2398 specification.getMultiplicity().value()
2399 } ), null );
2400
2401
2402 if ( cpModule.getSpecifications() == null )
2403 {
2404 cpModule.setSpecifications( new Specifications() );
2405 }
2406
2407 cpModule.getSpecifications().getSpecification().add( specification );
2408
2409 this.resolveClasspath( specification, cpModule );
2410 }
2411
2412 }
2413 catch ( final ClassNotFoundException e )
2414 {
2415 this.log( Level.FINE, this.getMessage( "noSuchClass", new Object[]
2416 {
2417 e.getMessage()
2418 } ), null );
2419
2420 }
2421 }
2422 }
2423
2424 private void resolveClasspath( final Specification specification, final Module cpModule )
2425 {
2426 if ( specification == null )
2427 {
2428 throw new NullPointerException( "specification" );
2429 }
2430
2431 Implementation implementation =
2432 cpModule.getImplementations() == null ? null
2433 : cpModule.getImplementations().getImplementation( specification.getIdentifier() );
2434
2435 if ( implementation == null )
2436 {
2437 String name = null;
2438
2439 try
2440 {
2441 final Class classpathImpl = Class.forName( specification.getClazz(), true, this.getClassLoader() );
2442 boolean classpathImplementation = false;
2443
2444 if ( Modifier.isPublic( classpathImpl.getModifiers() ) )
2445 {
2446 if ( !Modifier.isAbstract( classpathImpl.getModifiers() ) )
2447 {
2448 try
2449 {
2450 classpathImpl.getConstructor( NO_CLASSES );
2451 name = "init";
2452 classpathImplementation = true;
2453 }
2454 catch ( final NoSuchMethodException e )
2455 {
2456 this.log( Level.FINE, this.getMessage( "noSuchMethod", new Object[]
2457 {
2458 e.getMessage()
2459 } ), null );
2460
2461 }
2462 }
2463
2464 if ( !classpathImplementation )
2465 {
2466 final char[] c = classpathImpl.getName().substring(
2467 classpathImpl.getPackage().getName().length() + 1 ).toCharArray();
2468
2469 name = String.valueOf( c );
2470 c[0] = Character.toUpperCase( c[0] );
2471
2472 if ( this.checkFactoryMethod( classpathImpl, classpathImpl, "getDefault" ) )
2473 {
2474 name = "default";
2475 classpathImplementation = true;
2476 }
2477 else if ( this.checkFactoryMethod( classpathImpl, classpathImpl, "getInstance" ) )
2478 {
2479 name = "instance";
2480 classpathImplementation = true;
2481 }
2482 else if ( this.checkFactoryMethod( classpathImpl, classpathImpl, "get" + String.valueOf( c ) ) )
2483 {
2484 classpathImplementation = true;
2485 }
2486
2487 }
2488
2489 if ( classpathImplementation )
2490 {
2491 String vendor = null;
2492 String version = null;
2493 if ( classpathImpl.getPackage() != null )
2494 {
2495 vendor = classpathImpl.getPackage().getImplementationVendor();
2496 version = classpathImpl.getPackage().getImplementationVersion();
2497 }
2498
2499 implementation = new Implementation();
2500 implementation.setVendor( vendor );
2501 implementation.setFinal( true );
2502 implementation.setName( name );
2503 implementation.setIdentifier( specification.getIdentifier() );
2504 implementation.setClazz( classpathImpl.getName() );
2505 implementation.setVersion( version );
2506
2507 final Specifications implemented = new Specifications();
2508 final SpecificationReference ref = new SpecificationReference();
2509 ref.setIdentifier( specification.getIdentifier() );
2510 ref.setVersion( specification.getVersion() );
2511 implemented.getReference().add( ref );
2512 implementation.setSpecifications( implemented );
2513
2514 this.log( Level.FINE, this.getMessage( "classpathImplementation", new Object[]
2515 {
2516 implementation.getIdentifier(),
2517 specification.getIdentifier(),
2518 implementation.getName()
2519 } ), null );
2520
2521 if ( cpModule.getImplementations() == null )
2522 {
2523 cpModule.setImplementations( new Implementations() );
2524 }
2525
2526 cpModule.getImplementations().getImplementation().add( implementation );
2527 }
2528 else
2529 {
2530 this.log( Level.FINE, this.getMessage( "noClasspathImplementation", new Object[]
2531 {
2532 specification.getIdentifier()
2533 } ), null );
2534
2535 }
2536 }
2537 }
2538 catch ( final ClassNotFoundException e )
2539 {
2540 this.log( Level.FINE, this.getMessage( "noSuchClass", new Object[]
2541 {
2542 e.getMessage()
2543 } ), null );
2544
2545 }
2546 }
2547 }
2548
2549 private boolean checkFactoryMethod( final Class clazz, final Class type, final String methodName )
2550 {
2551 boolean factoryMethod = false;
2552
2553 try
2554 {
2555 final Method m = clazz.getMethod( methodName, NO_CLASSES );
2556 factoryMethod = Modifier.isStatic( m.getModifiers() ) && type.isAssignableFrom( m.getReturnType() );
2557 }
2558 catch ( final NoSuchMethodException e )
2559 {
2560 this.log( Level.FINE, this.getMessage( "noSuchMethod", new Object[]
2561 {
2562 e.getMessage()
2563 } ), null );
2564
2565 factoryMethod = false;
2566 }
2567
2568 return factoryMethod;
2569 }
2570
2571 private Method getFactoryMethod( final Class clazz, final String methodName )
2572 {
2573 Method m = null;
2574
2575 try
2576 {
2577 m = clazz.getMethod( methodName, NO_CLASSES );
2578 }
2579 catch ( final NoSuchMethodException e )
2580 {
2581 this.log( Level.FINE, this.getMessage( "noSuchMethod", new Object[]
2582 {
2583 e.getMessage()
2584 } ), null );
2585
2586 m = null;
2587 }
2588
2589 return m;
2590 }
2591
2592 /**
2593 * Searches all available {@code META-INF/MANIFEST.MF} resources and gets a set containing URLs of entries whose
2594 * name end with a known schema extension.
2595 *
2596 * @return URLs of any matching entries.
2597 *
2598 * @throws IOException if reading or parsing fails.
2599 */
2600 private Set<URL> getSchemaResources() throws IOException
2601 {
2602 if ( this.schemaResources == null )
2603 {
2604 this.schemaResources = new HashSet<URL>();
2605
2606 for ( final Enumeration<URL> e = this.getClassLoader().getResources( "META-INF/MANIFEST.MF" );
2607 e.hasMoreElements(); )
2608 {
2609 final URL manifestUrl = e.nextElement();
2610 final String externalForm = manifestUrl.toExternalForm();
2611 final String baseUrl = externalForm.substring( 0, externalForm.indexOf( "META-INF" ) );
2612 final InputStream manifestStream = manifestUrl.openStream();
2613 final Manifest mf = new Manifest( manifestStream );
2614 manifestStream.close();
2615
2616 for ( Map.Entry<String, Attributes> entry : mf.getEntries().entrySet() )
2617 {
2618 for ( int i = SCHEMA_EXTENSIONS.length - 1; i >= 0; i-- )
2619 {
2620 if ( entry.getKey().toLowerCase().endsWith( '.' + SCHEMA_EXTENSIONS[i].toLowerCase() ) )
2621 {
2622 final URL schemaUrl = new URL( baseUrl + entry.getKey() );
2623 this.schemaResources.add( schemaUrl );
2624 this.log( Level.FINE, this.getMessage( "processing", new Object[]
2625 {
2626 schemaUrl.toExternalForm()
2627 } ), null );
2628
2629 }
2630 }
2631 }
2632 }
2633 }
2634
2635 return this.schemaResources;
2636 }
2637
2638 /**
2639 * Gets the implementation of an object.
2640 *
2641 * @param modules The modules to search for the implementation of {@code object}.
2642 * @param object The object to get the implementation for.
2643 *
2644 * @return The implementation for {@code object} or {@code null}, if nothing is known about {@code object}.
2645 */
2646 private Implementation getImplementation( final Modules modules, final Object object )
2647 {
2648 return this.collectImplementation( modules, object.getClass() );
2649 }
2650
2651 private Implementation collectImplementation( final Modules modules, final Class clazz )
2652 {
2653 Implementation i = modules.getImplementation( clazz );
2654 if ( i == null && clazz.getSuperclass() != null )
2655 {
2656 i = this.collectImplementation( modules, clazz.getSuperclass() );
2657 }
2658
2659 return i;
2660 }
2661
2662 private void collectFinalSuperDependencies(
2663 final Modules modules, final Implementation implementation, final String dependencyName,
2664 final Implementations implementations, final Implementations seen, final boolean includeImplementation )
2665 {
2666 if ( implementation != null && seen.getImplementation( implementation.getIdentifier() ) == null )
2667 {
2668 seen.getImplementation().add( implementation );
2669
2670 if ( includeImplementation )
2671 {
2672 final Dependencies dependencies = modules.getDependencies( implementation.getIdentifier() );
2673
2674 if ( dependencies != null )
2675 {
2676 for ( Dependency d : dependencies.getDependency() )
2677 {
2678 if ( dependencyName.equals( d.getName() ) && d.isFinal() &&
2679 implementations.getImplementation( implementation.getIdentifier() ) == null )
2680 {
2681 implementations.getImplementation().add( implementation );
2682 }
2683 }
2684 }
2685 }
2686
2687 if ( implementation.getImplementations() != null )
2688 {
2689 for ( ImplementationReference r : implementation.getImplementations().getReference() )
2690 {
2691 this.collectFinalSuperDependencies( modules, modules.getImplementation( r.getIdentifier() ),
2692 dependencyName, implementations, seen, true );
2693
2694 }
2695 }
2696 }
2697 }
2698
2699 private void collectFinalSuperMessages(
2700 final Modules modules, final Implementation implementation, final String messageName,
2701 final Implementations implementations, final Implementations seen, final boolean includeImplementation )
2702 {
2703 if ( implementation != null && seen.getImplementation( implementation.getIdentifier() ) == null )
2704 {
2705 seen.getImplementation().add( implementation );
2706
2707 if ( includeImplementation )
2708 {
2709 final Messages messages = modules.getMessages( implementation.getIdentifier() );
2710
2711 if ( messages != null )
2712 {
2713 for ( Message m : messages.getMessage() )
2714 {
2715 if ( messageName.equals( m.getName() ) && m.isFinal() &&
2716 implementations.getImplementation( implementation.getIdentifier() ) == null )
2717 {
2718 implementations.getImplementation().add( implementation );
2719 }
2720 }
2721 }
2722 }
2723
2724 if ( implementation.getImplementations() != null )
2725 {
2726 for ( ImplementationReference r : implementation.getImplementations().getReference() )
2727 {
2728 this.collectFinalSuperMessages( modules, modules.getImplementation( r.getIdentifier() ),
2729 messageName, implementations, seen, true );
2730
2731 }
2732 }
2733 }
2734 }
2735
2736 private void collectFinalSuperProperties(
2737 final Modules modules, final Implementation implementation, final String propertyName,
2738 final Implementations implementations, final Implementations seen, final boolean includeImplementation )
2739 {
2740 if ( implementation != null && seen.getImplementation( implementation.getIdentifier() ) == null )
2741 {
2742 seen.getImplementation().add( implementation );
2743
2744 if ( includeImplementation )
2745 {
2746 final Properties properties = modules.getProperties( implementation.getIdentifier() );
2747
2748 if ( properties != null )
2749 {
2750 for ( Property p : properties.getProperty() )
2751 {
2752 if ( propertyName.equals( p.getName() ) && p.isFinal() &&
2753 implementations.getImplementation( implementation.getIdentifier() ) == null )
2754 {
2755 implementations.getImplementation().add( implementation );
2756 }
2757 }
2758 }
2759 }
2760
2761 if ( implementation.getImplementations() != null )
2762 {
2763 for ( ImplementationReference r : implementation.getImplementations().getReference() )
2764 {
2765 this.collectFinalSuperProperties( modules, modules.getImplementation( r.getIdentifier() ),
2766 propertyName, implementations, seen, true );
2767
2768 }
2769 }
2770 }
2771 }
2772
2773 private void collectFinalSuperSpecifications(
2774 final Modules modules, final Implementation implementation, final String specificationIdentifier,
2775 final Implementations implementations, final Implementations seen, final boolean includeImplementation )
2776 {
2777 if ( implementation != null && seen.getImplementation( implementation.getIdentifier() ) == null )
2778 {
2779 seen.getImplementation().add( implementation );
2780
2781 if ( includeImplementation )
2782 {
2783 final Specifications specifications = modules.getSpecifications( implementation.getIdentifier() );
2784
2785 if ( specifications != null )
2786 {
2787 for ( SpecificationReference r : specifications.getReference() )
2788 {
2789 if ( specificationIdentifier.equals( r.getIdentifier() ) && r.isFinal() &&
2790 implementations.getImplementation( implementation.getIdentifier() ) == null )
2791 {
2792 implementations.getImplementation().add( implementation );
2793 }
2794 }
2795 }
2796 }
2797
2798 if ( implementation.getImplementations() != null )
2799 {
2800 for ( ImplementationReference r : implementation.getImplementations().getReference() )
2801 {
2802 this.collectFinalSuperSpecifications( modules, modules.getImplementation( r.getIdentifier() ),
2803 specificationIdentifier, implementations, seen, true );
2804
2805 }
2806 }
2807 }
2808 }
2809
2810 private void collectFinalSuperImplementations( final Modules modules, final Implementation implementation,
2811 final Implementations implementations, final Implementations seen,
2812 final boolean includeImplementation )
2813 {
2814 if ( implementation != null && seen.getImplementation( implementation.getIdentifier() ) == null )
2815 {
2816 seen.getImplementation().add( implementation );
2817
2818 if ( includeImplementation && implementation.isFinal() &&
2819 implementations.getImplementation( implementation.getIdentifier() ) == null )
2820 {
2821 implementations.getImplementation().add( implementation );
2822 }
2823
2824 if ( implementation.getImplementations() != null )
2825 {
2826 for ( ImplementationReference r : implementation.getImplementations().getReference() )
2827 {
2828 this.collectFinalSuperImplementations( modules, modules.getImplementation( r.getIdentifier() ),
2829 implementations, seen, true );
2830
2831 }
2832 }
2833 }
2834 }
2835
2836 private Implementation findInheritanceCycle( final Modules modules, final Implementation current,
2837 final Implementation report, final Implementations implementations )
2838 {
2839 if ( current != null )
2840 {
2841 if ( implementations.getImplementation( current.getIdentifier() ) != null )
2842 {
2843 return report;
2844 }
2845
2846 implementations.getImplementation().add( current );
2847
2848 if ( current.getImplementations() != null )
2849 {
2850 for ( ImplementationReference r : current.getImplementations().getReference() )
2851 {
2852 return this.findInheritanceCycle( modules, modules.getImplementation( r.getIdentifier() ),
2853 current, implementations );
2854
2855 }
2856 }
2857 }
2858
2859 return null;
2860 }
2861
2862 private String getMessage( final String key, final Object args )
2863 {
2864 return new MessageFormat(
2865 ResourceBundle.getBundle( DefaultModelManager.class.getName().replace( '.', '/' ), Locale.getDefault() ).
2866 getString( key ) ).format( args );
2867
2868 }
2869
2870 private void assertImplementationMessagesUniqueness(
2871 final Implementation implementation, final List<ModelException.Detail> details )
2872 {
2873 if ( implementation.getMessages() != null )
2874 {
2875 for ( Message m : implementation.getMessages().getMessage() )
2876 {
2877 if ( implementation.getMessages().getReference( m.getName() ) != null )
2878 {
2879 final ModelException.Detail detail = new ModelException.Detail(
2880 "IMPLEMENTATION_MESSAGES_UNIQUENESS_CONSTRAINT", Level.SEVERE,
2881 this.getMessage( "messagesUniquenessConstraint", new Object[]
2882 {
2883 implementation.getIdentifier(), m.getName()
2884 } ) );
2885
2886 detail.setElement( this.getObjectFactory().createImplementation( implementation ) );
2887 details.add( detail );
2888 }
2889 }
2890 }
2891 }
2892
2893 private void assertImplementationPropertiesUniqueness(
2894 final Implementation implementation, final List<ModelException.Detail> details )
2895 {
2896 if ( implementation.getProperties() != null )
2897 {
2898 for ( Property p : implementation.getProperties().getProperty() )
2899 {
2900 if ( implementation.getProperties().getReference( p.getName() ) != null )
2901 {
2902 final ModelException.Detail detail = new ModelException.Detail(
2903 "IMPLEMENTATION_PROPERTIES_UNIQUENESS_CONSTRAINT", Level.SEVERE,
2904 this.getMessage( "propertiesUniquenessConstraint", new Object[]
2905 {
2906 implementation.getIdentifier(), p.getName()
2907 } ) );
2908
2909 detail.setElement( this.getObjectFactory().createImplementation( implementation ) );
2910 details.add( detail );
2911 }
2912 }
2913 }
2914 }
2915
2916 private ModelException.Detail newIncompatibleImplementationDetail(
2917 final JAXBElement<? extends ModelObject> element, final String implementation,
2918 final String implementationModule, final String specification, final String specificationModule,
2919 final String implementedVersion, final String specifiedVersion )
2920 {
2921 final ModelException.Detail detail = new ModelException.Detail(
2922 "IMPLEMENTATION_COMPATIBILITY_CONSTRAINT", Level.SEVERE,
2923 this.getMessage( "incompatibleImplementation", new Object[]
2924 {
2925 implementation, implementationModule, specification, specificationModule,
2926 implementedVersion, specifiedVersion
2927 } ) );
2928
2929 detail.setElement( element );
2930 return detail;
2931 }
2932
2933 private ModelException.Detail newIncompatibleDependencyDetail(
2934 final JAXBElement<? extends ModelObject> element, final String implementation,
2935 final String implementationModule, final String specification, final String specificationModule,
2936 final String requiredVersion, final String availableVersion )
2937 {
2938 final ModelException.Detail detail = new ModelException.Detail(
2939 "DEPENDENCY_COMPATIBILITY_CONSTRAINT", Level.SEVERE, this.getMessage( "incompatibleDependency", new Object[]
2940 {
2941 implementation, implementationModule, specification, specificationModule,
2942 requiredVersion, availableVersion
2943 } ) );
2944
2945 detail.setElement( element );
2946 return detail;
2947 }
2948
2949 private ModelException.Detail newImplementationNameConstraintDetail(
2950 final JAXBElement<? extends ModelObject> element, final Specification specification,
2951 final Implementation implementation )
2952 {
2953 final ModelException.Detail detail = new ModelException.Detail(
2954 "IMPLEMENTATION_NAME_CONSTRAINT", Level.SEVERE,
2955 this.getMessage( "implementationNameConstraint", new Object[]
2956 {
2957 implementation.getIdentifier(), specification.getIdentifier(), implementation.getName()
2958 } ) );
2959
2960 detail.setElement( element );
2961 return detail;
2962 }
2963
2964 private ModelException.Detail newMandatoryDependencyConstraintDetail(
2965 final JAXBElement<? extends ModelObject> element, final String implementation, final String dependencyName )
2966 {
2967 final ModelException.Detail detail = new ModelException.Detail(
2968 "MANDATORY_DEPENDENCY_CONSTRAINT", Level.SEVERE,
2969 this.getMessage( "mandatoryDependencyConstraint", new Object[]
2970 {
2971 implementation, dependencyName
2972 } ) );
2973
2974 detail.setElement( element );
2975 return detail;
2976 }
2977
2978 private ModelException.Detail newMultiplicityConstraintDetail(
2979 final JAXBElement<? extends ModelObject> element, final Specification specification,
2980 final Implementation implementation )
2981 {
2982 final ModelException.Detail detail = new ModelException.Detail(
2983 "MULTIPLICITY_CONSTRAINT", Level.SEVERE, this.getMessage( "multiplicityConstraint", new Object[]
2984 {
2985 implementation.getIdentifier(), specification.getIdentifier(), specification.getMultiplicity().value()
2986 } ) );
2987
2988 detail.setElement( element );
2989 return detail;
2990 }
2991
2992 private ModelException.Detail newImplementationInheritanceConstraintDetail(
2993 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
2994 final Implementation finalSuperImplementation )
2995 {
2996 final ModelException.Detail detail = new ModelException.Detail(
2997 "IMPLEMENTATION_INHERITANCE_CONSTRAINT", Level.SEVERE,
2998 this.getMessage( "implementationInheritanceConstraint", new Object[]
2999 {
3000 implementation.getIdentifier(), finalSuperImplementation.getIdentifier()
3001 } ) );
3002
3003 detail.setElement( element );
3004 return detail;
3005 }
3006
3007 private ModelException.Detail newSpecificationInheritanceConstraintDetail(
3008 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
3009 final SpecificationReference specification, final Implementation finalSuperSpecification )
3010 {
3011 final ModelException.Detail detail = new ModelException.Detail(
3012 "SPECIFICATION_INHERITANCE_CONSTRANT", Level.SEVERE,
3013 this.getMessage( "specificationInheritanceConstraint", new Object[]
3014 {
3015 implementation.getIdentifier(), specification.getIdentifier(), finalSuperSpecification.getIdentifier()
3016 } ) );
3017
3018 detail.setElement( element );
3019 return detail;
3020 }
3021
3022 private ModelException.Detail newDependencyInheritanceConstraintDetail(
3023 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
3024 final Dependency dependency, final Implementation finalSuperDependency )
3025 {
3026 final ModelException.Detail detail = new ModelException.Detail(
3027 "DEPENDENCY_INHERITANCE_CONSTRAINT", Level.SEVERE,
3028 this.getMessage( "dependencyInheritanceConstraint", new Object[]
3029 {
3030 implementation.getIdentifier(), dependency.getName(), finalSuperDependency.getIdentifier()
3031 } ) );
3032
3033 detail.setElement( element );
3034 return detail;
3035 }
3036
3037 private ModelException.Detail newPropertyInheritanceConstraintDetail(
3038 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
3039 final Property property, final Implementation finalSuperProperty )
3040 {
3041 final ModelException.Detail detail = new ModelException.Detail(
3042 "PROPERTY_INHERITANCE_CONSTRAINT", Level.SEVERE,
3043 this.getMessage( "propertyInheritanceConstraint", new Object[]
3044 {
3045 implementation.getIdentifier(), property.getName(), finalSuperProperty.getIdentifier()
3046 } ) );
3047
3048 detail.setElement( element );
3049 return detail;
3050 }
3051
3052 private ModelException.Detail newPropertyInheritanceConstraintDetail(
3053 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
3054 final PropertyReference reference, final Implementation finalSuperProperty )
3055 {
3056 final ModelException.Detail detail = new ModelException.Detail(
3057 "PROPERTY_INHERITANCE_CONSTRAINT", Level.SEVERE,
3058 this.getMessage( "propertyInheritanceConstraint", new Object[]
3059 {
3060 implementation.getIdentifier(), reference.getName(), finalSuperProperty.getIdentifier()
3061 } ) );
3062
3063 detail.setElement( element );
3064 return detail;
3065 }
3066
3067 private ModelException.Detail newMessageInheritanceConstraintDetail(
3068 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
3069 final Message message, final Implementation finalSuperMessage )
3070 {
3071 final ModelException.Detail detail = new ModelException.Detail(
3072 "MESSAGE_INHERITANCE_CONSTRAINT", Level.SEVERE,
3073 this.getMessage( "messageInheritanceConstraint", new Object[]
3074 {
3075 implementation.getIdentifier(), message.getName(), finalSuperMessage.getIdentifier()
3076 } ) );
3077
3078 detail.setElement( element );
3079 return detail;
3080 }
3081
3082 private ModelException.Detail newMessageInheritanceConstraintDetail(
3083 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
3084 final MessageReference reference, final Implementation finalSuperMessage )
3085 {
3086 final ModelException.Detail detail = new ModelException.Detail(
3087 "MESSAGE_INHERITANCE_CONSTRAINT", Level.SEVERE,
3088 this.getMessage( "messageInheritanceConstraint", new Object[]
3089 {
3090 implementation.getIdentifier(), reference.getName(), finalSuperMessage.getIdentifier()
3091 } ) );
3092
3093 detail.setElement( element );
3094 return detail;
3095 }
3096
3097 private ModelException.Detail newDependencyPropertyReferenceDeclarationConstraintDetail(
3098 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
3099 final Dependency dependency, final PropertyReference reference )
3100 {
3101 final ModelException.Detail detail = new ModelException.Detail(
3102 "DEPENDENCY_PROPERTY_REFERENCE_DECLARATION_CONSTRAINT", Level.SEVERE,
3103 this.getMessage( "dependencyPropertyReferenceDeclarationConstraint", new Object[]
3104 {
3105 implementation.getIdentifier(), dependency.getName(), reference.getName()
3106 } ) );
3107
3108 detail.setElement( element );
3109 return detail;
3110 }
3111
3112 private ModelException.Detail newDependencyPropertiesOverrideConstraintDetail(
3113 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
3114 final Dependency dependency, final Specification specification, final Property property )
3115 {
3116 final ModelException.Detail detail = new ModelException.Detail(
3117 "DEPENDENCY_PROPERTIES_OVERRIDE_CONSTRAINT", Level.SEVERE,
3118 this.getMessage( "dependencyPropertiesOverrideConstraint", new Object[]
3119 {
3120 implementation.getIdentifier(), dependency.getName(), specification.getIdentifier(),
3121 specification.getScope(), property.getName()
3122 } ) );
3123
3124 detail.setElement( element );
3125 return detail;
3126 }
3127
3128 private ModelException.Detail newImplementationSpecificationDeclarationConstraintDetail(
3129 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
3130 final Specification specification )
3131 {
3132 final ModelException.Detail detail = new ModelException.Detail(
3133 "IMPLEMENTATION_SPECIFICATION_DECLARATION_CONSTRAINT", Level.SEVERE,
3134 this.getMessage( "implementationSpecificationDeclarationConstraint", new Object[]
3135 {
3136 implementation.getIdentifier(), specification.getIdentifier()
3137 } ) );
3138
3139 detail.setElement( element );
3140 return detail;
3141 }
3142
3143 private ModelException.Detail newModuleMessageReferenceDeclarationConstraintDetail(
3144 final JAXBElement<? extends ModelObject> element, final Module module, final MessageReference reference )
3145 {
3146 final ModelException.Detail detail = new ModelException.Detail(
3147 "MODULE_MESSAGE_REFERENCE_DECLARATION_CONSTRAINT", Level.SEVERE,
3148 this.getMessage( "moduleMessageReferenceDeclarationConstraint", new Object[]
3149 {
3150 module.getName(), reference.getName()
3151 } ) );
3152
3153 detail.setElement( element );
3154 return detail;
3155 }
3156
3157 private ModelException.Detail newModulePropertyReferenceDeclarationConstraintDetail(
3158 final JAXBElement<? extends ModelObject> element, final Module module, final PropertyReference reference )
3159 {
3160 final ModelException.Detail detail = new ModelException.Detail(
3161 "MODULE_PROPERTY_REFERENCE_DECLARATION_CONSTRAINT", Level.SEVERE,
3162 this.getMessage( "modulePropertyReferenceDeclarationConstraint", new Object[]
3163 {
3164 module.getName(), reference.getName()
3165 } ) );
3166
3167 detail.setElement( element );
3168 return detail;
3169 }
3170
3171 private ModelException.Detail newModuleImplementationReferenceDeclarationConstraintDetail(
3172 final JAXBElement<? extends ModelObject> element, final Module module, final ImplementationReference reference )
3173 {
3174 final ModelException.Detail detail = new ModelException.Detail(
3175 "MODULE_IMPLEMENTATION_REFERENCE_DECLARATION_CONSTRAINT", Level.SEVERE,
3176 this.getMessage( "moduleImplementationReferenceDeclarationConstraint", new Object[]
3177 {
3178 module.getName(), reference.getIdentifier()
3179 } ) );
3180
3181 detail.setElement( element );
3182 return detail;
3183 }
3184
3185 private ModelException.Detail newImplementationImplementationDeclarationConstraintDetail(
3186 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
3187 final Implementation declaration )
3188 {
3189 final ModelException.Detail detail = new ModelException.Detail(
3190 "IMPLEMENTATION_IMPLEMENTATION_DECLARATION_CONSTRAINT", Level.SEVERE,
3191 this.getMessage( "implementationImplementationDeclarationConstraint", new Object[]
3192 {
3193 implementation.getIdentifier(), declaration.getIdentifier()
3194 } ) );
3195
3196 detail.setElement( element );
3197 return detail;
3198 }
3199
3200 private ModelException.Detail newModuleSpecificationReferenceDeclarationConstraintDetail(
3201 final JAXBElement<? extends ModelObject> element, final Module module, final SpecificationReference reference )
3202 {
3203 final ModelException.Detail detail = new ModelException.Detail(
3204 "MODULE_SPECIFICATION_REFERENCE_DECLARATION_CONSTRAINT", Level.SEVERE,
3205 this.getMessage( "moduleSpecificationReferenceDeclarationConstraint", new Object[]
3206 {
3207 module.getName(), reference.getIdentifier()
3208 } ) );
3209
3210 detail.setElement( element );
3211 return detail;
3212 }
3213
3214 private ModelException.Detail newDependencyOverrideConstraintDetail(
3215 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
3216 final Dependency dependency )
3217 {
3218 final ModelException.Detail detail = new ModelException.Detail(
3219 "DEPENDENCY_OVERRIDE_CONSTRAINT", Level.SEVERE,
3220 this.getMessage( "dependencyOverrideConstraint", new Object[]
3221 {
3222 implementation.getIdentifier(), dependency.getName()
3223 } ) );
3224
3225 detail.setElement( element );
3226 return detail;
3227 }
3228
3229 private ModelException.Detail newMessageOverrideConstraintDetail(
3230 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
3231 final Message message )
3232 {
3233 final ModelException.Detail detail = new ModelException.Detail(
3234 "MESSAGE_OVERRIDE_CONSTRAINT", Level.SEVERE, this.getMessage( "messageOverrideConstraint", new Object[]
3235 {
3236 implementation.getIdentifier(), message.getName()
3237 } ) );
3238
3239 detail.setElement( element );
3240 return detail;
3241 }
3242
3243 private ModelException.Detail newMessageOverrideConstraintDetail(
3244 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
3245 final MessageReference reference )
3246 {
3247 final ModelException.Detail detail = new ModelException.Detail(
3248 "MESSAGE_OVERRIDE_CONSTRAINT", Level.SEVERE, this.getMessage( "messageOverrideConstraint", new Object[]
3249 {
3250 implementation.getIdentifier(), reference.getName()
3251 } ) );
3252
3253 detail.setElement( element );
3254 return detail;
3255 }
3256
3257 private ModelException.Detail newPropertyOverrideConstraintDetail(
3258 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
3259 final Property property )
3260 {
3261 final ModelException.Detail detail = new ModelException.Detail(
3262 "PROPERTY_OVERRIDE_CONSTRAINT", Level.SEVERE, this.getMessage( "propertyOverrideConstraint", new Object[]
3263 {
3264 implementation.getIdentifier(), property.getName()
3265 } ) );
3266
3267 detail.setElement( element );
3268 return detail;
3269 }
3270
3271 private ModelException.Detail newPropertyOverrideConstraintDetail(
3272 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
3273 final PropertyReference reference )
3274 {
3275 final ModelException.Detail detail = new ModelException.Detail(
3276 "PROPERTY_OVERRIDE_CONSTRAINT", Level.SEVERE, this.getMessage( "propertyOverrideConstraint", new Object[]
3277 {
3278 implementation.getIdentifier(), reference.getName()
3279 } ) );
3280
3281 detail.setElement( element );
3282 return detail;
3283 }
3284
3285 private ModelException.Detail newSpecificationOverrideConstraintDetail(
3286 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
3287 final SpecificationReference reference )
3288 {
3289 final ModelException.Detail detail = new ModelException.Detail(
3290 "SPECIFICATION_OVERRIDE_CONSTRAINT", Level.SEVERE,
3291 this.getMessage( "specificationOverrideConstraint", new Object[]
3292 {
3293 implementation.getIdentifier(), reference.getIdentifier()
3294 } ) );
3295
3296 detail.setElement( element );
3297 return detail;
3298 }
3299
3300 private ModelException.Detail newAbstractLocationConstraintDetail(
3301 final JAXBElement<? extends ModelObject> element, final Implementation implementation, final String location )
3302 {
3303 final ModelException.Detail detail = new ModelException.Detail(
3304 "ABSTRACT_IMPLEMENTATION_LOCATION_CONSTRAINT", Level.SEVERE,
3305 this.getMessage( "abstractLocationConstraint", new Object[]
3306 {
3307 implementation.getIdentifier(), location
3308 } ) );
3309
3310 detail.setElement( element );
3311 return detail;
3312 }
3313
3314 private ModelException.Detail newFinalModuleMessageConstraintDetail(
3315 final JAXBElement<? extends ModelObject> element, final Module module, final Message message )
3316 {
3317 final ModelException.Detail detail = new ModelException.Detail(
3318 "FINAL_MODULE_MESSAGE_CONSTRAINT", Level.SEVERE,
3319 this.getMessage( "finalModuleMessageConstraint", new Object[]
3320 {
3321 module.getName(), message.getName()
3322 } ) );
3323
3324 detail.setElement( element );
3325 return detail;
3326 }
3327
3328 private ModelException.Detail newOverrideModuleMessageConstraintDetail(
3329 final JAXBElement<? extends ModelObject> element, final Module module, final Message message )
3330 {
3331 final ModelException.Detail detail = new ModelException.Detail(
3332 "OVERRIDE_MODULE_MESSAGE_CONSTRAINT", Level.SEVERE,
3333 this.getMessage( "overrideModuleMessageConstraint", new Object[]
3334 {
3335 module.getName(), message.getName()
3336 } ) );
3337
3338 detail.setElement( element );
3339 return detail;
3340 }
3341
3342 private ModelException.Detail newFinalModulePropertyConstraintDetail(
3343 final JAXBElement<? extends ModelObject> element, final Module module, final Property property )
3344 {
3345 final ModelException.Detail detail = new ModelException.Detail(
3346 "FINAL_MODULE_PROPERTY_CONSTRAINT", Level.SEVERE,
3347 this.getMessage( "finalModulePropertyConstraint", new Object[]
3348 {
3349 module.getName(), property.getName()
3350 } ) );
3351
3352 detail.setElement( element );
3353 return detail;
3354 }
3355
3356 private ModelException.Detail newOverrideModulePropertyConstraintDetail(
3357 final JAXBElement<? extends ModelObject> element, final Module module, final Property property )
3358 {
3359 final ModelException.Detail detail = new ModelException.Detail(
3360 "OVERRIDE_MODULE_PROPERTY_CONSTRAINT", Level.SEVERE,
3361 this.getMessage( "overrideModulePropertyConstraint", new Object[]
3362 {
3363 module.getName(), property.getName()
3364 } ) );
3365
3366 detail.setElement( element );
3367 return detail;
3368 }
3369
3370 private ModelException.Detail newSpecificationPropertyReferenceDeclarationConstraintDetail(
3371 final JAXBElement<? extends ModelObject> element, final Specification specification,
3372 final PropertyReference reference )
3373 {
3374 final ModelException.Detail detail = new ModelException.Detail(
3375 "SPECIFICATION_PROPERTY_REFERENCE_DECLARATION_CONSTRAINT", Level.SEVERE,
3376 this.getMessage( "specificationPropertyReferenceDeclarationConstraint", new Object[]
3377 {
3378 specification.getIdentifier(), reference.getName()
3379 } ) );
3380
3381 detail.setElement( element );
3382 return detail;
3383 }
3384
3385 private ModelException.Detail newSpecificationMultipleInheritanceContraintDetail(
3386 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
3387 final SpecificationReference reference )
3388 {
3389 final ModelException.Detail detail = new ModelException.Detail(
3390 "SPECIFICATION_MULTIPLE_INHERITANCE_CONSTRAINT", Level.SEVERE,
3391 this.getMessage( "multipleInheritanceSpecificationConstraint", new Object[]
3392 {
3393 implementation.getIdentifier(), reference.getIdentifier()
3394 } ) );
3395
3396 detail.setElement( element );
3397 return detail;
3398 }
3399
3400 private ModelException.Detail newDependencyMultipleInheritanceContraintDetail(
3401 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
3402 final Dependency dependency )
3403 {
3404 final ModelException.Detail detail = new ModelException.Detail(
3405 "DEPENDENCY_MULTIPLE_INHERITANCE_CONSTRAINT", Level.SEVERE,
3406 this.getMessage( "multipleInheritanceDependencyConstraint", new Object[]
3407 {
3408 implementation.getIdentifier(), dependency.getName()
3409 } ) );
3410
3411 detail.setElement( element );
3412 return detail;
3413 }
3414
3415 private ModelException.Detail newMessageMultipleInheritanceContraintDetail(
3416 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
3417 final Message message )
3418 {
3419 final ModelException.Detail detail = new ModelException.Detail(
3420 "MESSAGE_MULTIPLE_INHERITANCE_CONSTRAINT", Level.SEVERE,
3421 this.getMessage( "multipleInheritanceMessageConstraint", new Object[]
3422 {
3423 implementation.getIdentifier(), message.getName()
3424 } ) );
3425
3426 detail.setElement( element );
3427 return detail;
3428 }
3429
3430 private ModelException.Detail newPropertyMultipleInheritanceContraintDetail(
3431 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
3432 final Property property )
3433 {
3434 final ModelException.Detail detail = new ModelException.Detail(
3435 "PROPERTY_MULTIPLE_INHERITANCE_CONSTRAINT", Level.SEVERE,
3436 this.getMessage( "multipleInheritancePropertyConstraint", new Object[]
3437 {
3438 implementation.getIdentifier(), property.getName()
3439 } ) );
3440
3441 detail.setElement( element );
3442 return detail;
3443 }
3444
3445 private ModelException.Detail newImplementationInheritanceCycleConstraintDetail(
3446 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
3447 final Implementation cycle )
3448 {
3449 final ModelException.Detail detail = new ModelException.Detail(
3450 "IMPLEMENTATION_INHERITANCE_CYCLE_CONSTRAINT", Level.SEVERE,
3451 this.getMessage( "implementationInheritanceCycleConstraint", new Object[]
3452 {
3453 implementation.getIdentifier(), cycle.getIdentifier()
3454 } ) );
3455
3456 detail.setElement( element );
3457 return detail;
3458 }
3459
3460 private ModelException.Detail newImplementationInheritanceCompatibilityConstraintDetail(
3461 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
3462 final Implementation superImplementation, final String expectedVersion )
3463 {
3464 final ModelException.Detail detail = new ModelException.Detail(
3465 "IMPLEMENTATION_INHERITANCE_COMPATIBILITY_CONSTRAINT", Level.SEVERE,
3466 this.getMessage( "implementationInheritanceCompatibilityConstraint", new Object[]
3467 {
3468 implementation.getIdentifier(), superImplementation.getIdentifier(), superImplementation.getVersion(),
3469 expectedVersion
3470 } ) );
3471
3472 detail.setElement( element );
3473 return detail;
3474 }
3475
3476 private ModelException.Detail newSpecificationVersioningConstraintDetail(
3477 final JAXBElement<? extends ModelObject> element, final Implementation implementation,
3478 final Specification specification )
3479 {
3480 final ModelException.Detail detail = new ModelException.Detail(
3481 "SPECIFICATION_VERSIONING_CONSTRAINT", Level.SEVERE,
3482 this.getMessage( "specificationVersioningConstraint", new Object[]
3483 {
3484 implementation.getIdentifier(), specification.getIdentifier()
3485 } ) );
3486
3487 detail.setElement( element );
3488 return detail;
3489 }
3490
3491 private ModelException.Detail newImplementationVersioningConstraintDetail(
3492 final JAXBElement<? extends ModelObject> element, final Implementation declaring,
3493 final Implementation implementation )
3494 {
3495 final ModelException.Detail detail = new ModelException.Detail(
3496 "IMPLEMENTATION_VERSIONING_CONSTRAINT", Level.SEVERE,
3497 this.getMessage( "implementationVersioningConstraint", new Object[]
3498 {
3499 declaring.getIdentifier(), implementation.getIdentifier()
3500 } ) );
3501
3502 detail.setElement( element );
3503 return detail;
3504 }
3505
3506 // SECTION-END
3507 }