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