Java Source Code: org.exolab.adaptx.net.impl.URIUtils


   1: /*
   2:  * Redistribution and use of this software and associated documentation
   3:  * ("Software"), with or without modification, are permitted provided
   4:  * that the following conditions are met:
   5:  *
   6:  * 1. Redistributions of source code must retain copyright
   7:  *    statements and notices.  Redistributions must also contain a
   8:  *    copy of this document.
   9:  *
  10:  * 2. Redistributions in binary form must reproduce the
  11:  *    above copyright notice, this list of conditions and the
  12:  *    following disclaimer in the documentation and/or other
  13:  *    materials provided with the distribution.
  14:  *
  15:  * 3. The name "Exolab" must not be used to endorse or promote
  16:  *    products derived from this Software without prior written
  17:  *    permission of Intalio, Inc.  For written permission,
  18:  *    please contact info@exolab.org.
  19:  *
  20:  * 4. Products derived from this Software may not be called "Exolab"
  21:  *    nor may "Exolab" appear in their names without prior written
  22:  *    permission of Intalio, Inc. Exolab is a registered
  23:  *    trademark of Intalio, Inc.
  24:  *
  25:  * 5. Due credit should be given to the Exolab Project
  26:  *    (http://www.exolab.org/).
  27:  *
  28:  * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
  29:  * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
  30:  * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  31:  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
  32:  * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  33:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  34:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  35:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  36:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  37:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  38:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  39:  * OF THE POSSIBILITY OF SUCH DAMAGE.
  40:  *
  41:  * The Original Code is XSL:P XSLT processor.
  42:  * 
  43:  * The Initial Developer of the Original Code is Keith Visco.
  44:  * Portions created by Keith Visco (C) 1998-2001 Keith Visco.
  45:  * All Rights Reserved..
  46:  *
  47:  * Contributor(s): 
  48:  * Keith Visco, kvisco@ziplink.net
  49:  *    -- original author. 
  50:  *
  51:  * Copyright 2001 (C) Intalio, Inc. All Rights Reserved.
  52:  *
  53:  * $Id: URIUtils.java,v 1.3 2003/10/08 00:03:25 kvisco Exp $
  54:  */
  55:  
  56: package org.exolab.adaptx.net.impl;
  57: 
  58: 
  59: import java.io.File;
  60: import java.io.FileInputStream;
  61: import java.io.FileOutputStream;
  62: import java.io.FileNotFoundException;
  63: import java.io.InputStream;
  64: import java.io.InputStreamReader;
  65: import java.io.IOException;
  66: import java.io.OutputStream;
  67: import java.io.OutputStreamWriter;
  68: import java.io.Reader;
  69: import java.io.Writer;
  70: import java.net.MalformedURLException;
  71: import java.net.URL;
  72: import java.net.URLConnection;
  73: 
  74: /**
  75:  * A utility class for URI handling
  76:  *
  77:  * @author <a href="mailto:keith@kvisco.com">Keith Visco</a>
  78:  */
  79:	  public class URIUtils {
  80:
  81:    /**
  82:     * The File protocol name
  83:     */
  84:    private static final String FILE_PROTOCOL = "file";
  85:    
  86:    /**
  87:     * the File protocol prefix (name + :// + host + /)
  88:     * where host is empty, meaning local host
  89:     */
  90:    private static final String FILE_PROTOCOL_PREFIX = "file:///";
  91:    
  92:    /**
  93:     * the path separator for an URI
  94:     */
  95:    private static final char HREF_PATH_SEP = '/';
  96:    
  97:    /**
  98:     * The Device separator for an URI
  99:     */
 100:    private static final char DEVICE_SEP = '|';
 101:    
 102:    /**
 103:     * Returns an InputStream for the file represented by the href
 104:     * argument
 105:     * @param href the href of the file to get the input stream for.
 106:     * @param documentBase the document base of the href argument, if it
 107:     * is a relative href
 108:     * set documentBase to null if there is none.
 109:     * @return an InputStream to the desired resource
 110:     * @exception java.io.FileNotFoundException when the file could not be
 111:     * found
 112:     */
 113:    public static InputStream getInputStream(String href, String documentBase) 
 114:        throws FileNotFoundException, IOException
 115:	      {
 116:        
 117:        //-- check for URL with only using href
 118:        URL url = null;
 119:	          if ((url = getURL(href)) != null) {
 120:            return url.openStream();
 121:        }
 122:        
 123:        //-- join document base + href
 124:        String absHref = makeAbsolute(href, documentBase);
 125:        
 126:        //-- try using absolute URI
 127:	          if ((url = getURL(absHref)) != null) {
 128:            return url.openStream();
 129:        }
 130:        
 131:        // Try local files
 132:        File file = new File(href);
 133:	          if (file.exists()) {
 134:	              if (!file.isAbsolute()) {
 135:                File tmpFile = new File(absHref);
 136:                if (tmpFile.exists()) file = tmpFile;
 137:            }
 138:        }
 139:	          else {
 140:            file = new File(absHref);
 141:        }
 142:        return new FileInputStream(file);
 143:    } //-- getInputStream
 144:    
 145:    /**
 146:     * Returns an OutputStream for the file represented by the href
 147:     * argument
 148:     * @param href the href of the file to get the input stream for.
 149:     * @param documentBase the document base of the href argument, if it
 150:     * is a relative href
 151:     * set documentBase to null if there is none.
 152:     * @return an OutputStream to the desired resource
 153:     * @exception java.io.FileNotFoundException when the file could not be
 154:     * found
 155:     */
 156:    public static OutputStream getOutputStream(String href, String documentBase) 
 157:        throws FileNotFoundException, IOException
 158:	      {
 159:        
 160:        URL url = null;
 161:        
 162:        //-- try using href alone as it might already be a full URL
 163:	          if ((url = getURL(href)) != null) {
 164:            
 165:            //-- If we have a file protocol make sure we
 166:            //-- don't use connection#getOutputStream
 167:            //-- as it's not supported.
 168:	              if (FILE_PROTOCOL.equals(url.getProtocol())) {
 169:                //-- try local file
 170:                File file = new File(url.getFile());
 171:	                  if (file.exists()) {
 172:                    return new FileOutputStream(file);
 173:                }
 174:            }
 175:	              else {
 176:                URLConnection connection = url.openConnection();
 177:                return connection.getOutputStream();
 178:            }
 179:        }
 180:        
 181:        //-- try using documentBase
 182:        String absHref = makeAbsolute(href, documentBase);
 183:        
 184:	          if ((url = getURL(absHref)) != null) {
 185:            //-- If we have a file protocol make sure we
 186:            //-- don't use connection#getOutputStream
 187:            //-- as it's not supported.
 188:	              if (FILE_PROTOCOL.equals(url.getProtocol())) {
 189:                //-- try local file
 190:                File file = new File(url.getFile());
 191:	                  if (file.exists()) {
 192:                    return new FileOutputStream(file);
 193:                }
 194:            }
 195:	              else {
 196:                URLConnection connection = url.openConnection();
 197:                return connection.getOutputStream();
 198:            }
 199:        }
 200:            
 201:        // Try local files
 202:        File file = new File(href);
 203:	          if (file.exists()) {
 204:	              if (!file.isAbsolute()) {
 205:                File tmpFile = new File(absHref);
 206:                if (tmpFile.exists()) file = tmpFile;
 207:            }
 208:        }
 209:	          else {
 210:            file = new File(absHref);
 211:        }
 212:        return new FileOutputStream(file);
 213:        
 214:    } //-- getOutputStream
 215:    
 216:
 217:    /**
 218:     * Returns a Reader for the file represented by the href
 219:     * argument
 220:     * @param href the href of the file to get the input stream for.
 221:     * @param documentBase the document base of the href argument, if it
 222:     * is a relative href
 223:     * set documentBase to null if there is none.
 224:     * @return an InputStream to the desired resource
 225:     * @exception java.io.FileNotFoundException when the file could not be
 226:     * found
 227:     */
 228:    public static Reader getReader(String href, String documentBase) 
 229:        throws FileNotFoundException, IOException
 230:	      {
 231:        InputStream is = getInputStream(href, documentBase);
 232:        return new InputStreamReader(is);    
 233:    } //-- getReader
 234:    
 235:    /**
 236:     * Returns a Writer for the file represented by the href
 237:     * argument
 238:     * @param href the href of the file to get the input stream for.
 239:     * @param documentBase the document base of the href argument, if it
 240:     * is a relative href
 241:     * set documentBase to null if there is none.
 242:     * @return a Writer to the desired resource
 243:     * @exception java.io.FileNotFoundException when the file could not be
 244:     * found
 245:     */
 246:    public static Writer getWriter(String href, String documentBase) 
 247:        throws FileNotFoundException, IOException
 248:	      {
 249:        OutputStream is = getOutputStream(href, documentBase);
 250:        return new OutputStreamWriter(is);    
 251:    } //-- getWriter
 252:    
 253:    
 254:    /**
 255:     * Returns the document base of the href argument
 256:     * @return the document base of the given href
 257:     */
 258:	      public static String getDocumentBase(String href) {
 259:        
 260:        String docBase = "";
 261:        
 262:        if (href == null) return docBase;
 263:        
 264:        int idx = -1;
 265:        //-- check for URL
 266:	          try {
 267:            //-- try to create a new URL and see if MalformedURLExcetion is
 268:            //-- ever thrown
 269:            URL url = new URL(href);
 270:            url = null; //-- to remove compiler warnings
 271:            idx = href.lastIndexOf(HREF_PATH_SEP);
 272:        }
 273:	          catch(MalformedURLException muex) {
 274:            //-- The following contains a fix from Shane Hathaway 
 275:            //-- to handle the case when both "\" and "/" appear in filename
 276:            int idx2 = href.lastIndexOf(HREF_PATH_SEP);
 277:            idx = href.lastIndexOf(File.separator);
 278:            if (idx2 > idx) idx = idx2;            
 279:        }
 280:       
 281:        if (idx >= 0) docBase = href.substring(0,idx);
 282:        
 283:        return docBase;
 284:    } //-- getDocumentBase
 285:
 286:    /**
 287:     * Returns the relative URI of the href argument
 288:     *
 289:     * @return the relative URI the given href 
 290:     */
 291:	      public static String getRelativeURI(String href) {
 292:        
 293:        if (href == null) return href;
 294:        
 295:        int idx = -1;
 296:        //-- check for URL
 297:	          try {
 298:            //-- try to create a new URL and see if MalformedURLExcetion is
 299:            //-- ever thrown
 300:            URL url = new URL(href);
 301:            url = null; //-- to remove compiler warnings
 302:            idx = href.lastIndexOf(HREF_PATH_SEP);
 303:        }
 304:	          catch(MalformedURLException muex) {
 305:            //-- The following contains a fix from Shane Hathaway 
 306:            //-- to handle the case when both "\" and "/" appear in filename
 307:            int idx2 = href.lastIndexOf(HREF_PATH_SEP);
 308:            idx = href.lastIndexOf(File.separator);
 309:            if (idx2 > idx) idx = idx2;            
 310:        }
 311:       
 312:        if (idx >= 0) 
 313:            return href.substring(idx+1);
 314:        
 315:        return href;
 316:    } //-- getRelativeURI
 317:    
 318:    /**
 319:     * Returns the given href + documentBase
 320:     *
 321:     * @return the absolute URL as a string
 322:     */
 323:	      public static String resolveAsString(String href, String documentBase) {
 324:        
 325:	          if (getURL(href) != null) {
 326:            return href;
 327:        }
 328:        
 329:        String absHref = makeAbsolute(href, documentBase);
 330:        
 331:	          if (getURL(absHref) != null) {
 332:            return absHref;
 333:        }
 334:        
 335:        // Try local files
 336:        File file = new File(href);
 337:        if (file.isAbsolute())
 338:            absHref = createFileURL(file.getAbsolutePath());
 339:	          else {
 340:            file = new File(absHref);
 341:            absHref = createFileURL(file.getAbsolutePath());
 342:        }
 343:        return absHref;
 344:    } //-- resolveHref
 345:    
 346:    /**
 347:     * Creates a File URL for the given file name
 348:     *
 349:     * @param filename the name of the file
 350:     * @return the String representation of the File URL
 351:     */
 352:	      private static String createFileURL(String filename) {
 353:        
 354:        if (filename == null) return FILE_PROTOCOL_PREFIX;
 355:        int size = filename.length() + FILE_PROTOCOL_PREFIX.length();
 356:        StringBuffer sb = new StringBuffer(size);
 357:        sb.append(FILE_PROTOCOL_PREFIX);
 358:        char[] chars = filename.toCharArray();
 359:	          for (int i = 0; i < chars.length; i++) {
 360:            char ch = chars[i];
 361:	              switch (ch) {
 362:                case '\\':
 363:                    sb.append(HREF_PATH_SEP);
 364:                    break;
 365:                default:
 366:                    sb.append(ch);
 367:                    break;
 368:                    
 369:            }
 370:        }
 371:        return sb.toString();
 372:    } //-- createFileURL
 373:    
 374:    /**
 375:     * This is just a helper method so I don't have to write try/catch
 376:     * everywhere I'm testing if something is a URL or not.
 377:     * Returns the URL for the given uri, or null if the uri doesn't
 378:     * exist or is malformed.
 379:     *
 380:     * @return the URL or null.
 381:     */
 382:	      private static URL getURL(String uri) {
 383:	          try {
 384:            return new URL(uri);
 385:        }
 386:        catch (MalformedURLException muex) {};
 387:        return null;
 388:    } //-- getURL
 389:    
 390:    /**
 391:     * Returns the absolute URI for the given href
 392:     *
 393:     * @return the absolute URI for the given href
 394:     */
 395:	      private static String makeAbsolute(String href, String documentBase) {
 396:        
 397:        //-- join document base + href
 398:        String absHref = null;
 399:	          if ((documentBase != null) && (documentBase.length() > 0)) {
 400:            if (href.startsWith(documentBase)) return href;            
 401:            int idx = documentBase.lastIndexOf(HREF_PATH_SEP);
 402:            if (idx == (documentBase.length()-1))
 403:                absHref = documentBase+href;
 404:            else
 405:                absHref = documentBase+HREF_PATH_SEP+href;
 406:        }   
 407:        else absHref = href;
 408:        
 409:        return absHref;        
 410:    } //-- makeAbsolute
 411:    
 412:} //-- class: URIUtils