001 // Copyright 2004, 2005 The Apache Software Foundation 002 // 003 // Licensed under the Apache License, Version 2.0 (the "License"); 004 // you may not use this file except in compliance with the License. 005 // You may obtain a copy of the License at 006 // 007 // http://www.apache.org/licenses/LICENSE-2.0 008 // 009 // Unless required by applicable law or agreed to in writing, software 010 // distributed under the License is distributed on an "AS IS" BASIS, 011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012 // See the License for the specific language governing permissions and 013 // limitations under the License. 014 015 package org.apache.hivemind.impl; 016 017 import java.lang.reflect.Constructor; 018 import java.util.HashMap; 019 import java.util.Iterator; 020 import java.util.List; 021 import java.util.Map; 022 023 import org.apache.commons.logging.Log; 024 import org.apache.commons.logging.LogFactory; 025 import org.apache.hivemind.ApplicationRuntimeException; 026 import org.apache.hivemind.ErrorHandler; 027 import org.apache.hivemind.Location; 028 import org.apache.hivemind.internal.RegistryInfrastructure; 029 import org.apache.hivemind.schema.Translator; 030 import org.apache.hivemind.schema.rules.ClassTranslator; 031 import org.apache.hivemind.schema.rules.InstanceTranslator; 032 import org.apache.hivemind.schema.rules.ServiceTranslator; 033 import org.apache.hivemind.schema.rules.SmartTranslator; 034 035 /** 036 * Manages translators for {@link org.apache.hivemind.impl.RegistryInfrastructureImpl}. 037 * 038 * @author Howard Lewis Ship 039 */ 040 public class TranslatorManager 041 { 042 static final Log LOG = LogFactory.getLog(TranslatorManager.class); 043 044 public static final String TRANSLATORS_CONFIGURATION_ID = "hivemind.Translators"; 045 046 private ErrorHandler _errorHandler; 047 048 private RegistryInfrastructure _registry; 049 050 /** 051 * Map of Class, keyed on translator name, used to instantiate new 052 * {@link org.apache.hivemind.schema.Translator}s. Loaded from the 053 * <code>hivemind.Translators</code> configuration point; 054 */ 055 private Map _translatorClasses = new HashMap(); 056 057 private Map _translatorsCache = new HashMap(); 058 059 private boolean _translatorsLoaded; 060 061 public TranslatorManager(RegistryInfrastructure registry, ErrorHandler errorHandler) 062 { 063 _registry = registry; 064 _errorHandler = errorHandler; 065 066 // Seed the basic translators used to "bootstrap" the 067 // processing of the hivemind.Translators configuration point. 068 069 _translatorsCache.put("class", new ClassTranslator()); 070 _translatorsCache.put("service", new ServiceTranslator()); 071 _translatorsCache.put("smart", new SmartTranslator()); 072 _translatorsCache.put("instance", new InstanceTranslator()); 073 074 // smart may take an initializer, so we need to put it into the classes as 075 // well. 076 077 _translatorClasses.put("smart", SmartTranslator.class); 078 079 } 080 081 public synchronized Translator getTranslator(String constructor) 082 { 083 // The cache is preloaded with the hardcoded translators. 084 085 if (!_translatorsLoaded && !_translatorsCache.containsKey(constructor)) 086 loadTranslators(); 087 088 Translator result = (Translator) _translatorsCache.get(constructor); 089 090 if (result == null) 091 { 092 result = constructTranslator(constructor); 093 _translatorsCache.put(constructor, result); 094 } 095 096 return result; 097 } 098 099 private Translator constructTranslator(String constructor) 100 { 101 String name = constructor; 102 String initializer = null; 103 104 int commax = constructor.indexOf(','); 105 106 if (commax > 0) 107 { 108 name = constructor.substring(0, commax); 109 initializer = constructor.substring(commax + 1); 110 } 111 112 Class translatorClass = findTranslatorClass(name); 113 114 // TODO: check for null class, meaning that the translator is a service. 115 116 return createTranslator(translatorClass, initializer); 117 } 118 119 private Translator createTranslator(Class translatorClass, String initializer) 120 { 121 try 122 { 123 124 if (initializer == null) 125 return (Translator) translatorClass.newInstance(); 126 127 Constructor c = translatorClass.getConstructor(new Class[] 128 { String.class }); 129 130 return (Translator) c.newInstance(new Object[] 131 { initializer }); 132 } 133 catch (Exception ex) 134 { 135 throw new ApplicationRuntimeException(ImplMessages.translatorInstantiationFailure( 136 translatorClass, 137 ex), ex); 138 } 139 } 140 141 private Class findTranslatorClass(String translatorName) 142 { 143 Class result = (Class) _translatorClasses.get(translatorName); 144 145 if (result == null) 146 throw new ApplicationRuntimeException(ImplMessages.unknownTranslatorName( 147 translatorName, 148 TRANSLATORS_CONFIGURATION_ID)); 149 150 return result; 151 } 152 153 private void loadTranslators() 154 { 155 // Prevent endless recursion! 156 157 _translatorsLoaded = true; 158 159 List contributions = _registry.getConfiguration(TRANSLATORS_CONFIGURATION_ID, null); 160 161 Map locations = new HashMap(); 162 locations.put("class", null); 163 164 Iterator i = contributions.iterator(); 165 while (i.hasNext()) 166 { 167 TranslatorContribution c = (TranslatorContribution) i.next(); 168 169 String name = c.getName(); 170 Location oldLocation = (Location) locations.get(name); 171 172 if (oldLocation != null) 173 { 174 _errorHandler.error(LOG, ImplMessages.duplicateTranslatorName(name, oldLocation), c 175 .getLocation(), null); 176 177 continue; 178 } 179 180 locations.put(name, c.getLocation()); 181 182 Translator t = c.getTranslator(); 183 184 if (t != null) 185 { 186 _translatorsCache.put(name, t); 187 continue; 188 } 189 190 Class tClass = c.getTranslatorClass(); 191 192 if (tClass == null) 193 { 194 _errorHandler.error( 195 LOG, 196 ImplMessages.incompleteTranslator(c), 197 c.getLocation(), 198 null); 199 continue; 200 } 201 202 _translatorClasses.put(name, tClass); 203 } 204 205 } 206 207 }