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    
021    package org.granite.util;
022    
023    import java.io.BufferedInputStream;
024    import java.io.BufferedReader;
025    import java.io.ByteArrayOutputStream;
026    import java.io.File;
027    import java.io.FileInputStream;
028    import java.io.IOException;
029    import java.io.InputStream;
030    import java.io.InputStreamReader;
031    import java.net.JarURLConnection;
032    import java.net.URI;
033    import java.net.URISyntaxException;
034    import java.net.URL;
035    import java.net.URLConnection;
036    import java.nio.charset.Charset;
037    import java.util.jar.JarEntry;
038    import java.util.regex.Pattern;
039    
040    /**
041     * @author Franck WOLFF
042     */
043    public 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    }