1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir package com.sun.star.lib.util; 28*cdf0e10cSrcweir 29*cdf0e10cSrcweir import java.io.File; 30*cdf0e10cSrcweir import java.lang.reflect.Constructor; 31*cdf0e10cSrcweir import java.lang.reflect.InvocationTargetException; 32*cdf0e10cSrcweir import java.lang.reflect.Method; 33*cdf0e10cSrcweir import java.net.URL; 34*cdf0e10cSrcweir import java.net.URLDecoder; 35*cdf0e10cSrcweir import java.net.URLEncoder; 36*cdf0e10cSrcweir 37*cdf0e10cSrcweir /** 38*cdf0e10cSrcweir * Maps Java URL representations to File representations, on any Java version. 39*cdf0e10cSrcweir * 40*cdf0e10cSrcweir * @since UDK 3.2.8 41*cdf0e10cSrcweir */ 42*cdf0e10cSrcweir public final class UrlToFileMapper { 43*cdf0e10cSrcweir 44*cdf0e10cSrcweir // java.net.URLEncoder.encode(String, String) and java.net.URI are only 45*cdf0e10cSrcweir // available since Java 1.4: 46*cdf0e10cSrcweir private static Method urlEncoderEncode; 47*cdf0e10cSrcweir private static Constructor uriConstructor; 48*cdf0e10cSrcweir private static Constructor fileConstructor; 49*cdf0e10cSrcweir static { 50*cdf0e10cSrcweir try { 51*cdf0e10cSrcweir urlEncoderEncode = URLEncoder.class.getMethod( 52*cdf0e10cSrcweir "encode", new Class[] { String.class, String.class }); 53*cdf0e10cSrcweir Class uriClass = Class.forName("java.net.URI"); 54*cdf0e10cSrcweir uriConstructor = uriClass.getConstructor( 55*cdf0e10cSrcweir new Class[] { String.class }); 56*cdf0e10cSrcweir fileConstructor = File.class.getConstructor( 57*cdf0e10cSrcweir new Class[] { uriClass }); 58*cdf0e10cSrcweir } catch (ClassNotFoundException e) { 59*cdf0e10cSrcweir } catch (NoSuchMethodException e) { 60*cdf0e10cSrcweir } 61*cdf0e10cSrcweir } 62*cdf0e10cSrcweir 63*cdf0e10cSrcweir /** 64*cdf0e10cSrcweir * Maps Java URL representations to File representations. 65*cdf0e10cSrcweir * 66*cdf0e10cSrcweir * @param url some URL, possibly null. 67*cdf0e10cSrcweir * @return a corresponding File, or null on failure. 68*cdf0e10cSrcweir */ 69*cdf0e10cSrcweir public static File mapUrlToFile(URL url) { 70*cdf0e10cSrcweir if (url == null) { 71*cdf0e10cSrcweir return null; 72*cdf0e10cSrcweir } else if (fileConstructor == null) { 73*cdf0e10cSrcweir // If java.net.URI is not available, hope that the following works 74*cdf0e10cSrcweir // well: First, check that the given URL has a certain form. 75*cdf0e10cSrcweir // Second, use the URLDecoder to decode the URL path (taking care 76*cdf0e10cSrcweir // not to change any plus signs to spaces), hoping that the used 77*cdf0e10cSrcweir // default encoding is the proper one for file URLs. Third, create 78*cdf0e10cSrcweir // a File from the decoded path. 79*cdf0e10cSrcweir return url.getProtocol().equalsIgnoreCase("file") 80*cdf0e10cSrcweir && url.getAuthority() == null && url.getQuery() == null 81*cdf0e10cSrcweir && url.getRef() == null 82*cdf0e10cSrcweir ? new File(URLDecoder.decode( 83*cdf0e10cSrcweir StringHelper.replace(url.getPath(), '+', "%2B"))) 84*cdf0e10cSrcweir : null; 85*cdf0e10cSrcweir } else { 86*cdf0e10cSrcweir // If java.net.URI is avaliable, do 87*cdf0e10cSrcweir // URI uri = new URI(encodedUrl); 88*cdf0e10cSrcweir // try { 89*cdf0e10cSrcweir // return new File(uri); 90*cdf0e10cSrcweir // } catch (IllegalArgumentException e) { 91*cdf0e10cSrcweir // return null; 92*cdf0e10cSrcweir // } 93*cdf0e10cSrcweir // where encodedUrl is url.toString(), but since that may contain 94*cdf0e10cSrcweir // unsafe characters (e.g., space, " "), it is encoded, as otherwise 95*cdf0e10cSrcweir // the URI constructor might throw java.net.URISyntaxException (in 96*cdf0e10cSrcweir // Java 1.5, URL.toURI might be used instead). 97*cdf0e10cSrcweir String encodedUrl = encode(url.toString()); 98*cdf0e10cSrcweir try { 99*cdf0e10cSrcweir Object uri = uriConstructor.newInstance( 100*cdf0e10cSrcweir new Object[] { encodedUrl }); 101*cdf0e10cSrcweir try { 102*cdf0e10cSrcweir return (File) fileConstructor.newInstance( 103*cdf0e10cSrcweir new Object[] { uri }); 104*cdf0e10cSrcweir } catch (InvocationTargetException e) { 105*cdf0e10cSrcweir if (e.getTargetException() instanceof 106*cdf0e10cSrcweir IllegalArgumentException) { 107*cdf0e10cSrcweir return null; 108*cdf0e10cSrcweir } else { 109*cdf0e10cSrcweir throw e; 110*cdf0e10cSrcweir } 111*cdf0e10cSrcweir } 112*cdf0e10cSrcweir } catch (InstantiationException e) { 113*cdf0e10cSrcweir throw new RuntimeException("This cannot happen: " + e); 114*cdf0e10cSrcweir } catch (IllegalAccessException e) { 115*cdf0e10cSrcweir throw new RuntimeException("This cannot happen: " + e); 116*cdf0e10cSrcweir } catch (InvocationTargetException e) { 117*cdf0e10cSrcweir if (e.getTargetException() instanceof Error) { 118*cdf0e10cSrcweir throw (Error) e.getTargetException(); 119*cdf0e10cSrcweir } else if (e.getTargetException() instanceof RuntimeException) { 120*cdf0e10cSrcweir throw (RuntimeException) e.getTargetException(); 121*cdf0e10cSrcweir } else { 122*cdf0e10cSrcweir throw new RuntimeException("This cannot happen: " + e); 123*cdf0e10cSrcweir } 124*cdf0e10cSrcweir } 125*cdf0e10cSrcweir } 126*cdf0e10cSrcweir } 127*cdf0e10cSrcweir 128*cdf0e10cSrcweir 129*cdf0e10cSrcweir 130*cdf0e10cSrcweir private static String encode(String url) { 131*cdf0e10cSrcweir StringBuffer buf = new StringBuffer(); 132*cdf0e10cSrcweir for (int i = 0; i < url.length(); ++i) { 133*cdf0e10cSrcweir char c = url.charAt(i); 134*cdf0e10cSrcweir // The RFC 2732 <uric> characters: !$&'()*+,-./:;=?@[]_~ plus digits 135*cdf0e10cSrcweir // and letters; additionally, do not encode % again. 136*cdf0e10cSrcweir if (c >= 'a' && c <= 'z' || c >= '?' && c <= '[' 137*cdf0e10cSrcweir || c >= '$' && c <= ';' || c == '!' || c == '=' || c == ']' 138*cdf0e10cSrcweir || c == '_' || c == '~') 139*cdf0e10cSrcweir { 140*cdf0e10cSrcweir buf.append(c); 141*cdf0e10cSrcweir } else if (c == ' ') { 142*cdf0e10cSrcweir buf.append("%20"); 143*cdf0e10cSrcweir } else { 144*cdf0e10cSrcweir String enc; 145*cdf0e10cSrcweir try { 146*cdf0e10cSrcweir enc = (String) urlEncoderEncode.invoke( 147*cdf0e10cSrcweir null, 148*cdf0e10cSrcweir new Object[] {Character.toString(c), "UTF-8" }); 149*cdf0e10cSrcweir } catch (IllegalAccessException e) { 150*cdf0e10cSrcweir throw new RuntimeException("This cannot happen: " + e); 151*cdf0e10cSrcweir } catch (InvocationTargetException e) { 152*cdf0e10cSrcweir throw new RuntimeException("This cannot happen: " + e); 153*cdf0e10cSrcweir } 154*cdf0e10cSrcweir buf.append(enc); 155*cdf0e10cSrcweir } 156*cdf0e10cSrcweir } 157*cdf0e10cSrcweir return buf.toString(); 158*cdf0e10cSrcweir } 159*cdf0e10cSrcweir 160*cdf0e10cSrcweir private UrlToFileMapper() {} 161*cdf0e10cSrcweir } 162