001: /*
002: * <copyright>
003: *
004: * Copyright 1997-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.core.node;
028:
029: import java.io.FileNotFoundException;
030: import java.util.ArrayList;
031: import java.util.HashMap;
032: import java.util.List;
033: import java.util.Map;
034: import org.cougaar.bootstrap.SystemProperties;
035: import org.cougaar.core.component.ComponentDescription;
036: import org.cougaar.core.component.ServiceBroker;
037: import org.cougaar.core.component.ServiceProvider;
038: import org.cougaar.util.log.Logger;
039: import org.cougaar.util.log.Logging;
040:
041: /**
042: * {@link ServiceProvider} for the XML-based {@link
043: * ComponentInitializerService} that uses the {@link
044: * XSLTransformer}.
045: * <p>
046: * <pre>
047: * @property org.cougaar.society.file
048: * The name of the XML file from which to read this Node's
049: * definition
050: * @property org.cougaar.agent.defaultFile
051: * The name of the default XML configuration file for an agent,
052: * used if the agent configuration is not found in the node's
053: * XML (-Dorg.cougaar.society.file) or agent's XML (name+".xml").
054: * Defaults to "DefaultAgent.xml"
055: * </pre>
056: */
057: public class XMLComponentInitializerServiceProvider implements
058: ServiceProvider {
059:
060: private static final String XML_FILE_NAME_PROP = "org.cougaar.society.file";
061: private static final String XML_FILE_NAME = SystemProperties
062: .getProperty(XML_FILE_NAME_PROP);
063:
064: private static final String DEFAULT_AGENT_PROP = "org.cougaar.agent.defaultFile";
065: private static final String DEFAULT_AGENT;
066: static {
067: String s = SystemProperties.getProperty(DEFAULT_AGENT_PROP,
068: "DefaultAgent.xml");
069: // trim off trailing ".xml"
070: String x = ".xml";
071: int xlen = x.length();
072: int offset = s.length() - xlen;
073: if (s.regionMatches(true, offset, x, 0, xlen)) {
074: s = s.substring(0, offset);
075: }
076: if (s.length() == 0) {
077: s = null;
078: }
079: DEFAULT_AGENT = s;
080: }
081:
082: private static final String NODE_NAME_PROP = "org.cougaar.node.name";
083: private static final String NODE_NAME = SystemProperties
084: .getProperty(NODE_NAME_PROP);
085:
086: // backwards compatibility for the wp server:
087: private static final String IMPLICIT_WP_SERVER_PROP = "org.cougaar.core.load.wp.server";
088: private static final boolean IMPLICIT_WP_SERVER = SystemProperties
089: .getBoolean(IMPLICIT_WP_SERVER_PROP, true);
090:
091: private static final String MY_CLASS_NAME = XMLComponentInitializerServiceProvider.class
092: .getName();
093:
094: private final ComponentInitializerService serviceImpl = new ComponentInitializerServiceImpl();
095:
096: public XMLComponentInitializerServiceProvider() {
097: }
098:
099: private static Map get_overrides() {
100: Map ret = new HashMap();
101: // add node name
102: if (NODE_NAME != null && !NODE_NAME.equals("")) {
103: ret.put("node", NODE_NAME);
104: }
105: // backwards compatibility for the wp server:
106: if (!IMPLICIT_WP_SERVER) {
107: ret.put("wpserver", "false");
108: }
109: return ret;
110: }
111:
112: public Object getService(ServiceBroker sb, Object requestor,
113: Class serviceClass) {
114: return ((serviceClass == ComponentInitializerService.class) ? (serviceImpl)
115: : null);
116: }
117:
118: public void releaseService(ServiceBroker sb, Object requestor,
119: Class serviceClass, Object service) {
120: }
121:
122: private static class ComponentInitializerServiceImpl implements
123: ComponentInitializerService {
124:
125: private static final ComponentDescription[] NO_COMPONENTS = new ComponentDescription[0];
126:
127: private final Logger logger;
128:
129: // could make this a map of soft references
130: private final Map agents;
131:
132: public ComponentInitializerServiceImpl() {
133: this .logger = Logging.getLogger(MY_CLASS_NAME);
134: this .agents = parseAgents();
135: }
136:
137: private Map parseAgents() {
138: if (XML_FILE_NAME == null) {
139: throw new RuntimeException("\"-D" + XML_FILE_NAME_PROP
140: + "\" XML filename not set");
141: }
142:
143: if (logger.isShoutEnabled()) {
144: logger.shout("Initializing node \"" + NODE_NAME
145: + "\" from XML file \"" + XML_FILE_NAME + "\"");
146: }
147:
148: Map ret = XMLConfigParser.parseAgents(XML_FILE_NAME,
149: NODE_NAME, null, // all agents in this file
150: get_overrides());
151: if (logger.isDetailEnabled()) {
152: logger.detail("found " + ret.size() + " agents");
153: }
154:
155: // we should minimally have the node-agent's config
156: if (ret.isEmpty()) {
157: throw new RuntimeException(
158: "The configuration for node \"" + NODE_NAME
159: + "\" was not found in XML file \""
160: + XML_FILE_NAME + "\"");
161: }
162:
163: return ret;
164: }
165:
166: /**
167: * Get the descriptions of components with the named parent having
168: * an insertion point below the given container insertion point.
169: */
170: public ComponentDescription[] getComponentDescriptions(
171: String agentName, String containmentPoint)
172: throws InitializerException {
173:
174: if (logger.isInfoEnabled()) {
175: logger.info("Looking for direct sub-components of "
176: + agentName + " just below insertion point "
177: + containmentPoint);
178: }
179:
180: List agentDescs;
181: try {
182: agentDescs = getAgentDescs(agentName);
183: } catch (Exception e) {
184: logger.error("Failed getComponentDescriptions("
185: + agentName + ")", e);
186: throw new InitializerException(
187: "getComponentDescriptions(" + agentName + ")",
188: e);
189: }
190:
191: ComponentDescription[] ret = filterByContainmentPoint(
192: agentDescs, containmentPoint);
193:
194: if (logger.isDetailEnabled()) {
195: StringBuffer buf = new StringBuffer();
196: buf.append("returning ");
197: buf.append(ret.length);
198: buf.append(" component descriptions: ");
199: for (int i = 0; i < ret.length; i++) {
200: appendDesc(buf, ret[i]);
201: }
202: logger.detail(buf.toString());
203: }
204:
205: return ret;
206: }
207:
208: public boolean includesDefaultComponents() {
209: return true;
210: }
211:
212: private List getAgentDescs(String agentName) throws Exception {
213: if (agentName == null) {
214: throw new IllegalArgumentException("null agentName");
215: }
216:
217: // check already parsed XML_FILE_NAME
218: List l = (List) agents.get(agentName);
219: if (l != null) {
220: if (logger.isDebugEnabled()) {
221: logger.debug("Found cached agent " + agentName
222: + " config");
223: }
224: return l;
225: }
226:
227: // look for agent.xml
228: //
229: // we could cache a parse failure, but these are probably
230: // rare
231: try {
232: if (logger.isInfoEnabled()) {
233: logger.info("Parsing " + agentName + ".xml");
234: }
235: Map m = XMLConfigParser.parseAgents(agentName + ".xml",
236: null, // no "<node>"
237: agentName, // just this agent
238: get_overrides());
239: l = (List) m.get(agentName);
240: if (logger.isDetailEnabled()) {
241: logger.detail("found " + (l == null ? 0 : l.size())
242: + " components");
243: }
244:
245: // cache
246: agents.put(agentName, l);
247: } catch (Exception e) {
248: // look for a simple file-not-found error
249: FileNotFoundException fnfe = null;
250: for (Throwable t = e; t != null; t = t.getCause()) {
251: if (t instanceof FileNotFoundException) {
252: fnfe = (FileNotFoundException) t;
253: break;
254: }
255: }
256: if (fnfe == null) {
257: throw e;
258: }
259: // look for default agent xml
260: if (agentName.equals(DEFAULT_AGENT)
261: || DEFAULT_AGENT == null) {
262: return null;
263: }
264: if (logger.isInfoEnabled()) {
265: logger.info("Unable to find " + agentName
266: + ".xml, will try " + DEFAULT_AGENT);
267: }
268: // single-step recursion
269: l = getAgentDescs(DEFAULT_AGENT);
270: if (l == null) {
271: throw e;
272: }
273: }
274:
275: return l;
276: }
277:
278: private ComponentDescription[] filterByContainmentPoint(List l,
279: String containmentPoint) {
280: if (l == null || l.isEmpty()) {
281: return NO_COMPONENTS;
282: }
283: List retList = null;
284: for (int i = 0, n = l.size(); i < n; i++) {
285: ComponentDescription cd = (ComponentDescription) l
286: .get(i);
287: String ip = cd.getInsertionPoint();
288: if (ip.startsWith(containmentPoint)
289: && ip.indexOf('.',
290: containmentPoint.length() + 1) < 0) {
291: if (retList == null) {
292: retList = new ArrayList();
293: }
294: retList.add(cd);
295: }
296: }
297: if (retList == null) {
298: return NO_COMPONENTS;
299: }
300: return (ComponentDescription[]) retList
301: .toArray(new ComponentDescription[retList.size()]);
302: }
303:
304: private static void appendDesc(StringBuffer buf,
305: ComponentDescription cd) {
306: buf.append("\n <component name=\'");
307: buf.append(cd.getName());
308: buf.append("\' class=\'");
309: buf.append(cd.getClassname());
310: buf.append("\' priority=\'");
311: buf.append(cd.getPriority());
312: buf.append("\' insertionpoint=\'");
313: buf.append(cd.getInsertionPoint());
314: buf.append("\'");
315: Object o = cd.getParameter();
316: if (o == null) {
317: buf.append("/>");
318: return;
319: }
320: buf.append(">");
321: if (o instanceof List) {
322: List l = (List) o;
323: for (int i = 0, n = l.size(); i < n; i++) {
324: buf.append("\n <argument>");
325: buf.append(l.get(i));
326: buf.append("</argument>");
327: }
328: } else {
329: buf.append("\n <argument>");
330: buf.append(o);
331: buf.append("</argument>");
332: }
333: buf.append("\n </component>");
334: }
335: }
336: }
|