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