1 /* ***************************************************************************
2 * Copyright (c) 2008 Brabenetz Harald, Austria.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 *****************************************************************************/
17 package org.settings4j.contentresolver;
18
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.net.URL;
22
23 import org.apache.commons.io.IOUtils;
24 import org.settings4j.ContentResolver;
25
26 /**
27 * {@link ContentResolver} implementation to read content from the Classpath.
28 * <p>
29 * Uses the default ClassLoader: typically the thread context ClassLoader
30 * see {@link #getClassLoader()}.
31 * <p>
32 * Optional Path Prefix is "classpath:".
33 *
34 * @author Harald.Brabenetz
35 *
36 */
37 public class ClasspathContentResolver implements ContentResolver {
38
39 /** General Logger for this Class. */
40 private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(ClasspathContentResolver.class);
41
42 /** Pseudo URL prefix for loading from the class path: "classpath:". */
43 public static final String CLASSPATH_URL_PREFIX = "classpath:";
44
45
46 /** {@inheritDoc} */
47 public void addContentResolver(final ContentResolver contentResolver) {
48 throw new UnsupportedOperationException("ClasspathContentResolver cannot add other ContentResolvers");
49 }
50
51 /** {@inheritDoc} */
52 public byte[] getContent(final String key) {
53 final String normalizedKey = normalizeKey(key);
54
55 try {
56 final InputStream is = getClassLoader().getResourceAsStream(normalizedKey);
57 if (is != null) {
58 return IOUtils.toByteArray(is);
59 }
60 // else
61 return null;
62 } catch (final IOException e) {
63 LOG.error(e.getMessage(), e);
64 return null;
65 }
66 }
67
68 /**
69 * Method to get onlx the URL for the given Key.
70 * <p>
71 *
72 * @param key the key (could have a 'classpath:' prefix or not)
73 * @return The {@link URL}, see {@link ClassLoader#getResource(String)}.
74 */
75 public static URL getResource(final String key) {
76 final String normalizedKey = normalizeKey(key);
77
78 return getClassLoader().getResource(normalizedKey);
79 }
80
81
82 /**
83 * Return the default ClassLoader to use: typically the thread context ClassLoader, if available; the ClassLoader
84 * that loaded the ClasspathContentResolver class will be used as fallback.
85 * <p>
86 * Call this method if you intend to use the thread context ClassLoader in a scenario where you absolutely need a
87 * non-null ClassLoader reference: for example, for class path resource loading (but not necessarily for
88 * <code>Class.forName</code>, which accepts a <code>null</code> ClassLoader reference as well).
89 *
90 * @return the default ClassLoader (never <code>null</code>)
91 * @see java.lang.Thread#getContextClassLoader()
92 */
93 public static ClassLoader getClassLoader() {
94 ClassLoader cl = null;
95 try {
96 cl = Thread.currentThread().getContextClassLoader();
97 } catch (final Throwable ex) {
98 LOG.debug("Cannot access thread context ClassLoader - falling back to system class loader", ex);
99 }
100 if (cl == null) {
101 // No thread context class loader -> use class loader of this class.
102 cl = ClasspathContentResolver.class.getClassLoader();
103 }
104 return cl;
105 }
106
107 private static String normalizeKey(final String key) {
108 String normalizedKey = key;
109 if (normalizedKey.startsWith(CLASSPATH_URL_PREFIX)) {
110 normalizedKey = normalizedKey.substring(CLASSPATH_URL_PREFIX.length());
111 }
112 if (normalizedKey.startsWith("/")) {
113 normalizedKey = normalizedKey.substring(1);
114 }
115 return normalizedKey;
116 }
117 }