001: /*
002:
003: * <copyright>
004: *
005: * Copyright 2002-2007 BBNT Solutions, LLC
006: * under sponsorship of the Defense Advanced Research Projects
007: * Agency (DARPA).
008: *
009: * You can redistribute this software and/or modify it under the
010: * terms of the Cougaar Open Source License as published on the
011: * Cougaar Open Source Website (www.cougaar.org).
012: *
013: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
014: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
015: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
016: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
017: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
018: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
019: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
020: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
021: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
022: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
023: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
024: *
025: * </copyright>
026:
027: */
028:
029: package org.cougaar.qos.qrs;
030:
031: import java.io.FileInputStream;
032: import java.io.InputStream;
033: import java.net.URL;
034: import java.util.EnumMap;
035: import java.util.HashMap;
036: import java.util.HashSet;
037: import java.util.Hashtable;
038: import java.util.Map;
039: import java.util.Properties;
040: import java.util.Set;
041: import java.util.StringTokenizer;
042:
043: import org.cougaar.qos.qrs.sysstat.DirectSysStatSupplier;
044: import org.cougaar.util.log.Logger;
045:
046: /** The root of the ResourceContext tree */
047: public final class RSS extends ResourceContext {
048: static final String GUI_PROPERTY = "org.cougaar.qos.qrs.gui";
049: private static RSS instance;
050:
051: private final Map<String, DataFeed> data_feeds;
052: private SitesDB sites;
053: private final String sitesurl_string;
054: private final Properties props;
055: private final Object sites_lock = new Object();
056: private final EnumMap<Event, Set<EventSubscriber>> event_subscribers = new EnumMap<Event, Set<EventSubscriber>>(
057: Event.class);
058: // This is a universal cache of all ResourceContexts which appear
059: // as the root of a path.
060: private final Map<String, Map<Object, ResourceContext>> global_cache = new HashMap<String, Map<Object, ResourceContext>>();
061:
062: /**
063: * This constructor will try to instantiate the feeds listed in the given
064: * Properties collection.
065: */
066: private RSS(Properties props) throws ParameterError {
067: super (new String[0], null);
068: Logger static_logger = Logging.getLogger(RSS.class);
069: if (static_logger.isDebugEnabled()) {
070: static_logger.debug("RSS Property=" + props);
071: }
072: this .props = props;
073: instance = this ;
074: this .sitesurl_string = props.getProperty("rss.SitesURL");
075: data_feeds = new Hashtable<String, DataFeed>();
076:
077: String raw_feed_data = props.getProperty("rss.DataFeeds");
078: if (raw_feed_data != null) {
079: StringTokenizer tokenizer = new StringTokenizer(
080: raw_feed_data, " ");
081: while (tokenizer.hasMoreTokens()) {
082: String feed_name = tokenizer.nextToken().trim();
083: makeFeed(feed_name, props);
084: }
085: }
086:
087: String sysstat_interval_str = props.getProperty("rss.sysstat");
088: if (sysstat_interval_str != null) {
089: int sysstat_interval = Integer
090: .parseInt(sysstat_interval_str);
091: TimerQueueingDataFeed feed = new TimerQueueingDataFeed();
092: registerFeed(feed, "DirectEntry");
093: DirectSysStatSupplier supplier = new DirectSysStatSupplier(
094: null, feed);
095: supplier.schedule(sysstat_interval);
096: }
097:
098: String gui_id = props.getProperty(GUI_PROPERTY);
099: if (gui_id != null) {
100: new org.cougaar.qos.qrs.gui.MainWindow(gui_id);
101: }
102:
103: }
104:
105: protected DataFormula instantiateFormula(String kind) {
106: return null;
107: }
108:
109: public String toString() {
110: return "RSS root";
111: }
112:
113: void eventNotification(ResourceContext context, Event event_type) {
114: Set<EventSubscriber> set;
115: synchronized (event_subscribers) {
116: set = event_subscribers.get(event_type);
117: }
118: if (set != null) {
119: synchronized (set) {
120: for (EventSubscriber sub : set) {
121: sub.rssEvent(context, event_type);
122: }
123: }
124: }
125: }
126:
127: public boolean subscribeToEvent(EventSubscriber sub,
128: Event event_type) {
129: Set<EventSubscriber> set = null;
130: synchronized (event_subscribers) {
131: set = event_subscribers.get(event_type);
132: if (set == null) {
133: set = new HashSet<EventSubscriber>();
134: event_subscribers.put(event_type, set);
135: }
136: }
137: synchronized (set) {
138: set.add(sub);
139: }
140: return true;
141: }
142:
143: public void unsubscribeToEvent(EventSubscriber sub, Event event_type) {
144: Set<EventSubscriber> set = null;
145: synchronized (event_subscribers) {
146: set = event_subscribers.get(event_type);
147: }
148: if (set != null) {
149: synchronized (set) {
150: set.remove(sub);
151: }
152: }
153: }
154:
155: public void setProperty(String tag, Object value) {
156: props.put(tag, value);
157: }
158:
159: public Object getProperty(String tag) {
160: return props.get(tag);
161: }
162:
163: public SitesDB getSitesDB() {
164: synchronized (sites_lock) {
165: if (sites == null) {
166: sites = new SitesDB();
167: if (sitesurl_string != null) {
168: java.net.URL sitesURL = null;
169: try {
170: sitesURL = new java.net.URL(sitesurl_string);
171: } catch (java.net.MalformedURLException ex) {
172: Logger logger = Logging.getLogger(RSS.class);
173: logger.error(null, ex);
174: }
175: sites.populate(sitesURL);
176: } else {
177: // This is not always an error because sometimes
178: // the caller of this method may populate the db
179: }
180: }
181: }
182: return sites;
183: }
184:
185: protected void verifyParameters(String[] parameters)
186: throws ParameterError {
187: }
188:
189: public void deleteContext(ResourceContext context) {
190: synchronized (global_cache) {
191: Map<Object, ResourceContext> classcache = global_cache
192: .get(context.getContextKind());
193: if (classcache != null) {
194: classcache.remove(context.getID());
195: }
196: }
197: context.delete();
198: }
199:
200: // Delete a top-level context
201: public void deleteContext(String kind, String[] params) {
202: ResourceContext context = null;
203: synchronized (global_cache) {
204: Map<Object, ResourceContext> classcache = global_cache
205: .get(kind);
206: if (classcache != null) {
207: String id = (String) getIdentifier(kind, params);
208: context = classcache.get(id);
209: if (context != null) {
210: classcache.remove(id);
211: }
212: }
213: }
214: if (context != null) {
215: context.delete();
216: }
217: }
218:
219: protected void addChild(Object id, ResourceContext child) {
220: ResourceContext preferredParent = child.preferredParent(this );
221: if (preferredParent == null) {
222: Logger logger = Logging.getLogger(RSS.class);
223: logger.error(child + " cannot be the root of a path");
224: } else if (preferredParent == this ) {
225: super .addChild(id, child);
226: } else {
227: synchronized (global_cache) {
228: Map<Object, ResourceContext> classcache = global_cache
229: .get(child.getContextKind());
230: if (classcache == null) {
231: classcache = new HashMap<Object, ResourceContext>();
232: }
233: classcache.put(id, child);
234: global_cache.put(child.getContextKind(), classcache);
235: }
236: preferredParent.addChild(id, child);
237: }
238: }
239:
240: public ResourceContext resolveSpec(String kind, String[] parameters) {
241: Logger logger = Logging.getLogger(RSS.class);
242: if (logger.isDebugEnabled()) {
243: String paramString = "";
244: if (parameters != null && parameters.length > 0) {
245: paramString += "[" + parameters[0];
246: for (int i = 1; i < parameters.length; i++) {
247: paramString += ", " + parameters[i];
248: }
249: paramString += "]";
250: }
251: logger.debug("Resolving " + kind + paramString);
252: }
253: Object id = getIdentifier(kind, parameters);
254: ResourceContext context;
255: synchronized (global_cache) {
256: Map<Object, ResourceContext> classcache = global_cache
257: .get(kind);
258: if (classcache != null) {
259: context = classcache.get(id);
260: if (context != null) {
261: if (logger.isDebugEnabled()) {
262: logger.debug("Found " + context
263: + " in global cache");
264: }
265: return context;
266: }
267: }
268: }
269: return super .resolveSpec(id, kind, parameters);
270: }
271:
272: /**
273: * Returns an enumeration of all known feeds.
274: */
275: public Iterable<DataFeed> feeds() {
276: return data_feeds.values();
277: }
278:
279: public void registerFeed(DataFeed store, String name) {
280: store.setName(name);
281: data_feeds.put(name, store);
282: }
283:
284: public void unregisterFeed(String name) {
285: data_feeds.remove(name);
286: }
287:
288: public DataFeed getFeed(String key) {
289: return data_feeds.get(key);
290: }
291:
292: // Reflection!!!
293:
294: private void makeFeed(String name, Properties props) {
295: Logger logger = Logging.getLogger(RSS.class);
296:
297: String classname = props.getProperty(name + ".class");
298: if (classname == null) {
299: System.err.println("No .class property for feed " + name);
300: return;
301: }
302:
303: String[] args = null;
304:
305: String args_string = props.getProperty(name + ".args");
306: if (args_string != null) {
307: StringTokenizer tk = new StringTokenizer(args_string, " ");
308: args = new String[tk.countTokens()];
309: int i = 0;
310: while (tk.hasMoreTokens()) {
311: args[i++] = tk.nextToken();
312: }
313: } else {
314: Logger static_logger = Logging.getLogger(RSS.class);
315: if (static_logger.isDebugEnabled()) {
316: static_logger
317: .debug("MakeFeed " + name + " has no .arg");
318: }
319: }
320:
321: Object[] constructorArgs = new Object[1];
322: constructorArgs[0] = args;
323:
324: Class<?>[] constructorParamTypes = { String[].class };
325:
326: Object rawfeed = null;
327: try {
328: Class<?> cl = Class.forName(classname);
329: if (cl != null) {
330: java.lang.reflect.Constructor<?> cons = cl
331: .getConstructor(constructorParamTypes);
332: rawfeed = cons.newInstance(constructorArgs);
333: }
334:
335: if (!(rawfeed instanceof DataFeed)) {
336: logger.error(name + " is not a DataFeed");
337: } else {
338: DataFeed feed = (DataFeed) rawfeed;
339: feed.setName(name);
340: registerFeed(feed, name);
341: if (logger.isInfoEnabled()) {
342: logger.info("Created DataFeed '" + feed.getName()
343: + "' of " + rawfeed.getClass());
344: }
345: }
346: } catch (Exception ex) {
347: logger.error(null, ex);
348: }
349: }
350:
351: public synchronized static RSS instance() {
352: return instance;
353: }
354:
355: public synchronized static RSS makeInstance(Properties properties) {
356: Logger static_logger = Logging.getLogger(RSS.class);
357: if (instance != null) {
358: if (static_logger.isDebugEnabled()) {
359: static_logger
360: .debug("#### RSS instance already created!");
361: }
362: return instance;
363: }
364:
365: try {
366: instance = new RSS(properties);
367: } catch (ParameterError cant_happen) {
368: }
369:
370: return instance;
371: }
372:
373: public synchronized static RSS makeInstance(String name) {
374: Logger static_logger = Logging.getLogger(RSS.class);
375: Properties properties = new Properties();
376: InputStream is = null;
377: try {
378: URL url = new URL(name);
379: is = url.openStream();
380: } catch (Exception ex) {
381: // try it as a filename
382: try {
383: is = new FileInputStream(name);
384: } catch (Exception e) {
385: static_logger
386: .error("Error opening " + name + ": " + ex);
387: }
388: }
389:
390: if (is != null) {
391: try {
392: properties.load(is);
393: is.close();
394: } catch (java.io.IOException ex) {
395: static_logger
396: .error("Error loading RSS properties from "
397: + name + ": " + ex);
398: }
399: }
400:
401: return makeInstance(properties);
402: }
403:
404: public synchronized static RSS makeInstance(String[] args) {
405: ResourceStatusServiceImpl impl = null;
406: for (String arg : args) {
407: if (arg.equals("-rss.corba")) {
408: impl = new ResourceStatusServiceImpl();
409: }
410: }
411:
412: CorbaUtils.main(args, impl);
413: return instance();
414: }
415:
416: public static String getGUI_PROPERTY() {
417: return GUI_PROPERTY;
418: }
419:
420: public enum Event {
421: CREATION_EVENT;
422: }
423: }
|