Source code for /engineering/autohit-2003/src/autohit/server/SimpleSystemContext.javaOriginal file SimpleSystemContext.java
   1 /**
   2  * AUTOHIT 2003
   3  * Copyright Erich P Gatejen (c) 1989,1997,2003,2004
   4  * 
   5  * This program is free software; you can redistribute it and/or modify 
   6  * it under the terms of the GNU General Public License as published by 
   7  * the Free Software Foundation; either version 2 of the License, or (at
   8  * your option) any later version.
   9  * This program is distributed in the hope that it will be useful, but
  10  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  11  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12  * more details.
  13  * 
  14  * You should have received a copy of the GNU General Public License along
  15  * with this program; if not, write to the Free Software Foundation, Inc.,
  16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17  *
  18  * Additional license information can be found in the documentation.
  19  * @author Erich P Gatejen
  20  */
  21 package autohit.server;
  22 
  23 import java.io.FileInputStream;
  24 import java.io.FileOutputStream;
  25 
  26 import org.apache.commons.collections.ExtendedProperties;
  27 
  28 import autohit.common.AutohitBasicLogManager;
  29 import autohit.common.AutohitErrorCodes;
  30 import autohit.common.AutohitException;
  31 import autohit.common.AutohitLogDrain;
  32 import autohit.common.AutohitLogDrainDefault;
  33 import autohit.common.AutohitLogDrainRouting;
  34 import autohit.common.AutohitLogInjectorWrapper;
  35 import autohit.common.AutohitProperties;
  36 import autohit.common.Utils;
  37 import autohit.common.channels.Controller;
  38 import autohit.common.channels.Injector;
  39 import autohit.creator.compiler.SimCompiler;
  40 import autohit.creator.compiler.XmlCompiler;
  41 import autohit.server.command.CommandRegistry;
  42 import autohit.universe.Universe;
  43 import autohit.universe.UniverseFactory;
  44 import autohit.vm.VMLoader;
  45 
  46 /**
  47  * A simple system context for a server or invoker.
  48  * <p><pre>
  49  * It includes:
  50  * a basic log manager (@see #logger)
  51  * a root logger
  52  * a basic properties set (@see #prop)
  53  * a single script SIM compiler (@see #compiler)
  54  * a universe factory (@see #uf)
  55  * a LOCAL universe server
  56  * a Kernel (uninitialized!)
  57  * a root loader (uninitialized!)
  58  * </pre><p>
  59  * It requires the root property be set.
  60  *
  61  * @author Erich P. Gatejen
  62  * @version 1.0
  63  * <i>Version History</i>
  64  * <code>EPG - Initial - 25Apr03 
  65  * 
  66  */
  67 public class SimpleSystemContext implements SystemContext {
  68 
  69 	/**
  70 	 * Primary log manager
  71 	 */
  72 	public AutohitBasicLogManager logManager;
  73 
  74 	/**
  75 	 * Root log injector
  76 	 */
  77 	public AutohitLogInjectorWrapper logger;
  78 
  79 	/**
  80 	 * Script compiler.  Keep at least one around.
  81 	 */
  82 	public SimCompiler compiler;
  83 
  84 	/**
  85 	 * Our simple little universe.
  86 	 */
  87 	public Universe uni;
  88 
  89 	/**
  90 	 * The system properties set
  91 	 */
  92 	public ExtendedProperties prop;
  93 
  94 	/**
  95 	 * Invoker properties set
  96 	 */
  97 	public ExtendedProperties invokerprop;
  98 
  99 	/**
 100 	 * Universe factory
 101 	 */
 102 	public UniverseFactory uf;
 103 
 104 	/**
 105 	 * Channel controller
 106 	 */
 107 	public Controller cc;
 108 
 109 	/**
 110 	 * Kernel
 111 	 */
 112 	public Kernel k;
 113 
 114 	/**
 115 	 * Kernel
 116 	 */
 117 	private VMLoader loader;
 118 
 119 	/**
 120 	 * Debugging flag
 121 	 */
 122 	public boolean debug;
 123 
 124 	/**
 125 	 * Root path
 126 	 */
 127 	public String root;
 128 
 129 	/**
 130 	 * Unique number counter -- it will be unique for all instances of SimpleSystemContext.
 131 	 */
 132 	public static int uniqueN = 0;
 133 
 134 	/**
 135 	 *  Default Constructor.
 136 	 */
 137 	public SimpleSystemContext() throws Exception {
 138 		// Doesn't do anything
 139 	}
 140 
 141 	/**
 142 	 *  Properties constructor.  Give it a full path to the 
 143 	 *  properties file.
 144 	 */
 145 	public void init(ExtendedProperties props) throws Exception {
 146 
 147 		// save 'em
 148 		prop = props;
 149 
 150 		// defaults
 151 		debug = false;
 152 
 153 		// Make my universe factory
 154 		uf = new UniverseFactory();
 155 
 156 		// Make a channel controller
 157 		cc = new Controller();
 158 
 159 		// BUILD LOG MANAGER ---------------------------------------
 160 		
 161 		int ald_line_size = AutohitProperties.LOGS_LINE_SIZE_DEFAULT;
 162 		
 163 		// LINE SIZE?
 164 		String logsize =
 165 		(String) Utils.testGetProperty(
 166 				AutohitProperties.LOGS_LINE_SIZE,
 167 				prop);
 168 		if (logsize != null) {
 169 			try {
 170 				ald_line_size = Integer.parseInt(logsize);
 171 			} catch (Exception e) {
 172 				// No where to report it anyway
 173 			}
 174 		}
 175 				
 176 		// If a log type is file, use a file otherwise use console, 
 177 		// even if not set.
 178 		String logprop =
 179 			(String) Utils.testGetProperty(
 180 				AutohitProperties.LOGS_TYPE_CONTROL,
 181 				prop);
 182 		String logClientprop =
 183 			(String) Utils.testGetProperty(
 184 				AutohitProperties.LOGS_TYPE_CLIENT,
 185 				prop);
 186 		AutohitLogDrain controlDrain;
 187 		AutohitLogDrain clientDrain;
 188 
 189 		// CONTROL DRAIN
 190 		if ((logprop == null)
 191 			|| (logprop.equals(AutohitProperties.LOGS_TYPE__FILE))) {
 192 			try {
 193 				logprop =
 194 					(String) Utils.testGetProperty(
 195 						AutohitProperties.LOGS_LOCATION_CONTROL + AutohitProperties.literal_FS_LOG_EXTENSION,
 196 						prop);
 197 				FileOutputStream fco = new FileOutputStream(logprop, true);
 198 				controlDrain = new AutohitLogDrainDefault();
 199 				controlDrain.init(fco, ald_line_size);
 200 			} catch (Exception e) {
 201 				// If something goes wrong, default to console
 202 				controlDrain = new AutohitLogDrainDefault();
 203 				controlDrain.init(System.err, ald_line_size);
 204 			}
 205 		} else {
 206 			controlDrain = new AutohitLogDrainDefault(); // drain to stderr
 207 			controlDrain.init(System.err, ald_line_size);
 208 		}
 209 		// CLIENT DRAIN
 210 		if ((logClientprop == null)
 211 			|| (logClientprop.equals(AutohitProperties.LOGS_TYPE__FILE))) {
 212 			try {
 213 				logClientprop =
 214 					(String) Utils.testGetProperty(
 215 						AutohitProperties.LOGS_LOCATION_CLIENT,
 216 						prop);
 217 				FileOutputStream fco =
 218 					new FileOutputStream(logClientprop, true);
 219 				AutohitLogDrainRouting rclientDrain = new AutohitLogDrainRouting();
 220 				rclientDrain.init(fco, ald_line_size);
 221 				rclientDrain.setup(logClientprop);
 222 				clientDrain = rclientDrain;
 223 			} catch (Exception e) {
 224 				// If something goes wrong, default to console
 225 				clientDrain = new AutohitLogDrainDefault();
 226 				clientDrain.init(System.err, ald_line_size);
 227 				System.out.println("SimpleSystemContext:Could not build AutohitLogDrainRouting.  Using stderr instead.  message=" + e.getMessage());
 228 			}
 229 		} else {
 230 			clientDrain = new AutohitLogDrainDefault(); // drain to stderr
 231 			clientDrain.init(System.err, ald_line_size);
 232 		}
 233 		logManager = new AutohitBasicLogManager(controlDrain, clientDrain);
 234 
 235 		// CONFIGURE LOGGERS -----------------------------------------
 236 		// Get root logger.  Set some attributes
 237 		logger = logManager.getRootLogger();
 238 
 239 		// Configure the logger
 240 		logger.info(
 241 			"Root logger starting.",
 242 			AutohitErrorCodes.CODE_INFORMATIONAL_OK_VERBOSE);
 243 		logprop =
 244 			(String) Utils.testGetProperty(
 245 				AutohitProperties.LOGS_PRETTY_PRINT,
 246 				prop);
 247 		if ((logprop != null) && (logprop.equals("true"))) {
 248 			logger.info(
 249 				"Root logger pretty-print = true.",
 250 				AutohitErrorCodes.CODE_INFORMATIONAL_OK_VERBOSE);
 251 			logManager.pretty(true);
 252 		}
 253 		logprop =
 254 			(String) Utils.testGetProperty(
 255 				AutohitProperties.LOGS_TIMESTAMP,
 256 				prop);
 257 		if ((logprop != null) && (logprop.equals("true"))) {
 258 			logger.info(
 259 				"Root logger timestamp = true.",
 260 				AutohitErrorCodes.CODE_INFORMATIONAL_OK_VERBOSE);
 261 			logManager.stampit(true);
 262 		}
 263 
 264 		logprop =
 265 			(String) Utils.testGetProperty(
 266 				AutohitProperties.LOGS_LINE_LIMIT,
 267 				prop);
 268 		if (logprop != null) {
 269 			try {
 270 				int ll = Integer.parseInt(logprop);
 271 				logger.info(
 272 					"Root logger line limit set to " + ll,
 273 					AutohitErrorCodes.CODE_INFORMATIONAL_OK_VERBOSE);
 274 				logManager.getDrain().setLineLimit(ll);
 275 				logManager.getClientDrain().setLineLimit(ll);
 276 			} catch (Exception e) {
 277 				logger.error(
 278 					"Value for "
 279 						+ AutohitProperties.LOGS_LINE_LIMIT
 280 						+ " cannot be parsed as an integer.  Using default.  Value="
 281 						+ logprop,
 282 					AutohitErrorCodes.CODE_CONFIGURATION_ERROR);
 283 			}
 284 		}
 285 
 286 		// Are we debugging???
 287 		logprop =
 288 			(String) Utils.testGetProperty(
 289 				AutohitProperties.SYSTEM_DEBUG,
 290 				prop);
 291 		if ((logprop != null) && (logprop.equals("true"))) {
 292 			logger.info(
 293 				"DEBUGGING IS ON.",
 294 				AutohitErrorCodes.CODE_INFORMATIONAL_OK);
 295 			logManager.debugOn();
 296 			debug = true;
 297 		}
 298 
 299 		logger.debug(
 300 			"DEBUGGING root logger up.",
 301 			AutohitErrorCodes.CODE_INFORMATIONAL_OK);
 302 		logger.info(
 303 			"Root logger up.",
 304 			AutohitErrorCodes.CODE_INFORMATIONAL_OK_VERBOSE);
 305 
 306 		// At this point, log any exceptions and abort
 307 		try {
 308 
 309 			// Check for 
 310 			root =
 311 				(String) Utils.testGetProperty(
 312 					AutohitProperties.ROOT_PATH,
 313 					prop);
 314 			if (root == null) {
 315 				logger.error(
 316 					"ERROR.  Root property not set!",
 317 					AutohitErrorCodes.CODE_STARTUP_CONFIGURATION_FAULT);
 318 				throw new AutohitException(
 319 					"Required root property not set.",
 320 					AutohitException.CODE_STARTUP_CONFIGURATION_FAULT);
 321 			}
 322 
 323 			// BUILD COMPILER
 324 			compiler = new SimCompiler(this);
 325 
 326 			// Get universe config
 327 			String handle =
 328 				(String) Utils.testGetProperty(
 329 					AutohitProperties.DEFAULT_UNIVERSE_HANDLE,
 330 					prop);
 331 			if (handle == null) {
 332 				handle = AutohitProperties.literal_DEFAULT_UNIVERSE_HANDLE;
 333 			}
 334 			String upath =
 335 				(String) Utils.testGetProperty(
 336 					AutohitProperties.DEFAULT_UNIVERSE_PATH,
 337 					prop);
 338 			if (upath == null) {
 339 				upath = AutohitProperties.literal_DEFAULT_UNIVERSE_PATH;
 340 			}
 341 			String uprop =
 342 				(String) Utils.testGetProperty(
 343 					AutohitProperties.DEFAULT_UNIVERSE_PROP,
 344 					prop);
 345 			if (uprop == null) {
 346 				uprop = AutohitProperties.literal_DEFAULT_UNIVERSE_PROP;
 347 			}
 348 			
 349 			// INVOKER PROPERTIES
 350 			invokerprop = new ExtendedProperties();
 351 
 352 			// BUILD OUR UNIVERSE
 353 			uni = uf.create(handle, root + upath + "/" + uprop);
 354 
 355 			// BUILD THE ROOT KERNEL
 356 			k = new Kernel();
 357 			k.init(this);
 358 
 359 			// BUILD THE LOADER
 360 			loader = new VMLoader();
 361 			loader.init(this);
 362 
 363 		} catch (Exception e) {
 364 			logger.error(
 365 				"ERROR during context instantiation.  Aborting.  Exception="
 366 					+ e.getMessage(),
 367 				AutohitErrorCodes.CODE_STARTUP_FAULT);
 368 			throw e;
 369 		}
 370 	}
 371 
 372 	/**
 373 	 * Load properties.  It will delete any previously loaded properties.
 374 	 * @param props a properties set
 375 	 */
 376 	public void loadProperties(ExtendedProperties props) throws Exception {
 377 		prop.combine(props);
 378 	}
 379 
 380 	/**
 381 	 *  Get the default universe
 382 	 * @return Universe service interface
 383 	 */
 384 	public Universe getUniverse() {
 385 		return uni;
 386 	}
 387 
 388 	/**
 389 	 *  Get a universe service by handle.  This implementation ignores the
 390 	 *  handle and returns the only universe we have.
 391 	 * @param handle handle to the universe
 392 	 * @return Universe service interface
 393 	 */
 394 	public Universe getUniverse(String handle) {
 395 		// ignore the handle.  We only have one.
 396 		return uni;
 397 	}
 398 
 399 	/**
 400 	 *  Get the XML compiler
 401 	 * @return XmlCompiler base class
 402 	 */
 403 	public XmlCompiler getCompiler() {
 404 		return compiler;
 405 	}
 406 
 407 	/**
 408 	 *  Get a reference to a generic, root log injector
 409 	 * @return XmlCompiler base class
 410 	 */
 411 	public AutohitLogInjectorWrapper getRootLogger() {
 412 		return logger;
 413 	}
 414 
 415 	/**
 416 	 *  Cheat.  The logger will be our even dispacter
 417 	 * @return Injector reference
 418 	 */
 419 	public Injector getEventDispatcher() {
 420 		return (Injector) logger;
 421 	}
 422 
 423 	/**
 424 	 *  Get properties set
 425 	 * @return reference to the properties set
 426 	 */
 427 	public ExtendedProperties getPropertiesSet() {
 428 		return prop;
 429 	}
 430 
 431 	/**
 432 	 *  Get log manager reference
 433 	 * @return reference to the properties set
 434 	 */
 435 	public AutohitBasicLogManager getLogManager() {
 436 		return logManager;
 437 	}
 438 
 439 	/**
 440 	 *  Get the Kernel
 441 	 * @return reference to the kernel
 442 	 */
 443 	public Kernel getKernel() {
 444 		return k;
 445 	}
 446 
 447 	/**
 448 	 *  Get the VM Loader
 449 	 * @return reference to the kernel
 450 	 */
 451 	public VMLoader getLoader() {
 452 		return loader;
 453 	}
 454 
 455 	/**
 456 	 *  Get the command registry as a properties set.  It is not cached.  
 457 	 *  this implementation will always return the default set.
 458 	 * @return properties set representing the registry.  it will return null if it cannot be loaded
 459 	 */
 460 	public CommandRegistry getCommandRegistry() {
 461 
 462 		CommandRegistry rset = null;
 463 		try {
 464 			rset =
 465 				new CommandRegistry(
 466 					new FileInputStream(
 467 						root + AutohitProperties.COMMAND_DEFAULT_REGISTRY));
 468 
 469 		} catch (Exception e) {
 470 			// don't care.  it will return null.
 471 			logger.error(
 472 				"FAULT!  Fauled to create a CommandRegistry!  message="
 473 					+ e.getMessage(),
 474 				AutohitErrorCodes.CODE_COMMAND_REGISTRY_FAULT);
 475 		}
 476 		return rset;
 477 	}
 478 
 479 	/**
 480 	 *  Unique number
 481 	 * @return an integer number unique (at least) to this Context
 482 	 */
 483 	public synchronized int uniqueInteger() {
 484 		uniqueN++;
 485 		return uniqueN;
 486 	}
 487 	
 488 	/**
 489 	 *  Get debugging state
 490 	 * @return true if debugging active
 491 	 */
 492 	public boolean debuggingState() {
 493 		return debug;
 494 	}
 495 
 496 	/**
 497 	 * Get a reference to the invoker properties set.   Generally, only
 498 	 * invokers should add anything to the set.  It should be safe for anyone
 499 	 * to read from it.  It is up to the invoker to maintain its contents.
 500 	 * @return reference to the invoker properties set
 501 	 */
 502 	public ExtendedProperties getInvokerProperties() {
 503 		return invokerprop;
 504 	}
 505 
 506 }