001: /*
002: License $Id: Factory.java,v 1.5 2003/09/13 04:59:56 hendriks73 Exp $
003:
004: Copyright (c) 2001-2005 tagtraum industries.
005:
006: LGPL
007: ====
008:
009: jo! is free software; you can redistribute it and/or
010: modify it under the terms of the GNU Lesser General Public
011: License as published by the Free Software Foundation; either
012: version 2.1 of the License, or (at your option) any later version.
013:
014: jo! is distributed in the hope that it will be useful,
015: but WITHOUT ANY WARRANTY; without even the implied warranty of
016: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: Lesser General Public License for more details.
018:
019: You should have received a copy of the GNU Lesser General Public
020: License along with this library; if not, write to the Free Software
021: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
022:
023: For LGPL see <http://www.fsf.org/copyleft/lesser.txt>
024:
025:
026: Sun license
027: ===========
028:
029: This release contains software by Sun Microsystems. Therefore
030: the following conditions have to be met, too. They apply to the
031: files
032:
033: - lib/mail.jar
034: - lib/activation.jar
035: - lib/jsse.jar
036: - lib/jcert.jar
037: - lib/jaxp.jar
038: - lib/crimson.jar
039: - lib/servlet.jar
040: - lib/jnet.jar
041: - lib/jaas.jar
042: - lib/jaasmod.jar
043:
044: contained in this release.
045:
046: a. Licensee may not modify the Java Platform
047: Interface (JPI, identified as classes contained within the javax
048: package or any subpackages of the javax package), by creating additional
049: classes within the JPI or otherwise causing the addition to or modification
050: of the classes in the JPI. In the event that Licensee creates any
051: Java-related API and distribute such API to others for applet or
052: application development, you must promptly publish broadly, an accurate
053: specification for such API for free use by all developers of Java-based
054: software.
055:
056: b. Software is confidential copyrighted information of Sun and
057: title to all copies is retained by Sun and/or its licensors. Licensee
058: shall not modify, decompile, disassemble, decrypt, extract, or otherwise
059: reverse engineer Software. Software may not be leased, assigned, or
060: sublicensed, in whole or in part. Software is not designed or intended
061: for use in on-line control of aircraft, air traffic, aircraft navigation
062: or aircraft communications; or in the design, construction, operation or
063: maintenance of any nuclear facility. Licensee warrants that it will not
064: use or redistribute the Software for such purposes.
065:
066: c. Software is provided "AS IS," without a warranty
067: of any kind. ALL EXPRESS OR IMPLIED REPRESENTATIONS AND WARRANTIES,
068: INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
069: PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
070:
071: d. This License is effective until terminated. Licensee may
072: terminate this License at any time by destroying all copies of Software.
073: This License will terminate immediately without notice from Sun if Licensee
074: fails to comply with any provision of this License. Upon such termination,
075: Licensee must destroy all copies of Software.
076:
077: e. Software, including technical data, is subject to U.S.
078: export control laws, including the U.S. Export Administration Act and its
079: associated regulations, and may be subject to export or import regulations
080: in other countries. Licensee agrees to comply strictly with all such
081: regulations and acknowledges that it has the responsibility to obtain
082: licenses to export, re-export, or import Software. Software may not be
083: downloaded, or otherwise exported or re-exported (i) into, or to a national
084: or resident of, Cuba, Iraq, Iran, North Korea, Libya, Sudan, Syria or any
085: country to which the U.S. has embargoed goods; or (ii) to anyone on the
086: U.S. Treasury Department's list of Specially Designated Nations or the U.S.
087: Commerce Department's Table of Denial Orders.
088:
089:
090: Feedback
091: ========
092:
093: We encourage your feedback and suggestions and want to use your feedback to
094: improve the Software. Send all such feedback to:
095: <feedback@tagtraum.com>
096:
097: For more information on tagtraum industries and jo!
098: please see <http://www.tagtraum.com/>.
099:
100:
101: */
102: package com.tagtraum.framework.util;
103:
104: import java.util.*;
105:
106: /**
107: * Configurable universal Factory.
108: *
109: * @author <a href="mailto:hs@tagtraum.com">Hendrik Schreiber</a>
110: * @version 1.1beta1 $Id: Factory.java,v 1.5 2003/09/13 04:59:56 hendriks73 Exp $
111: */
112: public class Factory {
113:
114: /**
115: * "Almost" Singleton.
116: */
117: protected static Factory myFactory = null;
118:
119: /**
120: * Source-Version.
121: */
122: public static String vcid = "$Id: Factory.java,v 1.5 2003/09/13 04:59:56 hendriks73 Exp $";
123:
124: /**
125: * Packagepaths.
126: */
127: protected ArrayList myPackages = new ArrayList();
128:
129: /**
130: * Hashmap with aliases that point at classnames.
131: */
132: protected HashMap myAliases = new HashMap();
133:
134: /**
135: * Instantiates if necessary a <code>Factory</code>. Is already
136: * one present this is returned.
137: *
138: * @return <code>Factory</code>-Singleton
139: */
140: public static Factory getFactory() {
141: if (myFactory == null) {
142: synchronized (Factory.class) {
143: if (myFactory == null) {
144: myFactory = new Factory();
145: }
146: }
147: }
148:
149: return myFactory;
150: }
151:
152: /**
153: * Returns a <code>java.lang-Class</code> object for
154: * an alias or classname. To achieve this first the internal
155: * class cache is checked, then <code>Class.forName(String)</code>
156: * is used with <code>name</code> and all package paths.
157: *
158: * @exception ClassNotFoundException if the class could not be found
159: * @param name the class's full name, the class name or an alias
160: * @return the searched <code>class</code> object
161: */
162: public Class getClassForName(String name)
163: throws ClassNotFoundException {
164: return getClassForName(name, this .getClass().getClassLoader());
165: }
166:
167: /**
168: * Returns a <code>java.lang-Class</code> object for
169: * an alias or classname. To achieve this first the internal
170: * class cache is checked, then <code>Class.forName(String)</code>
171: * is used with <code>name</code> and all package paths.
172: *
173: * @exception ClassNotFoundException if the class could not be found
174: * @param name the class's full name, the class name or an alias
175: * @param cl ClassLoader to use.
176: * @return the searched <code>class</code> object
177: */
178: public Class getClassForName(String name, ClassLoader cl)
179: throws ClassNotFoundException {
180: name = resolveAlias(name);
181:
182: Class aClass = null;
183:
184: try {
185: aClass = Class.forName(name, true, cl);
186: } catch (ClassNotFoundException e1) {
187: Iterator i = myPackages.iterator();
188: String fullName;
189:
190: while (i.hasNext() && aClass == null) {
191: try {
192: fullName = (String) i.next() + name;
193: aClass = Class.forName(fullName, true, cl);
194: } catch (ClassNotFoundException e2) {
195: }
196: }
197: }
198:
199: if (aClass == null) {
200: throw new ClassNotFoundException(name);
201: }
202:
203: return aClass;
204: }
205:
206: /**
207: * Resolves an alias.
208: *
209: * @param anAlias alias to resolve
210: * @return the resolved alias or the alias itself if it
211: * is not resolvable
212: */
213: public synchronized String resolveAlias(String anAlias) {
214: String resolvedAlias = (String) myAliases.get(anAlias);
215:
216: if (resolvedAlias == null) {
217: return anAlias;
218: }
219:
220: return resolveAlias(resolvedAlias);
221: }
222:
223: /**
224: * Returns a new instance of the class. Alias resloving is used.
225: *
226: * @param className name or alias of the class ro instantiate
227: * @exception FactoryException if the class could not be instantiated
228: */
229: public Object get(String className) throws FactoryException {
230: return get(className, this .getClass().getClassLoader());
231: }
232:
233: /**
234: * Returns a new instance of the class. Alias resloving is used.
235: *
236: * @param className name or alias of the class ro instantiate
237: * @param aClassLoader the ClassLoader to use
238: * @exception FactoryException if the class could not be instantiated
239: */
240: public Object get(String className, ClassLoader aClassLoader)
241: throws FactoryException {
242: try {
243: Class aClass = getClassForName(className, aClassLoader);
244:
245: return aClass.newInstance();
246: } catch (Exception e) {
247: throw new FactoryException(e);
248: }
249: }
250:
251: /**
252: * Adds a path to the internal search path.<br>
253: * Example:
254: * <xmp>
255: * addPackagePath("java.lang");
256: * </xmp>
257: * When looking for a class the package paths a searched in
258: * the same order they were added.
259: *
260: * @param path importpath
261: */
262: public synchronized void addPackagePath(String path) {
263: path = normalizePath(path);
264:
265: // nachgucken, ob schon vorhanden...
266: if (!myPackages.contains(path)) {
267: myPackages.add(path);
268: }
269: }
270:
271: /**
272: * Removes a path from the internal search path
273: *
274: * @param path path to remove
275: */
276: public synchronized void removePackagePath(String path) {
277: path = normalizePath(path);
278:
279: myPackages.remove(path);
280: }
281:
282: /**
283: * Helper method that normalizes paths.
284: *
285: * @return the normalized path
286: * @param path path to normalize
287: */
288: protected String normalizePath(String path) {
289: // get rid of first dot
290: while (path.startsWith(".")) {
291: path = path.substring(1);
292: }
293:
294: // tolerate import-like syntax
295: if (path.endsWith("*")) {
296: path = path.substring(0, path.length() - 1);
297: }
298:
299: if (!path.endsWith(".")) {
300: path += ".";
301: }
302:
303: return path;
304: }
305:
306: /**
307: * Return an <code>Iterator</code> for the import paths.
308: *
309: * @return Iterator for the import paths.
310: */
311: public Iterator packagePaths() {
312: return myPackages.iterator();
313: }
314:
315: /**
316: * Adds an alias.
317: *
318: * @param anAlias the new alias
319: * @param anAliasedName name that denotes an alias. Note that this
320: * can be an alias itself, but circles are not allowed
321: */
322: public synchronized void addAlias(String anAlias,
323: String anAliasedName) {
324: if (anAlias.equals(resolveAlias(anAliasedName))) {
325: throw new IllegalArgumentException(
326: "Aliases aren't allowed to form circles.");
327: }
328:
329: myAliases.put(anAlias, anAliasedName);
330: }
331:
332: /**
333: * Removes an alias.
334: *
335: * @param anAlias alias to remove
336: */
337: public synchronized void removeAlias(String anAlias) {
338: myAliases.remove(anAlias);
339: }
340:
341: /**
342: * Removes all aliases.
343: */
344: public synchronized void removeAllAliases() {
345: myAliases.clear();
346: }
347:
348: /**
349: * Sets aliases from a <code>Hastable</code>. This method
350: * is usefull when using <code>Properties</code>.
351: */
352: public synchronized void addAliases(Hashtable aliases) {
353: String key;
354: String value;
355: Enumeration e = aliases.keys();
356:
357: while (e.hasMoreElements()) {
358: key = (String) e.nextElement();
359: value = (String) aliases.get(key);
360:
361: addAlias(key, value);
362: }
363: }
364:
365: }
|