/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.isis.core.commons.factory; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import org.apache.isis.core.commons.ensure.Assert; import org.apache.isis.core.commons.lang.ObjectExtensions; public final class InstanceUtil { private InstanceUtil() { } public static Object createInstance(final String className, Object... args) { return createInstance(className, (Class<?>) null, null, args); } public static Object createInstance(final Class<?> cls, Object... args) { return createInstance(cls, (Class<?>) null, null, args); } public static <T> T createInstance(final String className, final Class<T> requiredClass, Object... args) { return createInstance(className, (Class<T>) null, requiredClass, args); } public static <T> T createInstance(final Class<?> cls, final Class<T> requiredClass, Object... args) { return createInstance(cls, (Class<T>) null, requiredClass, args); } public static <T> T createInstance( final String className, final String defaultTypeName, final Class<T> requiredType, Object... args) { Class<? extends T> defaultType = null; if (defaultTypeName != null) { try { defaultType = ObjectExtensions.asT(Thread.currentThread().getContextClassLoader().loadClass(defaultTypeName)); if (defaultType == null) { throw new InstanceCreationClassException(String.format("Failed to load default type '%s'", defaultTypeName)); } } catch (final ClassNotFoundException e) { throw new UnavailableClassException(String.format("The default type '%s' cannot be found", defaultTypeName)); } catch (final NoClassDefFoundError e) { throw new InstanceCreationClassException(String.format("Default type '%s' found, but is missing a dependent class: %s", defaultTypeName, e.getMessage()), e); } } return createInstance(className, defaultType, requiredType, args); } public static <T> T createInstance( final Class<?> cls, final String defaultTypeName, final Class<T> requiredType, Object... args) { Class<? extends T> defaultType = null; if (defaultTypeName != null) { defaultType = loadClass(defaultTypeName, requiredType); try { defaultType = ObjectExtensions.asT(Thread.currentThread().getContextClassLoader().loadClass(defaultTypeName)); if (defaultType == null) { throw new InstanceCreationClassException(String.format("Failed to load default type '%s'", defaultTypeName)); } } catch (final ClassNotFoundException e) { throw new UnavailableClassException(String.format("The default type '%s' cannot be found", defaultTypeName)); } catch (final NoClassDefFoundError e) { throw new InstanceCreationClassException(String.format("Default type '%s' found, but is missing a dependent class: %s", defaultTypeName, e.getMessage()), e); } } return createInstance(cls, defaultType, requiredType, args); } public static <T> T createInstance( final String className, final Class<? extends T> defaultType, final Class<T> requiredType, Object... args) { Assert.assertNotNull("Class to instantiate must be specified", className); try { final Class<?> cls = Thread.currentThread().getContextClassLoader().loadClass(className); if (cls == null) { throw new InstanceCreationClassException(String.format("Failed to load class '%s'", className)); } return createInstance(cls, defaultType, requiredType, args); } catch (final ClassNotFoundException e) { if (className.indexOf('.') == -1) { throw new UnavailableClassException(String.format("The component '%s' cannot be found", className)); } throw new UnavailableClassException(String.format("The class '%s' cannot be found", className)); } catch (final NoClassDefFoundError e) { throw new InstanceCreationClassException(String.format("Class '%s' found , but is missing a dependent class: %s", className, e.getMessage()), e); } } public static <T> T createInstance( final Class<?> cls, final Class<? extends T> defaultType, final Class<T> requiredType, Object... args) { Assert.assertNotNull("Class to instantiate must be specified", cls); try { if (requiredType == null || requiredType.isAssignableFrom(cls)) { final Class<T> tClass = ObjectExtensions.asT(cls); if(args == null || args.length == 0) { return tClass.newInstance(); } else { Class<?>[] paramTypes = new Class[args.length]; for (int i = 0; i < args.length; i++) { final Object arg = args[i]; paramTypes[i] = arg.getClass(); } final Constructor<T> constructor = tClass.getConstructor(paramTypes); return constructor.newInstance(args); } } else { throw new InstanceCreationClassException(String.format("Class '%s' is not of type '%s'", cls.getName(), requiredType)); } } catch (final NoClassDefFoundError e) { throw new InstanceCreationClassException(String.format("Class '%s'found , but is missing a dependent class: %s", cls, e.getMessage()), e); } catch (final InstantiationException | InvocationTargetException e) { throw new InstanceCreationException(String.format("Could not instantiate an object of class '%s'; %s", cls.getName(), e.getMessage()), e); } catch (final IllegalAccessException e) { throw new InstanceCreationException(String.format("Could not access the class '%s'; %s", cls.getName(), e.getMessage()), e); } catch (NoSuchMethodException e) { throw new InstanceCreationException(String.format("Could not find constructor in the class '%s'; %s", cls.getName(), e.getMessage()), e); } } public static Class<?> loadClass(final String className) { Assert.assertNotNull("Class to instantiate must be specified", className); try { return Thread.currentThread().getContextClassLoader().loadClass(className); } catch (final ClassNotFoundException e) { throw new UnavailableClassException(String.format("The type '%s' cannot be found", className)); } catch (final NoClassDefFoundError e) { throw new InstanceCreationClassException(String.format("Type '%s' found, but is missing a dependent class: %s", className, e.getMessage()), e); } } public static <R, T extends R> Class<T> loadClass(final String className, final Class<R> requiredType) { Assert.assertNotNull("Class to instantiate must be specified", className); try { final Class<?> loadedClass = loadClass(className); if (requiredType != null && !requiredType.isAssignableFrom(loadedClass)) { throw new InstanceCreationClassException("Class '" + className + "' is not of type '" + requiredType + "'"); } return ObjectExtensions.asT(loadedClass); } catch (final NoClassDefFoundError e) { throw new InstanceCreationClassException(String.format("Default type '%s' found, but is missing a dependent class: %s", className, e.getMessage()), e); } } }