• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hazendaz / sitemesh2 / 59

22 Mar 2026 02:30AM UTC coverage: 40.347%. Remained the same
59

push

github

hazendaz
[mvn] Update maven wrapper

698 of 1891 branches covered (36.91%)

Branch coverage included in aggregate %.

1555 of 3693 relevant lines covered (42.11%)

0.42 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/main/java/com/opensymphony/module/sitemesh/taglib/page/ApplyDecoratorTag.java
1
/*
2
 * SPDX-License-Identifier: Apache-2.0
3
 * Copyright 2011-2026 Hazendaz
4
 */
5
/*
6
 * Title:        ApplyDecoratorTag
7
 * Description:
8
 *
9
 * This software is published under the terms of the OpenSymphony Software
10
 * License version 1.1, of which a copy has been included with this
11
 * distribution in the LICENSE.txt file.
12
 */
13

14
package com.opensymphony.module.sitemesh.taglib.page;
15

16
import com.opensymphony.module.sitemesh.Config;
17
import com.opensymphony.module.sitemesh.Decorator;
18
import com.opensymphony.module.sitemesh.DecoratorMapper;
19
import com.opensymphony.module.sitemesh.DefaultSitemeshBuffer;
20
import com.opensymphony.module.sitemesh.Factory;
21
import com.opensymphony.module.sitemesh.Page;
22
import com.opensymphony.module.sitemesh.PageParser;
23
import com.opensymphony.module.sitemesh.PageParserSelector;
24
import com.opensymphony.module.sitemesh.RequestConstants;
25
import com.opensymphony.module.sitemesh.SitemeshBufferWriter;
26
import com.opensymphony.module.sitemesh.filter.PageRequestWrapper;
27
import com.opensymphony.module.sitemesh.filter.PageResponseWrapper;
28

29
import jakarta.servlet.RequestDispatcher;
30
import jakarta.servlet.ServletException;
31
import jakarta.servlet.http.HttpServletRequest;
32
import jakarta.servlet.http.HttpServletResponse;
33
import jakarta.servlet.jsp.JspException;
34
import jakarta.servlet.jsp.tagext.BodyTagSupport;
35

36
import java.io.BufferedReader;
37
import java.io.IOException;
38
import java.io.InputStreamReader;
39
import java.net.URL;
40
import java.net.URLConnection;
41
import java.nio.charset.Charset;
42
import java.util.HashMap;
43
import java.util.Iterator;
44
import java.util.Map;
45

46
/**
47
 * This tag inserts an external resource as a panel into the current Page.
48
 * <p>
49
 * The page attribute should point to the panel resource which should expose an entire page (e.g. another JSP file
50
 * producing HTML). This attribute can be relative to the page it is being called from or an absolute path from the
51
 * context-root.
52
 * <p>
53
 * <strong>OR</strong>
54
 * <p>
55
 * If the page attribute is not specified, the body content is parsed into the
56
 * {@link com.opensymphony.module.sitemesh.Page} object and has the {@link com.opensymphony.module.sitemesh.Decorator}
57
 * applied.
58
 * <p>
59
 * The (optional) decorator attribute is the name of the {@link com.opensymphony.module.sitemesh.Decorator} to apply to
60
 * the included page. Note that the implementation of {@link com.opensymphony.module.sitemesh.DecoratorMapper} can
61
 * overide this.
62
 *
63
 * @author <a href="mailto:joe@truemesh.com">Joe Walnes</a>
64
 */
65
public class ApplyDecoratorTag extends BodyTagSupport implements RequestConstants {
×
66

67
    /** The Constant serialVersionUID. */
68
    private static final long serialVersionUID = 1L;
69

70
    /** The page. */
71
    private String page = null;
×
72

73
    /** The decorator. */
74
    private String decorator = null;
×
75

76
    /** The content type. */
77
    private String contentType = null;
×
78

79
    /** The encoding. */
80
    private String encoding = null;
×
81

82
    /** The params. */
83
    private Map<String, String> params = new HashMap<String, String>(6);
×
84

85
    /** The config. */
86
    private Config config = null;
×
87

88
    /** The decorator mapper. */
89
    private DecoratorMapper decoratorMapper = null;
×
90

91
    /** The factory. */
92
    private Factory factory;
93

94
    /**
95
     * Tag attribute: URI of page to include. Can be relative to page being called from, or absolute path from
96
     * context-root of web-app.
97
     *
98
     * @param page
99
     *            the new page
100
     */
101
    public void setPage(String page) {
102
        this.page = page;
×
103
    }
×
104

105
    /**
106
     * Add a parameter to the page. This has a package level access modifier so ParamTag can also call it.
107
     *
108
     * @param name
109
     *            the name
110
     * @param value
111
     *            the value
112
     */
113
    void addParam(String name, String value) {
114
        params.put(name, value);
×
115
    }
×
116

117
    /**
118
     * Tag attribute: If set, this value will override the 'title' property of the page. This is a convenience utility
119
     * and is identical to specifing a 'page:param name=title' tag.
120
     *
121
     * @param title
122
     *            the new title
123
     */
124
    public void setTitle(String title) {
125
        addParam("title", title);
×
126
    }
×
127

128
    /**
129
     * Tag attribute: If set, this value will override the 'id' property of the page. This is a convenience utility and
130
     * is identical to specifing a 'page:param name=id' tag.
131
     */
132
    @Override
133
    public void setId(String id) {
134
        addParam("id", id);
×
135
    }
×
136

137
    /**
138
     * Tag attribute: Name of Decorator to apply to Page. This is passed to DecoratorMapper to retrieve appropriate
139
     * Decorator. DecoratorMapper may override if needed.
140
     *
141
     * @param decorator
142
     *            the new name
143
     *
144
     * @see com.opensymphony.module.sitemesh.DecoratorMapper
145
     */
146
    public void setName(String decorator) {
147
        if (decorator != null) {
×
148
            this.decorator = decorator;
×
149
        }
150
    }
×
151

152
    /**
153
     * Sets the decorator.
154
     *
155
     * @param decorator
156
     *            the new decorator
157
     *
158
     * @deprecated Use setName() instead.
159
     */
160
    @Deprecated
161
    public void setDecorator(String decorator) {
162
        setName(decorator);
×
163
    }
×
164

165
    /**
166
     * Sets the content type.
167
     *
168
     * @param contentType
169
     *            the new content type
170
     */
171
    public void setContentType(String contentType) {
172
        this.contentType = contentType;
×
173
    }
×
174

175
    /**
176
     * Sets the encoding.
177
     *
178
     * @param encoding
179
     *            the new encoding
180
     */
181
    public void setEncoding(String encoding) {
182
        this.encoding = encoding;
×
183
    }
×
184

185
    @Override
186
    public int doStartTag() {
187
        if (config == null) {
×
188
            // set context if not already set
189
            config = new Config(pageContext.getServletConfig());
×
190
            factory = Factory.getInstance(config);
×
191
            decoratorMapper = factory.getDecoratorMapper();
×
192
        }
193
        // return page == null ? EVAL_BODY_BUFFERED : SKIP_BODY;
194
        return EVAL_BODY_BUFFERED;
×
195
    }
196

197
    /** Ensure that external page contents are included in bodycontent. */
198
    @Override
199
    public int doAfterBody() throws JspException {
200
        return SKIP_BODY;
×
201
    }
202

203
    /** Standard taglib method: apply decorator to page. */
204
    @Override
205
    public int doEndTag() throws JspException {
206
        try {
207
            // if composite decorator, remember last page
208
            Page oldPage = (Page) pageContext.getRequest().getAttribute(PAGE);
×
209

210
            // parse bodycontent into Page object
211
            PageParser parser = getParserSelector().getPageParser(contentType != null ? contentType : "text/html");
×
212
            Page pageObj;
213

214
            if (page == null) {
×
215
                // inline content
216
                if (bodyContent != null) {
×
217
                    // Would be nice if we could do our own buffering...
218
                    SitemeshBufferWriter sitemeshWriter = new SitemeshBufferWriter();
×
219
                    bodyContent.writeOut(sitemeshWriter);
×
220
                    pageObj = parser.parse(sitemeshWriter.getSitemeshBuffer());
×
221
                } else {
×
222
                    pageObj = parser.parse(new DefaultSitemeshBuffer(new char[] {}));
×
223
                }
224
            } else if (page.startsWith("http://") || page.startsWith("https://")) {
×
225
                try {
226
                    URL url = new URL(page);
×
227
                    URLConnection urlConn = url.openConnection();
×
228
                    urlConn.setUseCaches(true);
×
229

230
                    try (BufferedReader in = new BufferedReader(
×
231
                            new InputStreamReader(urlConn.getInputStream(), Charset.forName(encoding)));
×
232
                            SitemeshBufferWriter sitemeshWriter = new SitemeshBufferWriter()) {
×
233
                        char[] buf = new char[1000];
×
234
                        for (;;) {
235
                            int moved = in.read(buf);
×
236
                            if (moved < 0) {
×
237
                                break;
×
238
                            }
239
                            sitemeshWriter.write(buf, 0, moved);
×
240
                        }
×
241
                        pageObj = parser.parse(sitemeshWriter.getSitemeshBuffer());
×
242
                    }
243
                } catch (IOException e) {
×
244
                    throw new JspException(e);
×
245
                }
×
246
            } else {
247
                // external content
248
                String fullPath = page;
×
249
                if (fullPath.length() > 0 && fullPath.charAt(0) != '/') {
×
250
                    HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
×
251

252
                    // find absolute path if relative supplied
253
                    String thisPath = request.getServletPath();
×
254

255
                    // check if it did not return null (could occur when the servlet container
256
                    // does not use a servlet to serve the requested resouce)
257
                    if (thisPath == null) {
×
258
                        String requestURI = request.getRequestURI();
×
259
                        if (request.getPathInfo() != null) {
×
260
                            // strip the pathInfo from the requestURI
261
                            thisPath = requestURI.substring(0, requestURI.indexOf(request.getPathInfo()));
×
262
                        } else {
263
                            thisPath = requestURI;
×
264
                        }
265
                    }
266

267
                    fullPath = thisPath.substring(0, thisPath.lastIndexOf('/') + 1) + fullPath;
×
268
                    int dotdot;
269
                    while ((dotdot = fullPath.indexOf("..")) > -1) {
×
270
                        int prevSlash = fullPath.lastIndexOf('/', dotdot - 2);
×
271
                        fullPath = fullPath.substring(0, prevSlash) + fullPath.substring(dotdot + 2);
×
272
                    }
×
273
                }
274

275
                // include page using filter response
276
                RequestDispatcher rd = pageContext.getServletContext().getRequestDispatcher(fullPath);
×
277
                PageRequestWrapper pageRequest = new PageRequestWrapper((HttpServletRequest) pageContext.getRequest());
×
278
                PageResponseWrapper pageResponse = new PageResponseWrapper(
×
279
                        (HttpServletResponse) pageContext.getResponse(), factory);
×
280

281
                StringBuilder sb = new StringBuilder(contentType != null ? contentType : "text/html");
×
282
                if (encoding != null) {
×
283
                    sb.append(";charset=").append(encoding);
×
284
                }
285
                pageResponse.setContentType(sb.toString());
×
286

287
                // if rd == null, then the panel was not found, but this isn't correct, so we need to spit out
288
                // something appropriate. What this is, well...I don't know yet.
289
                if (rd == null) {
×
290
                    throw new ApplyDecoratorException(
×
291
                            "The specified resource in applyDecorator tag (" + fullPath + ") was not found.");
292
                }
293
                rd.include(pageRequest, pageResponse);
×
294
                pageObj = pageResponse.getPage();
×
295
            }
296

297
            // If pageObj == null, then the panel source had some weird error in
298
            // it. Stop writing bugs like this. They're ugly and they make you smell funny.
299
            if (pageObj == null) {
×
300
                throw new ApplyDecoratorException(page + " did not create a valid page to decorate.");
×
301
            }
302

303
            // add extra params to Page
304
            Iterator<String> paramKeys = params.keySet().iterator();
×
305
            while (paramKeys.hasNext()) {
×
306
                String k = (String) paramKeys.next();
×
307
                String v = (String) params.get(k);
×
308
                pageObj.addProperty(k, v);
×
309
            }
×
310

311
            // get decorator
312
            if (decorator == null) {
×
313
                decorator = "";
×
314
            }
315
            pageObj.setRequest((HttpServletRequest) pageContext.getRequest());
×
316
            pageContext.getRequest().setAttribute(DECORATOR, decorator);
×
317
            Decorator d = decoratorMapper.getDecorator((HttpServletRequest) pageContext.getRequest(), pageObj);
×
318
            pageContext.getRequest().removeAttribute(DECORATOR);
×
319

320
            // apply decorator
321
            if ((d == null) || (d.getPage() == null)) {
×
322
                throw new JspException("Cannot locate inline Decorator: " + decorator);
×
323
            }
324
            pageContext.getRequest().setAttribute(PAGE, pageObj);
×
325
            pageContext.include(d.getPage());
×
326

327
            // clean up
328
            pageContext.getRequest().setAttribute(PAGE, oldPage);
×
329
            params.clear(); // params need to be cleared between invocations - SIM-191
×
330
        } catch (IOException | ServletException e) {
×
331
            throw new JspException(e);
×
332
        } catch (ApplyDecoratorException e) {
×
333
            try {
334
                pageContext.getOut().println(e.getMessage());
×
335
            } catch (IOException ioe) {
×
336
                System.err.println("IOException thrown in applyDecorator tag: " + e.toString());
×
337
            }
×
338
        }
×
339
        return EVAL_PAGE;
×
340
    }
341

342
    /**
343
     * Gets the parser selector.
344
     *
345
     * @return the parser selector
346
     */
347
    private PageParserSelector getParserSelector() {
348
        return Factory.getInstance(config);
×
349
    }
350

351
    /**
352
     * The Class ApplyDecoratorException.
353
     */
354
    class ApplyDecoratorException extends Exception {
355

356
        /** The Constant serialVersionUID. */
357
        private static final long serialVersionUID = 1L;
358

359
        /**
360
         * Instantiates a new apply decorator exception.
361
         *
362
         * @param s
363
         *            the s
364
         */
365
        public ApplyDecoratorException(String s) {
×
366
            super(s);
×
367
        }
×
368
    }
369
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc