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