1*2be43276SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*2be43276SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*2be43276SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*2be43276SAndrew Rist * distributed with this work for additional information 6*2be43276SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*2be43276SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*2be43276SAndrew Rist * "License"); you may not use this file except in compliance 9*2be43276SAndrew Rist * with the License. You may obtain a copy of the License at 10*2be43276SAndrew Rist * 11*2be43276SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*2be43276SAndrew Rist * 13*2be43276SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*2be43276SAndrew Rist * software distributed under the License is distributed on an 15*2be43276SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*2be43276SAndrew Rist * KIND, either express or implied. See the License for the 17*2be43276SAndrew Rist * specific language governing permissions and limitations 18*2be43276SAndrew Rist * under the License. 19*2be43276SAndrew Rist * 20*2be43276SAndrew Rist *************************************************************/ 21*2be43276SAndrew Rist 22*2be43276SAndrew Rist 23cdf0e10cSrcweir package com.sun.star.lib.util; 24cdf0e10cSrcweir 25cdf0e10cSrcweir import java.io.File; 26cdf0e10cSrcweir import java.lang.reflect.Constructor; 27cdf0e10cSrcweir import java.lang.reflect.InvocationTargetException; 28cdf0e10cSrcweir import java.lang.reflect.Method; 29cdf0e10cSrcweir import java.net.URL; 30cdf0e10cSrcweir import java.net.URLDecoder; 31cdf0e10cSrcweir import java.net.URLEncoder; 32cdf0e10cSrcweir 33cdf0e10cSrcweir /** 34cdf0e10cSrcweir * Maps Java URL representations to File representations, on any Java version. 35cdf0e10cSrcweir * 36cdf0e10cSrcweir * @since UDK 3.2.8 37cdf0e10cSrcweir */ 38cdf0e10cSrcweir public final class UrlToFileMapper { 39cdf0e10cSrcweir 40cdf0e10cSrcweir // java.net.URLEncoder.encode(String, String) and java.net.URI are only 41cdf0e10cSrcweir // available since Java 1.4: 42cdf0e10cSrcweir private static Method urlEncoderEncode; 43cdf0e10cSrcweir private static Constructor uriConstructor; 44cdf0e10cSrcweir private static Constructor fileConstructor; 45cdf0e10cSrcweir static { 46cdf0e10cSrcweir try { 47cdf0e10cSrcweir urlEncoderEncode = URLEncoder.class.getMethod( 48cdf0e10cSrcweir "encode", new Class[] { String.class, String.class }); 49cdf0e10cSrcweir Class uriClass = Class.forName("java.net.URI"); 50cdf0e10cSrcweir uriConstructor = uriClass.getConstructor( 51cdf0e10cSrcweir new Class[] { String.class }); 52cdf0e10cSrcweir fileConstructor = File.class.getConstructor( 53cdf0e10cSrcweir new Class[] { uriClass }); 54cdf0e10cSrcweir } catch (ClassNotFoundException e) { 55cdf0e10cSrcweir } catch (NoSuchMethodException e) { 56cdf0e10cSrcweir } 57cdf0e10cSrcweir } 58cdf0e10cSrcweir 59cdf0e10cSrcweir /** 60cdf0e10cSrcweir * Maps Java URL representations to File representations. 61cdf0e10cSrcweir * 62cdf0e10cSrcweir * @param url some URL, possibly null. 63cdf0e10cSrcweir * @return a corresponding File, or null on failure. 64cdf0e10cSrcweir */ mapUrlToFile(URL url)65cdf0e10cSrcweir public static File mapUrlToFile(URL url) { 66cdf0e10cSrcweir if (url == null) { 67cdf0e10cSrcweir return null; 68cdf0e10cSrcweir } else if (fileConstructor == null) { 69cdf0e10cSrcweir // If java.net.URI is not available, hope that the following works 70cdf0e10cSrcweir // well: First, check that the given URL has a certain form. 71cdf0e10cSrcweir // Second, use the URLDecoder to decode the URL path (taking care 72cdf0e10cSrcweir // not to change any plus signs to spaces), hoping that the used 73cdf0e10cSrcweir // default encoding is the proper one for file URLs. Third, create 74cdf0e10cSrcweir // a File from the decoded path. 75cdf0e10cSrcweir return url.getProtocol().equalsIgnoreCase("file") 76cdf0e10cSrcweir && url.getAuthority() == null && url.getQuery() == null 77cdf0e10cSrcweir && url.getRef() == null 78cdf0e10cSrcweir ? new File(URLDecoder.decode( 79cdf0e10cSrcweir StringHelper.replace(url.getPath(), '+', "%2B"))) 80cdf0e10cSrcweir : null; 81cdf0e10cSrcweir } else { 82cdf0e10cSrcweir // If java.net.URI is avaliable, do 83cdf0e10cSrcweir // URI uri = new URI(encodedUrl); 84cdf0e10cSrcweir // try { 85cdf0e10cSrcweir // return new File(uri); 86cdf0e10cSrcweir // } catch (IllegalArgumentException e) { 87cdf0e10cSrcweir // return null; 88cdf0e10cSrcweir // } 89cdf0e10cSrcweir // where encodedUrl is url.toString(), but since that may contain 90cdf0e10cSrcweir // unsafe characters (e.g., space, " "), it is encoded, as otherwise 91cdf0e10cSrcweir // the URI constructor might throw java.net.URISyntaxException (in 92cdf0e10cSrcweir // Java 1.5, URL.toURI might be used instead). 93cdf0e10cSrcweir String encodedUrl = encode(url.toString()); 94cdf0e10cSrcweir try { 95cdf0e10cSrcweir Object uri = uriConstructor.newInstance( 96cdf0e10cSrcweir new Object[] { encodedUrl }); 97cdf0e10cSrcweir try { 98cdf0e10cSrcweir return (File) fileConstructor.newInstance( 99cdf0e10cSrcweir new Object[] { uri }); 100cdf0e10cSrcweir } catch (InvocationTargetException e) { 101cdf0e10cSrcweir if (e.getTargetException() instanceof 102cdf0e10cSrcweir IllegalArgumentException) { 103cdf0e10cSrcweir return null; 104cdf0e10cSrcweir } else { 105cdf0e10cSrcweir throw e; 106cdf0e10cSrcweir } 107cdf0e10cSrcweir } 108cdf0e10cSrcweir } catch (InstantiationException e) { 109cdf0e10cSrcweir throw new RuntimeException("This cannot happen: " + e); 110cdf0e10cSrcweir } catch (IllegalAccessException e) { 111cdf0e10cSrcweir throw new RuntimeException("This cannot happen: " + e); 112cdf0e10cSrcweir } catch (InvocationTargetException e) { 113cdf0e10cSrcweir if (e.getTargetException() instanceof Error) { 114cdf0e10cSrcweir throw (Error) e.getTargetException(); 115cdf0e10cSrcweir } else if (e.getTargetException() instanceof RuntimeException) { 116cdf0e10cSrcweir throw (RuntimeException) e.getTargetException(); 117cdf0e10cSrcweir } else { 118cdf0e10cSrcweir throw new RuntimeException("This cannot happen: " + e); 119cdf0e10cSrcweir } 120cdf0e10cSrcweir } 121cdf0e10cSrcweir } 122cdf0e10cSrcweir } 123cdf0e10cSrcweir 124cdf0e10cSrcweir 125cdf0e10cSrcweir encode(String url)126cdf0e10cSrcweir private static String encode(String url) { 127cdf0e10cSrcweir StringBuffer buf = new StringBuffer(); 128cdf0e10cSrcweir for (int i = 0; i < url.length(); ++i) { 129cdf0e10cSrcweir char c = url.charAt(i); 130cdf0e10cSrcweir // The RFC 2732 <uric> characters: !$&'()*+,-./:;=?@[]_~ plus digits 131cdf0e10cSrcweir // and letters; additionally, do not encode % again. 132cdf0e10cSrcweir if (c >= 'a' && c <= 'z' || c >= '?' && c <= '[' 133cdf0e10cSrcweir || c >= '$' && c <= ';' || c == '!' || c == '=' || c == ']' 134cdf0e10cSrcweir || c == '_' || c == '~') 135cdf0e10cSrcweir { 136cdf0e10cSrcweir buf.append(c); 137cdf0e10cSrcweir } else if (c == ' ') { 138cdf0e10cSrcweir buf.append("%20"); 139cdf0e10cSrcweir } else { 140cdf0e10cSrcweir String enc; 141cdf0e10cSrcweir try { 142cdf0e10cSrcweir enc = (String) urlEncoderEncode.invoke( 143cdf0e10cSrcweir null, 144cdf0e10cSrcweir new Object[] {Character.toString(c), "UTF-8" }); 145cdf0e10cSrcweir } catch (IllegalAccessException e) { 146cdf0e10cSrcweir throw new RuntimeException("This cannot happen: " + e); 147cdf0e10cSrcweir } catch (InvocationTargetException e) { 148cdf0e10cSrcweir throw new RuntimeException("This cannot happen: " + e); 149cdf0e10cSrcweir } 150cdf0e10cSrcweir buf.append(enc); 151cdf0e10cSrcweir } 152cdf0e10cSrcweir } 153cdf0e10cSrcweir return buf.toString(); 154cdf0e10cSrcweir } 155cdf0e10cSrcweir UrlToFileMapper()156cdf0e10cSrcweir private UrlToFileMapper() {} 157cdf0e10cSrcweir } 158