/** * Copyright 2006-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.mybatis.generator.internal; import static org.mybatis.generator.internal.util.StringUtility.stringHasValue; import static org.mybatis.generator.internal.util.messages.Messages.getString; import java.net.URL; import java.util.ArrayList; import java.util.List; import org.mybatis.generator.api.CommentGenerator; import org.mybatis.generator.api.ConnectionFactory; import org.mybatis.generator.api.FullyQualifiedTable; import org.mybatis.generator.api.JavaFormatter; import org.mybatis.generator.api.Plugin; import org.mybatis.generator.api.IntrospectedColumn; import org.mybatis.generator.api.IntrospectedTable; import org.mybatis.generator.api.JavaTypeResolver; import org.mybatis.generator.api.XmlFormatter; import org.mybatis.generator.api.dom.DefaultJavaFormatter; import org.mybatis.generator.api.dom.DefaultXmlFormatter; import org.mybatis.generator.codegen.ibatis2.IntrospectedTableIbatis2Java2Impl; import org.mybatis.generator.codegen.ibatis2.IntrospectedTableIbatis2Java5Impl; import org.mybatis.generator.codegen.mybatis3.IntrospectedTableMyBatis3Impl; import org.mybatis.generator.codegen.mybatis3.IntrospectedTableMyBatis3SimpleImpl; import org.mybatis.generator.config.CommentGeneratorConfiguration; import org.mybatis.generator.config.ConnectionFactoryConfiguration; import org.mybatis.generator.config.Context; import org.mybatis.generator.config.PluginConfiguration; import org.mybatis.generator.config.JavaTypeResolverConfiguration; import org.mybatis.generator.config.PropertyRegistry; import org.mybatis.generator.config.TableConfiguration; import org.mybatis.generator.internal.types.JavaTypeResolverDefaultImpl; /** * This class creates the different objects needed by the generator. * * @author Jeff Butler */ public class ObjectFactory { /** The external class loaders. */ private static List<ClassLoader> externalClassLoaders; /** The resource class loaders. */ private static List<ClassLoader> resourceClassLoaders; static { externalClassLoaders = new ArrayList<ClassLoader>(); resourceClassLoaders = new ArrayList<ClassLoader>(); } /** * Utility class. No instances allowed */ private ObjectFactory() { super(); } /** * Clears the class loaders. This method should be called at the beginning of * a generation run so that and change to the classloading configuration * will be reflected. For example, if the eclipse launcher changes configuration * it might not be updated if eclipse hasn't been restarted. * */ public static void reset() { externalClassLoaders.clear(); resourceClassLoaders.clear(); } /** * Adds a custom classloader to the collection of classloaders searched for resources. Currently, this is only used * when searching for properties files that may be referenced in the configuration file. * * @param classLoader * the class loader */ public static synchronized void addResourceClassLoader( ClassLoader classLoader) { ObjectFactory.resourceClassLoaders.add(classLoader); } /** * Adds a custom classloader to the collection of classloaders searched for "external" classes. These are classes * that do not depend on any of the generator's classes or interfaces. Examples are JDBC drivers, root classes, root * interfaces, etc. * * @param classLoader * the class loader */ public static synchronized void addExternalClassLoader( ClassLoader classLoader) { ObjectFactory.externalClassLoaders.add(classLoader); } /** * This method returns a class loaded from the context classloader, or the classloader supplied by a client. This is * appropriate for JDBC drivers, model root classes, etc. It is not appropriate for any class that extends one of * the supplied classes or interfaces. * * @param type * the type * @return the Class loaded from the external classloader * @throws ClassNotFoundException * the class not found exception */ public static Class<?> externalClassForName(String type) throws ClassNotFoundException { Class<?> clazz; for (ClassLoader classLoader : externalClassLoaders) { try { clazz = Class.forName(type, true, classLoader); return clazz; } catch (Throwable e) { // ignore - fail safe below } } return internalClassForName(type); } /** * Creates a new Object object. * * @param type * the type * @return the object */ public static Object createExternalObject(String type) { Object answer; try { Class<?> clazz = externalClassForName(type); answer = clazz.newInstance(); } catch (Exception e) { throw new RuntimeException(getString( "RuntimeError.6", type), e); //$NON-NLS-1$ } return answer; } /** * Internal class for name. * * @param type * the type * @return the class * @throws ClassNotFoundException * the class not found exception */ public static Class<?> internalClassForName(String type) throws ClassNotFoundException { Class<?> clazz = null; try { ClassLoader cl = Thread.currentThread().getContextClassLoader(); clazz = Class.forName(type, true, cl); } catch (Exception e) { // ignore - failsafe below } if (clazz == null) { clazz = Class.forName(type, true, ObjectFactory.class.getClassLoader()); } return clazz; } /** * Gets the resource. * * @param resource * the resource * @return the resource */ public static URL getResource(String resource) { URL url; for (ClassLoader classLoader : resourceClassLoaders) { url = classLoader.getResource(resource); if (url != null) { return url; } } ClassLoader cl = Thread.currentThread().getContextClassLoader(); url = cl.getResource(resource); if (url == null) { url = ObjectFactory.class.getClassLoader().getResource(resource); } return url; } /** * Creates a new Object object. * * @param type * the type * @return the object */ public static Object createInternalObject(String type) { Object answer; try { Class<?> clazz = internalClassForName(type); answer = clazz.newInstance(); } catch (Exception e) { throw new RuntimeException(getString( "RuntimeError.6", type), e); //$NON-NLS-1$ } return answer; } /** * Creates a new Object object. * * @param context * the context * @param warnings * the warnings * @return the java type resolver */ public static JavaTypeResolver createJavaTypeResolver(Context context, List<String> warnings) { JavaTypeResolverConfiguration config = context .getJavaTypeResolverConfiguration(); String type; if (config != null && config.getConfigurationType() != null) { type = config.getConfigurationType(); if ("DEFAULT".equalsIgnoreCase(type)) { //$NON-NLS-1$ type = JavaTypeResolverDefaultImpl.class.getName(); } } else { type = JavaTypeResolverDefaultImpl.class.getName(); } JavaTypeResolver answer = (JavaTypeResolver) createInternalObject(type); answer.setWarnings(warnings); if (config != null) { answer.addConfigurationProperties(config.getProperties()); } answer.setContext(context); return answer; } /** * Creates a new Object object. * * @param context * the context * @param pluginConfiguration * the plugin configuration * @return the plugin */ public static Plugin createPlugin(Context context, PluginConfiguration pluginConfiguration) { Plugin plugin = (Plugin) createInternalObject(pluginConfiguration .getConfigurationType()); plugin.setContext(context); plugin.setProperties(pluginConfiguration.getProperties()); return plugin; } /** * Creates a new Object object. * * @param context * the context * @return the comment generator */ public static CommentGenerator createCommentGenerator(Context context) { CommentGeneratorConfiguration config = context .getCommentGeneratorConfiguration(); CommentGenerator answer; String type; if (config == null || config.getConfigurationType() == null) { type = DefaultCommentGenerator.class.getName(); } else { type = config.getConfigurationType(); } answer = (CommentGenerator) createInternalObject(type); if (config != null) { answer.addConfigurationProperties(config.getProperties()); } return answer; } public static ConnectionFactory createConnectionFactory(Context context) { ConnectionFactoryConfiguration config = context .getConnectionFactoryConfiguration(); ConnectionFactory answer; String type; if (config == null || config.getConfigurationType() == null) { type = JDBCConnectionFactory.class.getName(); } else { type = config.getConfigurationType(); } answer = (ConnectionFactory) createInternalObject(type); if (config != null) { answer.addConfigurationProperties(config.getProperties()); } return answer; } /** * Creates a new Object object. * * @param context * the context * @return the java formatter */ public static JavaFormatter createJavaFormatter(Context context) { String type = context.getProperty(PropertyRegistry.CONTEXT_JAVA_FORMATTER); if (!stringHasValue(type)) { type = DefaultJavaFormatter.class.getName(); } JavaFormatter answer = (JavaFormatter) createInternalObject(type); answer.setContext(context); return answer; } /** * Creates a new Object object. * * @param context * the context * @return the xml formatter */ public static XmlFormatter createXmlFormatter(Context context) { String type = context.getProperty(PropertyRegistry.CONTEXT_XML_FORMATTER); if (!stringHasValue(type)) { type = DefaultXmlFormatter.class.getName(); } XmlFormatter answer = (XmlFormatter) createInternalObject(type); answer.setContext(context); return answer; } /** * Creates a new Object object. * * @param tableConfiguration * the table configuration * @param table * the table * @param context * the context * @return the introspected table */ public static IntrospectedTable createIntrospectedTable( TableConfiguration tableConfiguration, FullyQualifiedTable table, Context context) { IntrospectedTable answer = createIntrospectedTableForValidation(context); answer.setFullyQualifiedTable(table); answer.setTableConfiguration(tableConfiguration); return answer; } /** * This method creates an introspected table implementation that is only usable for validation (i.e. for a context * to determine if the target is ibatis2 or mybatis3). * * * @param context * the context * @return the introspected table */ public static IntrospectedTable createIntrospectedTableForValidation(Context context) { String type = context.getTargetRuntime(); if (!stringHasValue(type)) { type = IntrospectedTableMyBatis3Impl.class.getName(); } else if ("Ibatis2Java2".equalsIgnoreCase(type)) { //$NON-NLS-1$ type = IntrospectedTableIbatis2Java2Impl.class.getName(); } else if ("Ibatis2Java5".equalsIgnoreCase(type)) { //$NON-NLS-1$ type = IntrospectedTableIbatis2Java5Impl.class.getName(); } else if ("Ibatis3".equalsIgnoreCase(type)) { //$NON-NLS-1$ type = IntrospectedTableMyBatis3Impl.class.getName(); } else if ("MyBatis3".equalsIgnoreCase(type)) { //$NON-NLS-1$ type = IntrospectedTableMyBatis3Impl.class.getName(); } else if ("MyBatis3Simple".equalsIgnoreCase(type)) { //$NON-NLS-1$ type = IntrospectedTableMyBatis3SimpleImpl.class.getName(); } IntrospectedTable answer = (IntrospectedTable) createInternalObject(type); answer.setContext(context); return answer; } /** * Creates a new Object object. * * @param context * the context * @return the introspected column */ public static IntrospectedColumn createIntrospectedColumn(Context context) { String type = context.getIntrospectedColumnImpl(); if (!stringHasValue(type)) { type = IntrospectedColumn.class.getName(); } IntrospectedColumn answer = (IntrospectedColumn) createInternalObject(type); answer.setContext(context); return answer; } }