001/* 002 * Copyright (C) 2012 Christian Schulte <cs@schulte.it> 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 5101 2016-04-04 18:52:11Z schulte $ 029 * 030 */ 031package org.jomc.modlet; 032 033import java.security.AccessController; 034import java.security.PrivilegedAction; 035import java.text.MessageFormat; 036import java.util.Locale; 037import java.util.ResourceBundle; 038 039/** 040 * Interface to creating model contexts. 041 * 042 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 043 * @version $JOMC: ModelContextFactory.java 5101 2016-04-04 18:52:11Z schulte $ 044 * @since 1.2 045 */ 046public abstract class ModelContextFactory 047{ 048 049 /** 050 * Constant for the name of the default {@code ModelContextFactory} implementation. 051 */ 052 private static final String DEFAULT_MODEL_CONTEXT_FACTORY_CLASS_NAME = "org.jomc.modlet.DefaultModelContextFactory"; 053 054 /** 055 * Constant for the name of the system property controlling {@code ModelContextFactory} implementations. 056 */ 057 private static final String MODEL_CONTEXT_FACTORY_CLASS_NAME_PROPERTY = 058 "org.jomc.modlet.ModelContextFactory"; 059 060 /** 061 * Creates a new {@code ModelContextFactory} instance. 062 */ 063 protected ModelContextFactory() 064 { 065 super(); 066 } 067 068 /** 069 * Creates a new {@code ModelContextFactory} instance. 070 * <p> 071 * The name of the class providing the {@code ModelContextFactory} implementation loaded by this method is 072 * controlled by system property {@code org.jomc.modlet.ModelContextFactory}. If that property is not set, this 073 * methods returns a new default instance. 074 * </p> 075 * 076 * @return A new {@code ModelContextFactory} instance. 077 * 078 * @throws ModelContextFactoryError if creating a new instance fails. 079 */ 080 public static ModelContextFactory newInstance() throws ModelContextFactoryError 081 { 082 return newInstance( AccessController.doPrivileged( new PrivilegedAction<String>() 083 { 084 085 public String run() 086 { 087 return System.getProperty( MODEL_CONTEXT_FACTORY_CLASS_NAME_PROPERTY, 088 DEFAULT_MODEL_CONTEXT_FACTORY_CLASS_NAME ); 089 090 } 091 092 } ) ); 093 } 094 095 /** 096 * Creates a new {@code ModelContextFactory} instance. 097 * 098 * @param factoryClassName The name of the {@code ModelContextFactory} class to create an instance of. 099 * 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}