001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/component/tags/sakai_2-4-1/component-impl/impl/src/java/org/sakaiproject/component/impl/BasicConfigurationService.java $
003: * $Id: BasicConfigurationService.java 22311 2007-03-08 03:36:41Z ggolden@umich.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2003, 2004, 2005, 2006, 2007 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.impl;
021:
022: import java.io.File;
023: import java.io.FileInputStream;
024: import java.io.InputStream;
025: import java.util.HashMap;
026: import java.util.List;
027: import java.util.Map;
028: import java.util.Vector;
029:
030: import org.apache.commons.logging.Log;
031: import org.apache.commons.logging.LogFactory;
032: import org.sakaiproject.component.cover.ComponentManager;
033: import org.sakaiproject.component.api.ServerConfigurationService;
034: import org.sakaiproject.thread_local.api.ThreadLocalManager;
035: import org.sakaiproject.util.StringUtil;
036: import org.sakaiproject.util.Xml;
037: import org.sakaiproject.tool.api.SessionManager;
038: import org.springframework.core.io.ClassPathResource;
039: import org.w3c.dom.Document;
040: import org.w3c.dom.Element;
041: import org.w3c.dom.Node;
042: import org.w3c.dom.NodeList;
043:
044: /**
045: * <p>
046: * BasicConfigurationService is a basic implementation of the ServerConfigurationService.
047: * </p>
048: */
049: public abstract class BasicConfigurationService implements
050: ServerConfigurationService {
051: /** Our log (commons). */
052: private static Log M_log = LogFactory
053: .getLog(BasicConfigurationService.class);
054:
055: /** The instance id for this app server. */
056: protected String instanceId = null;
057:
058: /** This is computed, joining the configured serverId and the set instanceId. */
059: protected String serverIdInstance = null;
060:
061: /** The map of values from the loaded properties - not synchronized at access. */
062: protected Map m_properties = new HashMap();
063:
064: /** Full path to registration files. */
065: protected String m_registrationPath = null;
066:
067: /** File name within sakai.home for the tool order file. */
068: protected String toolOrderFile = null;
069:
070: /** loaded tool orders - map keyed by category of List of tool id strings. */
071: protected Map m_toolOrders = new HashMap();
072:
073: /** required tools - map keyed by category of List of tool id strings. */
074: protected Map m_toolsRequired = new HashMap();
075:
076: /** default tools - map keyed by category of List of tool id strings. */
077: protected Map m_defaultTools = new HashMap();
078:
079: /**********************************************************************************************************************************************************************************************************************************************************
080: * Dependencies
081: *********************************************************************************************************************************************************************************************************************************************************/
082:
083: /**
084: * @return the ThreadLocalManager collaborator.
085: */
086: protected abstract ThreadLocalManager threadLocalManager();
087:
088: /**
089: * @return the SessionManager collaborator.
090: */
091: protected abstract SessionManager sessionManager();
092:
093: /**********************************************************************************************************************************************************************************************************************************************************
094: * Configuration
095: *********************************************************************************************************************************************************************************************************************************************************/
096:
097: /**
098: * Configuration: set the file path for registration files.
099: *
100: * @param string
101: * The file path for registration files.
102: */
103: public void setRegistrationPath(String string) {
104: m_registrationPath = string;
105: }
106:
107: /**
108: * Configuration: set the file name within sakai.home for tool order file.
109: *
110: * @param string
111: * The file name for tool order file.
112: */
113: public void setToolOrderFile(String string) {
114: toolOrderFile = string;
115: }
116:
117: /**********************************************************************************************************************************************************************************************************************************************************
118: * Init and Destroy
119: *********************************************************************************************************************************************************************************************************************************************************/
120:
121: /**
122: * Final initialization, once all dependencies are set.
123: */
124: public void init() {
125: // load the properties, from the configuration manager's set of properties that were used to configure the components
126: m_properties.putAll(ComponentManager.getConfig());
127:
128: try {
129: // set a unique instance id for this server run
130: // Note: to reduce startup dependency, just use the current time, NOT the id service.
131: instanceId = Long.toString(System.currentTimeMillis());
132:
133: serverIdInstance = getServerId() + "-" + instanceId;
134: } catch (Throwable t) {
135: M_log.warn("init(): ", t);
136: }
137:
138: // load in the tool order, if specified, from the sakai home area
139: if (toolOrderFile != null) {
140: File f = new File(getSakaiHomePath() + toolOrderFile);
141: if (f.exists()) {
142: try {
143: loadToolOrder(new FileInputStream(f));
144: } catch (Throwable t) {
145: M_log
146: .warn("init(): trouble loading tool order from : "
147: + getSakaiHomePath()
148: + toolOrderFile
149: + " : "
150: + t.toString());
151: }
152: } else {
153: // start with the distributed defaults from the classpath
154: try {
155: ClassPathResource rsrc = new ClassPathResource(
156: "org/sakaiproject/config/toolOrder.xml");
157:
158: try {
159: loadToolOrder(rsrc.getInputStream());
160: } catch (Throwable t) {
161: M_log
162: .warn("init(): trouble loading tool order from org/sakaiproject/config/toolOrder.xml: "
163: + t.toString());
164: }
165: } catch (Throwable t) {
166: M_log.warn(t.toString());
167: }
168: }
169: }
170:
171: M_log.info("init()");
172: }
173:
174: /**
175: * Final cleanup.
176: */
177: public void destroy() {
178: M_log.info("destroy()");
179: }
180:
181: /**********************************************************************************************************************************************************************************************************************************************************
182: * ServerConfigurationService implementation
183: *********************************************************************************************************************************************************************************************************************************************************/
184:
185: /**
186: * {@inheritDoc}
187: */
188: public String getServerId() {
189: return (String) m_properties.get("serverId");
190: }
191:
192: /**
193: * {@inheritDoc}
194: */
195: public String getServerInstance() {
196: return instanceId;
197: }
198:
199: /**
200: * {@inheritDoc}
201: */
202: public String getServerIdInstance() {
203: return serverIdInstance;
204: }
205:
206: /**
207: * {@inheritDoc}
208: */
209: public String getServerUrl() {
210: // try to get the value pre-computed for this request, to better match the request server naming conventions
211: String rv = (String) threadLocalManager().get(
212: CURRENT_SERVER_URL);
213: if (rv == null) {
214: rv = (String) m_properties.get("serverUrl");
215: }
216:
217: return rv;
218:
219: }
220:
221: /**
222: * {@inheritDoc}
223: */
224: public String getServerName() {
225: return (String) m_properties.get("serverName");
226: }
227:
228: /**
229: * {@inheritDoc}
230: */
231: public String getAccessUrl() {
232: return getServerUrl() + (String) m_properties.get("accessPath");
233: }
234:
235: /**
236: * {@inheritDoc}
237: */
238: public String getAccessPath() {
239: return (String) m_properties.get("accessPath");
240: }
241:
242: /**
243: * {@inheritDoc}
244: */
245: public String getHelpUrl(String helpContext) {
246: String rv = getPortalUrl()
247: + (String) m_properties.get("helpPath") + "/main";
248: if (helpContext != null) {
249: rv += "?help=" + helpContext;
250: }
251:
252: return rv;
253: }
254:
255: /**
256: * {@inheritDoc}
257: */
258: public String getPortalUrl() {
259: String rv = (String) threadLocalManager().get(
260: CURRENT_PORTAL_PATH);
261: if (rv == null) {
262: rv = (String) m_properties.get("portalPath");
263: }
264:
265: String portalUrl = getServerUrl() + rv;
266:
267: return portalUrl;
268: }
269:
270: /**
271: * {@inheritDoc}
272: */
273: public String getToolUrl() {
274: return getServerUrl() + (String) m_properties.get("toolPath");
275: }
276:
277: /**
278: * {@inheritDoc}
279: */
280: public String getUserHomeUrl() {
281: // get the configured URL (the text "#UID#" will be repalced with the current logged in user id
282: // NOTE: this is relative to the server root
283: String rv = (String) m_properties.get("userHomeUrl");
284:
285: // form a site based portal id if not configured
286: if (rv == null) {
287: rv = (String) m_properties.get("portalPath")
288: + "/site/~#UID#";
289: }
290:
291: // check for a logged in user
292: String user = sessionManager().getCurrentSessionUserId();
293: boolean loggedIn = (user != null);
294:
295: // if logged in, replace the UID in the pattern
296: if (loggedIn) {
297: rv.replaceAll("#UID#", user);
298: }
299:
300: // make it full, adding the server root
301: rv = getServerUrl() + rv;
302:
303: return rv;
304: }
305:
306: /**
307: * {@inheritDoc}
308: */
309: public String getGatewaySiteId() {
310: String rv = (String) m_properties.get("gatewaySiteId");
311:
312: if (rv == null) {
313: rv = "~anon";
314: }
315:
316: return rv;
317: }
318:
319: /**
320: * {@inheritDoc}
321: */
322: public String getLoggedOutUrl() {
323: String rv = (String) m_properties.get("loggedOutUrl");
324: if (rv != null) {
325: // if not a full URL, add the server to the front
326: if (rv.startsWith("/")) {
327: rv = getServerUrl() + rv;
328: }
329: }
330:
331: // use the portal URL if there's no logout defined
332: else {
333: rv = getPortalUrl();
334: }
335:
336: return rv;
337: }
338:
339: /**
340: * {@inheritDoc}
341: */
342: public String getSakaiHomePath() {
343: String rv = System.getProperty("sakai.home");
344: if (rv == null) {
345: rv = "/usr/local/sakai/";
346: }
347: if (!rv.endsWith("/"))
348: rv = rv + "/";
349:
350: return rv;
351: }
352:
353: /**
354: * {@inheritDoc}
355: */
356: public String getString(String name) {
357: return getString(name, "");
358: }
359:
360: /**
361: * {@inheritDoc}
362: */
363: public String getString(String name, String dflt) {
364: String rv = StringUtil.trimToNull((String) m_properties
365: .get(name));
366: if (rv == null)
367: rv = dflt;
368:
369: return rv;
370: }
371:
372: /**
373: * {@inheritDoc}
374: */
375: public String[] getStrings(String name) {
376: // get the count
377: int count = getInt(name + ".count", 0);
378: if (count > 0) {
379: String[] rv = new String[count];
380: for (int i = 1; i <= count; i++) {
381: rv[i - 1] = getString(name + "." + i, "");
382: }
383: return rv;
384: }
385:
386: return null;
387: }
388:
389: /**
390: * {@inheritDoc}
391: */
392: public int getInt(String name, int dflt) {
393: String value = getString(name);
394:
395: if (value.length() == 0)
396: return dflt;
397:
398: return Integer.parseInt(value);
399: }
400:
401: /**
402: * {@inheritDoc}
403: */
404: public boolean getBoolean(String name, boolean dflt) {
405: String value = getString(name);
406:
407: if (value.length() == 0)
408: return dflt;
409:
410: return Boolean.valueOf(value).booleanValue();
411: }
412:
413: /**
414: * {@inheritDoc}
415: */
416: public List getToolOrder(String category) {
417: if (category != null) {
418: List order = (List) m_toolOrders.get(category);
419: if (order != null) {
420: return order;
421: }
422: }
423:
424: return new Vector();
425: }
426:
427: /**
428: * {@inheritDoc}
429: */
430: public List getToolsRequired(String category) {
431: if (category != null) {
432: List order = (List) m_toolsRequired.get(category);
433: if (order != null) {
434: return order;
435: }
436: }
437:
438: return new Vector();
439: }
440:
441: /**
442: * {@inheritDoc}
443: */
444: public List getDefaultTools(String category) {
445: if (category != null) {
446: List order = (List) m_defaultTools.get(category);
447: if (order != null) {
448: return order;
449: }
450: }
451:
452: return new Vector();
453: }
454:
455: /**
456: * Load this single file as a registration file, loading tools and locks.
457: *
458: * @param in
459: * The Stream to load
460: */
461: protected void loadToolOrder(InputStream in) {
462: Document doc = Xml.readDocumentFromStream(in);
463: Element root = doc.getDocumentElement();
464: if (!root.getTagName().equals("toolOrder")) {
465: M_log
466: .info("loadToolOrder: invalid root element (expecting \"toolOrder\"): "
467: + root.getTagName());
468: return;
469: }
470:
471: // read the children nodes
472: NodeList rootNodes = root.getChildNodes();
473: final int rootNodesLength = rootNodes.getLength();
474: for (int i = 0; i < rootNodesLength; i++) {
475: Node rootNode = rootNodes.item(i);
476: if (rootNode.getNodeType() != Node.ELEMENT_NODE)
477: continue;
478: Element rootElement = (Element) rootNode;
479:
480: // look for "category" elements
481: if (rootElement.getTagName().equals("category")) {
482: String name = StringUtil.trimToNull(rootElement
483: .getAttribute("name"));
484: if (name != null) {
485: // form a list for this category
486: List order = (List) m_toolOrders.get(name);
487: if (order == null) {
488: order = new Vector();
489: m_toolOrders.put(name, order);
490:
491: List required = new Vector();
492: m_toolsRequired.put(name, required);
493: List defaultTools = new Vector();
494: m_defaultTools.put(name, defaultTools);
495:
496: // get the kids
497: NodeList nodes = rootElement.getChildNodes();
498: final int nodesLength = nodes.getLength();
499: for (int c = 0; c < nodesLength; c++) {
500: Node node = nodes.item(c);
501: if (node.getNodeType() != Node.ELEMENT_NODE)
502: continue;
503: Element element = (Element) node;
504:
505: if (element.getTagName().equals("tool")) {
506: String id = StringUtil
507: .trimToNull(element
508: .getAttribute("id"));
509: if (id != null) {
510: order.add(id);
511: }
512:
513: String req = StringUtil
514: .trimToNull(element
515: .getAttribute("required"));
516: if ((req != null)
517: && (Boolean.TRUE.toString()
518: .equalsIgnoreCase(req))) {
519: required.add(id);
520: }
521:
522: String sel = StringUtil
523: .trimToNull(element
524: .getAttribute("selected"));
525: if ((sel != null)
526: && (Boolean.TRUE.toString()
527: .equalsIgnoreCase(sel))) {
528: defaultTools.add(id);
529: }
530: }
531: }
532: }
533: }
534: }
535: }
536: }
537: }
|