001/* 002 The Injector class is responsible for loading implementation based on a 003 interface. 004 005 Copyright (c) 2011-2018 The Regents of the University of California. 006 All rights reserved. 007 Permission is hereby granted, without written agreement and without 008 license or royalty fees, to use, copy, modify, and distribute this 009 software and its documentation for any purpose, provided that the above 010 copyright notice and the following two paragraphs appear in all copies 011 of this software. 012 013 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 014 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 015 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 016 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 017 SUCH DAMAGE. 018 019 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 020 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 021 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 022 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 023 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 024 ENHANCEMENTS, OR MODIFICATIONS. 025 026 PT_COPYRIGHT_VERSION_2 027 COPYRIGHTENDKEY 028 */ 029 030package ptolemy.actor.injection; 031 032import java.util.HashMap; 033 034/////////////////////////////////////////////////////////////////// 035//// Injector 036/** 037 * The Injector class is responsible for loading implementation based 038 * on a interface. The mappings from the interface to implementation 039 * must be loaded prior to that. 040 * 041 * @author Anar Huseynov, Erwin de Ley 042 * @version $Id$ 043 * @since Ptolemy II 10.0 044 * @Pt.ProposedRating Red (ahuseyno) 045 * @Pt.AcceptedRating Red (ahuseyno) 046 */ 047public class Injector { 048 049 /////////////////////////////////////////////////////////////////// 050 //// public methods //// 051 052 /** 053 * Get implementation for the provided interface based on the 054 * mappings loaded into the injector. 055 * Class<T> is the implementation. 056 * 057 * @param type The interface type to load. 058 * @return The implementation of the interface. 059 */ 060 public <T> T getInstance(Class<T> type) { 061 Class<T> implementation = (Class<T>) _resolvedInterfaceToImplementationMap 062 .get(type); 063 if (implementation != null) { 064 try { 065 return implementation.newInstance(); 066 } catch (InstantiationException e) { 067 throw new IllegalStateException( 068 "Problem instantiating type " + implementation, e); 069 } catch (IllegalAccessException e) { 070 throw new IllegalStateException( 071 "Problem instantiating type " + implementation, e); 072 } 073 } else { 074 try { 075 PtolemyModule module = _interfaceToImplementationMap 076 .get(type.getName()); 077 String implementationName = module.getBindings() 078 .get(type.getName()); 079 ClassLoader loader = module.getClassLoader() != null 080 ? module.getClassLoader() 081 : getClass().getClassLoader(); 082 if (implementationName != null) { 083 try { 084 Class<?> implementationClass = loader 085 .loadClass(implementationName); 086 _resolvedInterfaceToImplementationMap.put(type, 087 implementationClass); 088 return (T) implementationClass.newInstance(); 089 } catch (ClassNotFoundException e) { 090 throw new IllegalStateException( 091 "Problem loading type " + implementationName, 092 e); 093 } catch (InstantiationException e) { 094 throw new IllegalStateException( 095 "Problem instantiating type " 096 + implementationName, 097 e); 098 } catch (IllegalAccessException e) { 099 throw new IllegalStateException( 100 "Problem instantiating type " 101 + implementationName, 102 e); 103 } 104 } 105 } catch (NullPointerException e) { 106 // skip, the exception is thrown below 107 } 108 } 109 throw new IllegalStateException("Implementation for the interface " 110 + type + " was not found. " + "Perhaps\n" + type.getName() + "=" 111 + type.getName() 112 + "\nneeds to be added to the implementations class mappings file ptolemy/actor/*.properties such as ptolemy/actor/ActorModule.properties or some other injector file."); 113 114 } 115 116 /** 117 * Load the interface to implementation mappings into the injector. 118 * 119 * @param module The interface to implementation mapping. 120 */ 121 public void loadMappings(PtolemyModule module) { 122 for (String interfaceType : module.getBindings().keySet()) { 123 _interfaceToImplementationMap.put(interfaceType, module); 124 } 125 } 126 127 /////////////////////////////////////////////////////////////////// 128 //// private variables //// 129 /** 130 * The resolved interface to the implementation class mappings. 131 */ 132 private HashMap<Class<?>, Class<?>> _resolvedInterfaceToImplementationMap = new HashMap<Class<?>, Class<?>>(); 133 134 /** 135 * The resolved interface to the implementation class mappings. 136 */ 137 private HashMap<String, PtolemyModule> _interfaceToImplementationMap = new HashMap<String, PtolemyModule>(); 138}