001/**
002 *   GRANITE DATA SERVICES
003 *   Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S.
004 *
005 *   This file is part of the Granite Data Services Platform.
006 *
007 *   Granite Data Services 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 *   Granite Data Services 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 Lesser
015 *   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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
020 *   USA, or see <http://www.gnu.org/licenses/>.
021 */
022package org.granite.util;
023
024import java.io.BufferedInputStream;
025import java.io.BufferedReader;
026import java.io.ByteArrayOutputStream;
027import java.io.File;
028import java.io.FileInputStream;
029import java.io.IOException;
030import java.io.InputStream;
031import java.io.InputStreamReader;
032import java.net.JarURLConnection;
033import java.net.URI;
034import java.net.URISyntaxException;
035import java.net.URL;
036import java.net.URLConnection;
037import java.nio.charset.Charset;
038import java.util.jar.JarEntry;
039import java.util.regex.Pattern;
040
041/**
042 * @author Franck WOLFF
043 */
044public class URIUtil {
045
046    public static final String CLASSPATH_SCHEME = "class";
047    public static final String FILE_SCHEME = "file";
048    public static final Pattern WINDOWS_DRIVE_PATTERN = Pattern.compile("^[a-zA-Z]\\:.*$");
049
050    public static String normalize(String uri) {
051        if (uri == null)
052                return null;
053        uri = uri.replace('\\', '/').replace(" ", "%20");
054        while (uri.indexOf("//") != -1)
055                uri = uri.replace("//", "/");
056        return uri;
057    }
058
059    public static boolean isFileURI(String path) throws URISyntaxException {
060        return isFileURI(new URI(normalize(path)));
061    }
062
063    public static boolean isFileURI(URI uri) {
064        // scheme.length() == 1 -> assume windows drive letter.
065        return uri.getScheme() == null || uri.getScheme().length() <= 1 || FILE_SCHEME.equals(uri.getScheme());
066    }
067    
068    public static boolean isAbsolute(String path) throws URISyntaxException {
069        return isAbsolute(new URI(normalize(path)));
070    }
071    
072    public static boolean isAbsolute(URI uri) {
073        String schemeSpecificPart = uri.getSchemeSpecificPart();
074        if (schemeSpecificPart == null || schemeSpecificPart.length() == 0)
075                return uri.isAbsolute();
076        
077        String scheme = uri.getScheme();
078        if (scheme == null)
079                return schemeSpecificPart.charAt(0) == '/';
080        if (FILE_SCHEME.equals(scheme))
081                return schemeSpecificPart.charAt(0) == '/' || WINDOWS_DRIVE_PATTERN.matcher(schemeSpecificPart).matches();
082        return true;
083    }
084    
085    public static String getSchemeSpecificPart(String path) throws URISyntaxException {
086        return getSchemeSpecificPart(new URI(normalize(path)));
087    }
088    
089    public static String getSchemeSpecificPart(URI uri) {
090        if (uri.getScheme() != null && uri.getScheme().length() <= 1)
091                return uri.getScheme() + ":" + uri.getSchemeSpecificPart();
092        return uri.getSchemeSpecificPart();
093    }
094    
095    public static InputStream getInputStream(URI uri, ClassLoader loader) throws IOException {
096        InputStream is = null;
097
098        String scheme = uri.getScheme();
099        String path = getSchemeSpecificPart(uri);
100        if (CLASSPATH_SCHEME.equals(scheme)) {
101                if (loader != null)
102                        is = loader.getResourceAsStream(path);
103                if (is == null) {
104                        is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
105                    if (is == null)
106                        throw new IOException("Resource not found exception: " + uri);
107                }
108        }
109        else if (isFileURI(uri))
110            is = new FileInputStream(path);
111        else
112            is = uri.toURL().openStream();
113
114        return is;
115    }
116
117    public static InputStream getInputStream(URI uri) throws IOException {
118        return getInputStream(uri, null);
119    }
120
121    public static String getContentAsString(URI uri) throws IOException {
122        return getContentAsString(uri, Charset.defaultCharset());
123    }
124    public static String getContentAsString(URI uri, Charset charset) throws IOException {
125        InputStream is = null;
126        try {
127            is = getInputStream(uri);
128            BufferedReader reader = new BufferedReader(new InputStreamReader(is, charset));
129
130            StringBuilder sb = new StringBuilder(1024);
131
132            char[] chars = new char[256];
133            int count = -1;
134            while ((count = reader.read(chars)) != -1)
135                sb.append(chars, 0, count);
136
137            return sb.toString();
138        } finally {
139            if (is != null)
140                is.close();
141        }
142    }
143
144    public static byte[] getContentAsBytes(URI uri) throws IOException {
145        InputStream is = null;
146        try {
147            is = new BufferedInputStream(getInputStream(uri));
148
149            ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
150
151            int b = 0;
152            while ((b = is.read()) != -1)
153                baos.write(b);
154
155            return baos.toByteArray();
156        } finally {
157            if (is != null)
158                is.close();
159        }
160    }
161
162    public static long lastModified(URI uri) throws IOException {
163        if (uri == null)
164            return -1L;
165
166        String scheme = uri.getScheme();
167        if (scheme == null || scheme.length() <= 1)
168            return new File(uri).lastModified();
169        return lastModified(uri.toURL());
170    }
171
172    public static long lastModified(URL url) throws IOException {
173        long lastModified = -1L;
174
175        if (url != null) {
176            URLConnection connection = url.openConnection();
177            if (connection instanceof JarURLConnection) {
178                JarEntry entry = ((JarURLConnection)connection).getJarEntry();
179                if (entry != null)
180                    lastModified = entry.getTime();
181            }
182            if (lastModified == -1L)
183                lastModified = connection.getLastModified();
184        }
185
186        return (lastModified == 0L ? -1L : lastModified);
187    }
188}