001: /*
002: * ====================================================================
003: * JAFFA - Java Application Framework For All
004: *
005: * Copyright (C) 2002 JAFFA Development Group
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: * Redistribution and use of this software and associated documentation ("Software"),
022: * with or without modification, are permitted provided that the following conditions are met:
023: * 1. Redistributions of source code must retain copyright statements and notices.
024: * Redistributions must also contain a copy of this document.
025: * 2. Redistributions in binary form must reproduce the above copyright notice,
026: * this list of conditions and the following disclaimer in the documentation
027: * and/or other materials provided with the distribution.
028: * 3. The name "JAFFA" must not be used to endorse or promote products derived from
029: * this Software without prior written permission. For written permission,
030: * please contact mail to: jaffagroup@yahoo.com.
031: * 4. Products derived from this Software may not be called "JAFFA" nor may "JAFFA"
032: * appear in their names without prior written permission.
033: * 5. Due credit should be given to the JAFFA Project (http://jaffa.sourceforge.net).
034: *
035: * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: */
049:
050: /*
051: * URLHelper.java
052: *
053: * Created on August 23, 2001, 4:48 PM
054: */
055:
056: package org.jaffa.util;
057:
058: import org.apache.log4j.Logger;
059: import javax.servlet.http.HttpServletRequest;
060: import java.net.URL;
061: import java.net.URI;
062: import java.io.InputStream;
063: import java.io.FileInputStream;
064: import java.io.File;
065: import java.io.IOException;
066: import org.jaffa.util.SplitString;
067: import java.net.MalformedURLException;
068: import org.jaffa.config.Config;
069:
070: /** Utility class to manipulate URL's and provide some additional capability for using them.
071: *
072: * @author PaulE
073: * @version 1.0
074: */
075: public class URLHelper {
076: private static Logger log = Logger.getLogger(URLHelper.class
077: .getName());
078:
079: /** This contains the name of the URL protocol that implies the resouce can be located in the classpath */
080: public static final String PROTOCOL_CLASSPATH = "classpath";
081:
082: /** This contains the name of the URL protocol that implies the resource can be found relative to the location of the web-root on the local file system,
083: * This assumes that you are running this inside a servlet, on a web server
084: */
085: public static final String PROTOCOL_WEBROOT = "webroot";
086:
087: /** This is the default value for the initial page of the application */
088: public static final String DEFAULT_PAGE = "index.html";
089:
090: /** Based on a HttpRequest, this routine will ingure out the URL that represents the root of
091: * the web application. It derives the URL protocol, host, port and application.
092: * An example of a returned string may be http://www.example.org/myApp/
093: * or https://www.example.com:888/SecureApp/
094: *
095: * @param request A HttpRequest used to derive information about the root of the web applicatoin
096: * @return a string that represents the base URL for this web application
097: */
098: public static String getBase(HttpServletRequest request) {
099: StringBuffer buf = new StringBuffer();
100: buf.append(request.getScheme());
101: buf.append("://");
102: buf.append(request.getServerName());
103: if ("http".equals(request.getScheme())
104: && (80 == request.getServerPort())) {
105: ;
106: } else if ("https".equals(request.getScheme())
107: && (443 == request.getServerPort())) {
108: ;
109: } else {
110: buf.append(':');
111: buf.append(request.getServerPort());
112: }
113: buf.append(request.getContextPath() + "/");
114: return buf.toString();
115: }
116:
117: /** Build up a valid URL string based on the supplied source URL string.
118: * If the supplied string in null, use the string defined in DEFAULT_PAGE and
119: * append this to web root ( using URLHelper.getBase() )
120: * If the supplied string already is a valid url, leave it as is.
121: * If it is currently invalid, see if it can be made valid by making it relative to
122: * the web application base ( using URLHelper.getBase() ), if so return this value
123: * If this still doesn't yield a valid url, assume it was null, and build it based on
124: * DEFAULT_PAGE and getBase()
125: *
126: * @param url The URL to build and validate
127: * @param req The httpRequest needed to derive the web app base
128: * @return A fully expressed valid URL
129: */
130: public static String buildUrl(String url, HttpServletRequest req) {
131: String oldUrl = url;
132:
133: if (url == null)
134: url = getBase(req) + DEFAULT_PAGE;
135: else {
136: try {
137: URL u = new URL(url);
138: } catch (java.net.MalformedURLException e) {
139: // What should be done? ... Try to add the base on....
140: url = getBase(req)
141: + (url.charAt(0) == '/' ? url.substring(1)
142: : url);
143:
144: // See if this is OK now...
145: try {
146: URL u = new URL(url);
147: } catch (java.net.MalformedURLException ex) {
148: // Default to the base plus the DEFAULT PAGE
149: log.info("Invalid URL : " + url);
150: url = getBase(req) + DEFAULT_PAGE;
151: }
152: }
153: }
154: log.debug("Converted URL " + oldUrl + " to " + url);
155: return url;
156: }
157:
158: /** Get a complete string based representation of a request's source URL include query parameters
159: *
160: * @param request HttpRequest containing the url to extracts
161: * @return string representation of URL
162: */
163: public static String getFullUrl(HttpServletRequest request) {
164: return request.getRequestURL().toString()
165: + (request.getQueryString() == null ? "" : "?"
166: + request.getQueryString());
167: }
168:
169: /** This method will try to load the input resource off the classpath.
170: * If its not found, then it will look for it in the filesystem.
171: * A null will be returned, if the resource could not be located.
172: *
173: * @param resourceName the resource to be located.
174: * @throws IOException if any error occurs while opening the stream.
175: * @return an input stream for reading from the resource.
176: */
177: public static InputStream getInputStream(String resourceName)
178: throws IOException {
179: InputStream stream = null;
180:
181: URL url = getUrl(resourceName);
182: if (url != null)
183: stream = url.openStream();
184:
185: return stream;
186: }
187:
188: /** This method will try to load the input resource off the classpath.
189: * If its not found, then it will look for it in the filesystem.
190: * A null will be returned, if the resource could not be located.
191: *
192: * This method merely invokes the newExtendedURL() method, returning a null if any exception is raised.
193: *
194: * @param resourceName the resource to be located.
195: * @return a URL for reading from the resource.
196: * @deprecated Use the newExtendedURL() method.
197: */
198: public static URL getUrl(String resourceName) {
199: URL url = null;
200: try {
201: url = newExtendedURL(resourceName);
202: } catch (MalformedURLException e) {
203: // do nothing
204: }
205: return url;
206: }
207:
208: /** Create a URL object from a string, this can handle the two new Custom URL
209: * protocols, 'classpath:///' and 'webroot:///'. If either of these new ones are
210: * used they will be converted into the appropriate 'file://' format.
211: * If no protocol is specified, then it'll try to load the input resource off the classpath.
212: * If its not found, then it will look for the input resource in the filesystem.
213: *
214: * @param url source URL that may use one of the new protocols
215: * @throws MalformedURLException if the supplied URL is not valid, or can't be translated into something that is valid
216: * @return valid URL object, as these two new protocols are not really supported by the java.net.URL object
217: */
218: public static URL newExtendedURL(String url)
219: throws MalformedURLException {
220: // A null input is not allowed
221: if (url == null)
222: throw new IllegalArgumentException(
223: "The input url cannot be null");
224:
225: // try to read the resource off the filesystem
226: URL u = null;
227: u = getUrlFromFilesystem(url);
228:
229: if (u == null) {
230: // Now try to read it bu using the protocols
231: // convert the input into a URI, so as to obtain its scheme
232: URI uri = null;
233: try {
234: uri = new URI(url);
235: } catch (java.net.URISyntaxException e) {
236: throw new MalformedURLException(e.getMessage());
237: }
238:
239: // Check the scheme
240: if (uri.getScheme() != null) {
241: String path = uri.getPath().substring(
242: uri.getPath().startsWith("/") ? 1 : 0);
243: if (uri.getScheme()
244: .equalsIgnoreCase(PROTOCOL_CLASSPATH)) {
245: u = getUrlFromClasspath(path);
246: if (u == null)
247: throw new MalformedURLException(
248: "Can't Locate Resource in Classpath - "
249: + path);
250: } else if (uri.getScheme().equalsIgnoreCase(
251: PROTOCOL_WEBROOT)) {
252: String root = (String) Config.getProperty(
253: Config.PROP_WEB_SERVER_ROOT, "file:///");
254: String separator = "/"; // This is a normal url seperator
255: try {
256: if ((new URI(root)).getScheme()
257: .equalsIgnoreCase("file"))
258: separator = File.separator;
259: } catch (java.net.URISyntaxException e) {
260: }
261: u = new URL(root
262: + (root.endsWith(separator) ? ""
263: : separator) + path);
264: } else
265: u = new URL(url);
266: } else {
267: // Finally try to read the resource off the classpath
268: u = getUrlFromClasspath(url);
269: if (u == null)
270: throw new MalformedURLException(
271: "Can't Locate Resource in Classpath or the Filesystem - "
272: + url);
273: }
274: }
275: return u;
276: }
277:
278: /** Search for the input resource in the classpath */
279: private static URL getUrlFromClasspath(String resourceName) {
280: URL url = null;
281: ClassLoader classLoader = URLHelper.class.getClassLoader();
282: url = classLoader.getResource(resourceName);
283: if (url == null)
284: url = ClassLoader.getSystemResource(resourceName);
285: return url;
286: }
287:
288: /** Search for the input resource in the filesystem */
289: private static URL getUrlFromFilesystem(String resourceName) {
290: URL url = null;
291: File f = new File(resourceName);
292: try {
293: if (f.exists() && f.isFile())
294: url = f.toURI().toURL();
295: } catch (MalformedURLException e) {
296: // do nothing
297: url = null;
298: }
299: return url;
300: }
301:
302: /** Test rig
303: * @param args none required
304: */
305: public static void main(String[] args) {
306: // @todo : move this to a unit or httpunit test rig
307: try {
308: String a = "classpath:///org/jaffa/config/framework.properties";
309: System.out.println("URL: " + a);
310: System.out.println("Real URL: "
311: + newExtendedURL(a).toExternalForm());
312:
313: String b = "webroot:///index.html";
314: System.out.println("URL: " + b);
315: System.out.println("Real URL: "
316: + newExtendedURL(b).toExternalForm());
317:
318: String c = "file:///index.html";
319: System.out.println("URL: " + c);
320: System.out.println("Real URL: "
321: + newExtendedURL(c).toExternalForm());
322:
323: String d = "org/jaffa/config/framework.properties";
324: System.out.println("URL: " + d);
325: System.out.println("Real URL: "
326: + newExtendedURL(d).toExternalForm());
327:
328: String e = "bin";
329: System.out.println("URL: " + e);
330: System.out.println("Real URL: "
331: + newExtendedURL(e).toExternalForm());
332: } catch (Exception e) {
333: e.printStackTrace();
334: }
335: }
336:
337: }
|