1 /*
2 * Copyright (C) 2005 Christian Schulte <cs@schulte.it>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * o Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * o Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
18 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $JOMC: DefaultModletProvider.java 5293 2016-08-29 17:41:51Z schulte $
29 *
30 */
31 package org.jomc.modlet;
32
33 import java.lang.reflect.UndeclaredThrowableException;
34 import java.net.MalformedURLException;
35 import java.net.URI;
36 import java.net.URISyntaxException;
37 import java.net.URL;
38 import java.text.MessageFormat;
39 import java.util.ArrayList;
40 import java.util.Enumeration;
41 import java.util.HashSet;
42 import java.util.List;
43 import java.util.ResourceBundle;
44 import java.util.Set;
45 import java.util.concurrent.Callable;
46 import java.util.concurrent.CancellationException;
47 import java.util.concurrent.ExecutionException;
48 import java.util.concurrent.Future;
49 import java.util.logging.Level;
50 import javax.xml.bind.JAXBContext;
51 import javax.xml.bind.JAXBElement;
52 import javax.xml.bind.JAXBException;
53 import javax.xml.bind.UnmarshalException;
54 import javax.xml.bind.Unmarshaller;
55
56 /**
57 * Default {@code ModletProvider} implementation.
58 *
59 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
60 * @version $JOMC: DefaultModletProvider.java 5293 2016-08-29 17:41:51Z schulte $
61 * @see ModelContext#findModlets(org.jomc.modlet.Modlets)
62 */
63 public class DefaultModletProvider implements ModletProvider
64 {
65
66 /**
67 * Constant for the name of the model context attribute backing property {@code enabled}.
68 *
69 * @see #findModlets(org.jomc.modlet.ModelContext, org.jomc.modlet.Modlets)
70 * @see ModelContext#getAttribute(java.lang.String)
71 * @since 1.2
72 */
73 public static final String ENABLED_ATTRIBUTE_NAME = "org.jomc.modlet.DefaultModletProvider.enabledAttribute";
74
75 /**
76 * Constant for the name of the system property controlling property {@code defaultEnabled}.
77 *
78 * @see #isDefaultEnabled()
79 * @since 1.2
80 */
81 private static final String DEFAULT_ENABLED_PROPERTY_NAME =
82 "org.jomc.modlet.DefaultModletProvider.defaultEnabled";
83
84 /**
85 * Default value of the flag indicating the provider is enabled by default.
86 *
87 * @see #isDefaultEnabled()
88 * @since 1.2
89 */
90 private static final Boolean DEFAULT_ENABLED = Boolean.TRUE;
91
92 /**
93 * Flag indicating the provider is enabled by default.
94 */
95 private static volatile Boolean defaultEnabled;
96
97 /**
98 * Flag indicating the provider is enabled.
99 */
100 private volatile Boolean enabled;
101
102 /**
103 * Constant for the name of the model context attribute backing property {@code modletLocation}.
104 *
105 * @see #findModlets(org.jomc.modlet.ModelContext, org.jomc.modlet.Modlets)
106 * @see ModelContext#getAttribute(java.lang.String)
107 * @since 1.2
108 */
109 public static final String MODLET_LOCATION_ATTRIBUTE_NAME =
110 "org.jomc.modlet.DefaultModletProvider.modletLocationAttribute";
111
112 /**
113 * Constant for the name of the system property controlling property {@code defaultModletLocation}.
114 *
115 * @see #getDefaultModletLocation()
116 * @since 1.2
117 */
118 private static final String DEFAULT_MODLET_LOCATION_PROPERTY_NAME =
119 "org.jomc.modlet.DefaultModletProvider.defaultModletLocation";
120
121 /**
122 * Class path location searched for {@code Modlets} by default.
123 *
124 * @see #getDefaultModletLocation()
125 */
126 private static final String DEFAULT_MODLET_LOCATION = "META-INF/jomc-modlet.xml";
127
128 /**
129 * Default {@code Modlet} location.
130 */
131 private static volatile String defaultModletLocation;
132
133 /**
134 * Modlet location of the instance.
135 */
136 private volatile String modletLocation;
137
138 /**
139 * Constant for the name of the model context attribute backing property {@code validating}.
140 *
141 * @see #findModlets(org.jomc.modlet.ModelContext, java.lang.String)
142 * @see ModelContext#getAttribute(java.lang.String)
143 * @since 1.2
144 */
145 public static final String VALIDATING_ATTRIBUTE_NAME =
146 "org.jomc.modlet.DefaultModletProvider.validatingAttribute";
147
148 /**
149 * Constant for the name of the system property controlling property {@code defaultValidating}.
150 *
151 * @see #isDefaultValidating()
152 * @since 1.2
153 */
154 private static final String DEFAULT_VALIDATING_PROPERTY_NAME =
155 "org.jomc.modlet.DefaultModletProvider.defaultValidating";
156
157 /**
158 * Default value of the flag indicating the provider is validating resources by default.
159 *
160 * @see #isDefaultValidating()
161 * @since 1.2
162 */
163 private static final Boolean DEFAULT_VALIDATING = Boolean.TRUE;
164
165 /**
166 * Flag indicating the provider is validating resources by default.
167 *
168 * @since 1.2
169 */
170 private static volatile Boolean defaultValidating;
171
172 /**
173 * Flag indicating the provider is validating resources.
174 *
175 * @since 1.2
176 */
177 private volatile Boolean validating;
178
179 /**
180 * Constant for the name of the system property controlling property {@code defaultOrdinal}.
181 *
182 * @see #getDefaultOrdinal()
183 * @since 1.6
184 */
185 private static final String DEFAULT_ORDINAL_PROPERTY_NAME =
186 "org.jomc.modlet.DefaultModletProvider.defaultOrdinal";
187
188 /**
189 * Default value of the ordinal number of the provider.
190 *
191 * @see #getDefaultOrdinal()
192 * @since 1.6
193 */
194 private static final Integer DEFAULT_ORDINAL = 0;
195
196 /**
197 * Default ordinal number of the provider.
198 *
199 * @since 1.6
200 */
201 private static volatile Integer defaultOrdinal;
202
203 /**
204 * Ordinal number of the provider.
205 *
206 * @since 1.6
207 */
208 private volatile Integer ordinal;
209
210 /**
211 * Creates a new {@code DefaultModletProvider} instance.
212 */
213 public DefaultModletProvider()
214 {
215 super();
216 }
217
218 /**
219 * Gets a flag indicating the provider is enabled by default.
220 * <p>
221 * The default enabled flag is controlled by system property
222 * {@code org.jomc.modlet.DefaultModletProvider.defaultEnabled} holding a value indicating the provider is
223 * enabled by default. If that property is not set, the {@code true} default is returned.
224 * </p>
225 *
226 * @return {@code true}, if the provider is enabled by default; {@code false}, if the provider is disabled by
227 * default.
228 *
229 * @see #isEnabled()
230 * @see #setDefaultEnabled(java.lang.Boolean)
231 */
232 public static boolean isDefaultEnabled()
233 {
234 if ( defaultEnabled == null )
235 {
236 defaultEnabled = Boolean.valueOf( System.getProperty(
237 DEFAULT_ENABLED_PROPERTY_NAME, Boolean.toString( DEFAULT_ENABLED ) ) );
238
239 }
240
241 return defaultEnabled;
242 }
243
244 /**
245 * Sets the flag indicating the provider is enabled by default.
246 *
247 * @param value The new value of the flag indicating the provider is enabled by default or {@code null}.
248 *
249 * @see #isDefaultEnabled()
250 */
251 public static void setDefaultEnabled( final Boolean value )
252 {
253 defaultEnabled = value;
254 }
255
256 /**
257 * Gets a flag indicating the provider is enabled.
258 *
259 * @return {@code true}, if the provider is enabled; {@code false}, if the provider is disabled.
260 *
261 * @see #isDefaultEnabled()
262 * @see #setEnabled(java.lang.Boolean)
263 */
264 public final boolean isEnabled()
265 {
266 if ( this.enabled == null )
267 {
268 this.enabled = isDefaultEnabled();
269 }
270
271 return this.enabled;
272 }
273
274 /**
275 * Sets the flag indicating the provider is enabled.
276 *
277 * @param value The new value of the flag indicating the provider is enabled or {@code null}.
278 *
279 * @see #isEnabled()
280 */
281 public final void setEnabled( final Boolean value )
282 {
283 this.enabled = value;
284 }
285
286 /**
287 * Gets the default location searched for {@code Modlet} resources.
288 * <p>
289 * The default {@code Modlet} location is controlled by system property
290 * {@code org.jomc.modlet.DefaultModletProvider.defaultModletLocation} holding the location to search for
291 * {@code Modlet} resources by default. If that property is not set, the {@code META-INF/jomc-modlet.xml} default is
292 * returned.
293 * </p>
294 *
295 * @return The location searched for {@code Modlet} resources by default.
296 *
297 * @see #setDefaultModletLocation(java.lang.String)
298 */
299 public static String getDefaultModletLocation()
300 {
301 if ( defaultModletLocation == null )
302 {
303 defaultModletLocation = System.getProperty(
304 DEFAULT_MODLET_LOCATION_PROPERTY_NAME, DEFAULT_MODLET_LOCATION );
305
306 }
307
308 return defaultModletLocation;
309 }
310
311 /**
312 * Sets the default location searched for {@code Modlet} resources.
313 *
314 * @param value The new default location to search for {@code Modlet} resources or {@code null}.
315 *
316 * @see #getDefaultModletLocation()
317 */
318 public static void setDefaultModletLocation( final String value )
319 {
320 defaultModletLocation = value;
321 }
322
323 /**
324 * Gets the location searched for {@code Modlet} resources.
325 *
326 * @return The location searched for {@code Modlet} resources.
327 *
328 * @see #getDefaultModletLocation()
329 * @see #setModletLocation(java.lang.String)
330 */
331 public final String getModletLocation()
332 {
333 if ( this.modletLocation == null )
334 {
335 this.modletLocation = getDefaultModletLocation();
336 }
337
338 return this.modletLocation;
339 }
340
341 /**
342 * Sets the location searched for {@code Modlet} resources.
343 *
344 * @param value The new location to search for {@code Modlet} resources or {@code null}.
345 *
346 * @see #getModletLocation()
347 */
348 public final void setModletLocation( final String value )
349 {
350 this.modletLocation = value;
351 }
352
353 /**
354 * Gets a flag indicating the provider is validating resources by default.
355 * <p>
356 * The default validating flag is controlled by system property
357 * {@code org.jomc.modlet.DefaultModletProvider.defaultValidating} holding a value indicating the provider is
358 * validating resources by default. If that property is not set, the {@code true} default is returned.
359 * </p>
360 *
361 * @return {@code true}, if the provider is validating resources by default; {@code false}, if the provider is not
362 * validating resources by default.
363 *
364 * @see #isValidating()
365 * @see #setDefaultValidating(java.lang.Boolean)
366 *
367 * @since 1.2
368 */
369 public static boolean isDefaultValidating()
370 {
371 if ( defaultValidating == null )
372 {
373 defaultValidating = Boolean.valueOf( System.getProperty(
374 DEFAULT_VALIDATING_PROPERTY_NAME, Boolean.toString( DEFAULT_VALIDATING ) ) );
375
376 }
377
378 return defaultValidating;
379 }
380
381 /**
382 * Sets the flag indicating the provider is validating resources by default.
383 *
384 * @param value The new value of the flag indicating the provider is validating resources by default or
385 * {@code null}.
386 *
387 * @see #isDefaultValidating()
388 *
389 * @since 1.2
390 */
391 public static void setDefaultValidating( final Boolean value )
392 {
393 defaultValidating = value;
394 }
395
396 /**
397 * Gets a flag indicating the provider is validating resources.
398 *
399 * @return {@code true}, if the provider is validating resources; {@code false}, if the provider is not validating
400 * resources.
401 *
402 * @see #isDefaultValidating()
403 * @see #setValidating(java.lang.Boolean)
404 *
405 * @since 1.2
406 */
407 public final boolean isValidating()
408 {
409 if ( this.validating == null )
410 {
411 this.validating = isDefaultValidating();
412 }
413
414 return this.validating;
415 }
416
417 /**
418 * Sets the flag indicating the provider is validating resources.
419 *
420 * @param value The new value of the flag indicating the provider is validating resources or {@code null}.
421 *
422 * @see #isValidating()
423 *
424 * @since 1.2
425 */
426 public final void setValidating( final Boolean value )
427 {
428 this.validating = value;
429 }
430
431 /**
432 * Gets the default ordinal number of the provider.
433 * <p>
434 * The default ordinal number is controlled by system property
435 * {@code org.jomc.modlet.DefaultModletProvider.defaultOrdinal} holding the default ordinal number of the provider.
436 * If that property is not set, the {@code 0} default is returned.
437 * </p>
438 *
439 * @return The default ordinal number of the provider.
440 *
441 * @see #setDefaultOrdinal(java.lang.Integer)
442 *
443 * @since 1.6
444 */
445 public static int getDefaultOrdinal()
446 {
447 if ( defaultOrdinal == null )
448 {
449 defaultOrdinal = Integer.getInteger( DEFAULT_ORDINAL_PROPERTY_NAME, DEFAULT_ORDINAL );
450 }
451
452 return defaultOrdinal;
453 }
454
455 /**
456 * Sets the default ordinal number of the provider.
457 *
458 * @param value The new default ordinal number of the provider or {@code null}.
459 *
460 * @see #getDefaultOrdinal()
461 *
462 * @since 1.6
463 */
464 public static void setDefaultOrdinal( final Integer value )
465 {
466 defaultOrdinal = value;
467 }
468
469 /**
470 * Gets the ordinal number of the provider.
471 *
472 * @return The ordinal number of the provider.
473 *
474 * @see #getDefaultOrdinal()
475 * @see #setOrdinal(java.lang.Integer)
476 *
477 * @since 1.6
478 */
479 public final int getOrdinal()
480 {
481 if ( this.ordinal == null )
482 {
483 this.ordinal = getDefaultOrdinal();
484 }
485
486 return this.ordinal;
487 }
488
489 /**
490 * Sets the ordinal number of the provider.
491 *
492 * @param value The new ordinal number of the provider or {@code null}.
493 *
494 * @see #getOrdinal()
495 *
496 * @since 1.6
497 */
498 public final void setOrdinal( final Integer value )
499 {
500 this.ordinal = value;
501 }
502
503 /**
504 * Searches a given context for {@code Modlets}.
505 *
506 * @param context The context to search for {@code Modlets}.
507 * @param location The location to search at.
508 *
509 * @return The {@code Modlets} found at {@code location} in {@code context} or {@code null}, if no {@code Modlets}
510 * are found.
511 *
512 * @throws NullPointerException if {@code context} or {@code location} is {@code null}.
513 * @throws ModelException if searching the context fails.
514 *
515 * @see #isValidating()
516 * @see #VALIDATING_ATTRIBUTE_NAME
517 */
518 public Modlets findModlets( final ModelContext context, final String location ) throws ModelException
519 {
520 if ( context == null )
521 {
522 throw new NullPointerException( "context" );
523 }
524 if ( location == null )
525 {
526 throw new NullPointerException( "location" );
527 }
528
529 URL url = null;
530 try
531 {
532 boolean contextValidating = this.isValidating();
533 if ( DEFAULT_VALIDATING == contextValidating
534 && context.getAttribute( VALIDATING_ATTRIBUTE_NAME ) instanceof Boolean )
535 {
536 contextValidating = (Boolean) context.getAttribute( VALIDATING_ATTRIBUTE_NAME );
537 }
538
539 final Modlets modlets = new Modlets();
540 final long t0 = System.nanoTime();
541 final Enumeration<URL> modletResourceEnumeration = context.findResources( location );
542 final Set<URI> modletResources = new HashSet<URI>();
543 while ( modletResourceEnumeration.hasMoreElements() )
544 {
545 modletResources.add( modletResourceEnumeration.nextElement().toURI() );
546 }
547
548 if ( !modletResources.isEmpty() )
549 {
550 if ( context.getExecutorService() != null && modletResources.size() > 1 )
551 {
552 final JAXBContext ctx = context.createContext( ModletObject.MODEL_PUBLIC_ID );
553 final javax.xml.validation.Schema schema = context.createSchema( ModletObject.MODEL_PUBLIC_ID );
554 final ThreadLocal<Unmarshaller> threadLocalUnmarshaller = new ThreadLocal<Unmarshaller>();
555 final List<Callable<Object>> tasks = new ArrayList<Callable<Object>>( modletResources.size() );
556
557 class UnmarshalTask implements Callable<Object>
558 {
559
560 final URI resource;
561
562 final boolean validating;
563
564 UnmarshalTask( final URI resource, final boolean validating )
565 {
566 super();
567 this.resource = resource;
568 this.validating = validating;
569 }
570
571 public Object call() throws ModelException, JAXBException, MalformedURLException
572 {
573 Unmarshaller unmarshaller = threadLocalUnmarshaller.get();
574 if ( unmarshaller == null )
575 {
576 unmarshaller = ctx.createUnmarshaller();
577
578 if ( this.validating )
579 {
580 unmarshaller.setSchema( schema );
581 }
582
583 threadLocalUnmarshaller.set( unmarshaller );
584 }
585
586 return unmarshaller.unmarshal( this.resource.toURL() );
587 }
588
589 }
590
591 for ( final URI modletResoure : modletResources )
592 {
593 tasks.add( new UnmarshalTask( modletResoure, contextValidating ) );
594 }
595
596 for ( final Future<Object> task : context.getExecutorService().invokeAll( tasks ) )
597 {
598 Object content = task.get();
599 if ( content instanceof JAXBElement<?> )
600 {
601 content = ( (JAXBElement<?>) content ).getValue();
602 }
603
604 if ( content instanceof Modlet )
605 {
606 modlets.getModlet().add( (Modlet) content );
607 }
608 else if ( content instanceof Modlets )
609 {
610 modlets.getModlet().addAll( ( (Modlets) content ).getModlet() );
611 }
612 }
613 }
614 else
615 {
616 final JAXBContext ctx = context.createContext( ModletObject.MODEL_PUBLIC_ID );
617 final Unmarshaller u = ctx.createUnmarshaller();
618
619 if ( contextValidating )
620 {
621 u.setSchema( context.createSchema( ModletObject.MODEL_PUBLIC_ID ) );
622 }
623
624 for ( final URI modletResource : modletResources )
625 {
626 url = modletResource.toURL();
627 Object content = u.unmarshal( url );
628 if ( content instanceof JAXBElement<?> )
629 {
630 content = ( (JAXBElement<?>) content ).getValue();
631 }
632
633 if ( content instanceof Modlet )
634 {
635 modlets.getModlet().add( (Modlet) content );
636 }
637 else if ( content instanceof Modlets )
638 {
639 modlets.getModlet().addAll( ( (Modlets) content ).getModlet() );
640 }
641 }
642 }
643 }
644
645 if ( context.isLoggable( Level.FINE ) )
646 {
647 context.log( Level.FINE, getMessage( "contextReport",
648 modlets.getModlet().size(),
649 location, System.nanoTime() - t0 ), null );
650
651 }
652
653 return modlets.getModlet().isEmpty() ? null : modlets;
654 }
655 catch ( final CancellationException e )
656 {
657 throw new ModelException( getMessage( e ), e );
658 }
659 catch ( final InterruptedException e )
660 {
661 throw new ModelException( getMessage( e ), e );
662 }
663 catch ( final URISyntaxException e )
664 {
665 throw new ModelException( getMessage( e ), e );
666 }
667 catch ( final MalformedURLException e )
668 {
669 throw new ModelException( getMessage( e ), e );
670 }
671 catch ( final UnmarshalException e )
672 {
673 String message = getMessage( e );
674 if ( message == null && e.getLinkedException() != null )
675 {
676 message = getMessage( e.getLinkedException() );
677 }
678
679 if ( url != null )
680 {
681 message = getMessage( "unmarshalException", url.toExternalForm(),
682 message != null ? " " + message : "" );
683
684 }
685
686 throw new ModelException( message, e );
687 }
688 catch ( final JAXBException e )
689 {
690 String message = getMessage( e );
691 if ( message == null && e.getLinkedException() != null )
692 {
693 message = getMessage( e.getLinkedException() );
694 }
695
696 throw new ModelException( message, e );
697 }
698 catch ( final ExecutionException e )
699 {
700 if ( e.getCause() instanceof ModelException )
701 {
702 throw (ModelException) e.getCause();
703 }
704 else if ( e.getCause() instanceof JAXBException )
705 {
706 String message = getMessage( e.getCause() );
707 if ( message == null && ( (JAXBException) e.getCause() ).getLinkedException() != null )
708 {
709 message = getMessage( ( (JAXBException) e.getCause() ).getLinkedException() );
710 }
711
712 throw new ModelException( message, e.getCause() );
713 }
714 else if ( e.getCause() instanceof RuntimeException )
715 {
716 // The fork-join framework breaks the exception handling contract of Callable by re-throwing any
717 // exception caught using a runtime exception.
718 if ( e.getCause().getCause() instanceof ModelException )
719 {
720 throw (ModelException) e.getCause().getCause();
721 }
722 else if ( e.getCause().getCause() instanceof JAXBException )
723 {
724 String message = getMessage( e.getCause().getCause() );
725 if ( message == null && ( (JAXBException) e.getCause().getCause() ).getLinkedException() != null )
726 {
727 message = getMessage( ( (JAXBException) e.getCause().getCause() ).getLinkedException() );
728 }
729
730 throw new ModelException( message, e.getCause().getCause() );
731 }
732 else if ( e.getCause().getCause() instanceof MalformedURLException )
733 {
734 throw new ModelException( getMessage( e.getCause().getCause() ), e.getCause().getCause() );
735 }
736 else if ( e.getCause().getCause() instanceof RuntimeException )
737 {
738 throw (RuntimeException) e.getCause().getCause();
739 }
740 else if ( e.getCause().getCause() instanceof Error )
741 {
742 throw (Error) e.getCause().getCause();
743 }
744 else if ( e.getCause().getCause() instanceof Exception )
745 {
746 // Checked exception not declared to be thrown by the Callable's 'call' method.
747 throw new UndeclaredThrowableException( e.getCause().getCause() );
748 }
749 else
750 {
751 throw (RuntimeException) e.getCause();
752 }
753 }
754 else if ( e.getCause() instanceof Error )
755 {
756 throw (Error) e.getCause();
757 }
758 else
759 {
760 // Checked exception not declared to be thrown by the Callable's 'call' method.
761 throw new UndeclaredThrowableException( e.getCause() );
762 }
763 }
764 }
765
766 /**
767 * {@inheritDoc}
768 *
769 * @return The {@code Modlets} found in the context or {@code null}, if no {@code Modlets} are found or the provider
770 * is disabled.
771 *
772 * @see #isEnabled()
773 * @see #getModletLocation()
774 * @see #findModlets(org.jomc.modlet.ModelContext, java.lang.String)
775 * @see #ENABLED_ATTRIBUTE_NAME
776 * @see #MODLET_LOCATION_ATTRIBUTE_NAME
777 * @deprecated As of JOMC 1.6, this method has been replaced by {@link #findModlets(org.jomc.modlet.ModelContext, org.jomc.modlet.Modlets)}.
778 * This method will be removed in JOMC 2.0.
779 */
780 @Deprecated
781 public Modlets findModlets( final ModelContext context ) throws ModelException
782 {
783 if ( context == null )
784 {
785 throw new NullPointerException( "context" );
786 }
787
788 return this.findModlets( context, new Modlets() );
789 }
790
791 /**
792 * {@inheritDoc}
793 *
794 * @return The {@code Modlets} found in the context or {@code null}, if no {@code Modlets} are found or the provider
795 * is disabled.
796 *
797 * @see #isEnabled()
798 * @see #getModletLocation()
799 * @see #findModlets(org.jomc.modlet.ModelContext, java.lang.String)
800 * @see #ENABLED_ATTRIBUTE_NAME
801 * @see #MODLET_LOCATION_ATTRIBUTE_NAME
802 * @since 1.6
803 */
804 public Modlets findModlets( final ModelContext context, final Modlets modlets ) throws ModelException
805 {
806 if ( context == null )
807 {
808 throw new NullPointerException( "context" );
809 }
810 if ( modlets == null )
811 {
812 throw new NullPointerException( "context" );
813 }
814
815 Modlets provided = null;
816
817 boolean contextEnabled = this.isEnabled();
818 if ( DEFAULT_ENABLED == contextEnabled && context.getAttribute( ENABLED_ATTRIBUTE_NAME ) instanceof Boolean )
819 {
820 contextEnabled = (Boolean) context.getAttribute( ENABLED_ATTRIBUTE_NAME );
821 }
822
823 String contextModletLocation = this.getModletLocation();
824 if ( DEFAULT_MODLET_LOCATION.equals( contextModletLocation )
825 && context.getAttribute( MODLET_LOCATION_ATTRIBUTE_NAME ) instanceof String )
826 {
827 contextModletLocation = (String) context.getAttribute( MODLET_LOCATION_ATTRIBUTE_NAME );
828 }
829
830 if ( contextEnabled )
831 {
832 final Modlets found = this.findModlets( context, contextModletLocation );
833
834 if ( found != null )
835 {
836 provided = modlets.clone();
837 provided.getModlet().addAll( found.getModlet() );
838 }
839 }
840 else if ( context.isLoggable( Level.FINER ) )
841 {
842 context.log( Level.FINER, getMessage( "disabled", this.getClass().getSimpleName() ), null );
843 }
844
845 return provided;
846 }
847
848 private static String getMessage( final String key, final Object... arguments )
849 {
850 return MessageFormat.format( ResourceBundle.getBundle(
851 DefaultModletProvider.class.getName().replace( '.', '/' ) ).getString( key ), arguments );
852
853 }
854
855 private static String getMessage( final Throwable t )
856 {
857 return t != null
858 ? t.getMessage() != null && t.getMessage().trim().length() > 0
859 ? t.getMessage()
860 : getMessage( t.getCause() )
861 : null;
862
863 }
864
865 }