View Javadoc
1   /*-
2    * #%L
3    * io.earcam.instrumental.reflect
4    * %%
5    * Copyright (C) 2018 earcam
6    * %%
7    * SPDX-License-Identifier: (BSD-3-Clause OR EPL-1.0 OR Apache-2.0 OR MIT)
8    * 
9    * You <b>must</b> choose to accept, in full - any individual or combination of 
10   * the following licenses:
11   * <ul>
12   * 	<li><a href="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause</a></li>
13   * 	<li><a href="https://www.eclipse.org/legal/epl-v10.html">EPL-1.0</a></li>
14   * 	<li><a href="https://www.apache.org/licenses/LICENSE-2.0">Apache-2.0</a></li>
15   * 	<li><a href="https://opensource.org/licenses/MIT">MIT</a></li>
16   * </ul>
17   * #L%
18   */package io.earcam.instrumental.reflect;
19  
20  import static io.earcam.instrumental.reflect.Names.typeToResourceName;
21  
22  import java.io.ByteArrayOutputStream;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.io.UncheckedIOException;
26  import java.net.URI;
27  
28  import javax.annotation.WillClose;
29  
30  import io.earcam.unexceptional.Exceptional;
31  
32  /**
33   * <p>
34   * Resources class.
35   * </p>
36   *
37   */
38  public final class Resources {
39  
40  	private Resources()
41  	{}
42  
43  
44  	/**
45  	 * <p>
46  	 * classAsBytes.
47  	 * </p>
48  	 *
49  	 * @param type a {@link java.lang.Class} object.
50  	 * @return an array of {@link byte} objects.
51  	 */
52  	public static byte[] classAsBytes(Class<?> type)
53  	{
54  		return readAllBytes(classAsStream(type));
55  	}
56  
57  
58  	static byte[] readAllBytes(@WillClose InputStream input)
59  	{
60  		ByteArrayOutputStream baos = new ByteArrayOutputStream();
61  
62  		int read;
63  		try(InputStream in = input) {
64  			while((read = in.read()) != -1) {
65  				baos.write(read);
66  			}
67  		} catch(IOException e) {
68  			throw new UncheckedIOException(e);
69  		}
70  		return baos.toByteArray();
71  	}
72  
73  
74  	/**
75  	 * <p>
76  	 * classAsStream.
77  	 * </p>
78  	 *
79  	 * @param type a {@link java.lang.Class} object.
80  	 * @return a {@link java.io.InputStream} object.
81  	 */
82  	public static InputStream classAsStream(Class<?> type)
83  	{
84  		return type.getClassLoader().getResourceAsStream(typeToResourceName(type));
85  	}
86  
87  
88  	/**
89  	 * <p>
90  	 * sourceOfResource.
91  	 * </p>
92  	 *
93  	 * @param type a {@link java.lang.Class} object.
94  	 * @return a {@link java.lang.String} object.
95  	 */
96  	public static String sourceOfResource(Class<?> type)
97  	{
98  		ClassLoader classLoader = type.getClassLoader();
99  		return sourceOfResource(type, classLoader == null ? ClassLoader.getSystemClassLoader() : classLoader);
100 	}
101 
102 
103 	/**
104 	 * <p>
105 	 * sourceOfResource.
106 	 * </p>
107 	 *
108 	 * @param type a {@link java.lang.Class} object.
109 	 * @param classLoader a {@link java.lang.ClassLoader} object.
110 	 * @return a {@link java.lang.String} object.
111 	 */
112 	public static String sourceOfResource(Class<?> type, ClassLoader classLoader)
113 	{
114 		String className = Names.typeToResourceName(type);
115 		String resource = removeJarUrlDecoration(Exceptional.uri(classLoader.getResource(className)));
116 		int shebang = resource.indexOf('!');
117 		return shebang > -1 ? resource.substring(0, shebang)
118 				: resource.substring(0, resource.length() - className.length());
119 	}
120 
121 
122 	/**
123 	 * <p>
124 	 * removeJarUrlDecoration.
125 	 * </p>
126 	 *
127 	 * @param jar a {@link java.net.URI} object.
128 	 * @return a {@link java.lang.String} object.
129 	 */
130 	public static String removeJarUrlDecoration(URI jar)
131 	{
132 		return jar.toString()
133 				.replaceFirst("^jar:file:", "")
134 				.replaceFirst("^file:(//)?", "")
135 				.replaceAll("!/$", "");
136 	}
137 }