001/*
002  GRANITE DATA SERVICES
003  Copyright (C) 2011 GRANITE DATA SERVICES S.A.S.
004
005  This file is part of Granite Data Services.
006
007  Granite Data Services is free software; you can redistribute it and/or modify
008  it under the terms of the GNU Library General Public License as published by
009  the Free Software Foundation; either version 2 of the License, or (at your
010  option) any later version.
011
012  Granite Data Services is distributed in the hope that it will be useful, but
013  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015  for more details.
016
017  You should have received a copy of the GNU Library General Public License
018  along with this library; if not, see <http://www.gnu.org/licenses/>.
019*/
020
021package org.granite.util;
022
023import java.io.BufferedInputStream;
024import java.io.BufferedReader;
025import java.io.ByteArrayOutputStream;
026import java.io.File;
027import java.io.FileInputStream;
028import java.io.IOException;
029import java.io.InputStream;
030import java.io.InputStreamReader;
031import java.net.JarURLConnection;
032import java.net.URI;
033import java.net.URISyntaxException;
034import java.net.URL;
035import java.net.URLConnection;
036import java.nio.charset.Charset;
037import java.util.jar.JarEntry;
038import java.util.regex.Pattern;
039
040/**
041 * @author Franck WOLFF
042 */
043public class URIUtil {
044
045    public static final String CLASSPATH_SCHEME = "class";
046    public static final String FILE_SCHEME = "file";
047    public static final Pattern WINDOWS_DRIVE_PATTERN = Pattern.compile("^[a-zA-Z]\\:.*$");
048
049    public static String normalize(String uri) {
050        if (uri == null)
051                return null;
052        uri = uri.replace('\\', '/').replace(" ", "%20");
053        while (uri.indexOf("//") != -1)
054                uri = uri.replace("//", "/");
055        return uri;
056    }
057
058    public static boolean isFileURI(String path) throws URISyntaxException {
059        return isFileURI(new URI(normalize(path)));
060    }
061
062    public static boolean isFileURI(URI uri) {
063        // scheme.length() == 1 -> assume windows drive letter.
064        return uri.getScheme() == null || uri.getScheme().length() <= 1 || FILE_SCHEME.equals(uri.getScheme());
065    }
066    
067    public static boolean isAbsolute(String path) throws URISyntaxException {
068        return isAbsolute(new URI(normalize(path)));
069    }
070    
071    public static boolean isAbsolute(URI uri) {
072        String schemeSpecificPart = uri.getSchemeSpecificPart();
073        if (schemeSpecificPart == null || schemeSpecificPart.length() == 0)
074                return uri.isAbsolute();
075        
076        String scheme = uri.getScheme();
077        if (scheme == null)
078                return schemeSpecificPart.charAt(0) == '/';
079        if (FILE_SCHEME.equals(scheme))
080                return schemeSpecificPart.charAt(0) == '/' || WINDOWS_DRIVE_PATTERN.matcher(schemeSpecificPart).matches();
081        return true;
082    }
083    
084    public static String getSchemeSpecificPart(String path) throws URISyntaxException {
085        return getSchemeSpecificPart(new URI(normalize(path)));
086    }
087    
088    public static String getSchemeSpecificPart(URI uri) {
089        if (uri.getScheme() != null && uri.getScheme().length() <= 1)
090                return uri.getScheme() + ":" + uri.getSchemeSpecificPart();
091        return uri.getSchemeSpecificPart();
092    }
093    
094    public static InputStream getInputStream(URI uri, ClassLoader loader) throws IOException {
095        InputStream is = null;
096
097        String scheme = uri.getScheme();
098        String path = getSchemeSpecificPart(uri);
099        if (CLASSPATH_SCHEME.equals(scheme)) {
100                if (loader != null)
101                        is = loader.getResourceAsStream(path);
102                if (is == null) {
103                        is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
104                    if (is == null)
105                        throw new IOException("Resource not found exception: " + uri);
106                }
107        }
108        else if (isFileURI(uri))
109            is = new FileInputStream(path);
110        else
111            is = uri.toURL().openStream();
112
113        return is;
114    }
115
116    public static InputStream getInputStream(URI uri) throws IOException {
117        return getInputStream(uri, null);
118    }
119
120    public static String getContentAsString(URI uri) throws IOException {
121        return getContentAsString(uri, Charset.defaultCharset());
122    }
123    public static String getContentAsString(URI uri, Charset charset) throws IOException {
124        InputStream is = null;
125        try {
126            is = getInputStream(uri);
127            BufferedReader reader = new BufferedReader(new InputStreamReader(is, charset));
128
129            StringBuilder sb = new StringBuilder(1024);
130
131            char[] chars = new char[256];
132            int count = -1;
133            while ((count = reader.read(chars)) != -1)
134                sb.append(chars, 0, count);
135
136            return sb.toString();
137        } finally {
138            if (is != null)
139                is.close();
140        }
141    }
142
143    public static byte[] getContentAsBytes(URI uri) throws IOException {
144        InputStream is = null;
145        try {
146            is = new BufferedInputStream(getInputStream(uri));
147
148            ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
149
150            int b = 0;
151            while ((b = is.read()) != -1)
152                baos.write(b);
153
154            return baos.toByteArray();
155        } finally {
156            if (is != null)
157                is.close();
158        }
159    }
160
161    public static long lastModified(URI uri) throws IOException {
162        if (uri == null)
163            return -1L;
164
165        String scheme = uri.getScheme();
166        if (scheme == null || scheme.length() <= 1)
167            return new File(uri).lastModified();
168        return lastModified(uri.toURL());
169    }
170
171    public static long lastModified(URL url) throws IOException {
172        long lastModified = -1L;
173
174        if (url != null) {
175            URLConnection connection = url.openConnection();
176            if (connection instanceof JarURLConnection) {
177                JarEntry entry = ((JarURLConnection)connection).getJarEntry();
178                if (entry != null)
179                    lastModified = entry.getTime();
180            }
181            if (lastModified == -1L)
182                lastModified = connection.getLastModified();
183        }
184
185        return (lastModified == 0L ? -1L : lastModified);
186    }
187}