1 /*
2 * Copyright (C) 2012 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: ModelContextFactory.java 5101 2016-04-04 18:52:11Z 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 5101 2016-04-04 18:52:11Z 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 }