001// Copyright 2007, 2008, 2012 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.renderers;
016
017import org.apache.tapestry5.MarkupWriter;
018import org.apache.tapestry5.SymbolConstants;
019import org.apache.tapestry5.commons.util.CollectionFactory;
020import org.apache.tapestry5.http.TapestryHttpSymbolConstants;
021import org.apache.tapestry5.http.services.Context;
022import org.apache.tapestry5.http.services.Request;
023import org.apache.tapestry5.internal.services.PageSource;
024import org.apache.tapestry5.internal.structure.Page;
025import org.apache.tapestry5.ioc.annotations.Primary;
026import org.apache.tapestry5.ioc.annotations.Symbol;
027import org.apache.tapestry5.ioc.internal.util.InternalUtils;
028import org.apache.tapestry5.services.ComponentClassResolver;
029import org.apache.tapestry5.services.ObjectRenderer;
030import org.apache.tapestry5.services.pageload.PageClassLoaderContext;
031import org.apache.tapestry5.services.pageload.PageClassLoaderContextManager;
032
033import java.util.ArrayList;
034import java.util.Collections;
035import java.util.Comparator;
036import java.util.List;
037import java.util.stream.Collectors;
038
039public class RequestRenderer implements ObjectRenderer<Request>
040{
041    private final Context context;
042
043    private final String contextPath;
044
045    private final ObjectRenderer masterObjectRenderer;
046    
047    private final boolean productionMode;
048    
049    private final PageClassLoaderContextManager pageClassLoaderContextManager;
050    
051    private final PageSource pageSource;
052    
053    private final ComponentClassResolver componentClassResolver;
054
055    public RequestRenderer(
056            @Primary ObjectRenderer masterObjectRenderer, 
057            Context context, 
058            @Symbol(TapestryHttpSymbolConstants.CONTEXT_PATH) String contextPath,
059            @Symbol(SymbolConstants.PRODUCTION_MODE) boolean productionMode,
060            PageClassLoaderContextManager pageClassLoaderContextManager,
061            PageSource pageSource,
062            ComponentClassResolver componentClassResolver)
063    {
064        this.masterObjectRenderer = masterObjectRenderer;
065        this.context = context;
066        this.contextPath = contextPath;
067        this.productionMode = productionMode;
068        this.pageClassLoaderContextManager = pageClassLoaderContextManager;
069        this.pageSource = pageSource;
070        this.componentClassResolver = componentClassResolver;
071    }
072
073    public void render(Request request, MarkupWriter writer)
074    {
075        coreProperties(request, writer);
076        parameters(request, writer);
077        headers(request, writer);
078        attributes(request, writer);
079        context(writer);
080        
081//        pageClassloaderContext(writer);
082//        pages(writer);
083    }
084
085    private void coreProperties(Request request, MarkupWriter writer)
086    {
087        writer.element("dl", "class", "dl-horizontal");
088
089        dt(writer, "Context Path");
090
091        writer.element("dd");
092
093        if (contextPath.equals(""))
094        {
095            writer.element("em");
096            writer.write("none (deployed as root)");
097            writer.end();
098        } else
099        {
100            writer.write(contextPath);
101        }
102
103        writer.end(); // dd
104
105        dt(writer, "Path", request.getPath());
106
107        dt(writer, "Locale", request.getLocale().toString());
108
109        dt(writer, "Server Name", request.getServerName());
110
111
112        List<String> flags = CollectionFactory.newList();
113        if (request.isSecure())
114        {
115            flags.add("secure");
116        }
117
118        if (request.isXHR())
119        {
120            flags.add("XHR");
121        }
122
123        if (request.isRequestedSessionIdValid())
124        {
125            flags.add("requested session id valid");
126        }
127
128        if (request.isSessionInvalidated())
129        {
130            flags.add("session invalidated");
131        }
132
133        if (!flags.isEmpty())
134        {
135            dt(writer, "Flags", InternalUtils.join(flags));
136        }
137
138        dt(writer, "Ports (local/server)",
139                String.format("%d / %d", request.getLocalPort(), request.getServerPort()));
140
141        dt(writer, "Method", request.getMethod());
142
143        writer.end();
144    }
145
146    private void context(MarkupWriter writer)
147    {
148        List<String> attributeNames = context.getAttributeNames();
149
150        if (attributeNames.isEmpty()) return;
151
152        section(writer, "Context Attributes");
153
154        writer.element("dl");
155
156        for (String name : attributeNames)
157        {
158            dt(writer, name);
159
160            writer.element("dd");
161
162            masterObjectRenderer.render(context.getAttribute(name), writer);
163
164            writer.end(); // dd
165        }
166
167        writer.end(); // dl
168    }
169
170    private void parameters(Request request, MarkupWriter writer)
171    {
172        List<String> parameterNames = request.getParameterNames();
173
174        if (parameterNames.isEmpty())
175            return;
176
177        section(writer, "Query Parameters");
178
179        writer.element("dl");
180
181        for (String name : parameterNames)
182        {
183            String[] values = request.getParameters(name);
184
185            dt(writer, name);
186
187            writer.element("dd");
188
189            if (values.length > 1)
190            {
191                writer.element("ul");
192
193                for (String value : values)
194                {
195                    writer.element("li");
196                    writer.write(value);
197                    writer.end();
198                }
199
200                writer.end(); // ul
201            } else
202            {
203                writer.write(values[0]);
204            }
205
206            writer.end(); // dd
207        }
208
209        writer.end(); // dl
210    }
211
212    private void dt(MarkupWriter writer, String name, String value)
213    {
214        if (value != null)
215        {
216            dt(writer, name);
217            dd(writer, value);
218        }
219    }
220
221    private void dt(MarkupWriter writer, String name)
222    {
223        writer.element("dt");
224        writer.write(name);
225        writer.end();
226    }
227
228    private void dd(MarkupWriter writer, String name)
229    {
230        writer.element("dd");
231        writer.write(name);
232        writer.end();
233    }
234
235    private void section(MarkupWriter writer, String name)
236    {
237        writer.element("h3");
238        writer.write(name);
239        writer.end();
240    }
241
242    private void headers(Request request, MarkupWriter writer)
243    {
244        section(writer, "Headers");
245
246        writer.element("dl", "class", "dl-horizontal");
247
248        for (String name : request.getHeaderNames())
249        {
250            dt(writer, name, request.getHeader(name));
251        }
252
253        writer.end(); // dl
254
255    }
256
257    private void attributes(Request request, MarkupWriter writer)
258    {
259        List<String> attributeNames = request.getAttributeNames();
260
261        if (attributeNames.isEmpty())
262        {
263            return;
264        }
265
266        section(writer, "Attributes");
267
268        writer.element("dl");
269
270        for (String name : attributeNames)
271        {
272            dt(writer, name, String.valueOf(request.getAttribute(name)));
273        }
274
275        writer.end(); // dl
276    }
277
278//    private void pageClassloaderContext(MarkupWriter writer) 
279//    {
280//        if (!productionMode)
281//        {
282//            section(writer, "Page Classloader Context");
283//            writer.element("ul");
284//            render(pageClassLoaderContextManager.getRoot(), writer);
285//            writer.end(); // ul
286//        }
287//    }
288//
289//    private void render(PageClassloaderContext context, MarkupWriter writer) 
290//    {
291//        if (context != null)
292//        {
293//        
294//            writer.element("li");
295//            
296//            writer.element("p");
297//            writer.element("em");
298//            writer.write(context.getName());
299//            writer.write(", ");
300//            writer.write(context.getClassLoader().toString());
301//            writer.end(); // em
302//            writer.end(); // p
303//            
304//            writer.element("p");
305//            writer.write(context.getClassNames().stream().collect(Collectors.joining(", ")));
306//            writer.end(); // p
307//            
308//            if (!context.getChildren().isEmpty())
309//            {
310//                writer.element("ul");
311//                for (PageClassloaderContext child : context.getChildren())
312//                {
313//                    render(child, writer);
314//                }
315//                writer.end(); // ul
316//            }
317//            writer.end(); // li
318//            
319//        }
320//        
321//    }
322//    
323//    private void pages(MarkupWriter writer) 
324//    {
325//        if (!productionMode)
326//        {
327//            section(writer, "Pages");
328//            writer.element("table", "class", "table table-condensed table-hover table-striped exception-report-threads");
329//            writer.element("thead");
330//            
331//            writer.element("td");
332//            writer.write("Name");
333//            writer.end(); //td Name
334//
335//            writer.element("td");
336//            writer.write("Context");
337//            writer.end(); //td Context
338//
339//            writer.end(); // thead
340//            
341//            writer.element("tbody");
342//            
343//            List<Page> pages = new ArrayList<>(pageSource.getAllPages());
344//            Collections.sort(pages, Comparator.comparing(Page::getName));
345//            
346//            for (Page page : pages) {
347//                writer.element("tr");
348//                writer.element("td");
349//                writer.write(page.getName());
350//                writer.end(); // td                
351//                writer.element("td");
352//                writer.write(pageClassLoaderContextManager.getRoot().findByClassName(componentClassResolver.getClassName(page.getName())).toString());
353//                writer.end(); // td                
354//                writer.end(); // tr
355//            }
356//            
357//            writer.end(); // tbody
358//            
359//            writer.end(); // table
360//        }        
361//    }
362    
363}