001: /*
002: * hgcommons 7
003: * Hammurapi Group Common Library
004: * Copyright (C) 2003 Hammurapi Group
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * URL: http://www.hammurapi.biz/hammurapi-biz/ef/xmenu/hammurapi-group/products/products/hgcommons/index.html
021: * e-Mail: support@hammurapi.biz
022: */
023: package biz.hammurapi.util;
024:
025: import java.io.IOException;
026: import java.io.InputStream;
027: import java.util.ArrayList;
028: import java.util.Collection;
029: import java.util.Iterator;
030: import java.util.Locale;
031: import java.util.Map;
032: import java.util.Properties;
033:
034: import biz.hammurapi.config.ConfigurationException;
035: import biz.hammurapi.config.Context;
036: import biz.hammurapi.config.DomConfigFactory;
037: import biz.hammurapi.config.RuntimeConfigurationException;
038:
039: /**
040: * Utility class which searches class hierarchy for a resource.
041: * Resource shall be named after class name, profile name is separated from
042: * class name by ! and locale separated from class name/profile by _.
043: * @author Pavel Vlasov
044: * @revision $Revision$
045: */
046: public class ClassResourceLoader {
047: private Visitable visitable;
048: private Class clazz;
049:
050: /**
051: *
052: */
053: public ClassResourceLoader(Class clazz) {
054: this .visitable = new ClassHierarchyVisitable(clazz);
055: this .clazz = clazz;
056: }
057:
058: /**
059: *
060: * @param profile Profile, can be null
061: * @param extension Extension, can be null
062: * @return
063: */
064: public InputStream getResourceAsStream(String profile,
065: String extension) {
066: return getResourceAsStream(profile, Locale.getDefault(),
067: extension);
068: }
069:
070: /**
071: * @param profile
072: * @param extension
073: * @return
074: */
075: public InputStream getResourceAsStream(final String profile,
076: final Locale locale, final String extension) {
077: final InputStream[] ret = { null };
078: visitable.accept(new Visitor() {
079: Locale actualLocale = locale == null ? Locale.getDefault()
080: : locale;
081:
082: public boolean visit(Object target) {
083: Class currentClass = (Class) target;
084: for (int i = 0; i < 4; i++) {
085: String variant = currentClass.getName().replace(
086: '.', '/');
087: if (profile != null) {
088: variant += "!" + profile;
089: }
090:
091: switch (i) {
092: case 0:
093: variant += "_" + actualLocale;
094: break;
095: case 1:
096: variant += "_" + actualLocale.getLanguage();
097: if (actualLocale.getCountry().length() != 0) {
098: variant += "_" + actualLocale.getCountry();
099: }
100: break;
101: case 2:
102: variant += "_" + actualLocale.getLanguage();
103: break;
104: case 3:
105: break;
106: }
107:
108: if (extension != null) {
109: variant += "." + extension;
110: }
111:
112: ret[0] = clazz.getClassLoader()
113: .getResourceAsStream(variant);
114: if (ret[0] != null) {
115: return false;
116: }
117: }
118:
119: return true;
120: }
121:
122: });
123:
124: return ret[0];
125: }
126:
127: /**
128: *
129: * @param profile Profile, can be null
130: * @param extension Extension, can be null
131: * @return
132: */
133: public Properties getProperties(String profile, String extension) {
134: return getProperties(profile, Locale.getDefault(), extension);
135: }
136:
137: /**
138: * @param profile
139: * @param extension
140: * @return
141: */
142: public Properties getProperties(final String profile,
143: final Locale locale, final String extension) {
144: final Properties ret = new Properties();
145: visitable.accept(new Visitor() {
146:
147: public boolean visit(Object target) {
148: Class currentClass = (Class) target;
149: for (int i = 0; i < 4; i++) {
150: String variant = currentClass.getName().replace(
151: '.', '/');
152: if (profile != null) {
153: variant += profile;
154: }
155:
156: switch (i) {
157: case 0:
158: variant += "_" + locale;
159: break;
160: case 1:
161: variant += "_" + locale.getLanguage();
162: if (locale.getCountry().length() != 0) {
163: variant += "_" + locale.getCountry();
164: }
165: break;
166: case 2:
167: variant += "_" + locale.getLanguage();
168: break;
169: case 3:
170: break;
171: }
172:
173: if (extension != null) {
174: variant += "." + extension;
175: }
176:
177: InputStream s = clazz.getClassLoader()
178: .getResourceAsStream(variant);
179: if (s != null) {
180: Properties cp = new Properties();
181: try {
182: cp.load(s);
183: Iterator it = cp.entrySet().iterator();
184: while (it.hasNext()) {
185: Map.Entry entry = (Map.Entry) it.next();
186: if (!ret.containsKey(entry.getKey())) {
187: ret.setProperty((String) entry
188: .getKey(), (String) entry
189: .getValue());
190: }
191: }
192: } catch (IOException e) {
193: throw new RuntimeConfigurationException(
194: "Cannot load properties from resource "
195: + variant, e);
196: }
197:
198: break;
199: }
200: }
201:
202: return true;
203: }
204:
205: });
206:
207: return ret;
208: }
209:
210: /**
211: * @param profile
212: * @param extension
213: * @return
214: */
215: public Context getContext(final String profile, Locale locale,
216: final String extension) {
217: final Locale actualLocale = locale == null ? Locale
218: .getDefault() : locale;
219: final Collection contexts = new ArrayList();
220: final DomConfigFactory dcf = new DomConfigFactory();
221: visitable.accept(new Visitor() {
222:
223: public boolean visit(Object target) {
224: Class currentClass = (Class) target;
225: for (int i = 0; i < 4; i++) {
226: String variant = currentClass.getName().replace(
227: '.', '/');
228: if (profile != null) {
229: variant += profile;
230: }
231:
232: switch (i) {
233: case 0:
234: variant += "_" + actualLocale;
235: break;
236: case 1:
237: variant += "_" + actualLocale.getLanguage();
238: if (actualLocale.getCountry().length() != 0) {
239: variant += "_" + actualLocale.getCountry();
240: }
241: break;
242: case 2:
243: variant += "_" + actualLocale.getLanguage();
244: break;
245: case 3:
246: break;
247: }
248:
249: if (extension != null) {
250: variant += "." + extension;
251: }
252:
253: InputStream s = clazz.getClassLoader()
254: .getResourceAsStream(variant);
255: if (s != null) {
256: try {
257: contexts.add(dcf.create(s, null));
258: } catch (ConfigurationException e) {
259: throw new RuntimeConfigurationException(e);
260: } catch (IOException e) {
261: throw new RuntimeConfigurationException(e);
262: }
263: break;
264: }
265: }
266:
267: return true;
268: }
269:
270: });
271:
272: return contexts.isEmpty() ? null : new Context() {
273:
274: public Object get(String name) {
275: Iterator it = contexts.iterator();
276: while (it.hasNext()) {
277: Object ret = ((Context) it.next()).get(name);
278: if (ret != null) {
279: return ret;
280: }
281: }
282: return null;
283: }
284:
285: };
286: }
287: }
|