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 }