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