001// Copyright 2008-2014 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
015package org.apache.tapestry5.internal.structure;
016
017import org.apache.tapestry5.ComponentResources;
018import org.apache.tapestry5.commons.*;
019import org.apache.tapestry5.commons.services.TypeCoercer;
020import org.apache.tapestry5.commons.util.CommonsUtils;
021import org.apache.tapestry5.http.Link;
022import org.apache.tapestry5.http.services.Request;
023import org.apache.tapestry5.http.services.RequestGlobals;
024import org.apache.tapestry5.internal.services.ComponentClassCache;
025import org.apache.tapestry5.internal.services.LinkSource;
026import org.apache.tapestry5.internal.services.RequestPageCache;
027import org.apache.tapestry5.ioc.IOOperation;
028import org.apache.tapestry5.ioc.Invokable;
029import org.apache.tapestry5.ioc.LoggerSource;
030import org.apache.tapestry5.ioc.OperationTracker;
031import org.apache.tapestry5.ioc.services.PerThreadValue;
032import org.apache.tapestry5.ioc.services.PerthreadManager;
033import org.apache.tapestry5.model.ComponentModel;
034import org.apache.tapestry5.services.ComponentClassResolver;
035import org.apache.tapestry5.services.ContextValueEncoder;
036import org.apache.tapestry5.services.messages.ComponentMessagesSource;
037import org.apache.tapestry5.services.pageload.ComponentResourceSelector;
038import org.slf4j.Logger;
039
040import java.io.IOException;
041
042public class ComponentPageElementResourcesImpl implements ComponentPageElementResources
043{
044    private final ComponentResourceSelector selector;
045
046    private final ComponentMessagesSource componentMessagesSource;
047
048    private final TypeCoercer typeCoercer;
049
050    private final ComponentClassCache componentClassCache;
051
052    private final ContextValueEncoder contextValueEncoder;
053
054    private final LinkSource linkSource;
055
056    private final RequestPageCache requestPageCache;
057
058    private final ComponentClassResolver componentClassResolver;
059
060    private final LoggerSource loggerSource;
061
062    private final OperationTracker tracker;
063
064    private final PerthreadManager perThreadManager;
065
066    private final boolean productionMode, componentTracingEnabled;
067
068    private final RequestGlobals requestGlobals;
069
070    public ComponentPageElementResourcesImpl(ComponentResourceSelector selector,
071                                             ComponentMessagesSource componentMessagesSource, TypeCoercer typeCoercer,
072                                             ComponentClassCache componentClassCache, ContextValueEncoder contextValueEncoder, LinkSource linkSource,
073                                             RequestPageCache requestPageCache, ComponentClassResolver componentClassResolver,
074                                             LoggerSource loggerSource, OperationTracker tracker, PerthreadManager perThreadManager, boolean productionMode, boolean componentTracingEnabled, RequestGlobals requestGlobals)
075    {
076        this.selector = selector;
077        this.componentMessagesSource = componentMessagesSource;
078        this.typeCoercer = typeCoercer;
079        this.componentClassCache = componentClassCache;
080        this.contextValueEncoder = contextValueEncoder;
081        this.linkSource = linkSource;
082        this.requestPageCache = requestPageCache;
083        this.componentClassResolver = componentClassResolver;
084        this.loggerSource = loggerSource;
085        this.tracker = tracker;
086        this.perThreadManager = perThreadManager;
087        this.productionMode = productionMode;
088        this.componentTracingEnabled = componentTracingEnabled;
089        this.requestGlobals = requestGlobals;
090    }
091
092    public ComponentResourceSelector getSelector()
093    {
094        return selector;
095    }
096
097    public Messages getMessages(ComponentModel componentModel)
098    {
099        return componentMessagesSource.getMessages(componentModel, selector);
100    }
101
102    public <S, T> T coerce(S input, Class<T> targetType)
103    {
104        return typeCoercer.coerce(input, targetType);
105    }
106
107    public Class toClass(String className)
108    {
109        return componentClassCache.forName(className);
110    }
111
112    public Link createComponentEventLink(ComponentResources resources, String eventType, boolean forForm,
113                                         Object... context)
114    {
115        Page page = requestPageCache.get(resources.getPageName());
116
117        return linkSource.createComponentEventLink(page, resources.getNestedId(), eventType, forForm,
118                defaulted(context));
119    }
120
121    public Link createPageRenderLink(String pageName, boolean override, Object... context)
122    {
123        return linkSource.createPageRenderLink(pageName, override, defaulted(context));
124    }
125
126    public Link createPageRenderLink(Class pageClass, boolean override, Object... context)
127    {
128        assert pageClass != null;
129        String pageName = componentClassResolver.resolvePageClassNameToPageName(pageClass.getName());
130
131        return linkSource.createPageRenderLink(pageName, override, defaulted(context));
132    }
133
134    public Logger getEventLogger(Logger componentLogger)
135    {
136        String name = "tapestry.events." + componentLogger.getName();
137
138        return loggerSource.getLogger(name);
139    }
140
141    public String toClient(Object value)
142    {
143        return contextValueEncoder.toClient(value);
144    }
145
146    public <T> T toValue(Class<T> requiredType, String clientValue)
147    {
148        return contextValueEncoder.toValue(requiredType, clientValue);
149    }
150
151    private Object[] defaulted(Object[] context)
152    {
153        return context == null ? CommonsUtils.EMPTY_STRING_ARRAY : context;
154    }
155
156    public <T> T invoke(String description, Invokable<T> operation)
157    {
158        return tracker.invoke(description, operation);
159    }
160
161    public <T> T perform(String description, IOOperation<T> operation) throws IOException
162    {
163        return tracker.perform(description, operation);
164    }
165
166    public void run(String description, Runnable operation)
167    {
168        tracker.run(description, operation);
169    }
170
171    public <T> PerThreadValue<T> createPerThreadValue()
172    {
173        return perThreadManager.createValue();
174    }
175
176    public boolean isRenderTracingEnabled()
177    {
178        if (productionMode)
179        {
180            return false;
181        }
182
183        if (componentTracingEnabled)
184        {
185            return true;
186        }
187
188        Request request = requestGlobals.getRequest();
189
190        if (request == null)
191        {
192            return false;
193        }
194
195        return "true".equals(request.getParameter("t:component-trace"));
196    }
197
198}