001: package edu.indiana.lib.osid.base.loader;
002:
003: /**
004: * OsidLoader loads a specific implementation of an Open Service Interface
005: * Definition (OSID) with its getManager method. The getManager method loads
006: * an instance of the OSID's org.osid.OsidManager, assigns the manager's OsidContext,
007: * assigns any configuration information, and returns the instance of the OSID
008: * implementation. This usage of the getManager method in the OsidLoader is
009: * how applications should bind a particular implementation to an OSID. The
010: * value of this approach is that an application can defer which specific OSID
011: * implementation is used until runtime. The specific implementation package
012: * name can then be part of the configuration information rather than being
013: * hard coded. Changing implementations is simplified with this approach.
014: *
015: * <p>
016: * As an example, in order to create a new Hierarchy, an application does not
017: * use the new operator. It uses the OsidLoader getManager method to get an
018: * instance of a class that implements HierarchyManager (a subclass of
019: * org.osid.OsidManager). The application uses the HierarchyManager instance to create
020: * the Hierarchy. It is the createHierarchy() method in some package (e.g.
021: * org.osid.hierarchy.impl.HierarchyManager) which uses the new operator on
022: * org.osid.hierarchy.impl.Hierarchy, casts it as
023: * org.osid.hierarchy.Hierarchy, and returns it to the application. This
024: * indirection offers the significant value of being able to change
025: * implementations in one spot with one modification, namely by using a
026: * implementation package name argument for the OsidLoader getManager method.
027: * </p>
028: *
029: * <p>
030: * Sample:
031: * <blockquote>
032: * org.osid.OsidContext myContext = new org.osid.OsidContext();<br/
033: * >String key = "myKey";<br/
034: * >myContext.assignContext(key, "I want to save this string as context");<br/
035: * >String whatWasMyContext = myContext.getContext(key);<br/
036: * >org.osid.hierarchy.HierarchyManager hierarchyManager =
037: * <blockquote>
038: * org.osid.OsidLoader.getManager("org.osid.hierarchy.HierarchyManager","org.osid.shared.impl",myContext,null);
039: * </blockquote>
040: * org.osid.hierarchy.Hierarchy myHierarchy =
041: * hierarchyManager.createHierarchy(...);<br/>
042: * </blockquote>
043: * </p>
044: *
045: * <p>
046: * A similar technique can be used for creating other objects. OSIDs that have
047: * org.osid.OsidManager implementations loaded by OsidLoader, will define an
048: * appropriate interface to create these objects.
049: * </p>
050: *
051: * <p>
052: * The arguments to OsidLoader.getManager method are the OSID org.osid.OsidManager
053: * interface name, the implementing package name, the OsidContext, and any
054: * additional configuration information.
055: * </p>
056: *
057: * <p>
058: * OSID Version: 2.0
059: * </p>
060: *
061: * <p>
062: * Licensed under the {@link org.osid.SidImplementationLicenseMIT MIT
063: * O.K.I. OSID Definition License}.
064: * </p>
065: */
066: public class OsidLoader implements java.io.Serializable {
067:
068: private static org.apache.commons.logging.Log _log = edu.indiana.lib.twinpeaks.util.LogUtils
069: .getLog(OsidLoader.class);
070:
071: /**
072: * Returns an instance of the org.osid.OsidManager of the OSID specified by the OSID
073: * package org.osid.OsidManager interface name and the implementation package name.
074: * The implementation class name is constructed from the SID package
075: * Manager interface name. A configuration file name is constructed in a
076: * similar manner and if the file exists it is loaded into the
077: * implementation's org.osid.OsidManager's configuration.
078: *
079: * <p>
080: * Example: To load an implementation of the org.osid.Filing OSID
081: * implemented in a package "xyz", one would use:
082: * </p>
083: *
084: * <p>
085: * org.osid.filing.FilingManager fm =
086: * (org.osid.filing.FilingManager)org.osid.OsidLoader.getManager(
087: * </p>
088: *
089: * <p>
090: * "org.osid.filing.FilingManager" ,
091: * </p>
092: *
093: * <p>
094: * "xyz" ,
095: * </p>
096: *
097: * <p>
098: * new org.osid.OsidContext());
099: * </p>
100: *
101: * @param osidPackageManagerName osidPackageManagerName is a fully
102: * qualified org.osid.OsidManager interface name
103: * @param implPackageName implPackageName is a fully qualified
104: * implementation package name
105: * @param context
106: * @param additionalConfiguration
107: *
108: * @return org.osid.OsidManager
109: *
110: * @throws org.osid.OsidException An exception with one of the following
111: * messages defined in org.osid.OsidException: {@link
112: * org.osid.OsidException#OPERATION_FAILED OPERATION_FAILED},
113: * {@link org.osid.OsidException#NULL_ARGUMENT NULL_ARGUMENT},
114: * {@link org.osid.OsidException#VERSION_ERROR VERSION_ERROR},
115: * ={@link org.osid.OsidException#INTERFACE_NOT_FOUND
116: * INTERFACE_NOT_FOUND}, ={@link
117: * org.osid.OsidException#MANAGER_NOT_FOUND MANAGER_NOT_FOUND},
118: * ={@link org.osid.OsidException#MANAGER_INSTANTIATION_ERROR
119: * MANAGER_INSTANTIATION_ERROR}, ={@link
120: * org.osid.OsidException#ERROR_ASSIGNING_CONTEXT
121: * ERROR_ASSIGNING_CONTEXT}, ={@link
122: * org.osid.OsidException#ERROR_ASSIGNING_CONFIGURATION
123: * ERROR_ASSIGNING_CONFIGURATION}
124: */
125: public static org.osid.OsidManager getManager(
126: String osidPackageManagerName, String implPackageName,
127: org.osid.OsidContext context,
128: java.util.Properties additionalConfiguration)
129: throws org.osid.OsidException {
130:
131: try {
132: if ((null != context) && (null != osidPackageManagerName)
133: && (null != implPackageName)) {
134:
135: String osidInterfaceName = osidPackageManagerName;
136: String className = makeClassName(osidPackageManagerName);
137: String managerClassName = makeFullyQualifiedClassName(
138: implPackageName, className);
139:
140: Class osidInterface = Class.forName(osidInterfaceName);
141:
142: if (null != osidInterface) {
143: Class managerClass = Class
144: .forName(managerClassName);
145:
146: if (null != managerClass) {
147: if (osidInterface
148: .isAssignableFrom(managerClass)) {
149: org.osid.OsidManager manager = (org.osid.OsidManager) managerClass
150: .newInstance();
151:
152: if (null != manager) {
153: try {
154: manager.osidVersion_2_0();
155: } catch (Throwable ex) {
156: throw new org.osid.OsidException(
157: org.osid.OsidException.VERSION_ERROR);
158: }
159:
160: try {
161: manager.assignOsidContext(context);
162: } catch (Exception ex) {
163: throw new org.osid.OsidException(
164: org.osid.OsidException.ERROR_ASSIGNING_CONTEXT);
165: }
166:
167: try {
168: java.util.Properties configuration = getConfiguration(manager);
169:
170: if (null == configuration) {
171: configuration = new java.util.Properties();
172: }
173:
174: if (null != additionalConfiguration) {
175: java.util.Enumeration enumer = additionalConfiguration
176: .propertyNames();
177:
178: while (enumer.hasMoreElements()) {
179: java.io.Serializable key = (java.io.Serializable) enumer
180: .nextElement();
181:
182: if (null != key) {
183: java.io.Serializable value = (java.io.Serializable) additionalConfiguration
184: .get(key);
185:
186: if (null != value) {
187: configuration.put(
188: key, value);
189: }
190: }
191: }
192: }
193:
194: manager
195: .assignConfiguration(configuration);
196:
197: return manager;
198: } catch (Exception ex) {
199: throw new org.osid.OsidException(
200: org.osid.OsidException.ERROR_ASSIGNING_CONFIGURATION);
201: }
202: }
203:
204: throw new org.osid.OsidException(
205: org.osid.OsidException.MANAGER_INSTANTIATION_ERROR);
206: }
207:
208: throw new org.osid.OsidException(
209: org.osid.OsidException.MANAGER_NOT_OSID_IMPLEMENTATION);
210: }
211:
212: throw new org.osid.OsidException(
213: org.osid.OsidException.MANAGER_NOT_FOUND);
214: }
215:
216: throw new org.osid.OsidException(
217: org.osid.OsidException.INTERFACE_NOT_FOUND);
218: }
219:
220: throw new org.osid.OsidException(
221: org.osid.OsidException.NULL_ARGUMENT);
222: } catch (org.osid.OsidException oex) {
223: oex.printStackTrace();
224: throw new org.osid.OsidException(oex.getMessage());
225: } catch (java.lang.Throwable ex) {
226: ex.printStackTrace();
227: throw new org.osid.OsidException(
228: org.osid.OsidException.OPERATION_FAILED);
229: }
230: }
231:
232: private static String makeClassName(String packageManagerName)
233: throws org.osid.OsidException {
234: String className = packageManagerName;
235:
236: if (null != className) {
237: className = (className.endsWith(".") ? className.substring(
238: 0, className.length() - 1) : className);
239:
240: int lastdot = className.lastIndexOf(".");
241:
242: if (-1 != lastdot) {
243: className = className.substring(lastdot + 1);
244: }
245: }
246:
247: return className;
248: }
249:
250: private static String makeFullyQualifiedClassName(
251: String packageName, String className)
252: throws org.osid.OsidException {
253: String cName = className;
254:
255: if (null != packageName) {
256: String pName = (packageName.endsWith(".") ? packageName
257: : new String(packageName + "."));
258: cName = pName + className;
259: }
260:
261: return cName;
262: }
263:
264: /******* Utility Methods For Sakai Implementations ********/
265:
266: /**
267: * Get an InputStream for a particular file name - first check the sakai.home area and then
268: * revert to the classpath.
269: *
270: * This is a utility method used several places.
271: */
272: public static java.io.InputStream getConfigStream(String fileName,
273: Class curClass) {
274: String sakaiHome = System.getProperty("sakai.home");
275: String filePath = sakaiHome + fileName;
276:
277: try {
278: java.io.File f = new java.io.File(filePath);
279: if (f.exists()) {
280: return new java.io.FileInputStream(f);
281: }
282: } catch (Throwable t) {
283: // Not found in the sakai.home area
284: }
285:
286: if (curClass == null)
287: return null;
288:
289: // If there is a class context, load from the class context...
290: java.io.InputStream istream = null;
291:
292: // Load from the class loader
293: istream = curClass.getClassLoader().getResourceAsStream(
294: fileName);
295: if (istream != null)
296: return istream;
297:
298: // Load from the class relative
299: istream = curClass.getResourceAsStream(fileName);
300: if (istream != null)
301: return istream;
302:
303: // Loading from the class at the root
304: istream = curClass.getResourceAsStream("/" + fileName);
305: return istream;
306: }
307:
308: private static java.util.Properties getConfiguration(
309: org.osid.OsidManager manager) throws org.osid.OsidException {
310: java.util.Properties properties = null;
311:
312: if (null != manager) {
313: Class managerClass = manager.getClass();
314:
315: try {
316: String managerClassName = managerClass.getName();
317: int index = managerClassName.lastIndexOf(".");
318:
319: if (-1 != index) {
320: managerClassName = managerClassName
321: .substring(index + 1);
322: }
323:
324: String propertyName = managerClassName + ".properties";
325:
326: // java.io.InputStream is = managerClass.getResourceAsStream(managerClassName + ".properties");
327: java.io.InputStream is = getConfigStream(propertyName,
328: managerClass);
329:
330: if (null != is) {
331: properties = new java.util.Properties();
332: properties.load(is);
333: }
334: } catch (Throwable ex) {
335: }
336: }
337:
338: return properties;
339: }
340:
341: /**
342: * <p>
343: * MIT O.K.I. SID Definition License.
344: * </p>
345: *
346: * <p>
347: * <b>Copyright and license statement:</b>
348: * </p>
349: *
350: * <p>
351: * Copyright © 2003 Massachusetts Institute of Technology <or
352: * copyright holder>
353: * </p>
354: *
355: * <p>
356: * This work is being provided by the copyright holder(s) subject to
357: * the terms of the O.K.I. SID Definition License. By obtaining,
358: * using and/or copying this Work, you agree that you have read,
359: * understand, and will comply with the O.K.I. SID Definition
360: * License.
361: * </p>
362: *
363: * <p>
364: * THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
365: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
366: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
367: * NONINFRINGEMENT. IN NO EVENT SHALL MASSACHUSETTS INSTITUTE OF
368: * TECHNOLOGY, THE AUTHORS, OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
369: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
370: * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
371: * WITH THE WORK OR THE USE OR OTHER DEALINGS IN THE WORK.
372: * </p>
373: *
374: * <p>
375: * <b>O.K.I. SID Definition License</b>
376: * </p>
377: *
378: * <p>
379: * This work (the “Work”), including any software,
380: * documents, or other items related to O.K.I. SID definitions, is
381: * being provided by the copyright holder(s) subject to the terms of
382: * the O.K.I. SID Definition License. By obtaining, using and/or
383: * copying this Work, you agree that you have read, understand, and
384: * will comply with the following terms and conditions of the
385: * O.K.I. SID Definition License:
386: * </p>
387: *
388: * <p>
389: * You may use, copy, and distribute unmodified versions of this Work
390: * for any purpose, without fee or royalty, provided that you include
391: * the following on ALL copies of the Work that you make or
392: * distribute:
393: * </p>
394: *
395: * <ul>
396: * <li>
397: * The full text of the O.K.I. SID Definition License in a location
398: * viewable to users of the redistributed Work.
399: * </li>
400: * </ul>
401: *
402: *
403: * <ul>
404: * <li>
405: * Any pre-existing intellectual property disclaimers, notices, or terms
406: * and conditions. If none exist, a short notice similar to the following
407: * should be used within the body of any redistributed Work:
408: * “Copyright © 2003 Massachusetts Institute of Technology. All
409: * Rights Reserved.”
410: * </li>
411: * </ul>
412: *
413: * <p>
414: * You may modify or create Derivatives of this Work only for your
415: * internal purposes. You shall not distribute or transfer any such
416: * Derivative of this Work to any location or any other third party.
417: * For purposes of this license, “Derivative” shall mean
418: * any derivative of the Work as defined in the United States
419: * Copyright Act of 1976, such as a translation or modification.
420: * </p>
421: *
422: * <p>
423: * THE WORK PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
424: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
425: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
426: * NONINFRINGEMENT. IN NO EVENT SHALL MASSACHUSETTS INSTITUTE OF
427: * TECHNOLOGY, THE AUTHORS, OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
428: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
429: * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
430: * WITH THE WORK OR THE USE OR OTHER DEALINGS IN THE WORK.
431: * </p>
432: *
433: * <p>
434: * The name and trademarks of copyright holder(s) and/or O.K.I. may
435: * NOT be used in advertising or publicity pertaining to the Work
436: * without specific, written prior permission. Title to copyright in
437: * the Work and any associated documentation will at all times remain
438: * with the copyright holders.
439: * </p>
440: *
441: * <p>
442: * The export of software employing encryption technology may require a
443: * specific license from the United States Government. It is the
444: * responsibility of any person or organization contemplating export
445: * to obtain such a license before exporting this Work.
446: * </p>
447: */
448: }
|