001    // Copyright 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry.portlet;
016    
017    import javax.portlet.PortletURL;
018    
019    import org.apache.hivemind.util.Defense;
020    import org.apache.tapestry.engine.ILink;
021    import org.apache.tapestry.util.QueryParameterMap;
022    
023    /**
024     * Wrapper around {@link javax.portlet.PortletURL}.
025     * 
026     * @author Howard M. Lewis Ship
027     * @since 4.0
028     */
029    public class PortletLink implements ILink
030    {
031        private final PortletURL _portletURL;
032    
033        private final QueryParameterMap _parameters;
034    
035        public PortletLink(PortletURL portletURL, QueryParameterMap parameters)
036        {
037            Defense.notNull(portletURL, "portletURL");
038            Defense.notNull(parameters, "parameters");
039    
040            _portletURL = portletURL;
041            _parameters = parameters;
042        }
043    
044        public String getURL()
045        {
046            return getURL(null, true);
047        }
048    
049        public String getURL(String anchor, boolean includeParameters)
050        {
051            if (includeParameters)
052                loadParameters();
053    
054            String url = _portletURL.toString();
055    
056            url = unencode(url);
057    
058            if (anchor != null)
059                url = url + "#" + anchor;
060    
061            return url;
062        }
063    
064        /**
065         * The PortletURL class returns a url that's already XML-escaped, ready for inclusion directly
066         * into the response stream. However, the IMarkupWriter expects to do that encoding too ... and
067         * double encoding is bad. So we back out the most likely encoding (convert '&' to just
068         * '&').
069         */
070    
071        private String unencode(String url)
072        {
073            StringBuffer buffer = new StringBuffer(url.length());
074            String text = url;
075    
076            while (true)
077            {
078                int ampx = text.indexOf("&");
079    
080                if (ampx < 0)
081                    break;
082    
083                // Take up to and including the '&'
084    
085                buffer.append(text.substring(0, ampx + 1));
086    
087                text = text.substring(ampx + 5);
088            }
089    
090            buffer.append(text);
091    
092            return buffer.toString();
093        }
094    
095        private void loadParameters()
096        {
097            String[] names = _parameters.getParameterNames();
098    
099            for (int i = 0; i < names.length; i++)
100            {
101                String name = names[i];
102                String[] values = _parameters.getParameterValues(name);
103    
104                if (values != null)
105                    _portletURL.setParameter(name, values);
106            }
107        }
108    
109        public String getURL(String scheme, String server, int port, String anchor,
110                boolean includeParameters)
111        {
112            // Ignore scheme, server and port ... those are under the control of the portlet container.
113    
114            return getURL(anchor, includeParameters);
115        }
116    
117        public String getAbsoluteURL()
118        {
119            throw new UnsupportedOperationException(PortletMessages.unsupportedMethod("getAbsoluteURL"));
120        }
121    
122        public String getAbsoluteURL(String scheme, String server, int port, String anchor,
123                boolean includeParameters)
124        {
125            throw new UnsupportedOperationException(PortletMessages.unsupportedMethod("getAbsoluteURL"));
126        }
127    
128        public String[] getParameterNames()
129        {
130            return _parameters.getParameterNames();
131        }
132    
133        public String[] getParameterValues(String name)
134        {
135            return _parameters.getParameterValues(name);
136        }
137    
138    }