Source code for /engineering/autohit-2003/src/autohit/common/deployment/DeploymentConfigure.javaOriginal file DeploymentConfigure.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.common.deployment;
  22 
  23 import java.io.BufferedReader;
  24 import java.io.File;
  25 import java.io.FileReader;
  26 import java.util.StringTokenizer;
  27 
  28 import org.apache.commons.collections.ExtendedProperties;
  29 
  30 import autohit.common.AutohitProperties;
  31 import autohit.common.Constants;
  32 import autohit.common.Utils;
  33 
  34 /**
  35  * A deployment manager.  It will handle configuration, installation, and checkpointing.
  36  *
  37  * @author Erich P. Gatejen
  38  * @version 1.0
  39  * <i>Version History</i>
  40  * <code>EPG - Initial - 25Apr03 
  41  * 
  42  */
  43 public class DeploymentConfigure {
  44 
  45 	/**
  46 	 * Command system
  47 	 */
  48 	public ExtendedProperties props;
  49 
  50 	/**
  51 	 *  Default constructor. 
  52 	 */
  53 	public DeploymentConfigure() throws Exception {
  54 
  55 	}
  56 
  57 	/**
  58 	 *  Checkpoint the system
  59 	 * @param name checkpoint name
  60 	 * @param root directory root
  61 	 * @param cf configuration file
  62 	 * @param special unlock factory.  ALWAYS use FALSE
  63 	 * @return true if successful, false if there is an error
  64 	 */
  65 	public boolean checkpoint(
  66 		String name,
  67 		String root,
  68 		String cf,
  69 		boolean special) {
  70 
  71 		String[] currentLine;
  72 		String lf;
  73 		File lFile;
  74 		int count = 0;
  75 		int lineCount = 0;
  76 
  77 		// Is it trying to checkpoint to the factory settings?
  78 		if ((special == false)
  79 			&& (name.equals(AutohitProperties.vFACTORY_STORE))) {
  80 			System.out.println(
  81 				"You may not checkpoint to the factory settings.  Use a checkpoint name other than 'factory'.");
  82 			return false;
  83 		}
  84 
  85 		String configPath =
  86 			new String(root + AutohitProperties.vCONFIG_ROOT + name + "/");
  87 
  88 		// See if already saved.
  89 		File fdpath = new File(configPath);
  90 		if (fdpath.exists()) {
  91 			System.out.println(
  92 				"There is already a " + name + " checkpoint set.");
  93 			System.out.println("You can use the delete command to remove it.");
  94 			return false;
  95 		}
  96 
  97 		// Set the config file
  98 		if (cf == null) {
  99 			cf = AutohitProperties.vDEFAULT_CHECKPOINT;
 100 		}
 101 		lf = new String(root + AutohitProperties.vCONFIG_ROOT + cf);
 102 
 103 		// Get to work		
 104 		try {
 105 			// Make the dir
 106 			fdpath.mkdirs();
 107 
 108 			// Open config file
 109 			lFile = new File(lf);
 110 			BufferedReader inBR = new BufferedReader(new FileReader(lFile));
 111 
 112 			// example line: n bin/default.prop factory/standard/default.prop
 113 			currentLine = parseConfigLine(inBR);
 114 			while (currentLine != null) {
 115 				lineCount++;
 116 				switch (currentLine[0].charAt(0)) {
 117 
 118 					case Constants.CONFIG_DIR :
 119 						System.out.println(
 120 							Utils.copyDir(
 121 								root + "/" + currentLine[1],
 122 								configPath + Integer.toString(count),
 123 								false));
 124 						count++;
 125 						break;
 126 
 127 					case Constants.CONFIG_COMMENT :
 128 						// ignore
 129 						break;
 130 
 131 					case Constants.CONFIG_CHKPNT :
 132 					case Constants.CONFIG_CONFIG_YES :
 133 					case Constants.CONFIG_CONFIG_NO :
 134 						System.out.println(
 135 							Utils.copy(
 136 								root + "/" + currentLine[1],
 137 								configPath + Integer.toString(count)));
 138 						count++;
 139 						break;
 140 
 141 					default :
 142 						System.out.println(
 143 							"Bad command.  Line #"
 144 								+ lineCount
 145 								+ ".  Command ="
 146 								+ currentLine[0].charAt(0));
 147 				}
 148 				currentLine = parseConfigLine(inBR);
 149 			}
 150 
 151 			// Move the config file
 152 			inBR.close();
 153 			System.out.println(
 154 				Utils.copy(lf, configPath + AutohitProperties.vCONFIG_FILE));
 155 
 156 		} catch (Exception e) {
 157 			System.out.println("CHECKPOINT failed!");
 158 			e.printStackTrace();
 159 			return false;
 160 		}
 161 
 162 		System.out.println("CHECKPOINT is done.");
 163 		return true;
 164 	}
 165 
 166 	/**
 167 	 * Delete a checkpoint
 168 	 * @param name checkpoint name
 169 	 * @param root directory root
 170 	 * @return true if successful, false if there is an error
 171 	 */
 172 	public boolean delete(String name, String root) {
 173 
 174 		String[] currentLine;
 175 		String lf;
 176 		File lFile;
 177 		int count = 0;
 178 		int lineCount = 0;
 179 
 180 		String configPath =
 181 			new String(root + AutohitProperties.vCONFIG_ROOT + name);
 182 
 183 		// Is it trying to remove the factory settings?
 184 		if (name.equals(AutohitProperties.vFACTORY_STORE)) {
 185 			System.out.println("You may not delete the factory settings.");
 186 		}
 187 
 188 		// See if already saved.
 189 		File fdpath = new File(configPath);
 190 		if (!fdpath.exists()) {
 191 			System.out.println("Checkpoint set does not exist.");
 192 			return false;
 193 		}
 194 
 195 		System.out.println(Utils.wipeDir(configPath));
 196 		System.out.println("DELETE is done.  Check messages for errors.");
 197 		return true;
 198 	}
 199 
 200 	/**
 201 	 *  Restore a checkpoint
 202 	 * @param name checkpoint name
 203 	 * @param root directory root
 204 	 * @param wipe destructive restore
 205 	 * @return true if successful, false if there is an error
 206 	 */
 207 	public boolean restore(String name, String root, boolean wipe) {
 208 
 209 		String[] currentLine;
 210 		String lf;
 211 		File fdfile;
 212 		int count = 0;
 213 		int lineCount = 0;
 214 		BufferedReader inBR;
 215 
 216 		String configPath =
 217 			new String(root + AutohitProperties.vCONFIG_ROOT + name + "/");
 218 		String configFile =
 219 			new String(configPath + AutohitProperties.vCONFIG_FILE);
 220 
 221 		// See if it is there and get the configuration file
 222 		try {
 223 
 224 			fdfile = new File(configPath);
 225 			if (!fdfile.exists())
 226 				throw new Exception();
 227 			inBR = new BufferedReader(new FileReader(fdfile));
 228 
 229 		} catch (Exception e) {
 230 			System.out.println(
 231 				"Checkpoint does not exist or is invalid for " + name);
 232 			return false;
 233 		}
 234 
 235 		// Get to work		
 236 		try {
 237 
 238 			// example line: n bin/default.prop factory/standard/default.prop
 239 			currentLine = parseConfigLine(inBR);
 240 			while (currentLine != null) {
 241 				lineCount++;
 242 				switch (currentLine[1].charAt(0)) {
 243 
 244 					case Constants.CONFIG_DIR :
 245 						System.out.println(
 246 							Utils.copyDir(
 247 								configPath + Integer.toString(count),
 248 								root + "/" + currentLine[1],
 249 								wipe));
 250 						count++;
 251 						break;
 252 
 253 					case Constants.CONFIG_COMMENT :
 254 						// ignore
 255 						break;
 256 
 257 					case Constants.CONFIG_CHKPNT :
 258 					case Constants.CONFIG_CONFIG_YES :
 259 					case Constants.CONFIG_CONFIG_NO :
 260 						System.out.println(
 261 							Utils.copy(
 262 								root + "/" + currentLine[1],
 263 								configPath + Integer.toString(count)));
 264 						count++;
 265 						break;
 266 
 267 					default :
 268 						System.out.println(
 269 							"Bad command.  Line #"
 270 								+ lineCount
 271 								+ ".  Command ="
 272 								+ currentLine[1].charAt(0));
 273 				}
 274 				currentLine = parseConfigLine(inBR);
 275 			}
 276 
 277 		} catch (Exception e) {
 278 			System.out.println("RESTORE failed!");
 279 			e.printStackTrace();
 280 			return false;
 281 		}
 282 		System.out.println("RESTORE is done.");
 283 		return true;
 284 	}
 285 
 286 	/**config config [config name] [root] [prop file]
 287 	 * Process a configuration
 288 	 * @param config config file name
 289 	 * @param root directory root
 290 	 * @param vars variable replacement set.  a properties file.
 291 	 * @return true if successful, false if there is an error
 292 	 */
 293 	public boolean configure(String config, String root, String vars) {
 294 
 295 		ExtendedProperties varprops;
 296 
 297 		// Get variables file and load into varprops
 298 		String varPath = new String(root + AutohitProperties.vVAR_ROOT + vars);
 299 		File varFile = new File(varPath);
 300 		if (!varFile.exists()) {
 301 			System.out.println(
 302 				"Configuration values file does not exist= "
 303 					+ vars
 304 					+ ".  It should be under the /etc directory.");
 305 			return false;
 306 		}
 307 		try {
 308 			varprops = new ExtendedProperties(varPath);
 309 		} catch (Exception e) {
 310 			System.out.println("Configuration values file is unreadable.");
 311 			return false;
 312 		}
 313 		return configure(config, root, varprops);
 314 	}
 315 
 316 	/**config config [config name] [root] [prop file]
 317 	 * Process a configuration
 318 	 * @param config config file name
 319 	 * @param root directory root
 320 	 * @param varprops an ExtendedProperties set of configuration name/values.
 321 	 * @return true if successful, false if there is an error
 322 	 */
 323 	public boolean configure(
 324 		String config,
 325 		String root,
 326 		ExtendedProperties varprops) {
 327 
 328 		String[] currentLine;
 329 		String lf;
 330 		File fdfile;
 331 		int count = 0;
 332 		int lineCount = 0;
 333 		BufferedReader inBR;
 334 
 335 		String configPath;
 336 		String configPathFile;
 337 		File fConfigFile;
 338 
 339 		// See if it is there and get the configuration file
 340 		try {
 341 			// try the root
 342 			configPath =
 343 				new String(
 344 					root + AutohitProperties.vCONFIG_ROOT + config + "/");
 345 			configPathFile =
 346 				new String(configPath + AutohitProperties.vCONFIG_FILE);
 347 			fConfigFile = new File(configPathFile);
 348 			if (!fConfigFile.exists()) {
 349 				// see if there are any hanger-ons
 350 				configPathFile = new String(configPath + config);
 351 				fConfigFile = new File(configPathFile);
 352 				if (!fConfigFile.exists())
 353 					throw new Exception();
 354 			}
 355 			inBR = new BufferedReader(new FileReader(fConfigFile));
 356 		} catch (Exception e) {
 357 			System.out.println(
 358 				"Configuration descriptor is invalid for " + config);
 359 			return false;
 360 		}
 361 
 362 		// Get to work		
 363 		try {
 364 
 365 			// example line: n bin/default.prop factory/standard/default.prop
 366 			currentLine = parseConfigLine(inBR);
 367 			while (currentLine != null) {
 368 				lineCount++;
 369 System.out.println("linecount="+lineCount+" count=" + count + " line="+ currentLine[0]);				
 370 				switch (currentLine[0].charAt(0)) {
 371 
 372 					case Constants.CONFIG_DIR :
 373 						System.out.println(
 374 							Utils.copyDir(
 375 								configPath + Integer.toString(count),
 376 								root + "/" + currentLine[1],
 377 								false));
 378 						count++;
 379 						break;
 380 
 381 					case Constants.CONFIG_COMMENT :
 382 					case Constants.CONFIG_CHKPNT :
 383 						// ignore
 384 						break;
 385 
 386 					case Constants.CONFIG_CONFIG_YES :
 387 						System.out.println(
 388 							Utils.merge(
 389 								configPath + Integer.toString(count),
 390 								root + "/" + currentLine[1],
 391 								varprops));
 392 						count++;
 393 						break;
 394 
 395 					case Constants.CONFIG_CONFIG_NO :
 396 						System.out.println(
 397 							Utils.copy(
 398 								configPath + Integer.toString(count),
 399 								root + "/" + currentLine[1]));
 400 						count++;
 401 						break;
 402 
 403 					default :
 404 						System.out.println(
 405 							"Bad command.  Line #"
 406 								+ lineCount
 407 								+ ".  Command ="
 408 								+ currentLine[0].charAt(0));
 409 				}
 410 				currentLine = parseConfigLine(inBR);
 411 			}
 412 
 413 		} catch (Exception e) {
 414 			System.out.println("CONFIGURE failed!");
 415 			e.printStackTrace();
 416 			return false;
 417 		}
 418 		System.out.println("CONFIGURE is done.");
 419 		return true;
 420 	}
 421 
 422 	/**
 423 	 *  Parse the config line
 424 	 */
 425 	private String[] parseConfigLine(BufferedReader inR) {
 426 
 427 		String t[] = new String[3];
 428 		String working = null;
 429 		StringTokenizer st;
 430 
 431 		try {
 432 
 433 			working = inR.readLine();
 434 			while ((working.length() == 0)
 435 				|| (working.charAt(0) == '#')
 436 				|| (!Character.isLetter(working.charAt(0)))) {
 437 				working = inR.readLine();
 438 			}
 439 
 440 			// Working should be a valid line
 441 			try {
 442 
 443 				st = new StringTokenizer(working);
 444 				t[0] = st.nextToken();
 445 				t[1] = st.nextToken();
 446 				// the third field doesn't matter for checkpointing
 447 				try {
 448 					t[2] = st.nextToken();
 449 				} catch (Exception e) {
 450 					t[2] = null;
 451 				}
 452 
 453 			} catch (Exception e) {
 454 				System.out.println("BAD line in Files:\n" + working);
 455 				throw e;
 456 			}
 457 
 458 		} catch (Exception e) {
 459 			// Quit for ANY exception
 460 			return null;
 461 		}
 462 
 463 		return t;
 464 	}
 465 
 466 	/**
 467 	 *  Object main
 468 	 */
 469 	public void go(String[] args) {
 470 
 471 		char cmd = args[0].charAt(0);
 472 		switch (cmd) {
 473 			case 'S' :
 474 			case 's' :
 475 				if (args.length == 4) {
 476 					checkpoint(args[1], args[2], args[3], false);
 477 				} else if (args.length == 3) {
 478 					checkpoint(args[1], args[2], null, false);
 479 				} else {
 480 					System.out.println("ERROR: Bad number of parameters.");
 481 					usage();
 482 				}
 483 				break;
 484 
 485 			case 'F' :
 486 			case 'f' :
 487 				System.out.println("BUILD FACTORY SETTINGS");
 488 				// CHECKPOINT THE FACTORY
 489 				// YOU SHOULDN'T DO THIS!  IT'S FOR THE BUILD SYSTEM
 490 				// The command is "config factory PLEASE [root]" (cases sensitive)
 491 				if ((args.length == 3) && (args[1].charAt(0) == 'P')) {
 492 					checkpoint(
 493 						AutohitProperties.vFACTORY_STORE,
 494 						args[2],
 495 						AutohitProperties.vDEFAULT_CHECKPOINT,
 496 						true);
 497 				} else {
 498 					System.out.println("ERROR: Unknown command.");
 499 					usage();
 500 				}
 501 				break;
 502 
 503 			case 'R' :
 504 			case 'r' :
 505 				if (args.length == 3) {
 506 					restore(args[1], args[2], true);
 507 				} else {
 508 					System.out.println("ERROR: Bad number of parameters.");
 509 					usage();
 510 				}
 511 				break;
 512 			case 'M' :
 513 			case 'm' :
 514 				if (args.length == 3) {
 515 					restore(args[1], args[2], false);
 516 				} else {
 517 					System.out.println("ERROR: Bad number of parameters.");
 518 					usage();
 519 				}
 520 				break;
 521 			case 'D' :
 522 			case 'd' :
 523 				if (args.length == 3) {
 524 					delete(args[1], args[2]);
 525 				} else {
 526 					System.out.println("ERROR: Bad number of parameters.");
 527 					usage();
 528 				}
 529 
 530 				break;
 531 			case 'c' :
 532 			case 'C' :
 533 				if (args.length != 4) {
 534 					System.out.println("ERROR: Bad parameters.");
 535 				} else {
 536 					configure(args[1], args[2], args[3]);
 537 				}
 538 				break;
 539 
 540 			case 'H' :
 541 			case 'h' :
 542 			case '?' :
 543 			case '-' :
 544 				usage();
 545 				break;
 546 
 547 			default :
 548 				System.out.println("ERROR: Unknown command.");
 549 				usage();
 550 				break;
 551 		}
 552 	}
 553 
 554 	// Usage
 555 	public void usage() {
 556 		System.out.println("Deployment Configuration for Autohit (2003):");
 557 		System.out.println("  config config [name] [root] [var file]");
 558 		System.out.println("  config save [name] [root] (config file)");
 559 		System.out.println("  ...... save a checkpoint by name.");
 560 		System.out.println("  config delete [name] [root]");
 561 		System.out.println("  config restore [name] [root]");
 562 		System.out.println(
 563 			"  ...... restore a checkpoint.  It is destructive.");
 564 		System.out.println("  config merge [name] [root]");
 565 		System.out.println(
 566 			"  ...... merge a checkpoint.  It will only overwrite named files.");
 567 		System.out.println(
 568 			"  The configuration called 'factory' will restore to the system to");
 569 		System.out.println("  ...... out-of-the-box.");
 570 	}
 571 
 572 	/**
 573 	 * main interface
 574 	 */
 575 	public static void main(String[] args) {
 576 
 577 		try {
 578 			DeploymentConfigure me = new DeploymentConfigure();
 579 
 580 			// handle arguments
 581 			if (args.length == 0) {
 582 				System.out.println("Huh?  What did you want me to do?");
 583 				me.usage();
 584 				return;
 585 			}
 586 
 587 			me.go(args);
 588 		} catch (Exception e) {
 589 			e.printStackTrace();
 590 		}
 591 	}
 592 }