1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portlet;
24  
25  import com.liferay.portal.PortalException;
26  import com.liferay.portal.SystemException;
27  import com.liferay.portal.kernel.log.Log;
28  import com.liferay.portal.kernel.log.LogFactoryUtil;
29  import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
30  import com.liferay.portal.kernel.portlet.LiferayPortletURL;
31  import com.liferay.portal.kernel.servlet.URLEncoder;
32  import com.liferay.portal.kernel.util.ArrayUtil;
33  import com.liferay.portal.kernel.util.GetterUtil;
34  import com.liferay.portal.kernel.util.ParamUtil;
35  import com.liferay.portal.kernel.util.Validator;
36  import com.liferay.portal.model.Layout;
37  import com.liferay.portal.model.LayoutConstants;
38  import com.liferay.portal.model.Portlet;
39  import com.liferay.portal.model.PortletApp;
40  import com.liferay.portal.model.PortletURLListener;
41  import com.liferay.portal.service.LayoutLocalServiceUtil;
42  import com.liferay.portal.service.PortletLocalServiceUtil;
43  import com.liferay.portal.util.PortalUtil;
44  import com.liferay.portal.util.WebKeys;
45  
46  import java.lang.reflect.Constructor;
47  import java.lang.reflect.Method;
48  
49  import java.util.LinkedHashMap;
50  import java.util.Map;
51  import java.util.Set;
52  
53  import javax.portlet.PortletException;
54  import javax.portlet.PortletModeException;
55  import javax.portlet.PortletPreferences;
56  import javax.portlet.PortletRequest;
57  import javax.portlet.PortletResponse;
58  import javax.portlet.PortletURL;
59  import javax.portlet.PortletURLGenerationListener;
60  import javax.portlet.ResourceURL;
61  import javax.portlet.WindowStateException;
62  
63  import javax.servlet.http.Cookie;
64  import javax.servlet.http.HttpServletRequest;
65  import javax.servlet.http.HttpServletResponse;
66  
67  import org.w3c.dom.DOMException;
68  import org.w3c.dom.Element;
69  
70  /**
71   * <a href="PortletResponseImpl.java.html"><b><i>View Source</i></b></a>
72   *
73   * @author Brian Wing Shun Chan
74   *
75   */
76  public abstract class PortletResponseImpl implements LiferayPortletResponse {
77  
78      public static PortletResponseImpl getPortletResponseImpl(
79          PortletResponse portletResponse) {
80  
81          PortletResponseImpl portletResponseImpl = null;
82  
83          if (portletResponse instanceof PortletResponseImpl) {
84              portletResponseImpl = (PortletResponseImpl)portletResponse;
85          }
86          else {
87  
88              // LEP-4033
89  
90              try {
91                  Method method = portletResponse.getClass().getMethod(
92                      "getResponse");
93  
94                  Object obj = method.invoke(portletResponse, (Object[])null);
95  
96                  portletResponseImpl = getPortletResponseImpl(
97                      (PortletResponse)obj);
98              }
99              catch (Exception e) {
100                 throw new RuntimeException(
101                     "Unable to get the HTTP servlet resuest from " +
102                         portletResponse.getClass().getName());
103             }
104         }
105 
106         return portletResponseImpl;
107     }
108 
109     public void addDateHeader(String name, long date) {
110         if (Validator.isNull(name)) {
111             throw new IllegalArgumentException();
112         }
113 
114         if (_headers.containsKey(name)) {
115             Long[] values = (Long[])_headers.get(name);
116 
117             ArrayUtil.append(values, new Long(date));
118 
119             _headers.put(name, values);
120         }
121         else {
122             setDateHeader(name, date);
123         }
124     }
125 
126     public void addHeader(String name, String value) {
127         if (Validator.isNull(name)) {
128             throw new IllegalArgumentException();
129         }
130 
131         if (_headers.containsKey(name)) {
132             String[] values = (String[])_headers.get(name);
133 
134             ArrayUtil.append(values, value);
135 
136             _headers.put(name, values);
137         }
138         else {
139             setHeader(name, value);
140         }
141     }
142 
143     public void addIntHeader(String name, int value) {
144         if (Validator.isNull(name)) {
145             throw new IllegalArgumentException();
146         }
147 
148         if (_headers.containsKey(name)) {
149             Integer[] values = (Integer[])_headers.get(name);
150 
151             ArrayUtil.append(values, new Integer(value));
152 
153             _headers.put(name, values);
154         }
155         else {
156             setIntHeader(name, value);
157         }
158     }
159 
160     public void addProperty(Cookie cookie) {
161         if (Validator.isNull(cookie)) {
162             throw new IllegalArgumentException();
163         }
164 
165         if (_headers.containsKey("cookies")) {
166             Cookie[] cookies = (Cookie[])_headers.get("cookies");
167 
168             ArrayUtil.append(cookies, cookie);
169 
170             _headers.put("cookies", cookies);
171         }
172         else {
173             Cookie[] cookies = new Cookie[] {cookie};
174 
175             _headers.put("cookies", cookies);
176         }
177     }
178 
179     public void addProperty(String key, Element element) {
180         if (key == null) {
181             throw new IllegalArgumentException();
182         }
183     }
184 
185     public void addProperty(String key, String value) {
186         if (Validator.isNull(key)) {
187             throw new IllegalArgumentException();
188         }
189 
190         addHeader(key, value);
191     }
192 
193     public PortletURL createActionURL() {
194         return createActionURL(_portletName);
195     }
196 
197     public LiferayPortletURL createActionURL(String portletName) {
198         return createPortletURLImpl(portletName, PortletRequest.ACTION_PHASE);
199     }
200 
201     public Element createElement(String tagName) throws DOMException {
202         return null;
203     }
204 
205     public PortletURLImpl createPortletURLImpl(String lifecycle) {
206         return createPortletURLImpl(_portletName, lifecycle);
207     }
208 
209     public PortletURLImpl createPortletURLImpl(
210         String portletName, String lifecycle) {
211 
212         return createPortletURLImpl(_plid, portletName, lifecycle);
213     }
214 
215     public PortletURLImpl createPortletURLImpl(
216         long plid, String portletName, String lifecycle) {
217 
218         try {
219             Layout layout = (Layout)_portletRequestImpl.getAttribute(
220                 WebKeys.LAYOUT);
221 
222             PortletPreferences portletSetup =
223                 PortletPreferencesFactoryUtil.getLayoutPortletSetup(
224                     layout, _portletName);
225 
226             long layoutId = GetterUtil.getLong(portletSetup.getValue(
227                 "portlet-setup-link-to-layout-id", null));
228 
229             if (layoutId > 0) {
230                 try {
231                     Layout linkedLayout = LayoutLocalServiceUtil.getLayout(
232                         layout.getGroupId(), layout.isPrivateLayout(),
233                         layoutId);
234 
235                     plid = linkedLayout.getPlid();
236                 }
237                 catch (PortalException pe) {
238                 }
239             }
240             else {
241 
242                 // Backwards compatibility
243 
244                 plid = GetterUtil.getLong(portletSetup.getValue(
245                     "portlet-setup-link-to-plid", String.valueOf(plid)));
246             }
247         }
248         catch (SystemException e) {
249             if (_log.isWarnEnabled()) {
250                 _log.warn(e);
251             }
252         }
253 
254         if (plid == LayoutConstants.DEFAULT_PLID) {
255             plid = _plid;
256         }
257 
258         PortletURLImpl portletURLImpl = null;
259 
260         Portlet portlet = getPortlet();
261 
262         String portletURLClass = portlet.getPortletURLClass();
263 
264         if (portlet.getPortletId().equals(portletName) &&
265             Validator.isNotNull(portletURLClass)) {
266 
267             try {
268                 Class<?> portletURLClassObj = Class.forName(portletURLClass);
269 
270                 Constructor<?> constructor = portletURLClassObj.getConstructor(
271                     new Class[] {
272                         com.liferay.portlet.PortletResponseImpl.class,
273                         long.class, String.class
274                     });
275 
276                 portletURLImpl = (PortletURLImpl)constructor.newInstance(
277                     new Object[] {this, plid, lifecycle});
278             }
279             catch (Exception e) {
280                 _log.error(e);
281             }
282         }
283 
284         if (portletURLImpl == null) {
285             portletURLImpl = new PortletURLImpl(
286                 _portletRequestImpl, portletName, plid, lifecycle);
287         }
288 
289         PortletApp portletApp = portlet.getPortletApp();
290 
291         Set<PortletURLListener> portletURLListeners =
292             portletApp.getPortletURLListeners();
293 
294         for (PortletURLListener portletURLListener : portletURLListeners) {
295             try {
296                 PortletURLGenerationListener portletURLGenerationListener =
297                     PortletURLListenerFactory.create(portletURLListener);
298 
299                 if (lifecycle.equals(PortletRequest.ACTION_PHASE)) {
300                     portletURLGenerationListener.filterActionURL(
301                         portletURLImpl);
302                 }
303                 else if (lifecycle.equals(PortletRequest.RENDER_PHASE)) {
304                     portletURLGenerationListener.filterRenderURL(
305                         portletURLImpl);
306                 }
307                 else if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
308                     portletURLGenerationListener.filterResourceURL(
309                         portletURLImpl);
310                 }
311             }
312             catch (PortletException pe) {
313                 _log.error(pe, pe);
314             }
315         }
316 
317         try {
318             portletURLImpl.setWindowState(_portletRequestImpl.getWindowState());
319         }
320         catch (WindowStateException wse) {
321             _log.error(wse.getMessage());
322         }
323 
324         try {
325             portletURLImpl.setPortletMode(_portletRequestImpl.getPortletMode());
326         }
327         catch (PortletModeException pme) {
328             _log.error(pme.getMessage());
329         }
330 
331         if (lifecycle.equals(PortletRequest.ACTION_PHASE)) {
332             portletURLImpl.setCopyCurrentPublicRenderParameters(true);
333         }
334 
335         if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
336             portletURLImpl.setCopyCurrentPublicRenderParameters(true);
337             portletURLImpl.setCopyCurrentRenderParameters(true);
338         }
339 
340         return portletURLImpl;
341     }
342 
343     public PortletURL createRenderURL() {
344         return createRenderURL(_portletName);
345     }
346 
347     public LiferayPortletURL createRenderURL(String portletName) {
348         return createPortletURLImpl(portletName, PortletRequest.RENDER_PHASE);
349     }
350 
351     public ResourceURL createResourceURL() {
352         return createResourceURL(_portletName);
353     }
354 
355     public LiferayPortletURL createResourceURL(String portletName) {
356         return createPortletURLImpl(portletName, PortletRequest.RESOURCE_PHASE);
357     }
358 
359     public String encodeURL(String path) {
360         if ((path == null) ||
361             (!path.startsWith("#") && !path.startsWith("/") &&
362                 (path.indexOf("://") == -1))) {
363 
364             // Allow '#' as well to workaround a bug in Oracle ADF 10.1.3
365 
366             throw new IllegalArgumentException(
367                 "URL path must start with a '/' or include '://'");
368         }
369 
370         if (_urlEncoder != null) {
371             return _urlEncoder.encodeURL(_response, path);
372         }
373         else {
374             return path;
375         }
376     }
377 
378     public long getCompanyId() {
379         return _companyId;
380     }
381 
382     public HttpServletRequest getHttpServletRequest() {
383         return _portletRequestImpl.getHttpServletRequest();
384     }
385 
386     public HttpServletResponse getHttpServletResponse() {
387         return _response;
388     }
389 
390     public abstract String getLifecycle();
391 
392     public String getNamespace() {
393         if (_wsrp) {
394             return "wsrp_rewrite_";
395         }
396 
397         if (_namespace == null) {
398             _namespace = PortalUtil.getPortletNamespace(_portletName);
399         }
400 
401         return _namespace;
402     }
403 
404     public long getPlid() {
405         return _plid;
406     }
407 
408     public Portlet getPortlet() {
409         if (_portlet == null) {
410             try {
411                 _portlet = PortletLocalServiceUtil.getPortletById(
412                     _companyId, _portletName);
413             }
414             catch (Exception e) {
415                 _log.error(e);
416             }
417         }
418 
419         return _portlet;
420     }
421 
422     public String getPortletName() {
423         return _portletName;
424     }
425 
426     public PortletRequestImpl getPortletRequest() {
427         return _portletRequestImpl;
428     }
429 
430     public Map<String, String[]> getProperties() {
431         Map<String, String[]> properties =
432             new LinkedHashMap<String, String[]>();
433 
434         for (Map.Entry<String, Object> entry : _headers.entrySet()) {
435             String name = entry.getKey();
436             Object[] values = (Object[])entry.getValue();
437 
438             String[] valuesString = new String[values.length];
439 
440             for (int i = 0; i < values.length; i++) {
441                 valuesString[i] = values[i].toString();
442             }
443 
444             properties.put(name, valuesString);
445         }
446 
447         return properties;
448     }
449 
450     public URLEncoder getUrlEncoder() {
451         return _urlEncoder;
452     }
453 
454     public void setDateHeader(String name, long date) {
455         if (Validator.isNull(name)) {
456             throw new IllegalArgumentException();
457         }
458 
459         if (date <= 0) {
460             _headers.remove(name);
461         }
462         else {
463             _headers.put(name, new Long[] {new Long(date)});
464         }
465     }
466 
467     public void setHeader(String name, String value) {
468         if (Validator.isNull(name)) {
469             throw new IllegalArgumentException();
470         }
471 
472         if (Validator.isNull(value)) {
473             _headers.remove(name);
474         }
475         else {
476             _headers.put(name, new String[] {value});
477         }
478     }
479 
480     public void setIntHeader(String name, int value) {
481         if (Validator.isNull(name)) {
482             throw new IllegalArgumentException();
483         }
484 
485         if (value <= 0) {
486             _headers.remove(name);
487         }
488         else {
489             _headers.put(name, new Integer[] {new Integer(value)});
490         }
491     }
492 
493     public void setPlid(long plid) {
494         _plid = plid;
495 
496         if (_plid <= 0) {
497             Layout layout = (Layout)_portletRequestImpl.getAttribute(
498                 WebKeys.LAYOUT);
499 
500             if (layout != null) {
501                 _plid = layout.getPlid();
502             }
503         }
504     }
505 
506     public void setProperty(String key, String value) {
507         if (key == null) {
508             throw new IllegalArgumentException();
509         }
510 
511         setHeader(key, value);
512     }
513 
514     public void setURLEncoder(URLEncoder urlEncoder) {
515         _urlEncoder = urlEncoder;
516     }
517 
518     public void transferHeaders(HttpServletResponse response) {
519         for (Map.Entry<String, Object> entry : _headers.entrySet()) {
520             String name = entry.getKey();
521             Object values = entry.getValue();
522 
523             if (values instanceof Integer[]) {
524                 Integer[] intValues = (Integer[])values;
525 
526                 for (int value : intValues) {
527                     if (response.containsHeader(name)) {
528                         response.addIntHeader(name, value);
529                     }
530                     else {
531                         response.setIntHeader(name, value);
532                     }
533                 }
534             }
535             else if (values instanceof Long[]) {
536                 Long[] dateValues = (Long[])values;
537 
538                 for (long value : dateValues) {
539                     if (response.containsHeader(name)) {
540                         response.addDateHeader(name, value);
541                     }
542                     else {
543                         response.setDateHeader(name, value);
544                     }
545                 }
546             }
547             else if (values instanceof String[]) {
548                 String[] stringValues = (String[])values;
549 
550                 for (String value : stringValues) {
551                     if (response.containsHeader(name)) {
552                         response.addHeader(name, value);
553                     }
554                     else {
555                         response.setHeader(name, value);
556                     }
557                 }
558             }
559             else if (values instanceof Cookie[]) {
560                 Cookie[] cookies = (Cookie[])values;
561 
562                 for (Cookie cookie : cookies) {
563                     response.addCookie(cookie);
564                 }
565             }
566         }
567     }
568 
569     protected void init(
570         PortletRequestImpl portletRequestImpl, HttpServletResponse response,
571         String portletName, long companyId, long plid) {
572 
573         _portletRequestImpl = portletRequestImpl;
574         _response = response;
575         _portletName = portletName;
576         _companyId = companyId;
577         _wsrp = ParamUtil.getBoolean(getHttpServletRequest(), "wsrp");
578 
579         setPlid(plid);
580     }
581 
582     protected void recycle() {
583         _portletRequestImpl = null;
584         _response = null;
585         _portletName = null;
586         _portlet = null;
587         _namespace = null;
588         _companyId = 0;
589         _plid = 0;
590         _headers.clear();
591     }
592 
593     private static Log _log = LogFactoryUtil.getLog(PortletResponseImpl.class);
594 
595     private PortletRequestImpl _portletRequestImpl;
596     private HttpServletResponse _response;
597     private String _portletName;
598     private Portlet _portlet;
599     private String _namespace;
600     private long _companyId;
601     private long _plid;
602     private URLEncoder _urlEncoder;
603     private Map<String, Object> _headers = new LinkedHashMap<String, Object>();
604     private boolean _wsrp;
605 
606 }