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