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 015package org.apache.tapestry.services.impl; 016 017import java.util.Collections; 018import java.util.HashMap; 019import java.util.Map; 020 021import org.apache.commons.logging.Log; 022import org.apache.hivemind.ClassResolver; 023import org.apache.hivemind.service.ClassFactory; 024import org.apache.hivemind.util.Defense; 025import org.apache.tapestry.enhance.EnhancedClassValidator; 026import org.apache.tapestry.enhance.EnhancementOperationImpl; 027import org.apache.tapestry.enhance.EnhancementWorker; 028import org.apache.tapestry.event.ReportStatusEvent; 029import org.apache.tapestry.event.ReportStatusListener; 030import org.apache.tapestry.event.ResetEventListener; 031import org.apache.tapestry.services.ComponentConstructor; 032import org.apache.tapestry.services.ComponentConstructorFactory; 033import 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 */ 042public 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}