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