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