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