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.Iterator;
019    import java.util.List;
020    import java.util.Locale;
021    import java.util.Map;
022    
023    import org.apache.hivemind.ApplicationRuntimeException;
024    import org.apache.hivemind.ClassResolver;
025    import org.apache.hivemind.ErrorLog;
026    import org.apache.hivemind.Resource;
027    import org.apache.hivemind.service.ThreadLocale;
028    import org.apache.hivemind.util.Defense;
029    import org.apache.tapestry.IRequestCycle;
030    import org.apache.tapestry.asset.AssetFactory;
031    import org.apache.tapestry.coerce.ValueConverter;
032    import org.apache.tapestry.describe.HTMLDescriber;
033    import org.apache.tapestry.engine.IPageSource;
034    import org.apache.tapestry.engine.IPropertySource;
035    import org.apache.tapestry.engine.IScriptSource;
036    import org.apache.tapestry.engine.ISpecificationSource;
037    import org.apache.tapestry.engine.state.ApplicationStateManager;
038    import org.apache.tapestry.error.ExceptionPresenter;
039    import org.apache.tapestry.error.RequestExceptionReporter;
040    import org.apache.tapestry.error.StaleLinkExceptionPresenter;
041    import org.apache.tapestry.error.StaleSessionExceptionPresenter;
042    import org.apache.tapestry.listener.ListenerInvoker;
043    import org.apache.tapestry.listener.ListenerMapSource;
044    import org.apache.tapestry.markup.MarkupWriterSource;
045    import org.apache.tapestry.services.ClassFinder;
046    import org.apache.tapestry.services.ComponentMessagesSource;
047    import org.apache.tapestry.services.ComponentPropertySource;
048    import org.apache.tapestry.services.CookieSource;
049    import org.apache.tapestry.services.DataSqueezer;
050    import org.apache.tapestry.services.Infrastructure;
051    import org.apache.tapestry.services.LinkFactory;
052    import org.apache.tapestry.services.ObjectPool;
053    import org.apache.tapestry.services.RequestCycleFactory;
054    import org.apache.tapestry.services.ResetEventHub;
055    import org.apache.tapestry.services.ResponseRenderer;
056    import org.apache.tapestry.services.ServiceMap;
057    import org.apache.tapestry.services.TemplateSource;
058    import org.apache.tapestry.spec.IApplicationSpecification;
059    import org.apache.tapestry.web.WebContext;
060    import org.apache.tapestry.web.WebContextResource;
061    import org.apache.tapestry.web.WebRequest;
062    import org.apache.tapestry.web.WebResponse;
063    
064    /**
065     * Allows access to selected HiveMind services.
066     * 
067     * @author Howard Lewis Ship
068     * @since 4.0
069     */
070    public class InfrastructureImpl implements Infrastructure
071    {
072        /**
073         * List of {@link org.apache.tapestry.services.impl.InfrastructureContribution}.
074         */
075        private List _normalContributions;
076    
077        /**
078         * List of {@link org.apache.tapestry.services.impl.InfrastructureContribution}.
079         */
080        private List _overrideContributions;
081    
082        private Map _properties = new HashMap();
083    
084        private boolean _initialized;
085    
086        private String _mode;
087    
088        private ErrorLog _errorLog;
089    
090        private ClassResolver _classResolver;
091    
092        private ThreadLocale _threadLocale;
093    
094        public void setLocale(Locale locale)
095        {
096            _threadLocale.setLocale(locale);
097        }
098    
099        public String getApplicationId()
100        {
101            return (String) getProperty("applicationId");
102        }
103    
104        public IPropertySource getApplicationPropertySource()
105        {
106            return (IPropertySource) getProperty("applicationPropertySource");
107        }
108    
109        public IApplicationSpecification getApplicationSpecification()
110        {
111            return (IApplicationSpecification) getProperty("applicationSpecification");
112        }
113    
114        public ApplicationStateManager getApplicationStateManager()
115        {
116            return (ApplicationStateManager) getProperty("applicationStateManager");
117        }
118    
119        public ClassResolver getClassResolver()
120        {
121            return _classResolver;
122        }
123    
124        public ComponentMessagesSource getComponentMessagesSource()
125        {
126            return (ComponentMessagesSource) getProperty("componentMessagesSource");
127        }
128    
129        public ComponentPropertySource getComponentPropertySource()
130        {
131            return (ComponentPropertySource) getProperty("componentPropertySource");
132        }
133    
134        public String getContextPath()
135        {
136            return getRequest().getContextPath();
137        }
138    
139        public Resource getContextRoot()
140        {
141            WebContext context = (WebContext) getProperty("context");
142    
143            return new WebContextResource(context, "/");
144        }
145    
146        public DataSqueezer getDataSqueezer()
147        {
148            return (DataSqueezer) getProperty("dataSqueezer");
149        }
150    
151        public IPropertySource getGlobalPropertySource()
152        {
153            return (IPropertySource) getProperty("globalPropertySource");
154        }
155    
156        public LinkFactory getLinkFactory()
157        {
158            return (LinkFactory) getProperty("linkFactory");
159        }
160    
161        public ObjectPool getObjectPool()
162        {
163            return (ObjectPool) getProperty("objectPool");
164        }
165    
166        public IPageSource getPageSource()
167        {
168            return (IPageSource) getProperty("pageSource");
169        }
170    
171        public WebRequest getRequest()
172        {
173            return (WebRequest) getProperty("request");
174        }
175    
176        public RequestCycleFactory getRequestCycleFactory()
177        {
178            return (RequestCycleFactory) getProperty("requestCycleFactory");
179        }
180    
181        public RequestExceptionReporter getRequestExceptionReporter()
182        {
183            return (RequestExceptionReporter) getProperty("requestExceptionReporter");
184        }
185    
186        public ResetEventHub getResetEventHub()
187        {
188            return (ResetEventHub) getProperty("resetEventHub");
189        }
190    
191        public WebResponse getResponse()
192        {
193            return (WebResponse) getProperty("response");
194        }
195    
196        public ResponseRenderer getResponseRenderer()
197        {
198            return (ResponseRenderer) getProperty("responseRenderer");
199        }
200    
201        public IScriptSource getScriptSource()
202        {
203            return (IScriptSource) getProperty("scriptSource");
204        }
205    
206        public ServiceMap getServiceMap()
207        {
208            return (ServiceMap) getProperty("serviceMap");
209        }
210    
211        public ISpecificationSource getSpecificationSource()
212        {
213            return (ISpecificationSource) getProperty("specificationSource");
214        }
215    
216        public TemplateSource getTemplateSource()
217        {
218            return (TemplateSource) getProperty("templateSource");
219        }
220    
221        public String getOutputEncoding()
222        {
223            return getApplicationPropertySource().getPropertyValue(
224                    "org.apache.tapestry.output-encoding");
225        }
226    
227        public MarkupWriterSource getMarkupWriterSource()
228        {
229            return (MarkupWriterSource) getProperty("markupWriterSource");
230        }
231    
232        public HTMLDescriber getHTMLDescriber()
233        {
234            return (HTMLDescriber) getProperty("HTMLDescriber");
235        }
236    
237        public ExceptionPresenter getExceptionPresenter()
238        {
239            return (ExceptionPresenter) getProperty("exceptionPresenter");
240        }
241    
242        public ListenerMapSource getListenerMapSource()
243        {
244            return (ListenerMapSource) getProperty("listenerMapSource");
245        }
246    
247        public StaleSessionExceptionPresenter getStaleSessionExceptionPresenter()
248        {
249            return (StaleSessionExceptionPresenter) getProperty("staleSessionExceptionPresenter");
250        }
251    
252        public StaleLinkExceptionPresenter getStaleLinkExceptionPresenter()
253        {
254            return (StaleLinkExceptionPresenter) getProperty("staleLinkExceptionPresenter");
255        }
256    
257        public ValueConverter getValueConverter()
258        {
259            return (ValueConverter) getProperty("valueConverter");
260        }
261    
262        public ListenerInvoker getListenerInvoker()
263        {
264            return (ListenerInvoker) getProperty("listenerInvoker");
265        }
266    
267        public AssetFactory getAssetFactory()
268        {
269            return (AssetFactory) getProperty("assetFactory");
270        }
271    
272        public CookieSource getCookieSource()
273        {
274            return (CookieSource) getProperty("cookieSource");
275        }
276    
277        public ClassFinder getClassFinder()
278        {
279            return (ClassFinder) getProperty("classFinder");
280        }
281    
282        public IRequestCycle getRequestCycle()
283        {
284            return (IRequestCycle) getProperty("requestCycle");
285        }
286    
287        public Object getProperty(String propertyName)
288        {
289            Defense.notNull(propertyName, "propertyName");
290    
291            if (!_initialized)
292                throw new IllegalStateException(ImplMessages.infrastructureNotInitialized());
293    
294            Object result = _properties.get(propertyName);
295    
296            if (result == null)
297                throw new ApplicationRuntimeException(ImplMessages
298                        .missingInfrastructureProperty(propertyName));
299    
300            return result;
301        }
302    
303        public synchronized void initialize(String mode)
304        {
305            Defense.notNull(mode, "mode");
306    
307            if (_initialized)
308                throw new IllegalStateException(ImplMessages.infrastructureAlreadyInitialized(
309                        mode,
310                        _mode));
311    
312            Map normalByMode = buildMapFromContributions(_normalContributions, mode);
313            Map normal = buildMapFromContributions(_normalContributions, null);
314            Map overrideByMode = buildMapFromContributions(_overrideContributions, mode);
315            Map override = buildMapFromContributions(_overrideContributions, null);
316    
317            addToProperties(overrideByMode);
318            addToProperties(override);
319            addToProperties(normalByMode);
320            addToProperties(normal);
321    
322            _mode = mode;
323            _initialized = true;
324        }
325    
326        private Map buildMapFromContributions(List contributions, String mode)
327        {
328            Map result = new HashMap();
329    
330            Iterator i = contributions.iterator();
331            while (i.hasNext())
332            {
333                InfrastructureContribution ic = (InfrastructureContribution) i.next();
334    
335                if (!ic.matchesMode(mode))
336                    continue;
337    
338                String propertyName = ic.getProperty();
339    
340                InfrastructureContribution existing = (InfrastructureContribution) result
341                        .get(propertyName);
342    
343                if (existing != null)
344                {
345                    _errorLog.error(ImplMessages.duplicateInfrastructureContribution(ic, existing
346                            .getLocation()), ic.getLocation(), null);
347                    continue;
348                }
349    
350                result.put(propertyName, ic);
351            }
352    
353            return result;
354        }
355    
356        /**
357         * Adds to the master set of properties contributed objects that don't match an already existing
358         * key.
359         * 
360         * @param map
361         *            map of {@link org.apache.tapestry.services.impl.InfrastructureContribution}keyed
362         *            on property name (String).
363         */
364    
365        private void addToProperties(Map map)
366        {
367            Iterator i = map.values().iterator();
368            while (i.hasNext())
369            {
370                InfrastructureContribution ic = (InfrastructureContribution) i.next();
371                String propertyName = ic.getProperty();
372    
373                if (_properties.containsKey(propertyName))
374                    continue;
375    
376                _properties.put(propertyName, ic.getObject());
377            }
378        }
379    
380        public void setClassResolver(ClassResolver classResolver)
381        {
382            _classResolver = classResolver;
383        }
384    
385        public void setThreadLocale(ThreadLocale threadLocale)
386        {
387            _threadLocale = threadLocale;
388        }
389    
390        public void setNormalContributions(List normalContributions)
391        {
392            _normalContributions = normalContributions;
393        }
394    
395        public void setOverrideContributions(List overrideContributions)
396        {
397            _overrideContributions = overrideContributions;
398        }
399    
400        public void setErrorLog(ErrorLog errorLog)
401        {
402            _errorLog = errorLog;
403        }
404    }