001    package org.apache.turbine.util.uri;
002    
003    
004    /*
005     * Licensed to the Apache Software Foundation (ASF) under one
006     * or more contributor license agreements.  See the NOTICE file
007     * distributed with this work for additional information
008     * regarding copyright ownership.  The ASF licenses this file
009     * to you under the Apache License, Version 2.0 (the
010     * "License"); you may not use this file except in compliance
011     * with the License.  You may obtain a copy of the License at
012     *
013     *   http://www.apache.org/licenses/LICENSE-2.0
014     *
015     * Unless required by applicable law or agreed to in writing,
016     * software distributed under the License is distributed on an
017     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
018     * KIND, either express or implied.  See the License for the
019     * specific language governing permissions and limitations
020     * under the License.
021     */
022    
023    
024    import javax.servlet.http.HttpServletResponse;
025    
026    import org.apache.commons.lang.StringUtils;
027    
028    import org.apache.commons.logging.Log;
029    import org.apache.commons.logging.LogFactory;
030    
031    import org.apache.turbine.Turbine;
032    import org.apache.turbine.TurbineConstants;
033    
034    import org.apache.turbine.util.RunData;
035    import org.apache.turbine.util.ServerData;
036    
037    /**
038     * This is the base class for all dynamic URIs in the Turbine System.
039     *
040     * All of the classes used for generating URIs are derived from this.
041     *
042     * @author <a href="mailto:jon@clearink.com">Jon S. Stevens</a>
043     * @author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
044     * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
045     * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
046     * @version $Id: BaseURI.java 615328 2008-01-25 20:25:05Z tv $
047     */
048    
049    public abstract class BaseURI
050            implements URI,
051                       URIConstants
052    {
053        /** Logging */
054        private static Log log = LogFactory.getLog(BaseURI.class);
055    
056        /** ServerData Object for scheme, name, port etc. */
057        private ServerData serverData =
058                new ServerData(null, HTTP_PORT, HTTP, null, null);
059    
060        /** Whether we want to redirect or not. */
061        private boolean redirect = false;
062    
063        /** Servlet response interface. */
064        private HttpServletResponse response = null;
065    
066        /** Reference Anchor (#ref) */
067        private String reference = null;
068    
069        /*
070         * ========================================================================
071         *
072         * Constructors
073         *
074         * ========================================================================
075         *
076         */
077    
078        /**
079         * Empty C'tor. Uses Turbine.getDefaultServerData().
080         *
081         */
082        public BaseURI()
083        {
084            init(Turbine.getDefaultServerData());
085            setResponse(null);
086        }
087    
088        /**
089         * Constructor with a RunData object
090         *
091         * @param runData A RunData object
092         */
093        public BaseURI(RunData runData)
094        {
095            init(runData.getServerData());
096            setResponse(runData.getResponse());
097        }
098    
099        /**
100         * Constructor, set explicit redirection
101         *
102         * @param runData A RunData object
103         * @param redirect True if redirection allowed.
104         */
105        public BaseURI(RunData runData, boolean redirect)
106        {
107            init(runData.getServerData());
108            setResponse(runData.getResponse());
109            setRedirect(redirect);
110        }
111    
112        /**
113         * Constructor with a ServerData object
114         *
115         * @param serverData A ServerData object
116         */
117        public BaseURI(ServerData serverData)
118        {
119            init(serverData);
120            setResponse(null);
121        }
122    
123        /**
124         * Constructor, set explicit redirection
125         *
126         * @param serverData A ServerData object
127         * @param redirect True if redirection allowed.
128         */
129        public BaseURI(ServerData serverData, boolean redirect)
130        {
131            init(serverData);
132            setResponse(null);
133            setRedirect(redirect);
134        }
135    
136        /*
137         * ========================================================================
138         *
139         * Init
140         *
141         * ========================================================================
142         *
143         */
144    
145        /**
146         * Init with a ServerData object
147         *
148         * @param serverData A ServerData object
149         *
150         */
151        private void init(ServerData serverData)
152        {
153            log.debug("init(" + serverData + ")");
154    
155            if(serverData != null)
156            {
157                // We must clone this, because if BaseURI is used in a pull tool,
158                // then the fields might be changed. If we don't clone, this might pull
159                // through to the ServerData object saved at firstRequest() in the
160                // Turbine object.
161                this.serverData = (ServerData) serverData.clone();
162            }
163            else
164            {
165                log.error("Passed null ServerData object!");
166            }
167            reference = null;
168        }
169    
170        /*
171         * ========================================================================
172         *
173         * Getter / Setter
174         *
175         * ========================================================================
176         *
177         */
178    
179        /**
180         * Set the redirect Flag
181         *
182         * @param redirect The new value of the redirect flag.
183         */
184        public void setRedirect(boolean redirect)
185        {
186            this.redirect = redirect;
187        }
188    
189        /**
190         * Returns the current value of the Redirect flag
191         *
192         * @return True if Redirect is allowed
193         *
194         */
195        public boolean isRedirect()
196        {
197            return redirect;
198        }
199    
200        /**
201         * Gets the script name (/servlets/Turbine).
202         *
203         * @return A String with the script name.
204         */
205        public String getScriptName()
206        {
207            return serverData.getScriptName();
208        }
209    
210        /**
211         * Sets the script name (/servlets/Turbine).
212         *
213         * @param scriptName A String with the script name.
214         */
215        public void setScriptName(String scriptName)
216        {
217            serverData.setScriptName(scriptName);
218        }
219    
220        /**
221         * Gets the context path.
222         *
223         * @return A String with the context path.
224         */
225        public String getContextPath()
226        {
227            return serverData.getContextPath();
228        }
229    
230        /**
231         * Sets the context path.
232         *
233         * @param contextPath A String with the context path
234         */
235        public void setContextPath(String contextPath)
236        {
237            serverData.setContextPath(contextPath);
238        }
239    
240        /**
241         * Gets the server name.
242         *
243         * @return A String with the server name.
244         */
245        public String getServerName()
246        {
247            return serverData.getServerName();
248        }
249    
250        /**
251         * Sets the server name.
252         *
253         * @param serverName A String with the server name.
254         */
255        public void setServerName(String serverName)
256        {
257            serverData.setServerName(serverName);
258        }
259    
260        /**
261         * Gets the server port.
262         *
263         * @return A String with the server port.
264         */
265        public int getServerPort()
266        {
267            int serverPort = serverData.getServerPort();
268    
269            if (serverPort == 0)
270            {
271                if(getServerScheme().equals(HTTPS))
272                {
273                    serverPort = HTTPS_PORT;
274                }
275                else
276                {
277                    serverPort = HTTP_PORT;
278                }
279            }
280            return serverPort;
281        }
282    
283        /**
284         * Sets the server port.
285         *
286         * @param serverPort An int with the port.
287         */
288        public void setServerPort(int serverPort)
289        {
290            serverData.setServerPort(serverPort);
291        }
292    
293        /**
294         * Method to specify that a URI should use SSL. The default port
295         * is used.
296         */
297        public void setSecure()
298        {
299            setSecure(HTTPS_PORT);
300        }
301    
302        /**
303         * Method to specify that a URI should use SSL.
304         * Whether or not it does is determined from Turbine.properties.
305         * If use.ssl in the Turbine.properties is set to false, then
306         * http is used in any case. (Default of use.ssl is true).
307         *
308         * @param port An int with the port number.
309         */
310        public void setSecure(int port)
311        {
312            boolean useSSL =
313                    Turbine.getConfiguration()
314                    .getBoolean(TurbineConstants.USE_SSL_KEY,
315                            TurbineConstants.USE_SSL_DEFAULT);
316    
317            setServerScheme(useSSL ? HTTPS : HTTP);
318            setServerPort(port);
319        }
320    
321        /**
322         * Sets the scheme (HTTP or HTTPS).
323         *
324         * @param serverScheme A String with the scheme.
325         */
326        public void setServerScheme(String serverScheme)
327        {
328            serverData.setServerScheme(StringUtils.isNotEmpty(serverScheme)
329                    ? serverScheme : "");
330        }
331    
332        /**
333         * Returns the current Server Scheme
334         *
335         * @return The current Server scheme
336         *
337         */
338        public String getServerScheme()
339        {
340            String serverScheme = serverData.getServerScheme();
341    
342            return StringUtils.isNotEmpty(serverScheme) ? serverScheme : HTTP;
343        }
344    
345        /**
346         * Sets a reference anchor (#ref).
347         *
348         * @param reference A String containing the reference.
349         */
350        public void setReference(String reference)
351        {
352            this.reference = reference;
353        }
354    
355        /**
356         * Returns the current reference anchor.
357         *
358         * @return A String containing the reference.
359         */
360        public String getReference()
361        {
362            return hasReference() ? reference : "";
363        }
364    
365        /**
366         * Does this URI contain an anchor? (#ref)
367         *
368         * @return True if this URI contains an anchor.
369         */
370        public boolean hasReference()
371        {
372            return StringUtils.isNotEmpty(reference);
373        }
374    
375        /*
376         * ========================================================================
377         *
378         * Protected / Private Methods
379         *
380         * ========================================================================
381         *
382         */
383    
384        /**
385         * Set a Response Object to use when creating the
386         * response string.
387         *
388         */
389        protected void setResponse(HttpServletResponse response)
390        {
391            this.response = response;
392        }
393    
394        /**
395         * Returns the Response Object from the Servlet Container.
396         *
397         * @return The Servlet Response object or null
398         *
399         */
400        protected HttpServletResponse getResponse()
401        {
402            return response;
403        }
404    
405        /**
406         * Append the Context Path and Script Name to the passed
407         * String Buffer.
408         *
409         * <p>
410         * This is a convenience method to be
411         * used in the Link output routines of derived classes to
412         * easily append the correct path.
413         *
414         * @param sb The StringBuffer to store context path and script name.
415         */
416        protected void getContextAndScript(StringBuffer sb)
417        {
418            String context = getContextPath();
419    
420            if(StringUtils.isNotEmpty(context))
421            {
422                if(context.charAt(0) != '/')
423                {
424                    sb.append('/');
425                }
426                sb.append (context);
427            }
428    
429            // /servlet/turbine
430            String script = getScriptName();
431    
432            if(StringUtils.isNotEmpty(script))
433            {
434                if(script.charAt(0) != '/')
435                {
436                    sb.append('/');
437                }
438                sb.append (script);
439            }
440        }
441    
442        /**
443         * Appends Scheme, Server and optionally the port to the
444         * supplied String Buffer.
445         *
446         * <p>
447         * This is a convenience method to be
448         * used in the Link output routines of derived classes to
449         * easily append the correct server scheme.
450         *
451         * @param sb The StringBuffer to store the scheme and port information.
452         */
453        protected void getSchemeAndPort(StringBuffer sb)
454        {
455            // http(s)://<servername>
456            sb.append(getServerScheme());
457            sb.append(URIConstants.URI_SCHEME_SEPARATOR);
458            sb.append(getServerName());
459    
460            // (:<port>)
461            if ((getServerScheme().equals(HTTP)
462                        && getServerPort() != HTTP_PORT)
463                    || (getServerScheme().equals(HTTPS)
464                            && getServerPort() != HTTPS_PORT))
465            {
466                sb.append(':');
467                sb.append(getServerPort());
468            }
469        }
470    
471        /**
472         * Encodes a Response Uri according to the Servlet Container.
473         * This might add a Java session identifier or do redirection.
474         * The resulting String can be used in a page or template.
475         *
476         * @param uri The Uri to encode
477         *
478         * @return An Uri encoded by the container.
479         */
480        protected String encodeResponse(String uri)
481        {
482            String res = uri;
483    
484            HttpServletResponse response = getResponse();
485    
486            if(response == null)
487            {
488                log.debug("No Response Object!");
489            }
490            else
491            {
492                try
493                {
494                    if(isRedirect())
495                    {
496                        log.debug("Should Redirect");
497                        res = response.encodeRedirectURL(uri);
498                    }
499                    else
500                    {
501                        res = response.encodeURL(uri);
502                    }
503                }
504                catch(Exception e)
505                {
506                    log.error("response" + response + ", uri: " + uri);
507                    log.error("While trying to encode the URI: ", e);
508                }
509            }
510    
511            log.debug("encodeResponse():  " + res);
512            return res;
513        }
514    }