001: /**********************************************************************************
002: * $URL: $
003: * $Id: $
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 java.io.IOException;
023: import java.util.Enumeration;
024: import java.util.Hashtable;
025: import java.util.Iterator;
026: import java.util.ArrayList;
027: import java.util.List;
028: import java.util.Map;
029: import java.util.Set;
030: import java.util.TreeSet;
031: import java.util.Vector;
032:
033: import org.xml.sax.SAXException;
034: import org.xml.sax.SAXParseException;
035:
036: import org.w3c.dom.Document;
037: import org.w3c.dom.Element;
038: import org.w3c.dom.Node;
039: import org.w3c.dom.NodeList;
040:
041: import javax.xml.parsers.ParserConfigurationException;
042: import javax.xml.parsers.DocumentBuilder;
043: import javax.xml.parsers.DocumentBuilderFactory;
044:
045: import org.apache.commons.logging.Log;
046: import org.apache.commons.logging.LogFactory;
047:
048: import org.sakaiproject.citation.util.api.OsidConfigurationException;
049: import org.sakaiproject.citation.api.ConfigurationService;
050: import org.sakaiproject.citation.api.SiteOsidConfiguration;
051:
052: import org.sakaiproject.component.api.ServerConfigurationService;
053: import org.sakaiproject.component.cover.ComponentManager;
054: import org.sakaiproject.exception.IdUnusedException;
055: import org.sakaiproject.tool.api.SessionManager;
056:
057: /**
058: *
059: */
060: public class BaseConfigurationService implements ConfigurationService {
061: private static Log m_log = LogFactory
062: .getLog(BaseConfigurationService.class);
063:
064: /*
065: * All the following properties will be set by Spring using components.xml
066: */
067: // enable/disable entire helper
068: protected boolean m_citationsEnabledByDefault = false;
069: protected boolean m_allowSiteBySiteOverride = false;
070:
071: // enable/disable helper features -->
072: protected String m_googleSearchEnabled = "false";
073: protected String m_librarySearchEnabled = "false";
074:
075: // configuration XML file location
076: protected String m_databaseXml;
077: protected String m_siteConfigXml;
078:
079: // metasearch engine parameters
080: protected String m_metasearchUsername;
081: protected String m_metasearchPassword;
082: protected String m_metasearchBaseUrl;
083:
084: // which osid impl to use
085: protected String m_osidImpl;
086:
087: // openURL parameters -->
088: protected String m_openUrlLabel;
089: protected String m_openUrlResolverAddress;
090:
091: // google scholar parameters -->
092: protected String m_googleBaseUrl;
093: protected String m_sakaiServerKey;
094:
095: // site-specific config/authentication/authorization implementation -->
096: protected String m_osidConfig;
097:
098: // other config services -->
099: protected SessionManager m_sessionManager;
100: protected ServerConfigurationService m_serverConfigurationService;
101: /*
102: * End of components.xml properties
103: */
104:
105: /*
106: * Site specific OSID configuration instance
107: */
108: private static SiteOsidConfiguration m_siteConfigInstance = null;
109:
110: /*
111: * Interface methods
112: */
113:
114: /**
115: * Fetch the appropriate XML configuration document for this user
116: * @return Configuration XML (eg file:///tomcat-home/sakai/config.xml)
117: */
118: public String getConfigurationXml()
119: throws OsidConfigurationException {
120: SiteOsidConfiguration siteConfig = getSiteOsidConfiguration();
121: String configXml = null;
122:
123: if (siteConfig != null) {
124: configXml = siteConfig.getConfigurationXml();
125: }
126:
127: if (isNull(configXml)) {
128: configXml = m_siteConfigXml;
129: }
130: return configXml;
131: }
132:
133: /**
134: * Is the configuration XML file provided and readable
135: * @return true If the XML file is provided and readable, false otherwise
136: */
137: public boolean isConfigurationXmlAvailable() {
138: try {
139: // get the xml filename
140: String configXml = getConfigurationXml();
141: if (configXml == null) {
142: return false;
143: }
144:
145: // not null, try to open it for reading
146: java.io.FileInputStream fis = new java.io.FileInputStream(
147: configXml);
148: } catch (java.io.FileNotFoundException fnfe) {
149: // file not found
150: return false;
151: } catch (OsidConfigurationException ignore) {
152: }
153:
154: // filename is not null and the file is readable
155: return true;
156: }
157:
158: /**
159: * Fetch the appropriate XML database hierarchy document for this user
160: * @return Hierarchy XML (eg file:///tomcat-home/sakai/database.xml)
161: */
162: public String getDatabaseHierarchyXml()
163: throws OsidConfigurationException {
164: SiteOsidConfiguration siteConfig = getSiteOsidConfiguration();
165: String databaseXml = null;
166:
167: if (siteConfig != null) {
168: databaseXml = siteConfig.getDatabaseHierarchyXml();
169: }
170:
171: if (isNull(databaseXml)) {
172: databaseXml = m_databaseXml;
173: }
174: return databaseXml;
175: }
176:
177: /**
178: * Is the database hierarchy XML file provided and readable
179: * @return true If the XML file is provided and readable, false otherwise
180: */
181: public boolean isDatabaseHierarchyXmlAvailable() {
182: try {
183: // get the xml filename
184: String dbXml = getDatabaseHierarchyXml();
185: if (dbXml == null) {
186: return false;
187: }
188:
189: // not null, try to open it for reading
190: java.io.FileInputStream fis = new java.io.FileInputStream(
191: dbXml);
192: } catch (java.io.FileNotFoundException fnfe) {
193: // file not found
194: return false;
195: } catch (OsidConfigurationException ignore) {
196: }
197:
198: // filename is not null and the file is readable
199: return true;
200: }
201:
202: /**
203: * Fetch this user's group affiliations
204: * @return A list of group IDs (empty if no IDs exist)
205: */
206: public List<String> getGroupIds() throws OsidConfigurationException {
207: SiteOsidConfiguration siteConfig = getSiteOsidConfiguration();
208:
209: if (siteConfig == null) {
210: ArrayList<String> emptyList = new ArrayList();
211:
212: return emptyList;
213: }
214: return siteConfig.getGroupIds();
215: }
216:
217: /**
218: * Fetch the site specific Repository OSID package name
219: * @return Repository Package (eg org.sakaibrary.osid.repository.xserver)
220: */
221: public String getSiteConfigOsidPackageName() {
222: String value = getConfigurationParameter("osid-impl");
223:
224: return (value != null) ? value : getOsidImpl();
225: }
226:
227: /**
228: * Fetch the meta-search username
229: * @return the username
230: */
231: public String getSiteConfigMetasearchUsername() {
232: String value = getConfigurationParameter("metasearch-username");
233:
234: return (value != null) ? value : getMetasearchUsername();
235: }
236:
237: /**
238: * Fetch the meta-search password
239: * @return the password
240: */
241: public String getSiteConfigMetasearchPassword() {
242: String value = getConfigurationParameter("metasearch-password");
243:
244: return (value != null) ? value : getMetasearchPassword();
245: }
246:
247: /**
248: * Fetch the meta-search base-URL
249: * @return the username
250: */
251: public String getSiteConfigMetasearchBaseUrl() {
252: String value = getConfigurationParameter("metasearch-baseurl");
253:
254: return (value != null) ? value : getMetasearchBaseUrl();
255: }
256:
257: /**
258: * Fetch the OpenURL label
259: * @return the label text
260: */
261: public String getSiteConfigOpenUrlLabel() {
262: String value = getConfigurationParameter("openurl-label");
263:
264: return (value != null) ? value : getOpenUrlLabel();
265: }
266:
267: /**
268: * Fetch the OpenURL resolver address
269: * @return the resolver address (domain name ir IP)
270: */
271: public String getSiteConfigOpenUrlResolverAddress() {
272: String value = getConfigurationParameter("openurl-resolveraddress");
273:
274: return (value != null) ? value : getOpenUrlResolverAddress();
275: }
276:
277: /**
278: * Fetch the Google base-URL
279: * @return the URL
280: */
281: public String getSiteConfigGoogleBaseUrl() {
282: String value = getConfigurationParameter("google-baseurl");
283:
284: return (value != null) ? value : getGoogleBaseUrl();
285: }
286:
287: /**
288: * Fetch the Sakai server key
289: * @return the key text
290: */
291: public String getSiteConfigSakaiServerKey() {
292: String value = getConfigurationParameter("sakai-serverkey");
293:
294: return (value != null) ? value : getSakaiServerKey();
295: }
296:
297: /**
298: * Enable/disable Citations Helper by default
299: * @param state true to set default 'On'
300: */
301: public void setCitationsEnabledByDefault(
302: boolean citationsEnabledByDefault) {
303: m_citationsEnabledByDefault = citationsEnabledByDefault;
304: }
305:
306: /**
307: * Is Citations Helper by default enabled?
308: * @return true if so
309: */
310: public boolean isCitationsEnabledByDefault() {
311: return m_citationsEnabledByDefault;
312: }
313:
314: /**
315: * Enable/disable site by site Citations Helper override
316: * @param state true to enable site by site Citations Helper
317: */
318: public void setAllowSiteBySiteOverride(
319: boolean allowSiteBySiteOverride) {
320: m_allowSiteBySiteOverride = allowSiteBySiteOverride;
321: }
322:
323: /**
324: * Is site by site Citations Helper enabled?
325: * @return true if so
326: */
327: public boolean isAllowSiteBySiteOverride() {
328: return m_allowSiteBySiteOverride;
329: }
330:
331: /**
332: * Enable/disable Google support (no support for site spefic XML configuration)
333: * @param state true to enable Google support
334: */
335: public void setGoogleScholarEnabled(boolean state) {
336: String enabled = state ? "true" : "false";
337:
338: setGoogleSearchEnabled(enabled);
339: }
340:
341: /**
342: * Is Google search enabled? (no support for site spefic XML configuration)
343: * @return true if so
344: */
345: public boolean isGoogleScholarEnabled() {
346: String state = getGoogleSearchEnabled();
347:
348: return state.equals("true");
349: }
350:
351: /**
352: * Enable/disable library search support (no support for site spefic XML configuration)
353: * @param state true to enable support
354: */
355: public void setLibrarySearchEnabled(boolean state) {
356: String enabled = state ? "true" : "false";
357:
358: setLibrarySearchEnabled(enabled);
359: }
360:
361: /**
362: * Is library search enabled? (no support for site spefic XML configuration)
363: * @return true if so
364: */
365: public boolean isLibrarySearchEnabled() {
366: String state = getLibrarySearchEnabled();
367:
368: return state.equals("true");
369: }
370:
371: /*
372: * Helpers
373: */
374:
375: /**
376: * Get a named value from the site-specific XML configuration file
377: * @param parameter Configuration parameter to lookup
378: * @return Parameter value (null if none [or error])
379: */
380: protected String getConfigurationParameter(String parameter) {
381: String value = null;
382:
383: try {
384: SiteOsidConfiguration siteConfig = getSiteOsidConfiguration();
385:
386: if (siteConfig != null) {
387: value = getConfigurationFromXml(siteConfig
388: .getConfigurationXml(), parameter);
389: }
390: } catch (OsidConfigurationException exception) {
391: m_log.warn("Failed to get XML calue for " + parameter
392: + ", using components.xml value");
393: }
394: return value;
395: }
396:
397: /**
398: * Load and initialize the site-specific OSID configuration code
399: * @return The initialized, site-specific OSID configuration
400: * object (null on error)
401: */
402: protected SiteOsidConfiguration getSiteOsidConfiguration() {
403: SiteOsidConfiguration siteConfig;
404:
405: try {
406: siteConfig = getConfigurationHandler(m_osidConfig);
407: siteConfig.init();
408: } catch (Exception exception) {
409: m_log.warn("Failed to get " + m_osidConfig + ": "
410: + exception);
411: siteConfig = null;
412: }
413: return siteConfig;
414: }
415:
416: /**
417: * Return a SiteOsidConfiguration instance
418: * @return A SiteOsidConfiguration
419: */
420: public synchronized SiteOsidConfiguration getConfigurationHandler(
421: String osidConfigHandler)
422: throws java.lang.ClassNotFoundException,
423: java.lang.InstantiationException,
424: java.lang.IllegalAccessException {
425: if (m_siteConfigInstance == null) {
426: Class configClass = Class.forName(osidConfigHandler);
427:
428: m_siteConfigInstance = (SiteOsidConfiguration) configClass
429: .newInstance();
430: }
431: return m_siteConfigInstance;
432: }
433:
434: /**
435: * Fetch a configuration parameter from the site-selected configuration file
436: */
437: protected String getConfigurationFromXml(String configurationXml,
438: String parameter) {
439: org.w3c.dom.Document document;
440: String value;
441:
442: if (configurationXml == null) {
443: return null;
444: }
445:
446: document = parseXmlFromUri(configurationXml);
447: if (document == null) {
448: return null;
449: }
450:
451: if ((value = getText(document, parameter)) != null) {
452: m_log.debug("GetConfigurationFromXml " + parameter + " = "
453: + value);
454: }
455: return value;
456: }
457:
458: /**
459: * Parse an XML file into a Document.
460: * @param filename The filename (or URI) to parse
461: * @return DOM Document (null if parse fails)
462: */
463: protected Document parseXmlFromUri(String filename) {
464: try {
465: DocumentBuilder documentBuilder = getXmlDocumentBuilder();
466:
467: if (documentBuilder != null) {
468: return documentBuilder.parse(filename);
469: }
470: } catch (Exception exception) {
471: //m_log.debug("XML parse on \"" + filename + "\" failed: " + exception);
472: }
473: return null;
474: }
475:
476: /**
477: * Get a DOM Document builder.
478: * @return The DocumentBuilder
479: * @throws DomException
480: */
481: protected DocumentBuilder getXmlDocumentBuilder() {
482: try {
483: DocumentBuilderFactory factory;
484:
485: factory = DocumentBuilderFactory.newInstance();
486: factory.setNamespaceAware(false);
487:
488: return factory.newDocumentBuilder();
489: } catch (Exception exception) {
490: m_log.warn("Failed to get XML DocumentBuilder: "
491: + exception);
492: }
493: return null;
494: }
495:
496: /**
497: * "Normalize" XML text node content to create a simple string
498: * @param original Original text
499: * @param update Text to add to the original string (a space separates the two)
500: * @return Concatenated contents (trimmed)
501: */
502: protected String normalizeText(String original, String update) {
503: StringBuffer result;
504:
505: if (original == null) {
506: return (update == null) ? "" : update.trim();
507: }
508:
509: result = new StringBuffer(original.trim());
510: result.append(' ');
511: result.append(update.trim());
512:
513: return result.toString();
514: }
515:
516: /**
517: * Get the text associated with this element
518: * @param root The document containing the text element
519: * @return Text (trimmed of leading/trailing whitespace, null if none)
520: */
521: protected String getText(Document root, String elementName) {
522: return getText(root.getDocumentElement(), elementName);
523: }
524:
525: /**
526: * Get the text associated with this element
527: * @param root The root node of the text element
528: * @return Text (trimmed of leading/trailing whitespace, null if none)
529: */
530: protected String getText(Element root, String elementName) {
531: NodeList nodeList;
532: Node parent;
533: String text;
534:
535: nodeList = root.getElementsByTagName(elementName);
536: if (nodeList.getLength() == 0) {
537: return null;
538: }
539:
540: text = null;
541: parent = (Element) nodeList.item(0);
542:
543: for (Node child = parent.getFirstChild(); child != null; child = child
544: .getNextSibling()) {
545: switch (child.getNodeType()) {
546: case Node.TEXT_NODE:
547: text = normalizeText(text, child.getNodeValue());
548: break;
549:
550: default:
551: break;
552: }
553: }
554: return text == null ? text : text.trim();
555: }
556:
557: /**
558: * Null (or empty) String?
559: * @param string String to check
560: * @return true if so
561: */
562: private boolean isNull(String string) {
563: return (string == null) || (string.trim().equals(""));
564: }
565:
566: /*
567: * Inititialize and destroy
568: */
569: public void init() {
570: m_log.info("init()");
571: }
572:
573: public void destroy() {
574: m_log.info("destroy()");
575: }
576:
577: /*
578: * Getters/setters for components.xml parameters
579: */
580:
581: /**
582: * @return the OSID package name
583: */
584: public String getOsidImpl() {
585: return m_osidImpl;
586: }
587:
588: /**
589: * @param osidImpl the OSID package name
590: */
591: public void setOsidImpl(String osidImpl) {
592: m_osidImpl = osidImpl;
593: }
594:
595: /**
596: * @return the m_metasearchUsername
597: */
598: public String getMetasearchUsername() {
599: return m_metasearchUsername;
600: }
601:
602: /**
603: * @param username the m_metasearchUsername to set
604: */
605: public void setMetasearchUsername(String username) {
606: m_metasearchUsername = username;
607: }
608:
609: /**
610: * @return the m_metasearchBaseUrl
611: */
612: public String getMetasearchBaseUrl() {
613: return m_metasearchBaseUrl;
614: }
615:
616: /**
617: * @param baseUrl the m_metasearchBaseUrl to set
618: */
619: public void setMetasearchBaseUrl(String baseUrl) {
620: m_metasearchBaseUrl = baseUrl;
621: }
622:
623: /**
624: * @return the m_metasearchPassword
625: */
626: public String getMetasearchPassword() {
627: return m_metasearchPassword;
628: }
629:
630: /**
631: * @param password the m_metasearchPassword to set
632: */
633: public void setMetasearchPassword(String password) {
634: m_metasearchPassword = password;
635: }
636:
637: /**
638: * @return the Google base URL
639: */
640: public String getGoogleBaseUrl() {
641: return m_googleBaseUrl;
642: }
643:
644: /**
645: * @param googleBaseUrl the base URL to set
646: */
647: public void setGoogleBaseUrl(String googleBaseUrl) {
648: m_googleBaseUrl = googleBaseUrl;
649: }
650:
651: /**
652: * @return the sakaiServerKey
653: */
654: public String getSakaiServerKey() {
655: return m_sakaiServerKey;
656: }
657:
658: /**
659: * @param sakaiServerKey the sakaiServerKey to set
660: */
661: public void setSakaiServerKey(String sakaiId) {
662: m_sakaiServerKey = sakaiId;
663: }
664:
665: /**
666: * @return the OpenURL label
667: */
668: public String getOpenUrlLabel() {
669: return m_openUrlLabel;
670: }
671:
672: /**
673: * @param set the OpenURL label
674: */
675: public void setOpenUrlLabel(String openUrlLabel) {
676: m_openUrlLabel = openUrlLabel;
677: }
678:
679: /**
680: * @return the OpenURL resolver address
681: */
682: public String getOpenUrlResolverAddress() {
683: return m_openUrlResolverAddress;
684: }
685:
686: /**
687: * @param set the OpenURL resolver address
688: */
689: public void setOpenUrlResolverAddress(String openUrlResolverAddress) {
690: m_openUrlResolverAddress = openUrlResolverAddress;
691: }
692:
693: /**
694: * @return the database hierarchy XML filename/URI
695: */
696: public String getDatabaseXml() {
697: return m_databaseXml;
698: }
699:
700: /**
701: * @param set the database hierarchy XML filename/URI
702: */
703: public void setDatabaseXml(String databaseXml) {
704: m_databaseXml = databaseXml;
705: }
706:
707: /**
708: * @return the configuration XML filename/URI
709: */
710: public String getSiteConfigXml() {
711: return m_siteConfigXml;
712: }
713:
714: /**
715: * @param set the configuration XML filename/URI
716: */
717: public void setSiteConfigXml(String siteConfigXml) {
718: m_siteConfigXml = siteConfigXml;
719: }
720:
721: /**
722: * @return the serverConfigurationService
723: */
724: public ServerConfigurationService getServerConfigurationService() {
725: return m_serverConfigurationService;
726: }
727:
728: /**
729: * @param serverConfigurationService the serverConfigurationService to set
730: */
731: public void setServerConfigurationService(
732: ServerConfigurationService serverConfigurationService) {
733: m_serverConfigurationService = serverConfigurationService;
734: }
735:
736: /**
737: * @param sessionManager the SessionManager to save
738: */
739: public void setSessionManager(SessionManager sessionManager) {
740: m_sessionManager = sessionManager;
741: }
742:
743: /**
744: * @return the SessionManager
745: */
746: public SessionManager getSessionManager() {
747: return m_sessionManager;
748: }
749:
750: /**
751: * @return the site specific "OSID configuration" package name
752: */
753: public String getOsidConfig() {
754: return m_osidConfig;
755: }
756:
757: /**
758: * @param osidConfig the site specific "OSID configuration" package name
759: */
760: public void setOsidConfig(String osidConfig) {
761: m_osidConfig = osidConfig;
762: }
763:
764: /**
765: * @return Google search support status
766: */
767: public String getGoogleSearchEnabled() {
768: return m_googleSearchEnabled;
769: }
770:
771: /**
772: * @param googleSearchEnabled ("true" or "false")
773: */
774: public void setGoogleSearchEnabled(String googleSearchEnabled) {
775: if (googleSearchEnabled.equalsIgnoreCase("true")
776: || googleSearchEnabled.equalsIgnoreCase("false")) {
777: m_googleSearchEnabled = googleSearchEnabled;
778: return;
779: }
780:
781: m_log.warn("Invalid Google support setting \""
782: + googleSearchEnabled + "\", disabling Google search");
783:
784: m_googleSearchEnabled = "false";
785: }
786:
787: /**
788: * @return library search support status
789: */
790: public String getLibrarySearchEnabled() {
791: return m_librarySearchEnabled;
792: }
793:
794: /**
795: * @param librarySearchEnabled ("true" or "false")
796: */
797: public void setLibrarySearchEnabled(String librarySearchEnabled) {
798: if (librarySearchEnabled.equalsIgnoreCase("true")
799: || librarySearchEnabled.equalsIgnoreCase("false")) {
800: m_librarySearchEnabled = librarySearchEnabled;
801: return;
802: }
803:
804: m_log
805: .warn("Invalid library support setting \""
806: + librarySearchEnabled
807: + "\", disabling library search");
808:
809: m_librarySearchEnabled = "false";
810: }
811: }
|