001 /* 002 * Copyright (C) Christian Schulte, 2012-22 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without 006 * modification, are permitted provided that the following conditions 007 * are met: 008 * 009 * o Redistributions of source code must retain the above copyright 010 * notice, this list of conditions and the following disclaimer. 011 * 012 * o Redistributions in binary form must reproduce the above copyright 013 * notice, this list of conditions and the following disclaimer in 014 * the documentation and/or other materials provided with the 015 * distribution. 016 * 017 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 018 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 019 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 020 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, 021 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 022 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 023 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 024 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 025 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 026 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 027 * 028 * $JOMC: ModelContextFactory.java 4200 2012-01-25 09:46:13Z schulte2005 $ 029 * 030 */ 031 package org.jomc.modlet; 032 033 import java.security.AccessController; 034 import java.security.PrivilegedAction; 035 import java.text.MessageFormat; 036 import java.util.Locale; 037 import java.util.ResourceBundle; 038 039 /** 040 * Interface to creating model contexts. 041 * 042 * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a> 043 * @version $JOMC: ModelContextFactory.java 4200 2012-01-25 09:46:13Z schulte2005 $ 044 * @since 1.2 045 */ 046 public abstract class ModelContextFactory 047 { 048 049 /** Constant for the name of the default {@code ModelContextFactory} implementation. */ 050 private static final String DEFAULT_MODEL_CONTEXT_FACTORY_CLASS_NAME = "org.jomc.modlet.DefaultModelContextFactory"; 051 052 /** Constant for the name of the system property controlling {@code ModelContextFactory} implementations. */ 053 private static final String MODEL_CONTEXT_FACTORY_CLASS_NAME_PROPERTY = 054 "org.jomc.modlet.ModelContextFactory"; 055 056 /** Creates a new {@code ModelContextFactory} instance. */ 057 protected ModelContextFactory() 058 { 059 super(); 060 } 061 062 /** 063 * Creates a new {@code ModelContextFactory} instance. 064 * <p>The name of the class providing the {@code ModelContextFactory} implementation loaded by this method is 065 * controlled by system property {@code org.jomc.modlet.ModelContextFactory}. If that property is not set, this 066 * methods returns a new default instance.</p> 067 * 068 * @return A new {@code ModelContextFactory} instance. 069 * 070 * @throws ModelContextFactoryError if creating a new instance fails. 071 */ 072 public static ModelContextFactory newInstance() throws ModelContextFactoryError 073 { 074 return newInstance( AccessController.doPrivileged( new PrivilegedAction<String>() 075 { 076 077 public String run() 078 { 079 return System.getProperty( MODEL_CONTEXT_FACTORY_CLASS_NAME_PROPERTY, 080 DEFAULT_MODEL_CONTEXT_FACTORY_CLASS_NAME ); 081 082 } 083 084 } ) ); 085 } 086 087 /** 088 * Creates a new {@code ModelContextFactory} instance. 089 * 090 * @param factoryClassName The name of the {@code ModelContextFactory} class to create an instance of. 091 * 092 * @return A new {@code ModelContextFactory} instance. 093 * 094 * @throws NullPointerException if {@code factoryClassName} is {@code null}. 095 * @throws ModelContextFactoryError if creating a new instance fails. 096 */ 097 public static ModelContextFactory newInstance( final String factoryClassName ) throws ModelContextFactoryError 098 { 099 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 }