001package 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
024import javax.servlet.http.HttpServletResponse;
025
026import org.apache.commons.lang.StringUtils;
027
028import org.apache.commons.logging.Log;
029import org.apache.commons.logging.LogFactory;
030
031import org.apache.turbine.Turbine;
032import org.apache.turbine.TurbineConstants;
033
034import org.apache.turbine.util.RunData;
035import 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 1709648 2015-10-20 17:08:10Z tv $
047 */
048
049public 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 StringBuilder to store context path and script name.
415     */
416    protected void getContextAndScript(StringBuilder 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 StringBuilder to store the scheme and port information.
452     */
453    protected void getSchemeAndPort(StringBuilder 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}