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