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