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

hazendaz / displaytag / 1753

12 Feb 2026 03:17AM UTC coverage: 77.321% (-0.01%) from 77.334%
1753

push

github

web-flow
Merge pull request #1102 from hazendaz/renovate/javax-support-logback-monorepo

Update dependency ch.qos.logback:logback-classic to v1.5.29 (javax-support)

1438 of 2003 branches covered (71.79%)

Branch coverage included in aggregate %.

4034 of 5074 relevant lines covered (79.5%)

0.8 hits per line

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

87.7
/displaytag/src/main/java/org/displaytag/portlet/PortletHref.java
1
/*
2
 * SPDX-License-Identifier: MIT
3
 * See LICENSE file for details.
4
 *
5
 * Copyright 2002-2026 Fabrizio Giustina, the Displaytag team
6
 */
7
package org.displaytag.portlet;
8

9
import java.util.LinkedHashMap;
10
import java.util.Map;
11
import java.util.Map.Entry;
12
import java.util.Objects;
13

14
import javax.portlet.MimeResponse;
15
import javax.portlet.PortletMode;
16
import javax.portlet.PortletModeException;
17
import javax.portlet.PortletRequest;
18
import javax.portlet.PortletSecurityException;
19
import javax.portlet.PortletURL;
20
import javax.portlet.WindowState;
21
import javax.portlet.WindowStateException;
22

23
import org.apache.commons.lang3.builder.EqualsBuilder;
24
import org.apache.commons.lang3.builder.HashCodeBuilder;
25
import org.displaytag.util.Href;
26

27
/**
28
 * Implementation of the Href interface that generates URLs using the javax.portlet APIs. As the portlet API supports
29
 * the concept of WindowStates, PorletModes, secure URLs and actions versus render the implementation supports these
30
 * concepts as well through the standard {@link Href} APIs. <br>
31
 * <br>
32
 * The features are manipulated using special parameter names and values:
33
 * <table>
34
 * <caption>Portlet Href</caption>
35
 * <tr>
36
 * <th>Feature</th>
37
 * <th>Parameter Name</th>
38
 * <th>Parameter Value</th>
39
 * </tr>
40
 * <tr>
41
 * <td>Render vs Action URL</td>
42
 * <td>{@link #PARAM_TYPE} (portlet:type)</td>
43
 * <td>"render" for RenderURLs, "action" for ActionURLs</td>
44
 * </tr>
45
 * <tr>
46
 * <td>WindowState</td>
47
 * <td>{@link #PARAM_STATE} (portlet:state)</td>
48
 * <td>The value is used directly for the WindowState name</td>
49
 * </tr>
50
 * <tr>
51
 * <td>PorltetMode</td>
52
 * <td>{@link #PARAM_MODE} (portlet:mode)</td>
53
 * <td>The value is used directly for the PortletMode name</td>
54
 * </tr>
55
 * <tr>
56
 * <td>Secure URL</td>
57
 * <td>{@link #PARAM_SECURE} (portlet:secure)</td>
58
 * <td>"true" requests a secure URL, anything else requests a standard URL</td>
59
 * </tr>
60
 * </table>
61
 *
62
 * @author Eric Dalquist <a href="mailto:dalquist@gmail.com">dalquist@gmail.com</a>
63
 *
64
 * @version $Id$
65
 */
66
public class PortletHref implements Href {
67

68
    /** The Constant PARAM_PREFIX. */
69
    // Constants for working with the special parameters
70
    private static final String PARAM_PREFIX = "portlet:";
71

72
    /** The Constant PARAM_MODE. */
73
    public static final String PARAM_MODE = PortletHref.PARAM_PREFIX + "mode";
74

75
    /** The Constant PARAM_STATE. */
76
    public static final String PARAM_STATE = PortletHref.PARAM_PREFIX + "state";
77

78
    /** The Constant PARAM_SECURE. */
79
    public static final String PARAM_SECURE = PortletHref.PARAM_PREFIX + "secure";
80

81
    /** The Constant PARAM_TYPE. */
82
    public static final String PARAM_TYPE = PortletHref.PARAM_PREFIX + "type";
83

84
    /** The Constant TYPE_RENDER. */
85
    public static final String TYPE_RENDER = "render";
86

87
    /** The Constant TYPE_ACTION. */
88
    public static final String TYPE_ACTION = "action";
89

90
    /**
91
     * D1597A17A6.
92
     */
93
    private static final long serialVersionUID = 899149338534L;
94

95
    /** The portlet request. */
96
    // Portlet request and response are needed for feature checking and generating the URLs
97
    private final PortletRequest portletRequest;
98

99
    /** The render response. */
100
    private final MimeResponse renderResponse;
101

102
    /** The parameters. */
103
    private Map<String, String[]> parameters = new LinkedHashMap<>();
1✔
104

105
    /** The is action. */
106
    private boolean isAction;
107

108
    /** The requested mode. */
109
    private PortletMode requestedMode;
110

111
    /** The requested state. */
112
    private WindowState requestedState;
113

114
    /** The requested secure. */
115
    private boolean requestedSecure;
116

117
    /** The anchor. */
118
    private String anchor;
119

120
    /**
121
     * Creates a new PortletHref. The actual PortletURL object is not generated until the toString method is called.
122
     *
123
     * @param portletRequest
124
     *            request to to feature checking with, may not be null.
125
     * @param renderResponse
126
     *            response to generate the URLs from, may not be null.
127
     */
128
    public PortletHref(final PortletRequest portletRequest, final MimeResponse renderResponse) {
1✔
129
        if (portletRequest == null) {
1✔
130
            throw new IllegalArgumentException("portletRequest may not be null");
1✔
131
        }
132
        if (renderResponse == null) {
1✔
133
            throw new IllegalArgumentException("renderResponse may not be null");
1✔
134
        }
135

136
        this.portletRequest = portletRequest;
1✔
137
        this.renderResponse = renderResponse;
1✔
138
    }
1✔
139

140
    /**
141
     * Sets the full url.
142
     *
143
     * @param baseUrl
144
     *            the new full url
145
     *
146
     * @see org.displaytag.util.Href#setFullUrl(java.lang.String)
147
     */
148
    @Override
149
    public void setFullUrl(final String baseUrl) {
150
        // do nothing
151
    }
×
152

153
    /**
154
     * Checks if is action.
155
     *
156
     * @return Returns the isAction.
157
     */
158
    public boolean isAction() {
159
        return this.isAction;
1✔
160
    }
161

162
    /**
163
     * Sets the action.
164
     *
165
     * @param isAction
166
     *            The isAction to set.
167
     */
168
    public void setAction(final boolean isAction) {
169
        this.isAction = isAction;
1✔
170
    }
1✔
171

172
    /**
173
     * Gets the requested mode.
174
     *
175
     * @return Returns the requestedMode.
176
     */
177
    public PortletMode getRequestedMode() {
178
        return this.requestedMode;
1✔
179
    }
180

181
    /**
182
     * Sets the requested mode.
183
     *
184
     * @param requestedMode
185
     *            The requestedMode to set.
186
     */
187
    public void setRequestedMode(final PortletMode requestedMode) {
188
        this.requestedMode = requestedMode;
1✔
189
    }
1✔
190

191
    /**
192
     * Checks if is requested secure.
193
     *
194
     * @return Returns the requestedSecure.
195
     */
196
    public boolean isRequestedSecure() {
197
        return this.requestedSecure;
1✔
198
    }
199

200
    /**
201
     * Sets the requested secure.
202
     *
203
     * @param requestedSecure
204
     *            The requestedSecure to set.
205
     */
206
    public void setRequestedSecure(final boolean requestedSecure) {
207
        this.requestedSecure = requestedSecure;
1✔
208
    }
1✔
209

210
    /**
211
     * Gets the requested state.
212
     *
213
     * @return Returns the requestedState.
214
     */
215
    public WindowState getRequestedState() {
216
        return this.requestedState;
1✔
217
    }
218

219
    /**
220
     * Sets the requested state.
221
     *
222
     * @param requestedState
223
     *            The requestedState to set.
224
     */
225
    public void setRequestedState(final WindowState requestedState) {
226
        this.requestedState = requestedState;
1✔
227
    }
1✔
228

229
    /**
230
     * Adds the parameter.
231
     *
232
     * @param name
233
     *            the name
234
     * @param value
235
     *            the value
236
     *
237
     * @return the href
238
     *
239
     * @see org.displaytag.util.Href#addParameter(java.lang.String, int)
240
     */
241
    @Override
242
    public Href addParameter(final String name, final int value) {
243
        return this.addParameter(name, Integer.toString(value));
1✔
244
    }
245

246
    /**
247
     * Adds the parameter.
248
     *
249
     * @param name
250
     *            the name
251
     * @param objValue
252
     *            the obj value
253
     *
254
     * @return the href
255
     *
256
     * @see org.displaytag.util.Href#addParameter(String, Object)
257
     */
258
    @Override
259
    public Href addParameter(final String name, final Object objValue) {
260
        final String value = Objects.toString(objValue, null);
1✔
261

262
        if (name != null && name.startsWith(PortletHref.PARAM_PREFIX)) {
1!
263
            if (PortletHref.PARAM_TYPE.equals(name)) {
1✔
264
                if (PortletHref.TYPE_RENDER.equals(value)) {
1✔
265
                    this.setAction(false);
1✔
266
                } else if (PortletHref.TYPE_ACTION.equals(value)) {
1✔
267
                    this.setAction(true);
1✔
268
                } else {
269
                    throw new IllegalArgumentException(
1✔
270
                            "Value of parameter '" + name + "' must be equal to '" + PortletHref.TYPE_RENDER + "' or '"
271
                                    + PortletHref.TYPE_ACTION + "'. '" + value + "' is not allowed.");
272
                }
273
            } else if (PortletHref.PARAM_SECURE.equals(name)) {
1✔
274
                if (Boolean.parseBoolean(value)) {
1✔
275
                    this.setRequestedSecure(true);
1✔
276
                } else {
277
                    this.setRequestedSecure(false);
1✔
278
                }
279
            } else if (PortletHref.PARAM_MODE.equals(name)) {
1✔
280
                if (value == null) {
1✔
281
                    this.setRequestedMode(null);
1✔
282
                } else {
283
                    final PortletMode mode = new PortletMode(value);
1✔
284

285
                    if (!this.portletRequest.isPortletModeAllowed(mode)) {
1✔
286
                        throw new IllegalArgumentException(
1✔
287
                                "PortletMode '" + mode + "' is not allowed for this request.");
288
                    }
289

290
                    this.setRequestedMode(mode);
1✔
291
                }
1✔
292
            } else if (PortletHref.PARAM_STATE.equals(name)) {
1✔
293
                if (value == null) {
1✔
294
                    this.setRequestedState(null);
1✔
295
                } else {
296
                    final WindowState state = new WindowState(value);
1✔
297

298
                    if (!this.portletRequest.isWindowStateAllowed(state)) {
1✔
299
                        throw new IllegalArgumentException(
1✔
300
                                "WindowState '" + state + "' is not allowed for this request.");
301
                    }
302

303
                    this.setRequestedState(state);
1✔
304
                }
1✔
305
            } else {
306
                throw new IllegalArgumentException(
1✔
307
                        "'" + name + "' is not a valid '" + PortletHref.PARAM_PREFIX + "' prefixed parameter.");
308
            }
309
        } else {
310
            this.parameters.put(name, new String[] { value });
1✔
311
        }
312

313
        return this;
1✔
314
    }
315

316
    /**
317
     * Adds the parameter map.
318
     *
319
     * @param parametersMap
320
     *            the parameters map
321
     *
322
     * @see org.displaytag.util.Href#addParameterMap(java.util.Map)
323
     */
324
    @Override
325
    public void addParameterMap(final Map<String, String[]> parametersMap) {
326
        for (final Entry<String, String[]> entry : parametersMap.entrySet()) {
1✔
327
            final String name = entry.getKey();
1✔
328

329
            // Allow multivalued parameters since code elsewhere calls this method to copy
330
            // parameters from the request to the response. Ensures that developer specified
331
            // multivalued parameters are retained correctly.
332

333
            if (entry.getValue() == null) {
1!
334
                this.addParameter(name, entry.getValue());
×
335
            } else if (entry.getValue().length == 1) {
1✔
336
                // addParameter does some special processing of portlet parameters
337
                this.addParameter(name, entry.getValue()[0]);
1✔
338
            } else if (entry.getValue().getClass().isArray()) {
1!
339
                this.parameters.put(name, entry.getValue());
1✔
340
            }
341
        }
1✔
342
    }
1✔
343

344
    /**
345
     * Sets the parameter map.
346
     *
347
     * @param parametersMap
348
     *            the parameters map
349
     *
350
     * @see org.displaytag.util.Href#setParameterMap(java.util.Map)
351
     */
352
    @Override
353
    public void setParameterMap(final Map<String, String[]> parametersMap) {
354
        this.parameters.clear();
1✔
355
        this.addParameterMap(parametersMap);
1✔
356
    }
1✔
357

358
    /**
359
     * Warning, parameters added to the Map directly will not be parsed by the PortletUrl feature support portions of
360
     * this class.
361
     *
362
     * @return the parameter map
363
     *
364
     * @see org.displaytag.util.Href#getParameterMap()
365
     */
366
    @Override
367
    public Map<String, String[]> getParameterMap() {
368
        return this.parameters;
1✔
369
    }
370

371
    /**
372
     * Removes the parameter.
373
     *
374
     * @param name
375
     *            the name
376
     *
377
     * @see org.displaytag.util.Href#removeParameter(java.lang.String)
378
     */
379
    @Override
380
    public void removeParameter(final String name) {
381
        this.parameters.remove(name);
1✔
382
    }
1✔
383

384
    /**
385
     * Sets the anchor.
386
     *
387
     * @param name
388
     *            the new anchor
389
     *
390
     * @see org.displaytag.util.Href#setAnchor(java.lang.String)
391
     */
392
    @Override
393
    public void setAnchor(final String name) {
394
        this.anchor = name;
1✔
395
    }
1✔
396

397
    /**
398
     * Gets the anchor.
399
     *
400
     * @return the anchor
401
     *
402
     * @see org.displaytag.util.Href#getAnchor()
403
     */
404
    @Override
405
    public String getAnchor() {
406
        return this.anchor;
1✔
407
    }
408

409
    /**
410
     * Generates a render or action URL depending on the use of the PortletUrl specific features of this class.
411
     *
412
     * @return the base url
413
     *
414
     * @see org.displaytag.util.Href#getBaseUrl()
415
     */
416
    @Override
417
    public String getBaseUrl() {
418
        if (this.isAction()) {
1✔
419
            return this.renderResponse.createActionURL().toString();
1✔
420
        }
421
        return this.renderResponse.createRenderURL().toString();
1✔
422
    }
423

424
    /**
425
     * Clone.
426
     *
427
     * @return the object
428
     *
429
     * @see org.displaytag.util.Href#clone()
430
     */
431
    @Override
432
    public Object clone() {
433
        PortletHref href;
434

435
        try {
436
            href = (PortletHref) super.clone();
1✔
437
        } catch (final CloneNotSupportedException cnse) {
×
438
            throw new RuntimeException("Parent through a CloneNotSupportedException, this should never happen", cnse);
×
439
        }
1✔
440

441
        href.isAction = this.isAction;
1✔
442
        href.parameters = new LinkedHashMap<>();
1✔
443
        href.parameters.putAll(this.parameters);
1✔
444
        href.requestedMode = this.requestedMode;
1✔
445
        href.requestedState = this.requestedState;
1✔
446
        href.requestedSecure = this.requestedSecure;
1✔
447
        href.anchor = this.anchor;
1✔
448

449
        return href;
1✔
450
    }
451

452
    /**
453
     * Equals.
454
     *
455
     * @param object
456
     *            the object
457
     *
458
     * @return true, if successful
459
     *
460
     * @see org.displaytag.util.Href#equals(java.lang.Object)
461
     */
462
    @Override
463
    public boolean equals(final Object object) {
464
        if (this == object) {
1!
465
            return true;
×
466
        }
467
        if (!(object instanceof PortletHref)) {
1!
468
            return false;
×
469
        }
470
        final PortletHref rhs = (PortletHref) object;
1✔
471
        return new EqualsBuilder().append(this.isAction, rhs.isAction).append(this.parameters, rhs.parameters)
1✔
472
                .append(this.requestedMode, rhs.requestedMode).append(this.requestedState, rhs.requestedState)
1✔
473
                .append(this.requestedSecure, rhs.requestedSecure).append(this.anchor, rhs.anchor).isEquals();
1✔
474
    }
475

476
    /**
477
     * Hash code.
478
     *
479
     * @return the int
480
     *
481
     * @see java.lang.Object#hashCode()
482
     */
483
    @Override
484
    public int hashCode() {
485
        return new HashCodeBuilder(1313733113, -431360889).append(this.isAction).append(this.parameters)
1✔
486
                .append(this.requestedMode).append(this.requestedState).append(this.requestedSecure).append(this.anchor)
1✔
487
                .toHashCode();
1✔
488
    }
489

490
    /**
491
     * To string.
492
     *
493
     * @return the string
494
     *
495
     * @see org.displaytag.util.Href#toString()
496
     */
497
    @Override
498
    public String toString() {
499
        final PortletURL url;
500
        if (this.isAction()) {
1✔
501
            url = this.renderResponse.createActionURL();
1✔
502
        } else {
503
            url = this.renderResponse.createRenderURL();
1✔
504
        }
505

506
        if (this.isRequestedSecure()) {
1✔
507
            try {
508
                url.setSecure(true);
1✔
509
            } catch (final PortletSecurityException pse) {
×
510
                throw new RuntimeException("Creating secure PortletURL Failed.", pse);
×
511
            }
1✔
512
        }
513

514
        if (this.getRequestedMode() != null) {
1✔
515
            try {
516
                url.setPortletMode(this.getRequestedMode());
1✔
517
            } catch (final PortletModeException pme) {
×
518
                final IllegalStateException ise = new IllegalStateException(
×
519
                        "Requested PortletMode='" + this.getRequestedMode() + "' could not be set.");
×
520
                ise.initCause(pme);
×
521
                throw ise;
×
522
            }
1✔
523
        }
524

525
        if (this.getRequestedState() != null) {
1✔
526
            try {
527
                url.setWindowState(this.getRequestedState());
1✔
528
            } catch (final WindowStateException wse) {
×
529
                final IllegalStateException ise = new IllegalStateException(
×
530
                        "Requested WindowState='" + this.getRequestedState() + "' could not be set.");
×
531
                ise.initCause(wse);
×
532
                throw ise;
×
533
            }
1✔
534
        }
535

536
        for (final Entry<String, String[]> entry : this.parameters.entrySet()) {
1✔
537
            final String name = entry.getKey();
1✔
538
            final String[] value = entry.getValue();
1✔
539

540
            url.setParameter(name, value);
1✔
541
        }
1✔
542

543
        if (this.getAnchor() == null) {
1✔
544
            return url.toString();
1✔
545
        }
546
        return url.toString() + "#" + this.getAnchor();
1✔
547
    }
548

549
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc