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.HashMap; 018 import java.util.Map; 019 020 import org.apache.hivemind.ApplicationRuntimeException; 021 import org.apache.hivemind.ClassResolver; 022 import org.apache.hivemind.Resource; 023 import org.apache.hivemind.util.ClasspathResource; 024 import org.apache.tapestry.INamespace; 025 import org.apache.tapestry.asset.AssetSource; 026 import org.apache.tapestry.engine.ISpecificationSource; 027 import org.apache.tapestry.engine.Namespace; 028 import org.apache.tapestry.event.ResetEventListener; 029 import org.apache.tapestry.parse.ISpecificationParser; 030 import org.apache.tapestry.services.NamespaceResources; 031 import org.apache.tapestry.spec.IApplicationSpecification; 032 import org.apache.tapestry.spec.IComponentSpecification; 033 import org.apache.tapestry.spec.ILibrarySpecification; 034 import org.apache.tapestry.spec.LibrarySpecification; 035 import org.apache.tapestry.util.xml.DocumentParseException; 036 037 /** 038 * Default implementation of {@link ISpecificationSource} that expects to use the normal class 039 * loader to locate component specifications from within the classpath. 040 * <p> 041 * Caches specifications in memory forever, or until {@link #resetDidOccur()()} is invoked. 042 * 043 * @author Howard Lewis Ship 044 */ 045 046 public class SpecificationSourceImpl implements ISpecificationSource, ResetEventListener 047 { 048 private ClassResolver _classResolver; 049 050 private IApplicationSpecification _specification; 051 052 private ISpecificationParser _parser; 053 054 private NamespaceResources _namespaceResources; 055 056 private INamespace _applicationNamespace; 057 058 private INamespace _frameworkNamespace; 059 060 private AssetSource _assetSource; 061 062 /** 063 * Contains previously parsed component specifications. 064 */ 065 066 private Map _componentCache = new HashMap(); 067 068 /** 069 * Contains previously parsed page specifications. 070 * 071 * @since 2.2 072 */ 073 074 private Map _pageCache = new HashMap(); 075 076 /** 077 * Contains previously parsed library specifications, keyed on specification resource path. 078 * 079 * @since 2.2 080 */ 081 082 private Map _libraryCache = new HashMap(); 083 084 /** 085 * Contains {@link INamespace} instances, keyed on id (which will be null for the application 086 * specification). 087 */ 088 089 private Map _namespaceCache = new HashMap(); 090 091 public void initializeService() 092 { 093 _namespaceResources = new NamespaceResourcesImpl(this, _assetSource); 094 } 095 096 /** 097 * Clears the specification cache. This is used during debugging. 098 */ 099 100 public synchronized void resetEventDidOccur() 101 { 102 _componentCache.clear(); 103 _pageCache.clear(); 104 _libraryCache.clear(); 105 _namespaceCache.clear(); 106 107 _applicationNamespace = null; 108 _frameworkNamespace = null; 109 } 110 111 protected IComponentSpecification parseSpecification(Resource resource, boolean asPage) 112 { 113 IComponentSpecification result = null; 114 115 try 116 { 117 if (asPage) 118 result = _parser.parsePageSpecification(resource); 119 else 120 result = _parser.parseComponentSpecification(resource); 121 } 122 catch (DocumentParseException ex) 123 { 124 throw new ApplicationRuntimeException( 125 ImplMessages.unableToParseSpecification(resource), ex); 126 } 127 128 return result; 129 } 130 131 protected ILibrarySpecification parseLibrarySpecification(Resource resource) 132 { 133 try 134 { 135 return _parser.parseLibrarySpecification(resource); 136 } 137 catch (DocumentParseException ex) 138 { 139 throw new ApplicationRuntimeException( 140 ImplMessages.unableToParseSpecification(resource), ex); 141 } 142 143 } 144 145 /** 146 * Gets a component specification. 147 * 148 * @param resourcePath 149 * the complete resource path to the specification. 150 * @throws ApplicationRuntimeException 151 * if the specification cannot be obtained. 152 */ 153 154 public synchronized IComponentSpecification getComponentSpecification(Resource resourceLocation) 155 { 156 IComponentSpecification result = (IComponentSpecification) _componentCache 157 .get(resourceLocation); 158 159 if (result == null) 160 { 161 result = parseSpecification(resourceLocation, false); 162 163 _componentCache.put(resourceLocation, result); 164 } 165 166 return result; 167 } 168 169 public synchronized IComponentSpecification getPageSpecification(Resource resourceLocation) 170 { 171 IComponentSpecification result = (IComponentSpecification) _pageCache.get(resourceLocation); 172 173 if (result == null) 174 { 175 result = parseSpecification(resourceLocation, true); 176 177 _pageCache.put(resourceLocation, result); 178 } 179 180 return result; 181 } 182 183 public synchronized ILibrarySpecification getLibrarySpecification(Resource resourceLocation) 184 { 185 ILibrarySpecification result = (LibrarySpecification) _libraryCache.get(resourceLocation); 186 187 if (result == null) 188 { 189 result = parseLibrarySpecification(resourceLocation); 190 _libraryCache.put(resourceLocation, result); 191 } 192 193 return result; 194 } 195 196 public synchronized INamespace getApplicationNamespace() 197 { 198 if (_applicationNamespace == null) 199 _applicationNamespace = new Namespace(null, null, _specification, _namespaceResources); 200 201 return _applicationNamespace; 202 } 203 204 public synchronized INamespace getFrameworkNamespace() 205 { 206 if (_frameworkNamespace == null) 207 { 208 Resource resource = new ClasspathResource(_classResolver, 209 "/org/apache/tapestry/Framework.library"); 210 211 ILibrarySpecification ls = getLibrarySpecification(resource); 212 213 _frameworkNamespace = new Namespace(INamespace.FRAMEWORK_NAMESPACE, null, ls, 214 _namespaceResources); 215 } 216 217 return _frameworkNamespace; 218 } 219 220 public void setParser(ISpecificationParser parser) 221 { 222 _parser = parser; 223 } 224 225 public void setClassResolver(ClassResolver resolver) 226 { 227 _classResolver = resolver; 228 } 229 230 public void setSpecification(IApplicationSpecification specification) 231 { 232 _specification = specification; 233 } 234 235 public void setAssetSource(AssetSource assetSource) 236 { 237 _assetSource = assetSource; 238 } 239 }