001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.util;
018    
019    import java.io.File;
020    import java.io.FileInputStream;
021    import java.io.FileNotFoundException;
022    import java.io.IOException;
023    import java.io.InputStream;
024    import java.net.HttpURLConnection;
025    import java.net.MalformedURLException;
026    import java.net.URI;
027    import java.net.URISyntaxException;
028    import java.net.URL;
029    import java.net.URLConnection;
030    import java.util.Map;
031    
032    import org.apache.camel.spi.ClassResolver;
033    
034    /**
035     * Helper class for loading resources on the classpath or file system.
036     */
037    public final class ResourceHelper {
038    
039        private ResourceHelper() {
040            // utility class
041        }
042    
043        /**
044         * Determines whether the URI has a scheme (e.g. file:, classpath: or http:)
045         *
046         * @param uri the URI
047         * @return <tt>true</tt> if the URI starts with a scheme
048         */
049        public static boolean hasScheme(String uri) {
050            if (uri == null) {
051                return false;
052            }
053    
054            return uri.startsWith("file:") || uri.startsWith("classpath:") || uri.startsWith("http:");
055        }
056    
057        /**
058         * Gets the scheme from the URI (e.g. file:, classpath: or http:)
059         *
060         * @param uri  the uri
061         * @return the scheme, or <tt>null</tt> if no scheme
062         */
063        public static String getScheme(String uri) {
064            if (hasScheme(uri)) {
065                return uri.substring(0, uri.indexOf(":") + 1);
066            } else {
067                return null;
068            }
069        }
070    
071        /**
072         * Resolves the mandatory resource.
073         * <p/>
074         * If possible recommended to use {@link #resolveMandatoryResourceAsUrl(org.apache.camel.spi.ClassResolver, String)}
075         *
076         * @param classResolver the class resolver to load the resource from the classpath
077         * @param uri URI of the resource
078         * @return the resource as an {@link InputStream}.  Remember to close this stream after usage.
079         * @throws java.io.IOException is thrown if the resource file could not be found or loaded as {@link InputStream}
080         */
081        public static InputStream resolveMandatoryResourceAsInputStream(ClassResolver classResolver, String uri) throws IOException {
082            if (uri.startsWith("file:")) {
083                uri = ObjectHelper.after(uri, "file:");
084                return new FileInputStream(uri);
085            } else if (uri.startsWith("http:")) {
086                URL url = new URL(uri);
087                URLConnection con = url.openConnection();
088                con.setUseCaches(false);
089                try {
090                    return con.getInputStream();
091                } catch (IOException e) {
092                    // close the http connection to avoid
093                    // leaking gaps in case of an exception
094                    if (con instanceof HttpURLConnection) {
095                        ((HttpURLConnection) con).disconnect();
096                    }
097                    throw e;
098                }
099            } else if (uri.startsWith("classpath:")) {
100                uri = ObjectHelper.after(uri, "classpath:");
101            }
102    
103            // load from classpath by default
104            InputStream is = classResolver.loadResourceAsStream(uri);
105            if (is == null) {
106                throw new FileNotFoundException("Cannot find resource in classpath for URI: " + uri);
107            } else {
108                return is;
109            }
110        }
111    
112        /**
113         * Resolves the mandatory resource.
114         *
115         * @param classResolver the class resolver to load the resource from the classpath
116         * @param uri uri of the resource
117         * @return the resource as an {@link InputStream}.  Remember to close this stream after usage.
118         * @throws java.io.FileNotFoundException is thrown if the resource file could not be found
119         * @throws java.net.MalformedURLException if the URI is malformed
120         */
121        public static URL resolveMandatoryResourceAsUrl(ClassResolver classResolver, String uri) throws FileNotFoundException, MalformedURLException {
122            if (uri.startsWith("file:")) {
123                // check if file exists first
124                String name = ObjectHelper.after(uri, "file:");
125                File file = new File(name);
126                if (!file.exists()) {
127                    throw new FileNotFoundException("File " + file + " not found");
128                }
129                return new URL(uri);
130            } else if (uri.startsWith("http:")) {
131                return new URL(uri);
132            } else if (uri.startsWith("classpath:")) {
133                uri = ObjectHelper.after(uri, "classpath:");
134            }
135    
136            // load from classpath by default
137            URL url = classResolver.loadResourceAsURL(uri);
138            if (url == null) {
139                throw new FileNotFoundException("Cannot find resource in classpath for URI: " + uri);
140            } else {
141                return url;
142            }
143        }
144    
145        /**
146         * Is the given uri a http uri?
147         *
148         * @param uri the uri
149         * @return <tt>true</tt> if the uri starts with <tt>http:</tt> or <tt>https:</tt>
150         */
151        public static boolean isHttpUri(String uri) {
152            if (uri == null) {
153                return false;
154            }
155            return uri.startsWith("http:") || uri.startsWith("https:");
156        }
157    
158        /**
159         * Appends the parameters to the given uri
160         *
161         * @param uri the uri
162         * @param parameters the additional parameters (will clear the map)
163         * @return a new uri with the additional parameters appended
164         * @throws URISyntaxException is thrown if the uri is invalid
165         */
166        public static String appendParameters(String uri, Map<String, Object> parameters) throws URISyntaxException {
167            // add additional parameters to the resource uri
168            if (!parameters.isEmpty()) {
169                String query = URISupport.createQueryString(parameters);
170                URI u = new URI(uri);
171                u = URISupport.createURIWithQuery(u, query);
172                parameters.clear();
173                return u.toString();
174            } else {
175                return uri;
176            }
177        }
178    }