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