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    
032        private final PortletURL _portletURL;
033    
034        private final QueryParameterMap _parameters;
035    
036        public PortletLink(PortletURL portletURL, QueryParameterMap parameters)
037        {
038            Defense.notNull(portletURL, "portletURL");
039            Defense.notNull(parameters, "parameters");
040    
041            _portletURL = portletURL;
042            _parameters = parameters;
043        }
044    
045        public String getURL()
046        {
047            return getURL(null, true);
048        }
049    
050        public String getURL(String anchor, boolean includeParameters)
051        {
052            if (includeParameters) loadParameters();
053    
054            String url = _portletURL.toString();
055    
056            url = unencode(url);
057    
058            if (anchor != null) url = url + "#" + anchor;
059    
060            return url;
061        }
062    
063        /**
064         * The PortletURL class returns a url that's already XML-escaped, ready for
065         * inclusion directly into the response stream. However, the IMarkupWriter
066         * expects to do that encoding too ... and double encoding is bad. So we
067         * back out the most likely encoding (convert '&' to just '&').
068         */
069    
070        private String unencode(String url)
071        {
072            StringBuffer buffer = new StringBuffer(url.length());
073            String text = url;
074    
075            while(true)
076            {
077                int ampx = text.indexOf("&");
078    
079                if (ampx < 0) break;
080    
081                // Take up to and including the '&'
082    
083                buffer.append(text.substring(0, ampx + 1));
084    
085                text = text.substring(ampx + 5);
086            }
087    
088            buffer.append(text);
089    
090            return buffer.toString();
091        }
092    
093        private void loadParameters()
094        {
095            String[] names = _parameters.getParameterNames();
096    
097            for(int i = 0; i < names.length; i++)
098            {
099                String name = names[i];
100                String[] values = _parameters.getParameterValues(name);
101    
102                if (values != null) _portletURL.setParameter(name, values);
103            }
104        }
105    
106        public String getURL(String scheme, String server, int port, String anchor,
107                boolean includeParameters)
108        {
109            // Ignore scheme, server and port ... those are under the control of the
110            // portlet container.
111    
112            return getURL(anchor, includeParameters);
113        }
114    
115        public String getAbsoluteURL()
116        {
117            throw new UnsupportedOperationException(PortletMessages
118                    .unsupportedMethod("getAbsoluteURL"));
119        }
120    
121        public String getAbsoluteURL(String scheme, String server, int port,
122                String anchor, boolean includeParameters)
123        {
124            throw new UnsupportedOperationException(PortletMessages
125                    .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    }