1 | /* |
2 | @license.text@ |
3 | */ |
4 | package com.hammurapi.common; |
5 | |
6 | import java.io.IOException; |
7 | import java.io.InputStream; |
8 | import java.net.URL; |
9 | import java.util.Locale; |
10 | import java.util.Map; |
11 | import java.util.Properties; |
12 | |
13 | |
14 | /** |
15 | * Utility class which searches class hierarchy for a resource. |
16 | * Resource shall be named after class name, profile name is separated from |
17 | * class name by ! and locale separated from class name/profile by _. |
18 | * @author Pavel Vlasov |
19 | * @revision $Revision$ |
20 | */ |
21 | public class ClassResourceLoader { |
22 | private Visitable<Class<?>> visitable; |
23 | private String prefix; |
24 | private ClassLoader classLoader; |
25 | |
26 | public ClassResourceLoader(Class<?> clazz, String prefix, ClassLoader classLoader) { |
27 | this.visitable=new ClassHierarchyVisitable(clazz); |
28 | this.classLoader = classLoader==null ? clazz.getClassLoader() : classLoader; |
29 | this.prefix = prefix; |
30 | } |
31 | |
32 | /** |
33 | * |
34 | * @param profile Profile, can be null |
35 | * @param extension Extension, can be null |
36 | * @return |
37 | */ |
38 | public URL getResource(String profile, String extension) { |
39 | return getResource(profile, Locale.getDefault(), extension); |
40 | } |
41 | |
42 | /** |
43 | * @param profile |
44 | * @param extension |
45 | * @return |
46 | */ |
47 | public URL getResource(final String profile, final Locale locale, final String extension) { |
48 | final URL[] ret={null}; |
49 | visitable.accept(new Visitor<Class<?>>() { |
50 | Locale actualLocale = locale==null ? Locale.getDefault() : locale; |
51 | |
52 | public boolean visit(Class<?> currentClass) { |
53 | for (int i=0; i<4; i++) { |
54 | String variant=currentClass.getName().replace('.','/'); |
55 | if (prefix!=null) { |
56 | variant = prefix + variant; |
57 | } |
58 | if (profile!=null) { |
59 | variant+="!"+profile; |
60 | } |
61 | |
62 | switch (i) { |
63 | case 0: |
64 | variant+="_"+actualLocale; |
65 | break; |
66 | case 1: |
67 | variant+="_"+actualLocale.getLanguage(); |
68 | if (actualLocale.getCountry().length()!=0) { |
69 | variant+="_"+actualLocale.getCountry(); |
70 | } |
71 | break; |
72 | case 2: |
73 | variant+="_"+actualLocale.getLanguage(); |
74 | break; |
75 | case 3: |
76 | break; |
77 | } |
78 | |
79 | if (extension!=null) { |
80 | variant+="."+extension; |
81 | } |
82 | |
83 | |
84 | ret[0]=classLoader.getResource(variant); |
85 | if (ret[0]!=null) { |
86 | return false; |
87 | } |
88 | } |
89 | |
90 | return true; |
91 | } |
92 | |
93 | }); |
94 | |
95 | return ret[0]; |
96 | } |
97 | |
98 | /** |
99 | * Collects properties from class hierarchy. |
100 | * @param profile Profile, can be null |
101 | * @param extension Extension, can be null |
102 | * @return |
103 | */ |
104 | public Properties getProperties(String profile, String extension) { |
105 | return getProperties(profile, Locale.getDefault(), extension); |
106 | } |
107 | |
108 | /** |
109 | * Collects properties from class hierarchy. |
110 | * @param profile |
111 | * @param extension |
112 | * @return |
113 | */ |
114 | public Properties getProperties(final String profile, final Locale locale, final String extension) { |
115 | final Properties ret=new Properties(); |
116 | visitable.accept(new Visitor<Class<?>>() { |
117 | |
118 | public boolean visit(Class<?> currentClass) { |
119 | for (int i=0; i<4; i++) { |
120 | String variant=currentClass.getName().replace('.','/'); |
121 | if (prefix!=null) { |
122 | variant = prefix + variant; |
123 | } |
124 | if (profile!=null) { |
125 | variant+=profile; |
126 | } |
127 | |
128 | switch (i) { |
129 | case 0: |
130 | variant+="_"+locale; |
131 | break; |
132 | case 1: |
133 | variant+="_"+locale.getLanguage(); |
134 | if (locale.getCountry().length()!=0) { |
135 | variant+="_"+locale.getCountry(); |
136 | } |
137 | break; |
138 | case 2: |
139 | variant+="_"+locale.getLanguage(); |
140 | break; |
141 | case 3: |
142 | break; |
143 | } |
144 | |
145 | if (extension!=null) { |
146 | variant+="."+extension; |
147 | } |
148 | |
149 | |
150 | InputStream s=classLoader.getResourceAsStream(variant); |
151 | if (s!=null) { |
152 | Properties cp=new Properties(); |
153 | try { |
154 | cp.load(s); |
155 | for (Map.Entry<Object, Object> entry: cp.entrySet()) { |
156 | if (!ret.containsKey(entry.getKey())) { |
157 | ret.setProperty((String) entry.getKey(), (String) entry.getValue()); |
158 | } |
159 | } |
160 | } catch (IOException e) { |
161 | throw new RuntimeException("Cannot load properties from resource "+variant, e); |
162 | } |
163 | |
164 | break; |
165 | } |
166 | } |
167 | |
168 | |
169 | return true; |
170 | } |
171 | |
172 | }); |
173 | |
174 | return ret; |
175 | } |
176 | |
177 | } |