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.tapestry.services.impl; 016 017 import java.util.Collections; 018 import java.util.HashMap; 019 import java.util.Map; 020 021 import org.apache.commons.logging.Log; 022 import org.apache.hivemind.ClassResolver; 023 import org.apache.hivemind.service.ClassFactory; 024 import org.apache.hivemind.util.Defense; 025 import org.apache.tapestry.enhance.EnhancedClassValidator; 026 import org.apache.tapestry.enhance.EnhancementOperationImpl; 027 import org.apache.tapestry.enhance.EnhancementWorker; 028 import org.apache.tapestry.event.ResetEventListener; 029 import org.apache.tapestry.services.ComponentConstructor; 030 import org.apache.tapestry.services.ComponentConstructorFactory; 031 import org.apache.tapestry.spec.IComponentSpecification; 032 033 /** 034 * Implementation of the {@link org.apache.tapestry.services.ComponentConstructorFactory} service 035 * interface. 036 * 037 * @author Howard M. Lewis Ship 038 * @since 4.0 039 */ 040 public class ComponentConstructorFactoryImpl implements ComponentConstructorFactory, 041 ResetEventListener 042 { 043 private Log _log; 044 045 private ClassFactory _classFactory; 046 047 private ClassResolver _classResolver; 048 049 private EnhancedClassValidator _validator; 050 051 private EnhancementWorker _chain; 052 053 /** 054 * Map of {@link org.apache.tapestry.services.ComponentConstructor}keyed on 055 * {@link org.apache.tapestry.spec.IComponentSpecification}. 056 */ 057 058 private Map _cachedConstructors = Collections.synchronizedMap(new HashMap()); 059 060 public void resetEventDidOccur() 061 { 062 _cachedConstructors.clear(); 063 } 064 065 public ComponentConstructor getComponentConstructor(IComponentSpecification specification, 066 String className) 067 { 068 Defense.notNull(specification, "specification"); 069 070 synchronized (specification) 071 { 072 ComponentConstructor result = (ComponentConstructor) _cachedConstructors 073 .get(specification); 074 075 if (result == null) 076 { 077 Class baseClass = _classResolver.findClass(className); 078 079 EnhancementOperationImpl eo = new EnhancementOperationImpl(_classResolver, 080 specification, baseClass, _classFactory, _log); 081 082 // Invoking on the chain is the same as invoking on every 083 // object in the chain (because method performEnhancement() is type void). 084 085 _chain.performEnhancement(eo, specification); 086 087 result = eo.getConstructor(); 088 089 // TODO: This should be optional to work around that IBM JVM bug. 090 091 _validator.validate(baseClass, result.getComponentClass(), specification); 092 093 _cachedConstructors.put(specification, result); 094 } 095 096 return result; 097 } 098 } 099 100 public void setClassFactory(ClassFactory classFactory) 101 { 102 _classFactory = classFactory; 103 } 104 105 public void setClassResolver(ClassResolver classResolver) 106 { 107 _classResolver = classResolver; 108 } 109 110 public void setValidator(EnhancedClassValidator validator) 111 { 112 _validator = validator; 113 } 114 115 public void setChain(EnhancementWorker chain) 116 { 117 _chain = chain; 118 } 119 120 public void setLog(Log log) 121 { 122 _log = log; 123 } 124 }