001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
023    import com.liferay.portal.kernel.portlet.LiferayPortletURL;
024    import com.liferay.portal.kernel.servlet.URLEncoder;
025    import com.liferay.portal.kernel.util.ArrayUtil;
026    import com.liferay.portal.kernel.util.GetterUtil;
027    import com.liferay.portal.kernel.util.ParamUtil;
028    import com.liferay.portal.kernel.util.StringUtil;
029    import com.liferay.portal.kernel.util.Validator;
030    import com.liferay.portal.model.Layout;
031    import com.liferay.portal.model.LayoutConstants;
032    import com.liferay.portal.model.Portlet;
033    import com.liferay.portal.model.PortletApp;
034    import com.liferay.portal.model.PortletURLListener;
035    import com.liferay.portal.security.lang.DoPrivilegedUtil;
036    import com.liferay.portal.security.xml.SecureXMLFactoryProviderUtil;
037    import com.liferay.portal.service.LayoutLocalServiceUtil;
038    import com.liferay.portal.service.PortletLocalServiceUtil;
039    import com.liferay.portal.struts.StrutsActionPortletURL;
040    import com.liferay.portal.theme.ThemeDisplay;
041    import com.liferay.portal.util.PortalUtil;
042    import com.liferay.portal.util.PropsValues;
043    import com.liferay.portal.util.WebKeys;
044    
045    import java.io.Writer;
046    
047    import java.lang.reflect.Constructor;
048    
049    import java.security.PrivilegedAction;
050    
051    import java.util.ArrayList;
052    import java.util.LinkedHashMap;
053    import java.util.List;
054    import java.util.Map;
055    import java.util.Set;
056    import java.util.concurrent.ConcurrentHashMap;
057    
058    import javax.portlet.MimeResponse;
059    import javax.portlet.PortletException;
060    import javax.portlet.PortletModeException;
061    import javax.portlet.PortletPreferences;
062    import javax.portlet.PortletRequest;
063    import javax.portlet.PortletResponse;
064    import javax.portlet.PortletURL;
065    import javax.portlet.PortletURLGenerationListener;
066    import javax.portlet.ResourceURL;
067    import javax.portlet.WindowStateException;
068    import javax.portlet.filter.PortletResponseWrapper;
069    
070    import javax.servlet.http.Cookie;
071    import javax.servlet.http.HttpServletRequest;
072    import javax.servlet.http.HttpServletResponse;
073    
074    import javax.xml.parsers.DocumentBuilder;
075    import javax.xml.parsers.DocumentBuilderFactory;
076    import javax.xml.parsers.ParserConfigurationException;
077    import javax.xml.transform.OutputKeys;
078    import javax.xml.transform.Transformer;
079    import javax.xml.transform.TransformerFactory;
080    import javax.xml.transform.dom.DOMSource;
081    import javax.xml.transform.stream.StreamResult;
082    
083    import org.w3c.dom.DOMException;
084    import org.w3c.dom.Document;
085    import org.w3c.dom.Element;
086    
087    /**
088     * @author Brian Wing Shun Chan
089     */
090    public abstract class PortletResponseImpl implements LiferayPortletResponse {
091    
092            public static PortletResponseImpl getPortletResponseImpl(
093                    PortletResponse portletResponse) {
094    
095                    while (!(portletResponse instanceof PortletResponseImpl)) {
096                            if (portletResponse instanceof PortletResponseWrapper) {
097                                    PortletResponseWrapper portletResponseWrapper =
098                                            (PortletResponseWrapper)portletResponse;
099    
100                                    portletResponse = portletResponseWrapper.getResponse();
101                            }
102                            else {
103                                    throw new RuntimeException(
104                                            "Unable to unwrap the portlet response from " +
105                                                    portletResponse.getClass());
106                            }
107                    }
108    
109                    return (PortletResponseImpl)portletResponse;
110            }
111    
112            @Override
113            public void addDateHeader(String name, long date) {
114                    if (Validator.isNull(name)) {
115                            throw new IllegalArgumentException();
116                    }
117    
118                    Long[] values = (Long[])_headers.get(name);
119    
120                    if (values == null) {
121                            setDateHeader(name, date);
122                    }
123                    else {
124                            values = ArrayUtil.append(values, new Long(date));
125    
126                            _headers.put(name, values);
127                    }
128            }
129    
130            @Override
131            public void addHeader(String name, String value) {
132                    if (Validator.isNull(name)) {
133                            throw new IllegalArgumentException();
134                    }
135    
136                    String[] values = (String[])_headers.get(name);
137    
138                    if (values == null) {
139                            setHeader(name, value);
140                    }
141                    else {
142                            values = ArrayUtil.append(values, value);
143    
144                            _headers.put(name, values);
145                    }
146            }
147    
148            @Override
149            public void addIntHeader(String name, int value) {
150                    if (Validator.isNull(name)) {
151                            throw new IllegalArgumentException();
152                    }
153    
154                    Integer[] values = (Integer[])_headers.get(name);
155    
156                    if (values == null) {
157                            setIntHeader(name, value);
158                    }
159                    else {
160                            values = ArrayUtil.append(values, new Integer(value));
161    
162                            _headers.put(name, values);
163                    }
164            }
165    
166            @Override
167            public void addProperty(Cookie cookie) {
168                    if (cookie == null) {
169                            throw new IllegalArgumentException();
170                    }
171    
172                    Cookie[] cookies = (Cookie[])_headers.get("cookies");
173    
174                    if (cookies == null) {
175                            _headers.put("cookies", new Cookie[] {cookie});
176                    }
177                    else {
178                            cookies = ArrayUtil.append(cookies, cookie);
179    
180                            _headers.put("cookies", cookies);
181                    }
182            }
183    
184            @Override
185            public void addProperty(String key, Element element) {
186                    if (key == null) {
187                            throw new IllegalArgumentException();
188                    }
189    
190                    if (StringUtil.equalsIgnoreCase(
191                                    key, MimeResponse.MARKUP_HEAD_ELEMENT)) {
192    
193                            List<Element> values = _markupHeadElements.get(key);
194    
195                            if (values != null) {
196                                    if (element != null) {
197                                            values.add(element);
198                                    }
199                                    else {
200                                            _markupHeadElements.remove(key);
201                                    }
202                            }
203                            else {
204                                    if (element != null) {
205                                            values = new ArrayList<Element>();
206    
207                                            values.add(element);
208    
209                                            _markupHeadElements.put(key, values);
210                                    }
211                            }
212                    }
213            }
214    
215            @Override
216            public void addProperty(String key, String value) {
217                    if (Validator.isNull(key)) {
218                            throw new IllegalArgumentException();
219                    }
220    
221                    addHeader(key, value);
222            }
223    
224            @Override
225            public PortletURL createActionURL() {
226                    return createActionURL(_portletName);
227            }
228    
229            @Override
230            public LiferayPortletURL createActionURL(String portletName) {
231                    return createLiferayPortletURL(
232                            portletName, PortletRequest.ACTION_PHASE);
233            }
234    
235            @Override
236            public Element createElement(String tagName) throws DOMException {
237                    if (_document == null) {
238                            try {
239                                    DocumentBuilderFactory documentBuilderFactory =
240                                            SecureXMLFactoryProviderUtil.newDocumentBuilderFactory();
241    
242                                    DocumentBuilder documentBuilder =
243                                            documentBuilderFactory.newDocumentBuilder();
244    
245                                    _document = documentBuilder.newDocument();
246                            }
247                            catch (ParserConfigurationException pce) {
248                                    throw new DOMException(
249                                            DOMException.INVALID_STATE_ERR, pce.getMessage());
250                            }
251                    }
252    
253                    return _document.createElement(tagName);
254            }
255    
256            @Override
257            public LiferayPortletURL createLiferayPortletURL(
258                    long plid, String portletName, String lifecycle) {
259    
260                    return createLiferayPortletURL(plid, portletName, lifecycle, true);
261            }
262    
263            @Override
264            public LiferayPortletURL createLiferayPortletURL(
265                    long plid, String portletName, String lifecycle,
266                    boolean includeLinkToLayoutUuid) {
267    
268                    return DoPrivilegedUtil.wrap(
269                            new LiferayPortletURLPrivilegedAction(
270                                    plid, portletName, lifecycle, includeLinkToLayoutUuid));
271            }
272    
273            @Override
274            public LiferayPortletURL createLiferayPortletURL(String lifecycle) {
275                    return createLiferayPortletURL(_portletName, lifecycle);
276            }
277    
278            @Override
279            public LiferayPortletURL createLiferayPortletURL(
280                    String portletName, String lifecycle) {
281    
282                    return createLiferayPortletURL(_plid, portletName, lifecycle);
283            }
284    
285            @Override
286            public PortletURL createRenderURL() {
287                    return createRenderURL(_portletName);
288            }
289    
290            @Override
291            public LiferayPortletURL createRenderURL(String portletName) {
292                    return createLiferayPortletURL(
293                            portletName, PortletRequest.RENDER_PHASE);
294            }
295    
296            @Override
297            public ResourceURL createResourceURL() {
298                    return createResourceURL(_portletName);
299            }
300    
301            @Override
302            public LiferayPortletURL createResourceURL(String portletName) {
303                    return createLiferayPortletURL(
304                            portletName, PortletRequest.RESOURCE_PHASE);
305            }
306    
307            @Override
308            public String encodeURL(String path) {
309                    if ((path == null) ||
310                            (!path.startsWith("#") && !path.startsWith("/") &&
311                             !path.contains("://"))) {
312    
313                            // Allow '#' as well to workaround a bug in Oracle ADF 10.1.3
314    
315                            throw new IllegalArgumentException(
316                                    "URL path must start with a '/' or include '://'");
317                    }
318    
319                    if (_urlEncoder != null) {
320                            return _urlEncoder.encodeURL(_response, path);
321                    }
322                    else {
323                            return path;
324                    }
325            }
326    
327            public long getCompanyId() {
328                    return _companyId;
329            }
330    
331            public HttpServletRequest getHttpServletRequest() {
332                    return _portletRequestImpl.getHttpServletRequest();
333            }
334    
335            @Override
336            public HttpServletResponse getHttpServletResponse() {
337                    return _response;
338            }
339    
340            public abstract String getLifecycle();
341    
342            @Override
343            public String getNamespace() {
344                    if (_wsrp) {
345                            return "wsrp_rewrite_";
346                    }
347    
348                    if (_namespace == null) {
349                            _namespace = PortalUtil.getPortletNamespace(_portletName);
350                    }
351    
352                    return _namespace;
353            }
354    
355            public long getPlid() {
356                    return _plid;
357            }
358    
359            public Portlet getPortlet() {
360                    if (_portlet == null) {
361                            try {
362                                    _portlet = PortletLocalServiceUtil.getPortletById(
363                                            _companyId, _portletName);
364                            }
365                            catch (Exception e) {
366                                    _log.error(e);
367                            }
368                    }
369    
370                    return _portlet;
371            }
372    
373            public String getPortletName() {
374                    return _portletName;
375            }
376    
377            public PortletRequestImpl getPortletRequest() {
378                    return _portletRequestImpl;
379            }
380    
381            @Override
382            public Map<String, String[]> getProperties() {
383                    Map<String, String[]> properties =
384                            new LinkedHashMap<String, String[]>();
385    
386                    for (Map.Entry<String, Object> entry : _headers.entrySet()) {
387                            String name = entry.getKey();
388                            Object[] values = (Object[])entry.getValue();
389    
390                            String[] valuesString = new String[values.length];
391    
392                            for (int i = 0; i < values.length; i++) {
393                                    valuesString[i] = values[i].toString();
394                            }
395    
396                            properties.put(name, valuesString);
397                    }
398    
399                    return properties;
400            }
401    
402            public URLEncoder getUrlEncoder() {
403                    return _urlEncoder;
404            }
405    
406            @Override
407            public void setDateHeader(String name, long date) {
408                    if (Validator.isNull(name)) {
409                            throw new IllegalArgumentException();
410                    }
411    
412                    if (date <= 0) {
413                            _headers.remove(name);
414                    }
415                    else {
416                            _headers.put(name, new Long[] {new Long(date)});
417                    }
418            }
419    
420            @Override
421            public void setHeader(String name, String value) {
422                    if (Validator.isNull(name)) {
423                            throw new IllegalArgumentException();
424                    }
425    
426                    if (Validator.isNull(value)) {
427                            _headers.remove(name);
428                    }
429                    else {
430                            _headers.put(name, new String[] {value});
431                    }
432            }
433    
434            @Override
435            public void setIntHeader(String name, int value) {
436                    if (Validator.isNull(name)) {
437                            throw new IllegalArgumentException();
438                    }
439    
440                    if (value <= 0) {
441                            _headers.remove(name);
442                    }
443                    else {
444                            _headers.put(name, new Integer[] {new Integer(value)});
445                    }
446            }
447    
448            public void setPlid(long plid) {
449                    _plid = plid;
450    
451                    if (_plid <= 0) {
452                            Layout layout = (Layout)_portletRequestImpl.getAttribute(
453                                    WebKeys.LAYOUT);
454    
455                            if (layout != null) {
456                                    _plid = layout.getPlid();
457                            }
458                    }
459            }
460    
461            @Override
462            public void setProperty(String key, String value) {
463                    if (key == null) {
464                            throw new IllegalArgumentException();
465                    }
466    
467                    setHeader(key, value);
468            }
469    
470            public void setURLEncoder(URLEncoder urlEncoder) {
471                    _urlEncoder = urlEncoder;
472            }
473    
474            public void transferHeaders(HttpServletResponse response) {
475                    for (Map.Entry<String, Object> entry : _headers.entrySet()) {
476                            String name = entry.getKey();
477                            Object values = entry.getValue();
478    
479                            if (values instanceof Integer[]) {
480                                    Integer[] intValues = (Integer[])values;
481    
482                                    for (int value : intValues) {
483                                            if (response.containsHeader(name)) {
484                                                    response.addIntHeader(name, value);
485                                            }
486                                            else {
487                                                    response.setIntHeader(name, value);
488                                            }
489                                    }
490                            }
491                            else if (values instanceof Long[]) {
492                                    Long[] dateValues = (Long[])values;
493    
494                                    for (long value : dateValues) {
495                                            if (response.containsHeader(name)) {
496                                                    response.addDateHeader(name, value);
497                                            }
498                                            else {
499                                                    response.setDateHeader(name, value);
500                                            }
501                                    }
502                            }
503                            else if (values instanceof String[]) {
504                                    String[] stringValues = (String[])values;
505    
506                                    for (String value : stringValues) {
507                                            if (response.containsHeader(name)) {
508                                                    response.addHeader(name, value);
509                                            }
510                                            else {
511                                                    response.setHeader(name, value);
512                                            }
513                                    }
514                            }
515                            else if (values instanceof Cookie[]) {
516                                    Cookie[] cookies = (Cookie[])values;
517    
518                                    for (Cookie cookie : cookies) {
519                                            response.addCookie(cookie);
520                                    }
521                            }
522                    }
523            }
524    
525            @Override
526            public void transferMarkupHeadElements() {
527                    List<Element> elements = _markupHeadElements.get(
528                            MimeResponse.MARKUP_HEAD_ELEMENT);
529    
530                    if ((elements == null) || elements.isEmpty()) {
531                            return;
532                    }
533    
534                    HttpServletRequest request = getHttpServletRequest();
535    
536                    List<String> markupHeadElements = (List<String>)request.getAttribute(
537                            MimeResponse.MARKUP_HEAD_ELEMENT);
538    
539                    if (markupHeadElements == null) {
540                            markupHeadElements = new ArrayList<String>();
541    
542                            request.setAttribute(
543                                    MimeResponse.MARKUP_HEAD_ELEMENT, markupHeadElements);
544                    }
545    
546                    for (Element element : elements) {
547                            try {
548                                    Writer writer = new UnsyncStringWriter();
549    
550                                    TransformerFactory transformerFactory =
551                                            TransformerFactory.newInstance();
552    
553                                    Transformer transformer = transformerFactory.newTransformer();
554    
555                                    transformer.setOutputProperty(
556                                            OutputKeys.OMIT_XML_DECLARATION, "yes");
557    
558                                    transformer.transform(
559                                            new DOMSource(element), new StreamResult(writer));
560    
561                                    markupHeadElements.add(writer.toString());
562                            }
563                            catch (Exception e) {
564                                    if (_log.isWarnEnabled()) {
565                                            _log.warn(e, e);
566                                    }
567                            }
568                    }
569            }
570    
571            protected LiferayPortletURL doCreateLiferayPortletURL(
572                    long plid, String portletName, String lifecycle,
573                    boolean includeLinkToLayoutUuid) {
574    
575                    try {
576                            Layout layout = (Layout)_portletRequestImpl.getAttribute(
577                                    WebKeys.LAYOUT);
578    
579                            if (layout == null) {
580                                    ThemeDisplay themeDisplay =
581                                            (ThemeDisplay)_portletRequestImpl.getAttribute(
582                                                    WebKeys.THEME_DISPLAY);
583    
584                                    if (themeDisplay != null) {
585                                            layout = themeDisplay.getLayout();
586                                    }
587                            }
588    
589                            if (_portletSetup == null) {
590                                    _portletSetup =
591                                            PortletPreferencesFactoryUtil.getStrictLayoutPortletSetup(
592                                                    layout, _portletName);
593                            }
594    
595                            String linkToLayoutUuid = GetterUtil.getString(
596                                    _portletSetup.getValue("portletSetupLinkToLayoutUuid", null));
597    
598                            if (PropsValues.PORTLET_CROSS_LAYOUT_INVOCATION_MODE.equals(
599                                            "render") &&
600                                    !PortletRequest.RENDER_PHASE.equals(lifecycle)) {
601    
602                                    includeLinkToLayoutUuid = false;
603                            }
604    
605                            if (Validator.isNotNull(linkToLayoutUuid) &&
606                                    includeLinkToLayoutUuid) {
607    
608                                    try {
609                                            Layout linkedLayout =
610                                                    LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
611                                                            linkToLayoutUuid, layout.getGroupId(),
612                                                            layout.isPrivateLayout());
613    
614                                            plid = linkedLayout.getPlid();
615                                    }
616                                    catch (PortalException pe) {
617                                    }
618                            }
619                    }
620                    catch (SystemException se) {
621                            if (_log.isWarnEnabled()) {
622                                    _log.warn(se);
623                            }
624                    }
625    
626                    if (plid == LayoutConstants.DEFAULT_PLID) {
627                            plid = _plid;
628                    }
629    
630                    PortletURLImpl portletURLImpl = null;
631    
632                    Portlet portlet = getPortlet();
633    
634                    String portletURLClass = portlet.getPortletURLClass();
635    
636                    if (portlet.getPortletId().equals(portletName) &&
637                            Validator.isNotNull(portletURLClass)) {
638    
639                            if (portletURLClass.equals(
640                                            StrutsActionPortletURL.class.getName())) {
641    
642                                    portletURLImpl = new StrutsActionPortletURL(
643                                            this, plid, lifecycle);
644                            }
645                            else {
646                                    try {
647                                            Constructor<? extends PortletURLImpl> constructor =
648                                                    _constructors.get(portletURLClass);
649    
650                                            if (constructor == null) {
651                                                    Class<?> portletURLClassObj = Class.forName(
652                                                            portletURLClass);
653    
654                                                    constructor = (Constructor<? extends PortletURLImpl>)
655                                                            portletURLClassObj.getConstructor(
656                                                                    new Class[] {
657                                                                            PortletResponseImpl.class, long.class,
658                                                                            String.class
659                                                                    });
660    
661                                                    _constructors.put(portletURLClass, constructor);
662                                            }
663    
664                                            portletURLImpl = constructor.newInstance(
665                                                    new Object[] {this, plid, lifecycle});
666                                    }
667                                    catch (Exception e) {
668                                            _log.error(e);
669                                    }
670                            }
671                    }
672    
673                    if (portletURLImpl == null) {
674                            portletURLImpl = new PortletURLImpl(
675                                    _portletRequestImpl, portletName, plid, lifecycle);
676                    }
677    
678                    PortletApp portletApp = portlet.getPortletApp();
679    
680                    Set<PortletURLListener> portletURLListeners =
681                            portletApp.getPortletURLListeners();
682    
683                    for (PortletURLListener portletURLListener : portletURLListeners) {
684                            try {
685                                    PortletURLGenerationListener portletURLGenerationListener =
686                                            PortletURLListenerFactory.create(portletURLListener);
687    
688                                    if (lifecycle.equals(PortletRequest.ACTION_PHASE)) {
689                                            portletURLGenerationListener.filterActionURL(
690                                                    portletURLImpl);
691                                    }
692                                    else if (lifecycle.equals(PortletRequest.RENDER_PHASE)) {
693                                            portletURLGenerationListener.filterRenderURL(
694                                                    portletURLImpl);
695                                    }
696                                    else if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
697                                            portletURLGenerationListener.filterResourceURL(
698                                                    portletURLImpl);
699                                    }
700                            }
701                            catch (PortletException pe) {
702                                    _log.error(pe, pe);
703                            }
704                    }
705    
706                    try {
707                            portletURLImpl.setWindowState(_portletRequestImpl.getWindowState());
708                    }
709                    catch (WindowStateException wse) {
710                            _log.error(wse.getMessage());
711                    }
712    
713                    try {
714                            portletURLImpl.setPortletMode(_portletRequestImpl.getPortletMode());
715                    }
716                    catch (PortletModeException pme) {
717                            _log.error(pme.getMessage());
718                    }
719    
720                    if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
721                            portletURLImpl.setCopyCurrentRenderParameters(true);
722                    }
723    
724                    return portletURLImpl;
725            }
726    
727            protected void init(
728                    PortletRequestImpl portletRequestImpl, HttpServletResponse response,
729                    String portletName, long companyId, long plid) {
730    
731                    _portletRequestImpl = portletRequestImpl;
732                    _response = response;
733                    _portletName = portletName;
734                    _companyId = companyId;
735                    _wsrp = ParamUtil.getBoolean(getHttpServletRequest(), "wsrp");
736    
737                    setPlid(plid);
738            }
739    
740            private static Log _log = LogFactoryUtil.getLog(PortletResponseImpl.class);
741    
742            private long _companyId;
743            private Map<String, Constructor<? extends PortletURLImpl>> _constructors =
744                    new ConcurrentHashMap<String, Constructor<? extends PortletURLImpl>>();
745            private Document _document;
746            private Map<String, Object> _headers = new LinkedHashMap<String, Object>();
747            private Map<String, List<Element>> _markupHeadElements =
748                    new LinkedHashMap<String, List<Element>>();
749            private String _namespace;
750            private long _plid;
751            private Portlet _portlet;
752            private String _portletName;
753            private PortletRequestImpl _portletRequestImpl;
754            private PortletPreferences _portletSetup;
755            private HttpServletResponse _response;
756            private URLEncoder _urlEncoder;
757            private boolean _wsrp;
758    
759            private class LiferayPortletURLPrivilegedAction
760                    implements PrivilegedAction<LiferayPortletURL> {
761    
762                    public LiferayPortletURLPrivilegedAction(
763                            long plid, String portletName, String lifecycle,
764                            boolean includeLinkToLayoutUuid) {
765    
766                            _plid = plid;
767                            _portletName = portletName;
768                            _lifecycle = lifecycle;
769                            _includeLinkToLayoutUuid = includeLinkToLayoutUuid;
770                    }
771    
772                    @Override
773                    public LiferayPortletURL run() {
774                            return doCreateLiferayPortletURL(
775                                    _plid, _portletName, _lifecycle, _includeLinkToLayoutUuid);
776                    }
777    
778                    private boolean _includeLinkToLayoutUuid;
779                    private String _lifecycle;
780                    private long _plid;
781                    private String _portletName;
782    
783            }
784    
785    }