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