View Javadoc
1   /*
2    *   Copyright (C) Christian Schulte <cs@schulte.it>, 2012-22
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: ModelContextFactory.java 5043 2015-05-27 07:03:39Z schulte $
29   *
30   */
31  package org.jomc.modlet;
32  
33  import java.security.AccessController;
34  import java.security.PrivilegedAction;
35  import java.text.MessageFormat;
36  import java.util.Locale;
37  import java.util.ResourceBundle;
38  
39  /**
40   * Interface to creating model contexts.
41   *
42   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
43   * @version $JOMC: ModelContextFactory.java 5043 2015-05-27 07:03:39Z schulte $
44   * @since 1.2
45   */
46  public abstract class ModelContextFactory
47  {
48  
49      /**
50       * Constant for the name of the default {@code ModelContextFactory} implementation.
51       */
52      private static final String DEFAULT_MODEL_CONTEXT_FACTORY_CLASS_NAME = "org.jomc.modlet.DefaultModelContextFactory";
53  
54      /**
55       * Constant for the name of the system property controlling {@code ModelContextFactory} implementations.
56       */
57      private static final String MODEL_CONTEXT_FACTORY_CLASS_NAME_PROPERTY =
58          "org.jomc.modlet.ModelContextFactory";
59  
60      /**
61       * Creates a new {@code ModelContextFactory} instance.
62       */
63      protected ModelContextFactory()
64      {
65          super();
66      }
67  
68      /**
69       * Creates a new {@code ModelContextFactory} instance.
70       * <p>
71       * The name of the class providing the {@code ModelContextFactory} implementation loaded by this method is
72       * controlled by system property {@code org.jomc.modlet.ModelContextFactory}. If that property is not set, this
73       * methods returns a new default instance.
74       * </p>
75       *
76       * @return A new {@code ModelContextFactory} instance.
77       *
78       * @throws ModelContextFactoryError if creating a new instance fails.
79       */
80      public static ModelContextFactory newInstance() throws ModelContextFactoryError
81      {
82          return newInstance( AccessController.doPrivileged( new PrivilegedAction<String>()
83          {
84  
85              public String run()
86              {
87                  return System.getProperty( MODEL_CONTEXT_FACTORY_CLASS_NAME_PROPERTY,
88                                             DEFAULT_MODEL_CONTEXT_FACTORY_CLASS_NAME );
89  
90              }
91  
92          } ) );
93      }
94  
95      /**
96       * Creates a new {@code ModelContextFactory} instance.
97       *
98       * @param factoryClassName The name of the {@code ModelContextFactory} class to create an instance of.
99       *
100      * @return A new {@code ModelContextFactory} instance.
101      *
102      * @throws NullPointerException if {@code factoryClassName} is {@code null}.
103      * @throws ModelContextFactoryError if creating a new instance fails.
104      */
105     public static ModelContextFactory newInstance( final String factoryClassName ) throws ModelContextFactoryError
106     {
107         if ( factoryClassName == null )
108         {
109             throw new NullPointerException( "factoryClassName" );
110         }
111 
112         try
113         {
114             final Class<?> factoryClass = Class.forName( factoryClassName );
115 
116             if ( !ModelContextFactory.class.isAssignableFrom( factoryClass ) )
117             {
118                 throw new ModelContextFactoryError( getMessage( "illegalFactory", factoryClassName,
119                                                                 ModelContextFactory.class.getName() ) );
120 
121             }
122 
123             return factoryClass.asSubclass( ModelContextFactory.class ).newInstance();
124         }
125         catch ( final ClassNotFoundException e )
126         {
127             throw new ModelContextFactoryError( getMessage( "classNotFound", factoryClassName ), e );
128         }
129         catch ( final InstantiationException e )
130         {
131             final String message = getMessage( e );
132             throw new ModelContextFactoryError( getMessage( "instantiationException", factoryClassName,
133                                                             message != null ? " " + message : "" ), e );
134 
135         }
136         catch ( final IllegalAccessException e )
137         {
138             final String message = getMessage( e );
139             throw new ModelContextFactoryError( getMessage( "accessDenied", factoryClassName,
140                                                             message != null ? " " + message : "" ), e );
141 
142         }
143     }
144 
145     /**
146      * Creates a new {@code ModelContext} instance.
147      *
148      * @return A new {@code ModelContext} instance.
149      */
150     public abstract ModelContext newModelContext();
151 
152     /**
153      * Creates a new {@code ModelContext} instance.
154      *
155      * @param classLoader The class loader to create a new instance with or {@code null}, to create a new instance
156      * using the bootstrap class loader.
157      *
158      * @return A new {@code ModelContext} instance for {@code classLoader}.
159      */
160     public abstract ModelContext newModelContext( final ClassLoader classLoader );
161 
162     private static String getMessage( final String key, final Object... args )
163     {
164         return MessageFormat.format( ResourceBundle.getBundle( ModelContextFactory.class.getName().replace( '.', '/' ),
165                                                                Locale.getDefault() ).getString( key ), args );
166 
167     }
168 
169     private static String getMessage( final Throwable t )
170     {
171         return t != null
172                    ? t.getMessage() != null && t.getMessage().trim().length() > 0
173                          ? t.getMessage()
174                          : getMessage( t.getCause() )
175                    : null;
176 
177     }
178 
179 }