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